home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / b / bmh02src.zip / BUFFER.C < prev    next >
C/C++ Source or Header  |  1992-08-16  |  9KB  |  363 lines

  1. /*
  2.    buffer.c : Copyright Paul Healy, EI9GL, 1992.
  3.  
  4.    A file is opened in binary mode and dumped to a buffer (in its entirety
  5.    if the buffer is big enough). Two pointers are retured to the buffer in
  6.    order to let clients walk through the buffer.
  7.  
  8.    It is up the client routines to call refill if the end of the buffer is
  9.    reached. 'getstring' will automatically call refill if needed.
  10.  
  11.    The mail is locked while dumping to the buffer. If the size of the mailfile
  12.    changes between loading and subsequent refills, then
  13.  
  14.    920527 : Created.
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <fcntl.h>
  19. #include <sys/stat.h>
  20. #include <io.h>
  21. #include <alloc.h>
  22. #include <ctype.h>
  23. #include <string.h>
  24. #include "rc.h"
  25. #include "lock.h"
  26. #include "buffer.h"
  27. #include "misc.h"
  28. #include "header.h"
  29. #include "current.h"
  30.  
  31. static unsigned BufSize = 0;
  32. static char *Buffer = NULL, Finished = -1, *FileName = NULL, *LockFile = NULL;
  33. static struct stat Stat;
  34. static long Where = -1l;
  35.  
  36. void
  37. freebuf(void)
  38. {
  39. /*
  40.    BufSize = 0;
  41.    if (Buffer != NULL) {
  42.       free(Buffer);
  43.       Buffer = NULL;
  44.       }
  45.    else
  46.       fprintf(stderr, "freebuf: freeing buffer before allocating it\n");
  47. */
  48.    if (FileName != NULL) {
  49.       free(FileName);
  50.       FileName = NULL;
  51.       }
  52.    if (LockFile != NULL) {
  53.       free(LockFile);
  54.       LockFile = NULL;
  55.       }
  56.    Finished = -1;
  57.    Where = -1L;
  58. }
  59.  
  60. static int
  61. fill(char **start, char **end, struct stat *statbuf)
  62. {
  63.    int handle, result;
  64.  
  65.    if ( (LockFile != NULL) && (bm_lock(LockFile) == -1) ) {
  66.       fprintf(stderr, "fill: can't lock %s\n", LockFile);
  67.       return -1;
  68.       }
  69.  
  70.    if ( (handle = open (FileName, O_RDONLY | O_BINARY)) == -1) {
  71.       bm_unlock(LockFile);
  72. /*
  73.       fprintf(stderr, "fill: can't open %s\n", FileName);
  74. */
  75.       return -1;
  76.       }
  77.    if ( (Where != -1l) && (lseek(handle, Where, SEEK_SET) == -1L) ) {
  78.       fprintf(stderr, "fill: can't seek %s\n", FileName);
  79.       close(handle);
  80.       bm_unlock(LockFile);
  81.       return -1;
  82.       }
  83.  
  84.    /*
  85.     * read returns an integer, but since we may be asking for more
  86.     * bytes that a 16 bit signed int can hold, the cast to unsigned
  87.     * further on is required.
  88.     */
  89.    if ( (result =  read(handle, Buffer+1, BufSize)) == -1 ) {
  90.       fprintf(stderr, "fill: error reading %s\n", FileName);
  91.       close(handle);
  92.       bm_unlock(LockFile);
  93.       return -1;
  94.       }
  95.    *start = Buffer+1;
  96.    *end = *start + (unsigned) result;
  97.  
  98.    **end = 'F'; /* Optimization for searching */
  99.  
  100. /*
  101.    printf("fill: %u bytes read\n", result);
  102. */
  103.    (void) fstat(handle, statbuf);    /* Record create time and size */
  104.  
  105.    if ( (Finished = eof(handle)) == 0);
  106.       Where = tell(handle);
  107.  
  108.    close(handle);
  109.  
  110.    return bm_unlock(LockFile);
  111. }
  112.  
  113. int
  114. loadbuf(char *s, char **start, char **end, char *lockfile)
  115. {
  116.    if (BufSize == 0)
  117.       BufSize = atol(getrc(bufsize));
  118.  
  119.    if ( (Buffer == NULL) && ( (Buffer = (char *) malloc(BufSize+2)) == NULL ) ) {
  120.       fprintf(stderr, "loadbuf: no room\n");
  121.       return -1;
  122.       }
  123.  
  124.    Buffer[0] = '\n'; /* Ensure that a 'From' at the start of the file is  */
  125.                      /* recognised by starting the buffer with a new line */
  126.  
  127.    if ( ( FileName=strdup(s) ) == NULL) {
  128.       fprintf(stderr, "loadbuf: no room\n");
  129.       return -1;
  130.       }
  131.  
  132.    if ( (lockfile != NULL) && ( (LockFile = strdup(lockfile)) == NULL ) ) {
  133.       fprintf(stderr, "loadbuf: no room\n");
  134.       return -1;
  135.       }
  136. /*
  137.    printf("loadbuf: bufsize=%u, file=%s\n", BufSize, FileName);
  138. */
  139.    return fill(start, end, &Stat);
  140. }
  141.  
  142. int
  143. loadmail(char *prog, char *folder, char **start, char **end)
  144. {
  145.    char file[256], lock[256];
  146.  
  147.    sprintf(file, "%s/%s%s", getrc(maildir), folder, EXT);
  148.    sprintf(lock, "%s/%s", getrc(maildir), folder);
  149.    if ( loadbuf(file, start, end, lock) == -1) {
  150.       fprintf(stderr, "%s: can't load %s\n", prog, file);
  151.       return -1;
  152.       }
  153.    return 0;
  154. }
  155.  
  156. int         
  157. refill(char **start, char **end)
  158. {
  159.    struct stat statbuf;
  160.    int result;
  161.  
  162.    if (Finished != 0)       /* 1 for not eof, and -1 for error condition */
  163.       return 1;
  164.  
  165.    Buffer[0] = Buffer[BufSize-1]; /* refill will only be call on previously */
  166.                                   /* full buffers */
  167.    result = fill(start, end, &statbuf);
  168.  
  169.    if ( statbuf.st_size != Stat.st_size ) {
  170.       fprintf(stderr, "bm: %s has been updated (%ld, %ld)\n", FileName,
  171.          statbuf.st_size, Stat.st_size);
  172.       return -2;
  173.       }
  174.    else
  175.       return result;
  176. }
  177.  
  178. long
  179. filesize(void)
  180. {
  181.    return FileName == NULL ? -1L : Stat.st_size;
  182. }
  183.  
  184. char *
  185. getstring(char **start, char **end, char *s, int max)
  186. {
  187.    char *p = *start, *e = *end;
  188.  
  189.    if (Finished && (p == e) )
  190.       return NULL;
  191.  
  192.    do {
  193.       while ( p < e ) {
  194. #ifdef MSDOS
  195.          if ( (*s = *p++) == '\r')      /* dispose of extra msdos line marker */
  196.             continue;
  197. #endif
  198.          if (*s == '\n') {
  199.             *s = '\0';
  200.             break;
  201.             }
  202.          max--;   
  203.          if (max == 0) {
  204.             *(s+1) = '\0';
  205.             break;
  206.             }
  207.          s++;
  208.          }
  209.       }
  210.    while ( (p == e) && (refill(&p, &e) == 0) );
  211.  
  212.    *start = p;
  213.    *end = e;
  214.  
  215.    return s;
  216. }
  217.  
  218. /*
  219.  * General purpose buffer processing. Designed to replace the existing
  220.  * misc. versions all over the place.
  221.  *
  222.  * Can be called in three different ways:
  223.  *  1. wantall = 1: call 'fn' for every msg (note that fn can return
  224.  *     immediately and let walk process the rest of a msg)
  225.  *  2. wantall = 0, argv = NULL: 'fn' will only be called when the
  226.  *     message number in argc is met.
  227.  *  3. wantall = 0, argv != NULL, argc = # of pointers in argv. 'fn'
  228.  *     will be called each time the 'wanted' function is true for a msg.
  229.  */
  230. /* was a const int, but tcc objects */
  231. #define WalkStrLength 256
  232.  
  233. int
  234. walk(char *p, char *end, int wantall, MsgFn fn, int argc, char *argv[])
  235. {
  236.    int num = 0;
  237.  
  238.    while (1) {
  239.       while ( *p != 'F' )
  240.          p++;
  241.       if ( (p==end) && (refill(&p, &end) != 0) )
  242.          break;
  243.       if (*(p-1) != '\n')
  244.          p++;
  245.       else {
  246.          char s[WalkStrLength];
  247.  
  248.          getstring(&p, &end, s, sizeof(s));
  249.          while (strncmp(s, "From ", 5) == 0) {
  250.             num++;
  251.             if ( wantall ||
  252.                  ( (argv == NULL) && (argc == num) ) ||
  253.                  ( (argv != NULL) && wanted(num, argc, argv, 0) )
  254.                )
  255.                fn(num, &p, &end, s); /* correct calling syntax? */
  256.             else
  257.                break;
  258.             }
  259.          }
  260.       }
  261.    return num;
  262. }
  263.  
  264. /* -------------------------------------------------------------------- */
  265.  
  266. static int sm_wantheader;
  267. static FILE *sm_fp;
  268.  
  269. static int
  270. savemsg(int num, char **start, char **end, char *line)
  271. {
  272.    if (!sm_wantheader) {
  273.       char *argv[MAXHDR];
  274.  
  275.       if ( parseheader(start, end, argv) == -1) {
  276.          fprintf(stderr, "savemsg: bad header on message %d\n", num);
  277.          freeheader(argv);
  278.          return -1;
  279.          }
  280.       freeheader(argv);
  281.       }
  282.  
  283.    while (getstring(start, end, line, WalkStrLength) != NULL)
  284.       if (strncmp(line, "From ", 5) == 0)
  285.          break;                             /* have hit next message */
  286.       else {
  287.          if (line[0] != '\0')  /* fputs returns EOF on being asked to */
  288.                                /* write an empty string... */
  289.             if ( fputs(line, sm_fp) == EOF ) {
  290.                fprintf(stderr, "savemsg: error writing message # %d\n", num);
  291.                return -1;
  292.                }
  293.          if ( fputc('\n', sm_fp) == EOF) {
  294.             fprintf(stderr, "savemsg: error writing message # %d\n", num);
  295.             return -1;
  296.             }
  297.          }
  298.  
  299.    return 0;
  300. }
  301.  
  302. int
  303. msg2file(char *p, char *end, FILE *fp, int msg, int wantheader)
  304. {
  305.    sm_fp = fp;
  306.    sm_wantheader = wantheader;
  307.  
  308.    return walk(p, end, 0, savemsg, msg, NULL);
  309. }
  310.  
  311. int
  312. savemsgs(int argc, char *argv[], char *filename, int wantheaders)
  313. {
  314.    char *s, *p, *end;
  315.    int msg;
  316.  
  317.    if (setupbm()==-1)
  318.       return -1;
  319.  
  320.    if (getcurrent(argc, argv, &s, &msg) == -1)
  321.       return -1;
  322.    
  323.    if (loadmail("savemsgs", s, &p, &end) == -1)
  324.       return -1;
  325.  
  326.    if ( (sm_fp = fopen(filename, "a")) == NULL) {
  327.       fprintf(stderr, "savemsg: can't open %s\n", filename);
  328.       return -1;
  329.       }
  330.  
  331.    sm_wantheader = wantheaders;
  332.  
  333.    if (argc == 1)
  334.       walk(p, end, 0, savemsg, msg, NULL);
  335.    else 
  336.       walk(p, end, 0, savemsg, argc, argv);
  337.  
  338.    return fclose(sm_fp);
  339. }
  340.  
  341. /* -------------------------------------------------------------------- */
  342.  
  343. #ifdef BUFFER_PROG
  344.  
  345. int
  346. main(int argc, char *argv[])
  347. {
  348.    char *start, *end;
  349.  
  350.    printf("coreleft before creating buffer= %u\n", coreleft() );
  351.    if (loadbuf(argv[1], &start, &end, NULL) == -1) {
  352.       fprintf(stderr, "Problem\n");
  353.       exit(-1);
  354.       }
  355.    printf("coreleft after buffer is allocated= %u\n", coreleft() );
  356.  
  357.    while (start<end)
  358.       putchar(start++);
  359.  
  360.    return 0;
  361. }
  362. #endif
  363.