home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / brik-2.0-src.lha / brik-2.0 / brik.c < prev    next >
C/C++ Source or Header  |  1993-08-30  |  30KB  |  975 lines

  1. /* ::[[ @(#) brik.c 1.55 89/07/12 03:31:06 ]]:: */
  2. #ifndef LINT
  3.  static char sccsid[]="::[[ @(#) brik.c 1.55 89/07/12 03:31:06 ]]::";
  4. #endif
  5.  
  6. #define DATESTAMP "1989/07/11"
  7. #define VERSION   "2.0"
  8.  
  9. /*
  10. (c) Copyright 1989 Rahul Dhesi, All rights reserved.  Permission is
  11. granted to use, copy, and distribute this file under the terms of the
  12. GNU General Public License version 1.0.
  13. */
  14.  
  15. /*
  16. Checksum: 2990338384      (check or update this with "brik")
  17. */
  18.  
  19. static char copyright[] =
  20. "\
  21. Copyright 1989 Rahul Dhesi, All rights reserved.  Use and distribution is\n\
  22. permitted under the terms of the GNU General Public License version 1.0.\n\
  23. ";
  24.  
  25. /*
  26. The following code assumes the ASCII character set and 8-bit bytes.
  27. */
  28.  
  29. #ifndef OK_STDIO
  30. # include <stdio.h>
  31. # define OK_STDIO
  32. #endif
  33.  
  34. #include "brik.h"          /* configuration options */
  35. #include "assert.h"
  36.  
  37. typedef unsigned long tcrc; /* type of crc value -- same as in addbfcrc.c */
  38.  
  39. #ifdef GENTAB
  40. void mkcrctab PARMS ((void));
  41. #endif /* GENTAB */
  42.  
  43. #ifdef STDINCLUDE
  44. # include <stdlib.h>
  45. # include <string.h>
  46. #else
  47.  FILE *fopen PARMS ((char *filename, char *mode));
  48.  char *nextfile PARMS ((int, char *, int));
  49.  char *strcat PARMS ((char *, char *));
  50.  char *strchr PARMS ((char *, char));
  51.  char *strcpy PARMS ((char *, char *));
  52.  char *strncat PARMS ((char *, char *, int));
  53.  int strcmp PARMS ((char *, char *));
  54.  int strlen PARMS ((char *));
  55.  void exit PARMS ((int status));
  56. #endif /* STDINCLUDE */
  57.  
  58. /* twilight zone functions -- may or may not be standard */
  59. int main PARMS ((int, char **));
  60. int getopt PARMS ((int, char **, char *));
  61.  
  62. /* our own functions */
  63. FILE *efopen PARMS ((char *filename, char *mode, int errlevel));
  64. char suffix PARMS ((void));
  65. char *nextfile PARMS ((int, char *, int));
  66. void dofname PARMS ((char *));
  67. void dofptr PARMS ((FILE *, char *));
  68. int lowerit PARMS ((int));
  69. void printhdr PARMS ((void));
  70. void readnames PARMS ((FILE *));
  71. void updatefile PARMS ((FILE *, long, tcrc, char *));
  72. void whole_check PARMS ((FILE *, char *));
  73. tcrc findcrc PARMS ((FILE *, char *, int *));
  74. tcrc xatol PARMS ((char *));
  75. void addbfcrc PARMS ((char *, int));
  76. void brktst PARMS ((void));
  77. void hdrcrc PARMS ((FILE *, char *));
  78. void longhelp PARMS ((void));
  79. void shorthelp PARMS ((void));
  80. void showerr PARMS ((char *, int));
  81.  
  82. /* the following constants can be changed if you know what you are doing */
  83. #define ERRLIMIT  127      /* exit(n) returns n not exceeding this */
  84. #define LINESIZE  8192     /* handle lines of up to this length */
  85. #define ERRBUFSIZ 1024     /* buffer size for perror() message */
  86. #define BACKSIZE  1024     /* how much to seek back looking for header */
  87. #define BINTABSIZ 256      /* size of binary char test table */
  88. #ifdef CTRLZ_CHECK
  89. # define Z_THRESHOLD 10    /* see how CTRLZ_CHECK is used later */
  90. #endif /* CTRLZ_CHECK */
  91.  
  92. /* the following constants should not be changed */
  93. #define MYNL      10       /* newline for CRC calculation */
  94. #define PATTERN   "Checksum:"    /* look for this header */
  95. #define CHARSINCRC 10      /* characters in CRC */
  96. #define CMTCH     '#'      /* begins comment in CRC list */
  97.  
  98. /* error levels */
  99. #define LVL_WARN  0
  100. #define LVL_ERR   1
  101. #define LVL_FATAL 2
  102.  
  103. #ifdef  USEINDEX
  104. # define strchr   index
  105. #endif  /* USEINDEX */
  106.  
  107. #ifdef NOTRAIL_B              /* avoid trailing "b" in mode string */
  108. # define BRIK_RD  "r"
  109. # define BRIK_RW  "r+"
  110. # define BRIK_RDB "r"
  111. #else
  112. # define BRIK_RD  "r"
  113. # define BRIK_RW  "r+"
  114. # define BRIK_RDB "rb"
  115. #endif   /* NOTRAIL_B */
  116.  
  117. #define  whitespace(x)     (strchr(" \t\n",(x)) != NULL)
  118. /* format strings for printing CRCs and filenames etc. */
  119. static char ok[] =      "ok ";
  120. static char bad[] =     "BAD";
  121. static char blank[] =   "   ";
  122. static char fmtstr[] = "%10lu%c %s %s\n";
  123. static char hdrfmt[] = "Checksum: %10lu  %s\n";
  124.  
  125. static char version[] = VERSION;
  126. char bintab[BINTABSIZ];    /* binary char test table */
  127. int patlen;                /* length of PATTERN */
  128. int errcount = 0;          /* count of errors */
  129. int gen1 = 0;              /* generate CRCs for all files */
  130. int gen2 = 0;              /* generate CRCs for files with headers */
  131. int silent = 0;            /* be silent, just set error status */
  132. int quiet = 0;             /* talks less, but not completely silent */
  133. int verbose = 0;           /* be verbose, print message for good files too */
  134. int updfile = 0;           /* update file by inserting CRC */
  135. int check1 = 0;            /* whether to check header crcs */
  136. int check2 = 0;            /* whether to check whole file crcs */
  137. int fromfile = 0;          /* read filenames from a file */
  138. int binary = 0;            /* manipulate binary file */
  139. int trailing = 0;          /* include trailing empty lines */
  140. int prthdr = 0;            /* print Checksum: XXXXXXXXXX header */
  141. int autocheck = 0;         /* brik must decide if text or binary */
  142. int is_stdin = 0;          /* current file is stdin */
  143. int doubtful = 0;          /* text but doubtful */
  144.  
  145. #ifdef DEBUG
  146. int debugging = 0;
  147. #endif
  148.  
  149. /* opens file, prints error message if can't open */
  150. FILE *efopen (fname, mode, level)
  151. char *fname;               /* filename to open */
  152. char *mode;                /* mode, e.g. "r" or "r+" */
  153. int level;                 /* error level */
  154. {
  155.    FILE *fptr;
  156.    fptr = fopen (fname, mode);
  157.    if (fptr == NULL)
  158.       showerr (fname, level);
  159.    return (fptr);
  160. }
  161.  
  162. /* LOWERIT is a function or macro that returns lowercase of a character */
  163. #ifndef LOWERIT
  164. # ifdef AVOID_MACROS
  165. #  define LOWERIT    lowerit
  166. # else
  167. #  define LOWERIT(c)        ((c)>='A' && (c)<='Z' ? ('a'-'A')+(c) : (c))
  168. # endif
  169. #endif
  170.  
  171. /* Function needed by SEEKFIX code even if a macro is available */
  172. int lowerit (c) int c;  /* returns lowercase of an ASCII character */
  173. {
  174.   if (c >= 'A' && c <= 'Z') return (('a'-'A') + c);
  175.   else return (c);
  176. }
  177.  
  178. /* STRNICMP is a case-insensitive strncmp */
  179. #ifndef STRNICMP
  180. int STRNICMP (s1, s2, n)
  181. register char *s1, *s2;
  182. int n;
  183. {
  184.    assert (n >= 0);
  185.    assert (LOWERIT('X') == 'x');
  186.    assert (LOWERIT('*') == '*');
  187.  
  188.    for ( ; LOWERIT(*s1) == LOWERIT(*s2);  s1++, s2++) {
  189.       if (--n == 0 || *s1 == '\0')
  190.          return(0);
  191.    }
  192.    return(LOWERIT(*s1) - LOWERIT(*s2));
  193. }
  194. #endif /* STRNICMP */
  195.  
  196. #ifdef AVOID_MACROS
  197. # define BRINCMP     STRNICMP
  198. #else
  199. # define BRINCMP(s1,s2,n) (LOWERIT(*(s1))!=LOWERIT(*(s2))||STRNICMP(s1,s2,n))
  200. #endif
  201.  
  202.  
  203. #define xdigit(x)    ((x) >= '0' && (x) <= '9')
  204.  
  205. /*
  206. xatol is given a string that (supposedly) begins with a string
  207. of digits.  It returns a corresponding positive numeric value.
  208. */
  209. tcrc xatol (str)
  210. char *str;
  211. {
  212.    tcrc retval;
  213.    retval = 0L;
  214.    while (xdigit(*str)) {
  215.       retval = retval * 10L + (*str-'0');
  216.       str++;
  217.    }
  218.    return (retval);
  219. }
  220.  
  221. main (argc, argv)
  222. int argc;
  223. char **argv;
  224. {
  225.    int i;
  226.    int c;                        /* next option letter */
  227.    int count = 0;                /* count of required options seen */
  228.    char *infname;                /* name of file to read filenames from */
  229.    FILE *infptr;                 /* open file ptr for infname */
  230.  
  231.    extern int optind;            /* from getopt: next arg to process */
  232.    extern int opterr;            /* used by getopt */
  233.  
  234.    opterr = 1;                   /* so getopt will print err msg */
  235.    argv[0] = "brik";             /* for getopt to use */
  236.  
  237.    patlen = strlen (PATTERN);
  238.  
  239. #ifdef DEBUG
  240.    while ((c = getopt (argc, argv, "cCgGasqvWHfbThd")) != EOF)
  241. #else
  242.    while ((c = getopt (argc, argv, "cCgGasqvWHfbTh")) != EOF)
  243. #endif
  244.    {
  245.       switch (c) {
  246.          case 'a':   autocheck++; binary = 0; trailing = 0; break;
  247.          case 'c':   check1++; count++; break;
  248.          case 'C':   check2++; count++; break;
  249.          case 'g':   gen1++; count++; break;
  250.          case 'G':   gen2++; count++; break;
  251.          case 's':   silent++; verbose = 0; break;
  252.          case 'q':   quiet++; verbose = 0; break;
  253.          case 'v':   verbose++; silent = 0; break;
  254.          case 'W':   updfile++; break;
  255.          case 'f':   fromfile++; break;
  256.          case 'b':   binary++; autocheck = 0; trailing = 0; break;
  257.          case 'T':   trailing++; binary = 0; autocheck = 0; break;
  258.          case 'H':   prthdr++; break;
  259. #ifdef DEBUG
  260.          case 'd':   debugging++; break;
  261. #endif
  262.          case 'h':   longhelp();
  263.          case '?':