ibmbin-request@crdgw1.crd.ge.com (09/06/90)
Checksum: 430137442 (Verify with "brik -cv") Posting-number: Volume 07, Issue inf03 Originally-from: dhesi@bsu-cs.bsu.edu Archive-name: admin/briksrc1 RKIV #!/bin/sh # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 4104 -rw-r--r-- Install # 3563 -rw-r--r-- Usenet # 6391 -rw-r--r-- addbfcrc.c # 754 -rw-r--r-- assert.h # 26440 -rw-r--r-- brik.c # 18671 -rw-r--r-- brik.doc # 7035 -rw-r--r-- brik.h # 66 -rw-r--r-- brik.prj # 675 -rw-r--r-- descrip.mms # 2808 -rw-r--r-- getopt.c # 403 -rw-r--r-- makebrik.com # 829 -rw-r--r-- makefile # 86 -rw-r--r-- mkbsd # 137 -rw-r--r-- mksysv # 127 -rw-r--r-- mkuport # 28 -rw-r--r-- options.opt # 8118 -rw-r--r-- turboc.c # 2419 -rw-r--r-- vms.c # # ============= Install ============== echo "x - extracting Install (Text)" sed 's/^X//' << 'SHAR_EOF' > Install && X X INSTALLING BRIK 1.0 X XThe following files should be in this package. The files brik.exe and Xtcconfig.tc are binary files. All other files are text files with Xlines terminated by linefeeds. X X bytes name description X ----- ---- ----------- X 4104 Install installation instructions X 6391 addbfcrc.c source X 754 assert.h source X 26440 brik.c source X 18671 brik.doc documentation X 16710 brik.exe executable for MS-DOS X 7035 brik.h source X 66 brik.prj project file for MS-DOS Turbo C 1.0 X 675 descrip.mms makefile for VAX/VMS 4.7 X 2808 getopt.c source for Turbo C 1.0 and VAX/VMS 4.7 X 403 makebrik.com makefile for VAX/VMS 4.7 X 829 makefile makefile for **IX X 86 mkbsd make script for 4.xBSD X 137 mksysv make script for System V X 127 mkuport make script for Microport System V/AT 2.2 X 28 options.opt linker options for VAX/VMS 4.7 X 1380 tcconfig.tc configuration file for MS-DOS Turbo C 1.0 X 8118 turboc.c source for MS-DOS Turbo C 1.0 X 2419 vms.c source file for VAX/VMS 4.7 X XBrik is believed to compile and execute in the following environments: X X1. MS-DOS 3.x, Turbo C 1.0 X2. VAX/VMS 4.7 with VAX/VMS C 2.4 X3. 4.3BSD from Berkeley on a VAX-11/785 X4. Microport System V/AT version 2.2 X XMake sure all the needed files are in the current directory. Then follow Xinstructions below for your specific type of system. If doing so doesn't Xgive you a running copy of brik, read brik.h and experiment with the various Xcompilation options. X X1. MS-DOS, Turbo C 1.0 X XUse the supplied tcconfig.tc configuration file. Load the interactive Xtc.exe compiler, revise those options that are different for your Xsystem, and compile. I don't know if this will work with Turbo C 2.0. X X2. VAX/VMS X X2.1. If you have DEC's make utility called "mms", proceed as follows: X X a. Delete "makefile" so mms won't get confused X b. Type "mms" at the VMS prompt X c. If all goes well, mms will compile and link the necessary files, X ending by creating "brik.exe" in the current directory. X d. Move "brik.exe" wherever you want it and define a symbol with X a command line of the following type: X X $ brik :== $my$disk:[bindir]brik.exe X X where my$disk is the name of your device and bindir is the name X of the directory in which "brik.exe" is kept. X X2.2. If you don't have "mms", use the command file supplied. Invoke it as: X X $ @makebrik X XWhen it exits, brik.exe should have been created in your current Xdirectory, and the symbol "brik" should also have been defined for Xyou. If you move brik.exe to another directory be sure to redefine the Xsymbol "brik" correctly as described above in part I. X XBe sure to read the section in the manul on VAX/VMS bugs. X X3. 4.xBSD X XInvoke the script "mkbsd" with the command "sh mkbsd". Finally move Xthe program "brik" into an appropriate directory and make sure that Xthat directory is in your execution search path. X X4. System V X XInvoke the script "mksysv" (for generic System V) or "mkuport" (for XMicroport System V/AT) with the command "sh mksysv" or "sh mkuport". XThe "mkuport" script will try to move the compiled "brik" into X/usr/local/bin/brik so revise it if you don't want this done. The X"mksysv" script will create "brik" in the current directory ready to be Xmoved to an appropriate directory in your search path. X XThe "mkuport" script compiles brik using the large memory model, Xbecause an unexpected bug in Microport System V/AT made all my small- Xmodel libraries vanish and I haven't had a chance to restore them from Xbackups. I suspect compiling in the small memory model will work. X X -- Rahul Dhesi X 1989/03/13 SHAR_EOF # ============= Usenet ============== echo "x - extracting Usenet (Text)" sed 's/^X//' << 'SHAR_EOF' > Usenet && XFrom ibmbin Sun Mar 19 19:58:56 EST 1989 XArticle 1793 of comp.binaries.ibm.pc: XPath: bsu-cs!ibmbin X>From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi) XNewsgroups: comp.binaries.ibm.pc XSubject: v01i217: brik, a general-purpose CRC-32 program v1.0 (part 01/02) XSummary: brik.arc, a general-purpose CRC-32 program v1.0 XMessage-ID: <6105@bsu-cs.UUCP> XDate: 14 Mar 89 09:01:09 GMT XSender: news@bsu-cs.UUCP XFollowup-To: comp.binaries.ibm.pc.d XLines: 694 XApproved: dhesi@bsu-cs.bsu.edu XX-Submissions-to: ibmpc-binaries@bsu-cs.bsu.edu XX-Questions-to: ibmpc-binaries-request@bsu-cs.bsu.edu X XChecksum: 2208628413 (verify or update with "brik") XPosting-number: Volume 01, Issue 217 XOriginally-from: Rahul Dhesi <dhesi@bsu-cs.bsu.edu> XSubmitted-by: Rahul Dhesi <dhesi@bsu-cs.bsu.edu> XArchive-name: brik10/part01 X XI intend this program to be the standard comp.binaries.ibm.pc mechanism Xfor automatic verification of incoming articles. Once it is working, Xyou will be able to tell tell at a glance whether an incoming posting Xin comp.binaries.ibm.pc was received in corrupted form. X XThe executable for MS-DOS, and C source suitable for System V, 4.3BSD, XVAX/VMS, and MS-DOS/Turbo C, are all in the archive. However, the Xfollowing description is not inside the archive. Save it separately if Xyou want to keep it. X XThis is brik version 1.0, a general-purpose program to generate and Xverify 32-bit CRCs in both text and binary files. The Checksum: Xheaders in recent comp.binaries.ibm.pc postings contain CRCs that can Xbe verified or updated with this program. X XAdvantages of brik over "sum" and most CRC programs I have seen are: X X(a) It is freely redistributable and its algorithm is not proprietary X or licensed by *T&T or anybody else. X X(b) It treats text files in a special way. If you use brik to find X the CRCs of text files on an MS-DOS system, transfer the files to X a **IX system with Kermit and use brik on the **IX system, the X CRC calculated there will match the CRC calculated on the MS-DOS X system. However, you can override this feature if you wish, X and simply get a binary CRC for every byte in a file. X X(c) Brik will also look for a Checksum: header in any text file (or X C source file) and verify it based on the contents of the file X that occur *after* the header. This allows Usenet software to X change the initial header portion of an article without affecting X your ability to check the integrity of all lines that occur X after the Checksum: header. Brik itself also updates the Checksum: X header if needed. X X(d) Brik can create either text-mode or binary-mode CRCs for a bunch X of files that can be later checked by brik on the same or a X different system in one batch. Although brik isn't designed for this X purpose, it can be used to keep track of files that change X unexpectedly (e.g. corrupted filesystems, viruses). Since brik X will happily accept filenames on the command line, or from standard X input, or from a list inside one or more files, it is flexible and X will work well with other programs such as "find" (**IX) and X "stuff" (MS-DOS). X XTo verify the CRC of any comp.binaries.ibm.pc posting from the "rn" Xnewsreader, type the command: X X | brik -c X XThis will feed the current article to "brik -c" as standard input. XBrik will search for the Checksum: header, compare the CRC in that Xheader with the calculated CRC of the rest of the file, and report any Xmismatch. X XRahul Dhesi UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi X ARPA: dhesi@bsu-cs.bsu.edu SHAR_EOF # ============= addbfcrc.c ============== echo "x - extracting addbfcrc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > addbfcrc.c && X/* @(#) addbfcrc.c 1.5 89/03/08 14:58:35 */ X/* Most of following CRC-32 stuff is from zmodem source code */ X X#ifndef LINT Xstatic char sccsid[]="::[[ @(#) addbfcrc.c 1.6 89/03/10 19:08:47 ]]::"; X#endif X X/* I claim no copyright over the contents of this file. -- Rahul Dhesi */ X X/* XChecksum: 951252172 (check or update this with "brik") X*/ X X Xlong crccode; X X/* X * Copyright (C) 1986 Gary S. Brown. You may use this program, or X * code or tables extracted from it, as desired without restriction. X */ X X/* First, the polynomial itself and its table of feedback terms. The */ X/* polynomial is */ X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ X/* Note that we take it "backwards" and put the highest-order term in */ X/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ X/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ X/* the MSB being 1. */ X X/* Note that the usual hardware shift register implementation, which */ X/* is what we're using (we're merely optimizing it by doing eight-bit */ X/* chunks at a time) shifts bits into the lowest-order term. In our */ X/* implementation, that means shifting towards the right. Why do we */ X/* do it this way? Because the calculated CRC must be transmitted in */ X/* order from highest-order term to lowest-order term. UARTs transmit */ X/* characters in order from LSB to MSB. By storing the CRC this way, */ X/* we hand it to the UART in the order low-byte to high-byte; the UART */ X/* sends each low-bit to hight-bit; and the result is transmission bit */ X/* by bit from highest- to lowest-order term without requiring any bit */ X/* shuffling on our part. Reception works similarly. */ X X/* The feedback terms table consists of 256, 32-bit entries. Notes: */ X/* */ X/* The table can be generated at runtime if desired; code to do so */ X/* is shown later. It might not be obvious, but the feedback */ X/* terms simply represent the results of eight shift/xor opera- */ X/* tions for all combinations of data and CRC register values. */ X/* */ X/* The values must be right-shifted by eight bits by the "updcrc" */ X/* logic; the shift must be unsigned (bring in zeroes). On some */ X/* hardware you could probably optimize the shift in assembler by */ X/* using byte-swap instructions. */ X Xlong crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ X 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, X 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, X 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, X 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, X 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, X 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, X 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, X 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, X 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, X 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, X 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, X 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, X 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, X 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, X 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, X 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, X 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, X 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, X 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, X 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, X 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, X 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, X 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, X 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, X 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, X 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, X 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, X 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, X 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, X 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, X 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, X 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, X 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, X 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, X 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, X 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, X 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, X 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, X 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, X 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, X 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, X 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, X 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, X 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, X 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, X 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, X 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, X 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, X 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, X 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, X 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, X 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, X 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, X 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, X 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, X 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, X 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, X 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, X 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, X 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, X 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, X 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, X 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, X 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d X}; X Xaddbfcrc (buf, size) Xregister char *buf; Xregister int size; X{ X int i; X for (i = 0; i < size; i ++) { X crccode = crc_32_tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^ X (((crccode) >> 8) & 0x00FFFFFFL); X } X} SHAR_EOF # ============= assert.h ============== echo "x - extracting assert.h (Text)" sed 's/^X//' << 'SHAR_EOF' > assert.h && X/* @(#) assert.h 1.5 89/03/08 14:59:02 */ X X/* I claim no copyright over the contents of this file. -- Rahul Dhesi */ X X/* XChecksum: 3376323427 (check or update this with "brik") X*/ X X/* X** Assertions are enabled only if NDEBUG is not defined. X** Not all compilers define __FILE__ and __LINE__. If yours X** doesn't, you can just let NDEBUG remain #defined in brik.h and no X** assertions will be compiled in. Or, if you want to enable X** assertions, redefine the assert() macro so it works with your X** compiler. X*/ X X#ifndef OK_STDIO X# include <stdio.h> X# define OK_STDIO X#endif X X#ifndef NDEBUG X#define assert(E) \ X{if(!(E))fprintf(stderr,"Assertion error in %s line %d\n",__FILE__,__LINE__);} X#else X#define assert(E) X#endif /* NDEBUG */ SHAR_EOF # ============= brik.c ============== echo "x - extracting brik.c (Text)" sed 's/^X//' << 'SHAR_EOF' > brik.c && X/* ::[[ @(#) brik.c 1.44 89/03/12 14:34:35 ]]:: */ X#ifndef LINT X static char sccsid[]="::[[ @(#) brik.c 1.44 89/03/12 14:34:35 ]]::"; X#endif X X#define DATESTAMP "1989/03/12 14:34:35" X X/* X(c) Copyright 1989 Rahul Dhesi, All rights reserved. Permission is Xgranted to copy and distribute this file in modified or unmodified Xform, for any purpose whether commercial or noncommercial, provided Xthat (a) this paragraph, and the author identification printed by Xthe program, are preserved unchanged, and (b) no attempt is made to Xrestrict redistribution of this file. Inclusion of this file in a Xcollection whose distribution is restricted by a compilation copyright Xshall be considered an attempt to restrict redistribution of this file. XNotwithstanding the above, there are no restrictions on the copying or Xdistribution of not-human-readable executable machine code created by Xprocessing this file with a language translator. X*/ X X/* XChecksum: 1280097858 (check or update this with "brik") X*/ X X/* XThe following code assumes the ASCII character set and 8-bit bytes. X*/ X X#ifndef OK_STDIO X# include <stdio.h> X# define OK_STDIO X#endif X X#include "brik.h" /* configuration options */ X#include "assert.h" X XFILE *fopen(); XFILE *efopen(); Xchar *fgets(); Xint fclose(); Xchar *strchr(); Xint strlen(); Xint strcmp(); Xchar *strcat(); Xint fseek(); Xlong ftell(); Xint fwrite(); Xvoid hdrcrc(); Xvoid showerr(); Xvoid longhelp(); Xvoid shorthelp(); Xlong findcrc(); X X#ifdef ANSIPROTO Xvoid addbfcrc (char *, int); Xint printhdr (void); XFILE *efopen (char *, char *, int); Xlong xatol (char *); Xint main (int, char **); Xint dofname (char *); Xint dofptr (FILE *, char *); Xint whole_check (FILE *, char *); Xvoid hdrcrc (FILE *, char *); Xlong findcrc (FILE *, char *); Xint updatefile (FILE *, long, long, char *); Xvoid longhelp(void); Xvoid shorthelp(void); Xvoid showerr (char *, int); Xchar suffix(void); Xint lowerit (int); X Xint strlen (char *); Xchar *strchr (char *, char); Xchar *strcpy (char *, char *); Xchar *strcat (char *, char *); Xchar *strncat (char *, char *, int); Xint getopt (int, char **, char *); Xvoid exit (int); Xint strcmp (char *, char *); Xint readnames (FILE *); Xchar *nextfile (int, char *, int); Xvoid brktst(void); X#endif X X#define MYNL 10 /* newline for CRC calculation */ X#define ERRLIMIT 127 /* exit(n) returns n not exceeding this */ X#define LINESIZE 8192 /* handle lines of up to this length */ X#define ERRBUFSIZ 1024 /* buffer size for perror() message */ X#define PATTERN "Checksum:" /* look for this header */ X#define CHARSINCRC 10 /* characters in CRC */ X#define BACKSIZE 1024 /* how much to seek back looking for header */ X#define CMTCH '#' /* begins comment in CRC list */ X X/* define macro for testing if chars within range */ X#ifndef BINCHAR X# define LOW_PRINT '\007' /* smallest printable char */ X# define HIGH_PRINT '\176' /* biggest printable char */ X# define BINCHAR(c) ((c) < LOW_PRINT || (c) > HIGH_PRINT) X#endif /* BINCHAR */ X X/* error levels */ X#define LVL_WARN 0 X#define LVL_ERR 1 X#define LVL_FATAL 2 X X#ifdef USEINDEX X# define strchr index X#endif /* USEINDEX */ X X#ifdef TRAIL_T /* need trailing "t" in fopen string */ X# define BRIK_RD "rt" X# define BRIK_RW "r+t" X# define BRIK_RDB "rb" X#else X# define BRIK_RD "r" X# define BRIK_RW "r+" X# define BRIK_RDB "r" X#endif /* TRAIL_T */ X X#define whitespace(x) (strchr(" \t\n",(x)) != NULL) X/* format strings for printing CRCs and filenames etc. */ Xstatic char ok[] = "ok "; Xstatic char bad[] = "BAD"; Xstatic char blank[] = " "; Xstatic char fmtstr[] = "%10lu%c %s %s\n"; X X Xint patlen; /* length of PATTERN */ Xint errcount = 0; /* count of errors */ Xint gen1 = 0; /* generate CRCs for all files */ Xint gen2 = 0; /* generate CRCs for files with headers */ Xint silent = 0; /* be quiet, just set error status */ Xint verbose = 0; /* be verbose, print message for good files too */ Xint updfile = 0; /* update file by inserting CRC */ Xint check1 = 0; /* whether to check header crcs */ Xint check2 = 0; /* whether to check whole file crcs */ Xint fromfile = 0; /* read filenames from a file */ Xint binary = 0; /* manipulate binary file */ Xint trailing = 0; /* include trailing empty lines */ X X#ifdef DEBUG Xint debugging = 0; X#endif X X/* opens file, prints error message if can't open */ XFILE *efopen (fname, mode, level) Xchar *fname; /* filename to open */ Xchar *mode; /* mode, e.g. "r" or "r+" */ Xint level; /* error level */ X{ X FILE *fptr; X fptr = fopen (fname, mode); X if (fptr == NULL) X showerr (fname, level); X return (fptr); X} X X/* LOWERIT is a function or macro that returns lowercase of a character */ X#ifndef LOWERIT X# ifdef AVOID_MACROS X# define LOWERIT lowerit X# else X# define LOWERIT(c) ((c)>='A' && (c)<='Z' ? ('a'-'A')+(c) : (c)) X# endif X#endif X X/* Function needed by SEEKFIX code even if a macro is available */ Xint lowerit (c) int c; /* returns lowercase of an ASCII character */ X{ X if (c >= 'A' && c <= 'Z') return (('a'-'A') + c); X else return (c); X} X X/* STRNICMP is a case-insensitive strncmp */ X#ifndef STRNICMP Xint STRNICMP (s1, s2, n) Xregister char *s1, *s2; Xint n; X{ X assert (n >= 0); X assert (LOWERIT('X') == 'x'); X assert (LOWERIT('*') == '*'); X X for ( ; LOWERIT(*s1) == LOWERIT(*s2); s1++, s2++) { X if (--n == 0 || *s1 == '\0') X return(0); X } X return(LOWERIT(*s1) - LOWERIT(*s2)); X} X#endif /* STRNICMP */ X X#ifdef AVOID_MACROS X# define BRINCMP STRNICMP X#else X# define BRINCMP(s1,s2,n) (LOWERIT(*(s1))!=LOWERIT(*(s2))||STRNICMP(s1,s2,n)) X#endif X X X#define xdigit(x) ((x) >= '0' && (x) <= '9') X X/* Xxatol is given a string that (supposedly) begins with a string Xof digits. It returns a corresponding positive numeric value. X*/ Xlong xatol (str) Xchar *str; X{ X long retval; X retval = 0L; X while (xdigit(*str)) { X retval = retval * 10L + (*str-'0'); X str++; X } X return (retval); X} X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X int i; X int c; /* next option letter */ X int count = 0; /* count of required options seen */ X char *infname; /* name of file to read filenames from */ X FILE *infptr; /* open file ptr for infname */ X X extern int optind; /* from getopt: next arg to process */ X extern int opterr; /* used by getopt */ X X opterr = 0; /* so getopt won't print err msg */ X X patlen = strlen (PATTERN); X X#ifdef DEBUG X while ((c = getopt (argc, argv, "cCgGsvWfbThd")) != EOF) X#else X while ((c = getopt (argc, argv, "cCgGsvWfbTh")) != EOF) X#endif X { X switch (c) { X case 'c': check1++; count++; break; X case 'C': check2++; count++; break; X case 'g': gen1++; count++; break; X case 'G': gen2++; count++; break; X case 's': silent++; verbose = 0; break; X case 'v': verbose++; silent = 0; break; X case 'W': updfile++; break; X case 'f': fromfile++; break; X case 'b': binary++; trailing = 0; break; X case 'T': trailing++; binary = 0; break; X#ifdef DEBUG X case 'd': debugging++; break; X#endif X case 'h': longhelp(); X case '?': shorthelp(); X } X } X X if (count != 1) X shorthelp(); X X if (binary && (check1 || gen1)) { X fprintf (stderr, "brik: fatal: Can't read or update CRC header in binary mode\n"); X exit (1); X } X X if (updfile && !gen1) { X fprintf (stderr, "brik: fatal: Use of -W requires -g\n"); X exit (1); X } X X if ((gen1 || gen2) && !updfile) X silent = 0; X X i = optind; X X if (fromfile) { /* read filenames from file */ X if (i >= argc) { /* need filenames after -f */ X fprintf (stderr, "brik: fatal: Filename(s) needed after -f\n"); X exit (1); X } X for (; i < argc; i++) { X infname = argv[i]; X if (strcmp(infname, "-") == 0) { /* "-" means stdin */ X readnames (stdin); X } else { X#ifdef WILDCARD X extern char *nextfile(); X nextfile (0, infname, 0); /* initialize fileset 0 */ X while ((infname = nextfile(1, (char *) NULL, 0)) != NULL) { X infptr = efopen (infname, BRIK_RD, LVL_ERR); X readnames (infptr); X fclose (infptr); X } X#else X infptr = efopen (infname, BRIK_RD, LVL_ERR); X readnames (infptr); X fclose (infptr); X#endif /* WILDCARD */ X } X } X } else { /* read filenames from command line */ X if (i >= argc) { X#ifdef TRAIL_T X if (binary) { X fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n"); X exit (1); X } X#endif X dofptr (stdin, "stdin"); /* if no files, read stdin */ X } else { X for (; i < argc; i ++) { X#ifdef WILDCARD X extern char *nextfile(); X char *one_name; /* a matching filename */ X nextfile (0, argv[i], 0); /* initialize fileset 0 */ X while ((one_name = nextfile(1, (char *) NULL, 0)) != NULL) X dofname (one_name); X#else X dofname (argv[i]); X#endif /* WILDCARD */ X } X } X } Xerrexit: X if (errcount > ERRLIMIT) X errcount = ERRLIMIT; /* don't overflow status code */ X exit (errcount); X /*NOTREACHED*/ X} X X/* X** Reads names from supplied file pointer and handles them. Just X** returns if supplied NULL file pointer. Will also expand wildcards X** in names read from this file. X*/ Xreadnames (infptr) XFILE *infptr; X{ X char buf[LINESIZE]; X if (infptr == NULL) X return; X while (fgets (buf, LINESIZE, infptr) != NULL) { X#ifdef WILDCARD X char *fname; /* matching filename */ X extern char *nextfile(); X#endif /* WILDCARD */ X buf[strlen(buf)-1] = '\0'; /* zap trailing newline */ X#ifdef WILDCARD X nextfile (0, buf, 1); /* initialize fileset 1 */ X while ((fname = nextfile(1, (char *) NULL, 1)) != NULL) { X dofname (fname); X } X#else X dofname (buf); X#endif /* WILDCARD */ X } X} X X/* do one filename */ Xdofname (this_arg) Xchar *this_arg; X{ X FILE *this_file; X char *mode; /* "r", "rb", "rw", etc. for fopen */ X#ifdef BRKTST X extern void brktst(); X brktst(); X#endif X X if (strcmp(this_arg,"-") == 0) { X#ifdef TRAIL_T X if (binary) { X fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n"); X exit (1); X } X#endif X this_file = stdin; X this_arg = "stdin"; X } else { X if (updfile) { X assert (!binary); X this_file = efopen (this_arg, BRIK_RW, LVL_ERR); X } else { X if (binary && !check2) /* check2 reads filenames, not data */ X mode = BRIK_RDB; X else X mode = BRIK_RD; X this_file = efopen (this_arg, mode, LVL_ERR); X } X } X if (this_file == NULL) X errcount++; X else { X#ifdef NOCASE X char *p; X for (p = this_arg; *p != '\0'; p++) X *p = LOWERIT(*p); X#endif X dofptr (this_file, this_arg); X fclose (this_file); X } X} X Xchar suffix() X{ X return (binary ? 'b' : (trailing ? 'T' : ' ')); X} X X X/* X** Do one file pointer. Decides if CRC header will be read or written, X** or whether just the whole file will be read. X*/ Xdofptr (fptr, fname) XFILE *fptr; Xchar *fname; X{ X if (check2) X whole_check (fptr, fname); /* do whole file check from list */ X else if (gen1 || check1) /* header-based CRC check or update */ X hdrcrc (fptr, fname); X else { /* whole-file CRC calculation */ X extern long crccode; X assert (gen2); X printhdr(); X findcrc (fptr, fname); X printf (fmtstr, crccode, suffix(), blank, fname); X } X} X X X/* Does whole file check from a list of files and CRCs */ Xwhole_check (fptr, listname) XFILE *fptr; /* open file ptr of CRC list file */ Xchar *listname; /* name of CRC list file */ X{ X long fcrc; /* recorded crc */ X char *fname; /* name of file whose CRC being checked */ X char buf [LINESIZE]; /* line buffer */ X char *p; /* temp ptr */ X FILE *orgfile; /* file pointer for original file to check */ X int lino = 0; /* line no. in list file for error msg */ X char *mode; /* mode string for fopen */ X X while (fgets (buf, LINESIZE, fptr) != NULL) { X lino++; X p = buf; X if (*p == CMTCH) /* skip comment lines */ X continue; X while (*p != '\0' && whitespace(*p)) /* skip whitespace */ X p++; X if (*p == '\0') X continue; /* skip empty lines */ X if (!xdigit(*p)) X goto badline; X fcrc = xatol (p); /* recorded CRC */ X X while (xdigit(*p)) X p++; /* skip past numeric chars */ X X binary = trailing = 0; X if (*p == 'b') /* 'b' means binary */ X binary = 1; X X if (*p == 'T') /* 'T' means trailing mode */ X trailing = 1; X X while (*p != '\0' && !whitespace(*p)) /* to whitespace */ X p++; X while (whitespace(*p)) /* skip whitespace */ X p++; X X if (*p == '\n' || *p == '\0') { /* if at end of line */ X goto badline; X } X fname = p; X while (*p != '\0' && !whitespace(*p)) /* skip to whitespace */ X p++; X *p = '\0'; /* null-terminate filename */ X X if (binary) X mode = BRIK_RDB; X else X mode = BRIK_RD; X X orgfile = efopen (fname, mode, LVL_ERR); X if (orgfile == NULL) { X errcount++; X } else { X long foundcrc; X assert (!(binary && trailing)); X foundcrc = findcrc (orgfile, fname); X if (foundcrc == fcrc) { X if (verbose) X printf (fmtstr, foundcrc, suffix(), ok, fname); X } else { X if (!silent) X printf (fmtstr, foundcrc, suffix(), bad, fname); X errcount ++; X } X fclose (orgfile); X } X } X return; Xbadline: X fprintf (stderr, X "brik: error: Abandoning %s due to badly formatted line %d\n", X listname, lino); X return; X} X X X/* XInitializing the CRC to all one bits avoids failure of detection Xshould entire data stream get cyclically bit-shifted by one position. XThe calculation of the probability of this happening is left as Xan exercise for the reader. X*/ X#define INITCRC 0xFFFFFFFFL; X X/* X** hdrcrc processes one file given an open file pointer X** and the filename. The filename is used for messages etc. X** It does all manipulation of header-related CRCs, i.e., X** checking generating header CRC. It deals only with text files. X*/ Xvoid hdrcrc (fptr, fname) XFILE *fptr; Xchar *fname; X{ X char buf[LINESIZE]; X int lino = 0; X char *ptr; X long fcrc; /* crc recorded in file */ X extern long crccode; X long hdrpos; /* where we found crc header in file */ X X crccode = INITCRC; X X assert (!binary); X X#ifndef NIXSEEK X hdrpos = ftell (fptr); X#endif X while (fgets (buf, LINESIZE, fptr) != NULL) { X#ifdef BRKTST X extern void brktst(); X brktst(); X#endif X lino++; X if (BRINCMP (buf, PATTERN, patlen) == 0) { /* found header */ X#ifdef NIXSEEK X hdrpos = ftell (fptr); /* seek posn of line with header */ X#endif X ptr = buf + patlen; /* point to beyond header */ X while (*ptr != '\0' && whitespace(*ptr)) X ptr++; /* skip white space */ X fcrc = xatol (ptr); /* get stored crc */ X while (xdigit(*ptr)) X ptr++; /* skip past digits */ X if (check1) { X if (*ptr == 'T') /* if 'T' suffix then */ X trailing = 1; /* ..include trailing empty lines */ X else X trailing = 0; X } X X findcrc (fptr, fname); /* find CRC for rest of file */ X X if (gen1) { /* generating CRC */ X if (updfile) { /* if updating file posn */ X updatefile (fptr, hdrpos, crccode, fname); /* then do it */ X } else if (!silent) X printf (fmtstr, crccode, suffix(), blank, fname); X } else { /* checking CRC */ X if (fcrc == crccode) { X if (verbose) X printf (fmtstr, crccode, suffix(), ok, fname); X } else { X if (!silent) X printf (fmtstr, crccode, suffix(), bad, fname); X errcount ++; X } X } X return; X } /* end if (BRINCMP (...) ) */ X#ifndef NIXSEEK X hdrpos = ftell (fptr); X#endif X } /* end of while (fgets(...)) */ X X /* reach here if header not found -- this is an error */ X if (!silent) X printf ("%10s %s\n", "????", fname); X errcount++; X return; X} X X/* update file with CRC -- must be seekable */ Xupdatefile (fptr, hdrpos, crccode, fname) XFILE *fptr; Xlong hdrpos; Xlong crccode; Xchar *fname; X{ X char buf[LINESIZE]; X int buflen; /* will hold count of chars in buf */ X int chars_to_print; /* chars needed to fill in CRC */ X X /* X 1 for blank, CHARSINCRC for actual CRC, and possibly X 1 more for 'T' suffix if including trailing empty lines too X */ X chars_to_print = 1 + CHARSINCRC + (trailing ? 1 : 0); X X#ifndef NIXSEEK X /* hdrpos is already seek position of header */ X if (fseek (fptr, hdrpos, 0) != 0) { /* seek back */ X fprintf(stderr, X "brik: error: No CRC written, seek failed on %s\n",fname); X return; X } X XSEEKFIX X X fgets (buf, LINESIZE, fptr); X if (BRINCMP (buf, PATTERN, patlen) == 0) X goto foundit; X fprintf(stderr, X "brik: error: No CRC written, header lost in %s\n",fname); X return; X#else X /* Following code does fseeks in a non-ANSI-conformant way */ X /* hdrpos is seek position *after* header was read. Need to get back */ X if (hdrpos >= BACKSIZE) X hdrpos -= BACKSIZE; X else X hdrpos = 0L; X if (fseek (fptr, hdrpos, 0) != 0) { /* seek back first */ X fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname); X return; X } X /* now seek forward until we see CRC header again */ X hdrpos = ftell (fptr); X while (fgets (buf, LINESIZE, fptr) != NULL) { X if (BRINCMP (buf, PATTERN, patlen) == 0) X goto foundit; X hdrpos = ftell (fptr); X } X fprintf(stderr,"brik: error: No CRC written, header lost in %s\n",fname); X return; X#endif /* NIXSEEK */ X Xfoundit: /* hdrpos points to line with header */ X if (fseek (fptr, hdrpos, 0) != 0) { /* seek failed */ X fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname); X return; X } XSEEKFIX X /* we are seeked back to the line with the CRC header */ X X#ifdef CHECKSEEK /* triple-check seeks */ X { X char tmpbf1[LINESIZE]; X char tmpbf2[LINESIZE]; X fseek (fptr, hdrpos, 0); X assert (ftell (fptr) == hdrpos); XSEEKFIX X fgets (tmpbf1, LINESIZE, fptr); X fseek (fptr, 0L, 0); fseek (fptr, 0L, 2); /* exercise seeks */ X fseek (fptr, hdrpos, 0); X assert (ftell (fptr) == hdrpos); XSEEKFIX X fgets (tmpbf2, LINESIZE, fptr); X if (strcmp(tmpbf1,tmpbf2) != 0 || BRINCMP(tmpbf1,PATTERN,patlen) != 0) { X fprintf (stderr, X "brik: error: Bad seek on %s, abandoning this file\n", fname); X return; X } X fseek (fptr, hdrpos, 0); XSEEKFIX X } X#endif /* CHECKSEEK */ X X#ifdef DEBUG X if (debugging) { /* zap newline, print buffer, restore newline */ X int nlpos; char savech; X nlpos = strlen(buf) - 1; savech = buf[nlpos]; buf[nlpos] = '\0'; X fprintf (stderr, "read header [%s]\n", buf); X buf[nlpos] = savech; X } X#endif X X buflen = strlen (buf); X#ifdef DEBUG X if (debugging) /* need chars_to_print plus one trailing space or newline */ X fprintf(stderr,"need %d chars, have %d\n",chars_to_print+1,buflen-patlen); X#endif X if (buflen - patlen > chars_to_print) { /* if enough space */ X char sprbuf[1+CHARSINCRC+1+1+6]; /* blank+CRC+suffix+null+fudge */ X char *ptr; X int i; X ptr = &buf[patlen]; /* point to beyond header */ X sprintf (sprbuf, " %10lu%c", crccode, 'T'); X for (i = 0; i < chars_to_print; i++) /* trailing 'T' possibly ignored */ X ptr[i] = sprbuf[i]; X if (ptr[i] != '\n') X ptr[i] = ' '; /* terminate with newline or blank */ X fseek (fptr, 0L, 1); /* after read, must seek before write */ X if (fwrite (buf, 1, buflen, fptr) != buflen) { X fprintf(stderr, X "brik: error: Write failed while writing CRC to %s\n",fname); X } else if (verbose) X printf (fmtstr, crccode, suffix(), blank, fname); X /* printf ("%10lu %s\n", crccode, fname); */ X#ifdef DEBUG X buf[strlen(buf)-1] = '\0'; /* zap trailing newline */ X if (debugging) X fprintf (stderr, "wrote header [%s]\n", buf); X#endif X } else { X fprintf(stderr,"brik: error: Not enough space for CRC in %s\n",fname); X return; X } X} X Xvoid longhelp() X{ Xprintf (" Brik 1.0 (%s), a free CRC-32 program by Rahul Dhesi\n\n", X DATESTAMP); X Xprintf ("Usage: brik -cCgGsvWfbT [ file ] ...\n\n"); X Xprintf ("Brik 1.0 generates and verifies 32-bit CRC values (checksums). Optionally\n"); Xprintf ("it will read or update a \"Checksum: xxxxxxxxxx\" header at the beginning of\n"); Xprintf ("a line in which xxxxxxxxxx represents the CRC of all lines in the file\n"); Xprintf ("*after* this header. One of -c, -C, -g, or -G is required. If no\n"); X#ifdef WILDCARD Xprintf ("filename is given, or if a filename is -, standard input is read.\n"); Xprintf ("Wildcards are allowed on the command line and in files read with -f.\n\n"); X#else X/* extra newline */ Xprintf ("filename is given, or if a filename is -, standard input is read.\n\n"); X#endif X Xprintf (" -g look for Checksum: header, generate CRC for rest of file\n"); Xprintf (" -c get CRC from header, verify CRC of rest of file\n"); Xprintf (" -G generate CRC for entire file (add -b for binary files)\n"); Xprintf (" -C verify all file CRCs from output of -G (-f is not needed)\n"); Xprintf (" -b use binary mode--read file byte by byte, not line by line\n"); X X#ifdef WILDCARD Xprintf (" -f read filenames (wildcards ok) from specified files\n"); X#else Xprintf (" -f read filenames from specified files\n"); X#endif X Xprintf (" -v be verbose, report all results (else only errors are reported)\n"); Xprintf (" -s be silent, say nothing, just return status code\n"); Xprintf (" -W after generating CRC with -g, write it to original header\n"); Xprintf (" -T include trailing empty lines, normally ignored (text mode only)\n\n"); X X#ifndef EXITBUG Xprintf ("The exit code is the number of files with bad or missing CRCs.\n"); X#endif X Xexit (1); X} X X/* X** Generates CRC of an open file, from current file position to end X** Except in -T mode, will ignore all trailing empty lines in text X** files. Algorithm for this is: X** 1. After each nonempty line, save crccode so far. X** 2. At end of file, if last line was empty, use saved crccode rather X** than current one. X*/ X Xlong findcrc (fptr, fname) XFILE *fptr; Xchar *fname; X{ X int count; X char buf[LINESIZE]; X extern long crccode; X int warned = 0; X long savedcrc; /* save crccode here to handle trailing empty lines */ X int buflen; X X savedcrc = crccode = INITCRC; X X if (binary) { /* binary */ X while ((count = fread (buf, 1, LINESIZE, fptr)) > 0) { X#ifdef BRKTST X extern void brktst(); brktst(); X#endif X addbfcrc (buf, count); X } X return (crccode); X } else { /* text */ X buflen = 1; /* assume empty lines so far */ X while (fgets (buf, LINESIZE, fptr) != NULL) { X char *p; X char *limit; X#ifdef BRKTST X extern void brktst(); brktst(); X#endif X buflen = strlen (buf); X limit = buf + buflen; X for (p = buf; p != limit; p++) { X if (!warned && BINCHAR(*p)) { X fprintf (stderr, X "brik: warning: File %s is probably binary, don't trust text mode CRC\n", X fname); X warned = 1; X } X if (*p == '\n') X *p = MYNL; X } X addbfcrc (buf, buflen); X if (buflen != 1) X savedcrc = crccode; X } X if (!trailing && buflen == 1) X crccode = savedcrc; X return (crccode); X } X} X Xprinthdr () X{ X static int firsttime = 1; X if (firsttime) { X printf ("%c Whole file CRCs generated by Brik v1.0. Use \"brik -C\" to verify them.\n\n", X CMTCH); X printf ("%c CRC-32 filename\n", CMTCH); X printf ("%c ------ --------\n\n", CMTCH); X firsttime = 0; X } X} X X/* X** Prints error message via perror(). The message is printed in the X** format "brik: %s: %s" where the first %s is the level text ("warning", X** "error", or "fatal") and the second %s is the string supplied by X** perror(). X** X** superfluous right now because it is only called from efopen() X** and only with level = LVL_ERR. X*/ X Xvoid showerr (errmsg, level) Xchar *errmsg; Xint level; X{ X#define ERRSTRMAX 40 /* don't copy more than this many chars */ X static char leveltext[][7] = {"warning", "error", "fatal"}; X char errbuf[ERRBUFSIZ]; /* buffer for error message */ X strcpy (errbuf, "brik: "); X assert (level >= LVL_WARN && level <= LVL_FATAL); X strncat (errbuf, leveltext[level], ERRSTRMAX); X strcat (errbuf, ": "); X strncat (errbuf, errmsg, ERRSTRMAX); X perror (errbuf); X} X Xvoid shorthelp() X{ X fprintf (stderr, X "brik: fatal: One of -cCgG required, -svWfbT are optional (-h for help)\n"); X exit (1); X} SHAR_EOF echo "End of part 1, continue with part 2" exit 0
ibmbin-request@crdgw1.crd.ge.com (11/18/90)
Checksum: 561698957 (Verify with "brik -cv") Posting-number: Volume 08, Issue inf03 Originally-from: dhesi@bsu-cs.bsu.edu Archive-name: admin/briksrc1 RKIV #!/bin/sh # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 4104 -rw-r--r-- Install # 3563 -rw-r--r-- Usenet # 6391 -rw-r--r-- addbfcrc.c # 754 -rw-r--r-- assert.h # 26440 -rw-r--r-- brik.c # 18671 -rw-r--r-- brik.doc # 7035 -rw-r--r-- brik.h # 66 -rw-r--r-- brik.prj # 675 -rw-r--r-- descrip.mms # 2808 -rw-r--r-- getopt.c # 403 -rw-r--r-- makebrik.com # 829 -rw-r--r-- makefile # 86 -rw-r--r-- mkbsd # 137 -rw-r--r-- mksysv # 127 -rw-r--r-- mkuport # 28 -rw-r--r-- options.opt # 8118 -rw-r--r-- turboc.c # 2419 -rw-r--r-- vms.c # # ============= Install ============== echo "x - extracting Install (Text)" sed 's/^X//' << 'SHAR_EOF' > Install && X X INSTALLING BRIK 1.0 X XThe following files should be in this package. The files brik.exe and Xtcconfig.tc are binary files. All other files are text files with Xlines terminated by linefeeds. X X bytes name description X ----- ---- ----------- X 4104 Install installation instructions X 6391 addbfcrc.c source X 754 assert.h source X 26440 brik.c source X 18671 brik.doc documentation X 16710 brik.exe executable for MS-DOS X 7035 brik.h source X 66 brik.prj project file for MS-DOS Turbo C 1.0 X 675 descrip.mms makefile for VAX/VMS 4.7 X 2808 getopt.c source for Turbo C 1.0 and VAX/VMS 4.7 X 403 makebrik.com makefile for VAX/VMS 4.7 X 829 makefile makefile for **IX X 86 mkbsd make script for 4.xBSD X 137 mksysv make script for System V X 127 mkuport make script for Microport System V/AT 2.2 X 28 options.opt linker options for VAX/VMS 4.7 X 1380 tcconfig.tc configuration file for MS-DOS Turbo C 1.0 X 8118 turboc.c source for MS-DOS Turbo C 1.0 X 2419 vms.c source file for VAX/VMS 4.7 X XBrik is believed to compile and execute in the following environments: X X1. MS-DOS 3.x, Turbo C 1.0 X2. VAX/VMS 4.7 with VAX/VMS C 2.4 X3. 4.3BSD from Berkeley on a VAX-11/785 X4. Microport System V/AT version 2.2 X XMake sure all the needed files are in the current directory. Then follow Xinstructions below for your specific type of system. If doing so doesn't Xgive you a running copy of brik, read brik.h and experiment with the various Xcompilation options. X X1. MS-DOS, Turbo C 1.0 X XUse the supplied tcconfig.tc configuration file. Load the interactive Xtc.exe compiler, revise those options that are different for your Xsystem, and compile. I don't know if this will work with Turbo C 2.0. X X2. VAX/VMS X X2.1. If you have DEC's make utility called "mms", proceed as follows: X X a. Delete "makefile" so mms won't get confused X b. Type "mms" at the VMS prompt X c. If all goes well, mms will compile and link the necessary files, X ending by creating "brik.exe" in the current directory. X d. Move "brik.exe" wherever you want it and define a symbol with X a command line of the following type: X X $ brik :== $my$disk:[bindir]brik.exe X X where my$disk is the name of your device and bindir is the name X of the directory in which "brik.exe" is kept. X X2.2. If you don't have "mms", use the command file supplied. Invoke it as: X X $ @makebrik X XWhen it exits, brik.exe should have been created in your current Xdirectory, and the symbol "brik" should also have been defined for Xyou. If you move brik.exe to another directory be sure to redefine the Xsymbol "brik" correctly as described above in part I. X XBe sure to read the section in the manul on VAX/VMS bugs. X X3. 4.xBSD X XInvoke the script "mkbsd" with the command "sh mkbsd". Finally move Xthe program "brik" into an appropriate directory and make sure that Xthat directory is in your execution search path. X X4. System V X XInvoke the script "mksysv" (for generic System V) or "mkuport" (for XMicroport System V/AT) with the command "sh mksysv" or "sh mkuport". XThe "mkuport" script will try to move the compiled "brik" into X/usr/local/bin/brik so revise it if you don't want this done. The X"mksysv" script will create "brik" in the current directory ready to be Xmoved to an appropriate directory in your search path. X XThe "mkuport" script compiles brik using the large memory model, Xbecause an unexpected bug in Microport System V/AT made all my small- Xmodel libraries vanish and I haven't had a chance to restore them from Xbackups. I suspect compiling in the small memory model will work. X X -- Rahul Dhesi X 1989/03/13 SHAR_EOF # ============= Usenet ============== echo "x - extracting Usenet (Text)" sed 's/^X//' << 'SHAR_EOF' > Usenet && XFrom ibmbin Sun Mar 19 19:58:56 EST 1989 XArticle 1793 of comp.binaries.ibm.pc: XPath: bsu-cs!ibmbin X>From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi) XNewsgroups: comp.binaries.ibm.pc XSubject: v01i217: brik, a general-purpose CRC-32 program v1.0 (part 01/02) XSummary: brik.arc, a general-purpose CRC-32 program v1.0 XMessage-ID: <6105@bsu-cs.UUCP> XDate: 14 Mar 89 09:01:09 GMT XSender: news@bsu-cs.UUCP XFollowup-To: comp.binaries.ibm.pc.d XLines: 694 XApproved: dhesi@bsu-cs.bsu.edu XX-Submissions-to: ibmpc-binaries@bsu-cs.bsu.edu XX-Questions-to: ibmpc-binaries-request@bsu-cs.bsu.edu X XChecksum: 2208628413 (verify or update with "brik") XPosting-number: Volume 01, Issue 217 XOriginally-from: Rahul Dhesi <dhesi@bsu-cs.bsu.edu> XSubmitted-by: Rahul Dhesi <dhesi@bsu-cs.bsu.edu> XArchive-name: brik10/part01 X XI intend this program to be the standard comp.binaries.ibm.pc mechanism Xfor automatic verification of incoming articles. Once it is working, Xyou will be able to tell tell at a glance whether an incoming posting Xin comp.binaries.ibm.pc was received in corrupted form. X XThe executable for MS-DOS, and C source suitable for System V, 4.3BSD, XVAX/VMS, and MS-DOS/Turbo C, are all in the archive. However, the Xfollowing description is not inside the archive. Save it separately if Xyou want to keep it. X XThis is brik version 1.0, a general-purpose program to generate and Xverify 32-bit CRCs in both text and binary files. The Checksum: Xheaders in recent comp.binaries.ibm.pc postings contain CRCs that can Xbe verified or updated with this program. X XAdvantages of brik over "sum" and most CRC programs I have seen are: X X(a) It is freely redistributable and its algorithm is not proprietary X or licensed by *T&T or anybody else. X X(b) It treats text files in a special way. If you use brik to find X the CRCs of text files on an MS-DOS system, transfer the files to X a **IX system with Kermit and use brik on the **IX system, the X CRC calculated there will match the CRC calculated on the MS-DOS X system. However, you can override this feature if you wish, X and simply get a binary CRC for every byte in a file. X X(c) Brik will also look for a Checksum: header in any text file (or X C source file) and verify it based on the contents of the file X that occur *after* the header. This allows Usenet software to X change the initial header portion of an article without affecting X your ability to check the integrity of all lines that occur X after the Checksum: header. Brik itself also updates the Checksum: X header if needed. X X(d) Brik can create either text-mode or binary-mode CRCs for a bunch X of files that can be later checked by brik on the same or a X different system in one batch. Although brik isn't designed for this X purpose, it can be used to keep track of files that change X unexpectedly (e.g. corrupted filesystems, viruses). Since brik X will happily accept filenames on the command line, or from standard X input, or from a list inside one or more files, it is flexible and X will work well with other programs such as "find" (**IX) and X "stuff" (MS-DOS). X XTo verify the CRC of any comp.binaries.ibm.pc posting from the "rn" Xnewsreader, type the command: X X | brik -c X XThis will feed the current article to "brik -c" as standard input. XBrik will search for the Checksum: header, compare the CRC in that Xheader with the calculated CRC of the rest of the file, and report any Xmismatch. X XRahul Dhesi UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi X ARPA: dhesi@bsu-cs.bsu.edu SHAR_EOF # ============= addbfcrc.c ============== echo "x - extracting addbfcrc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > addbfcrc.c && X/* @(#) addbfcrc.c 1.5 89/03/08 14:58:35 */ X/* Most of following CRC-32 stuff is from zmodem source code */ X X#ifndef LINT Xstatic char sccsid[]="::[[ @(#) addbfcrc.c 1.6 89/03/10 19:08:47 ]]::"; X#endif X X/* I claim no copyright over the contents of this file. -- Rahul Dhesi */ X X/* XChecksum: 951252172 (check or update this with "brik") X*/ X X Xlong crccode; X X/* X * Copyright (C) 1986 Gary S. Brown. You may use this program, or X * code or tables extracted from it, as desired without restriction. X */ X X/* First, the polynomial itself and its table of feedback terms. The */ X/* polynomial is */ X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ X/* Note that we take it "backwards" and put the highest-order term in */ X/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ X/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ X/* the MSB being 1. */ X X/* Note that the usual hardware shift register implementation, which */ X/* is what we're using (we're merely optimizing it by doing eight-bit */ X/* chunks at a time) shifts bits into the lowest-order term. In our */ X/* implementation, that means shifting towards the right. Why do we */ X/* do it this way? Because the calculated CRC must be transmitted in */ X/* order from highest-order term to lowest-order term. UARTs transmit */ X/* characters in order from LSB to MSB. By storing the CRC this way, */ X/* we hand it to the UART in the order low-byte to high-byte; the UART */ X/* sends each low-bit to hight-bit; and the result is transmission bit */ X/* by bit from highest- to lowest-order term without requiring any bit */ X/* shuffling on our part. Reception works similarly. */ X X/* The feedback terms table consists of 256, 32-bit entries. Notes: */ X/* */ X/* The table can be generated at runtime if desired; code to do so */ X/* is shown later. It might not be obvious, but the feedback */ X/* terms simply represent the results of eight shift/xor opera- */ X/* tions for all combinations of data and CRC register values. */ X/* */ X/* The values must be right-shifted by eight bits by the "updcrc" */ X/* logic; the shift must be unsigned (bring in zeroes). On some */ X/* hardware you could probably optimize the shift in assembler by */ X/* using byte-swap instructions. */ X Xlong crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ X 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, X 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, X 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, X 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, X 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, X 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, X 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, X 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, X 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, X 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, X 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, X 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, X 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, X 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, X 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, X 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, X 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, X 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, X 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, X 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, X 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, X 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, X 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, X 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, X 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, X 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, X 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, X 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, X 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, X 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, X 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, X 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, X 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, X 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, X 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, X 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, X 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, X 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, X 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, X 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, X 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, X 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, X 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, X 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, X 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, X 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, X 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, X 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, X 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, X 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, X 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, X 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, X 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, X 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, X 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, X 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, X 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, X 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, X 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, X 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, X 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, X 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, X 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, X 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d X}; X Xaddbfcrc (buf, size) Xregister char *buf; Xregister int size; X{ X int i; X for (i = 0; i < size; i ++) { X crccode = crc_32_tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^ X (((crccode) >> 8) & 0x00FFFFFFL); X } X} SHAR_EOF # ============= assert.h ============== echo "x - extracting assert.h (Text)" sed 's/^X//' << 'SHAR_EOF' > assert.h && X/* @(#) assert.h 1.5 89/03/08 14:59:02 */ X X/* I claim no copyright over the contents of this file. -- Rahul Dhesi */ X X/* XChecksum: 3376323427 (check or update this with "brik") X*/ X X/* X** Assertions are enabled only if NDEBUG is not defined. X** Not all compilers define __FILE__ and __LINE__. If yours X** doesn't, you can just let NDEBUG remain #defined in brik.h and no X** assertions will be compiled in. Or, if you want to enable X** assertions, redefine the assert() macro so it works with your X** compiler. X*/ X X#ifndef OK_STDIO X# include <stdio.h> X# define OK_STDIO X#endif X X#ifndef NDEBUG X#define assert(E) \ X{if(!(E))fprintf(stderr,"Assertion error in %s line %d\n",__FILE__,__LINE__);} X#else X#define assert(E) X#endif /* NDEBUG */ SHAR_EOF # ============= brik.c ============== echo "x - extracting brik.c (Text)" sed 's/^X//' << 'SHAR_EOF' > brik.c && X/* ::[[ @(#) brik.c 1.44 89/03/12 14:34:35 ]]:: */ X#ifndef LINT X static char sccsid[]="::[[ @(#) brik.c 1.44 89/03/12 14:34:35 ]]::"; X#endif X X#define DATESTAMP "1989/03/12 14:34:35" X X/* X(c) Copyright 1989 Rahul Dhesi, All rights reserved. Permission is Xgranted to copy and distribute this file in modified or unmodified Xform, for any purpose whether commercial or noncommercial, provided Xthat (a) this paragraph, and the author identification printed by Xthe program, are preserved unchanged, and (b) no attempt is made to Xrestrict redistribution of this file. Inclusion of this file in a Xcollection whose distribution is restricted by a compilation copyright Xshall be considered an attempt to restrict redistribution of this file. XNotwithstanding the above, there are no restrictions on the copying or Xdistribution of not-human-readable executable machine code created by Xprocessing this file with a language translator. X*/ X X/* XChecksum: 1280097858 (check or update this with "brik") X*/ X X/* XThe following code assumes the ASCII character set and 8-bit bytes. X*/ X X#ifndef OK_STDIO X# include <stdio.h> X# define OK_STDIO X#endif X X#include "brik.h" /* configuration options */ X#include "assert.h" X XFILE *fopen(); XFILE *efopen(); Xchar *fgets(); Xint fclose(); Xchar *strchr(); Xint strlen(); Xint strcmp(); Xchar *strcat(); Xint fseek(); Xlong ftell(); Xint fwrite(); Xvoid hdrcrc(); Xvoid showerr(); Xvoid longhelp(); Xvoid shorthelp(); Xlong findcrc(); X X#ifdef ANSIPROTO Xvoid addbfcrc (char *, int); Xint printhdr (void); XFILE *efopen (char *, char *, int); Xlong xatol (char *); Xint main (int, char **); Xint dofname (char *); Xint dofptr (FILE *, char *); Xint whole_check (FILE *, char *); Xvoid hdrcrc (FILE *, char *); Xlong findcrc (FILE *, char *); Xint updatefile (FILE *, long, long, char *); Xvoid longhelp(void); Xvoid shorthelp(void); Xvoid showerr (char *, int); Xchar suffix(void); Xint lowerit (int); X Xint strlen (char *); Xchar *strchr (char *, char); Xchar *strcpy (char *, char *); Xchar *strcat (char *, char *); Xchar *strncat (char *, char *, int); Xint getopt (int, char **, char *); Xvoid exit (int); Xint strcmp (char *, char *); Xint readnames (FILE *); Xchar *nextfile (int, char *, int); Xvoid brktst(void); X#endif X X#define MYNL 10 /* newline for CRC calculation */ X#define ERRLIMIT 127 /* exit(n) returns n not exceeding this */ X#define LINESIZE 8192 /* handle lines of up to this length */ X#define ERRBUFSIZ 1024 /* buffer size for perror() message */ X#define PATTERN "Checksum:" /* look for this header */ X#define CHARSINCRC 10 /* characters in CRC */ X#define BACKSIZE 1024 /* how much to seek back looking for header */ X#define CMTCH '#' /* begins comment in CRC list */ X X/* define macro for testing if chars within range */ X#ifndef BINCHAR X# define LOW_PRINT '\007' /* smallest printable char */ X# define HIGH_PRINT '\176' /* biggest printable char */ X# define BINCHAR(c) ((c) < LOW_PRINT || (c) > HIGH_PRINT) X#endif /* BINCHAR */ X X/* error levels */ X#define LVL_WARN 0 X#define LVL_ERR 1 X#define LVL_FATAL 2 X X#ifdef USEINDEX X# define strchr index X#endif /* USEINDEX */ X X#ifdef TRAIL_T /* need trailing "t" in fopen string */ X# define BRIK_RD "rt" X# define BRIK_RW "r+t" X# define BRIK_RDB "rb" X#else X# define BRIK_RD "r" X# define BRIK_RW "r+" X# define BRIK_RDB "r" X#endif /* TRAIL_T */ X X#define whitespace(x) (strchr(" \t\n",(x)) != NULL) X/* format strings for printing CRCs and filenames etc. */ Xstatic char ok[] = "ok "; Xstatic char bad[] = "BAD"; Xstatic char blank[] = " "; Xstatic char fmtstr[] = "%10lu%c %s %s\n"; X X Xint patlen; /* length of PATTERN */ Xint errcount = 0; /* count of errors */ Xint gen1 = 0; /* generate CRCs for all files */ Xint gen2 = 0; /* generate CRCs for files with headers */ Xint silent = 0; /* be quiet, just set error status */ Xint verbose = 0; /* be verbose, print message for good files too */ Xint updfile = 0; /* update file by inserting CRC */ Xint check1 = 0; /* whether to check header crcs */ Xint check2 = 0; /* whether to check whole file crcs */ Xint fromfile = 0; /* read filenames from a file */ Xint binary = 0; /* manipulate binary file */ Xint trailing = 0; /* include trailing empty lines */ X X#ifdef DEBUG Xint debugging = 0; X#endif X X/* opens file, prints error message if can't open */ XFILE *efopen (fname, mode, level) Xchar *fname; /* filename to open */ Xchar *mode; /* mode, e.g. "r" or "r+" */ Xint level; /* error level */ X{ X FILE *fptr; X fptr = fopen (fname, mode); X if (fptr == NULL) X showerr (fname, level); X return (fptr); X} X X/* LOWERIT is a function or macro that returns lowercase of a character */ X#ifndef LOWERIT X# ifdef AVOID_MACROS X# define LOWERIT lowerit X# else X# define LOWERIT(c) ((c)>='A' && (c)<='Z' ? ('a'-'A')+(c) : (c)) X# endif X#endif X X/* Function needed by SEEKFIX code even if a macro is available */ Xint lowerit (c) int c; /* returns lowercase of an ASCII character */ X{ X if (c >= 'A' && c <= 'Z') return (('a'-'A') + c); X else return (c); X} X X/* STRNICMP is a case-insensitive strncmp */ X#ifndef STRNICMP Xint STRNICMP (s1, s2, n) Xregister char *s1, *s2; Xint n; X{ X assert (n >= 0); X assert (LOWERIT('X') == 'x'); X assert (LOWERIT('*') == '*'); X X for ( ; LOWERIT(*s1) == LOWERIT(*s2); s1++, s2++) { X if (--n == 0 || *s1 == '\0') X return(0); X } X return(LOWERIT(*s1) - LOWERIT(*s2)); X} X#endif /* STRNICMP */ X X#ifdef AVOID_MACROS X# define BRINCMP STRNICMP X#else X# define BRINCMP(s1,s2,n) (LOWERIT(*(s1))!=LOWERIT(*(s2))||STRNICMP(s1,s2,n)) X#endif X X X#define xdigit(x) ((x) >= '0' && (x) <= '9') X X/* Xxatol is given a string that (supposedly) begins with a string Xof digits. It returns a corresponding positive numeric value. X*/ Xlong xatol (str) Xchar *str; X{ X long retval; X retval = 0L; X while (xdigit(*str)) { X retval = retval * 10L + (*str-'0'); X str++; X } X return (retval); X} X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X int i; X int c; /* next option letter */ X int count = 0; /* count of required options seen */ X char *infname; /* name of file to read filenames from */ X FILE *infptr; /* open file ptr for infname */ X X extern int optind; /* from getopt: next arg to process */ X extern int opterr; /* used by getopt */ X X opterr = 0; /* so getopt won't print err msg */ X X patlen = strlen (PATTERN); X X#ifdef DEBUG X while ((c = getopt (argc, argv, "cCgGsvWfbThd")) != EOF) X#else X while ((c = getopt (argc, argv, "cCgGsvWfbTh")) != EOF) X#endif X { X switch (c) { X case 'c': check1++; count++; break; X case 'C': check2++; count++; break; X case 'g': gen1++; count++; break; X case 'G': gen2++; count++; break; X case 's': silent++; verbose = 0; break; X case 'v': verbose++; silent = 0; break; X case 'W': updfile++; break; X case 'f': fromfile++; break; X case 'b': binary++; trailing = 0; break; X case 'T': trailing++; binary = 0; break; X#ifdef DEBUG X case 'd': debugging++; break; X#endif X case 'h': longhelp(); X case '?': shorthelp(); X } X } X X if (count != 1) X shorthelp(); X X if (binary && (check1 || gen1)) { X fprintf (stderr, "brik: fatal: Can't read or update CRC header in binary mode\n"); X exit (1); X } X X if (updfile && !gen1) { X fprintf (stderr, "brik: fatal: Use of -W requires -g\n"); X exit (1); X } X X if ((gen1 || gen2) && !updfile) X silent = 0; X X i = optind; X X if (fromfile) { /* read filenames from file */ X if (i >= argc) { /* need filenames after -f */ X fprintf (stderr, "brik: fatal: Filename(s) needed after -f\n"); X exit (1); X } X for (; i < argc; i++) { X infname = argv[i]; X if (strcmp(infname, "-") == 0) { /* "-" means stdin */ X readnames (stdin); X } else { X#ifdef WILDCARD X extern char *nextfile(); X nextfile (0, infname, 0); /* initialize fileset 0 */ X while ((infname = nextfile(1, (char *) NULL, 0)) != NULL) { X infptr = efopen (infname, BRIK_RD, LVL_ERR); X readnames (infptr); X fclose (infptr); X } X#else X infptr = efopen (infname, BRIK_RD, LVL_ERR); X readnames (infptr); X fclose (infptr); X#endif /* WILDCARD */ X } X } X } else { /* read filenames from command line */ X if (i >= argc) { X#ifdef TRAIL_T X if (binary) { X fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n"); X exit (1); X } X#endif X dofptr (stdin, "stdin"); /* if no files, read stdin */ X } else { X for (; i < argc; i ++) { X#ifdef WILDCARD X extern char *nextfile(); X char *one_name; /* a matching filename */ X nextfile (0, argv[i], 0); /* initialize fileset 0 */ X while ((one_name = nextfile(1, (char *) NULL, 0)) != NULL) X dofname (one_name); X#else X dofname (argv[i]); X#endif /* WILDCARD */ X } X } X } Xerrexit: X if (errcount > ERRLIMIT) X errcount = ERRLIMIT; /* don't overflow status code */ X exit (errcount); X /*NOTREACHED*/ X} X X/* X** Reads names from supplied file pointer and handles them. Just X** returns if supplied NULL file pointer. Will also expand wildcards X** in names read from this file. X*/ Xreadnames (infptr) XFILE *infptr; X{ X char buf[LINESIZE]; X if (infptr == NULL) X return; X while (fgets (buf, LINESIZE, infptr) != NULL) { X#ifdef WILDCARD X char *fname; /* matching filename */ X extern char *nextfile(); X#endif /* WILDCARD */ X buf[strlen(buf)-1] = '\0'; /* zap trailing newline */ X#ifdef WILDCARD X nextfile (0, buf, 1); /* initialize fileset 1 */ X while ((fname = nextfile(1, (char *) NULL, 1)) != NULL) { X dofname (fname); X } X#else X dofname (buf); X#endif /* WILDCARD */ X } X} X X/* do one filename */ Xdofname (this_arg) Xchar *this_arg; X{ X FILE *this_file; X char *mode; /* "r", "rb", "rw", etc. for fopen */ X#ifdef BRKTST X extern void brktst(); X brktst(); X#endif X X if (strcmp(this_arg,"-") == 0) { X#ifdef TRAIL_T X if (binary) { X fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n"); X exit (1); X } X#endif X this_file = stdin; X this_arg = "stdin"; X } else { X if (updfile) { X assert (!binary); X this_file = efopen (this_arg, BRIK_RW, LVL_ERR); X } else { X if (binary && !check2) /* check2 reads filenames, not data */ X mode = BRIK_RDB; X else X mode = BRIK_RD; X this_file = efopen (this_arg, mode, LVL_ERR); X } X } X if (this_file == NULL) X errcount++; X else { X#ifdef NOCASE X char *p; X for (p = this_arg; *p != '\0'; p++) X *p = LOWERIT(*p); X#endif X dofptr (this_file, this_arg); X fclose (this_file); X } X} X Xchar suffix() X{ X return (binary ? 'b' : (trailing ? 'T' : ' ')); X} X X X/* X** Do one file pointer. Decides if CRC header will be read or written, X** or whether just the whole file will be read. X*/ Xdofptr (fptr, fname) XFILE *fptr; Xchar *fname; X{ X if (check2) X whole_check (fptr, fname); /* do whole file check from list */ X else if (gen1 || check1) /* header-based CRC check or update */ X hdrcrc (fptr, fname); X else { /* whole-file CRC calculation */ X extern long crccode; X assert (gen2); X printhdr(); X findcrc (fptr, fname); X printf (fmtstr, crccode, suffix(), blank, fname); X } X} X X X/* Does whole file check from a list of files and CRCs */ Xwhole_check (fptr, listname) XFILE *fptr; /* open file ptr of CRC list file */ Xchar *listname; /* name of CRC list file */ X{ X long fcrc; /* recorded crc */ X char *fname; /* name of file whose CRC being checked */ X char buf [LINESIZE]; /* line buffer */ X char *p; /* temp ptr */ X FILE *orgfile; /* file pointer for original file to check */ X int lino = 0; /* line no. in list file for error msg */ X char *mode; /* mode string for fopen */ X X while (fgets (buf, LINESIZE, fptr) != NULL) { X lino++; X p = buf; X if (*p == CMTCH) /* skip comment lines */ X continue; X while (*p != '\0' && whitespace(*p)) /* skip whitespace */ X p++; X if (*p == '\0') X continue; /* skip empty lines */ X if (!xdigit(*p)) X goto badline; X fcrc = xatol (p); /* recorded CRC */ X X while (xdigit(*p)) X p++; /* skip past numeric chars */ X X binary = trailing = 0; X if (*p == 'b') /* 'b' means binary */ X binary = 1; X X if (*p == 'T') /* 'T' means trailing mode */ X trailing = 1; X X while (*p != '\0' && !whitespace(*p)) /* to whitespace */ X p++; X while (whitespace(*p)) /* skip whitespace */ X p++; X X if (*p == '\n' || *p == '\0') { /* if at end of line */ X goto badline; X } X fname = p; X while (*p != '\0' && !whitespace(*p)) /* skip to whitespace */ X p++; X *p = '\0'; /* null-terminate filename */ X X if (binary) X mode = BRIK_RDB; X else X mode = BRIK_RD; X X orgfile = efopen (fname, mode, LVL_ERR); X if (orgfile == NULL) { X errcount++; X } else { X long foundcrc; X assert (!(binary && trailing)); X foundcrc = findcrc (orgfile, fname); X if (foundcrc == fcrc) { X if (verbose) X printf (fmtstr, foundcrc, suffix(), ok, fname); X } else { X if (!silent) X printf (fmtstr, foundcrc, suffix(), bad, fname); X errcount ++; X } X fclose (orgfile); X } X } X return; Xbadline: X fprintf (stderr, X "brik: error: Abandoning %s due to badly formatted line %d\n", X listname, lino); X return; X} X X X/* XInitializing the CRC to all one bits avoids failure of detection Xshould entire data stream get cyclically bit-shifted by one position. XThe calculation of the probability of this happening is left as Xan exercise for the reader. X*/ X#define INITCRC 0xFFFFFFFFL; X X/* X** hdrcrc processes one file given an open file pointer X** and the filename. The filename is used for messages etc. X** It does all manipulation of header-related CRCs, i.e., X** checking generating header CRC. It deals only with text files. X*/ Xvoid hdrcrc (fptr, fname) XFILE *fptr; Xchar *fname; X{ X char buf[LINESIZE]; X int lino = 0; X char *ptr; X long fcrc; /* crc recorded in file */ X extern long crccode; X long hdrpos; /* where we found crc header in file */ X X crccode = INITCRC; X X assert (!binary); X X#ifndef NIXSEEK X hdrpos = ftell (fptr); X#endif X while (fgets (buf, LINESIZE, fptr) != NULL) { X#ifdef BRKTST X extern void brktst(); X brktst(); X#endif X lino++; X if (BRINCMP (buf, PATTERN, patlen) == 0) { /* found header */ X#ifdef NIXSEEK X hdrpos = ftell (fptr); /* seek posn of line with header */ X#endif X ptr = buf + patlen; /* point to beyond header */ X while (*ptr != '\0' && whitespace(*ptr)) X ptr++; /* skip white space */ X fcrc = xatol (ptr); /* get stored crc */ X while (xdigit(*ptr)) X ptr++; /* skip past digits */ X if (check1) { X if (*ptr == 'T') /* if 'T' suffix then */ X trailing = 1; /* ..include trailing empty lines */ X else X trailing = 0; X } X X findcrc (fptr, fname); /* find CRC for rest of file */ X X if (gen1) { /* generating CRC */ X if (updfile) { /* if updating file posn */ X updatefile (fptr, hdrpos, crccode, fname); /* then do it */ X } else if (!silent) X printf (fmtstr, crccode, suffix(), blank, fname); X } else { /* checking CRC */ X if (fcrc == crccode) { X if (verbose) X printf (fmtstr, crccode, suffix(), ok, fname); X } else { X if (!silent) X printf (fmtstr, crccode, suffix(), bad, fname); X errcount ++; X } X } X return; X } /* end if (BRINCMP (...) ) */ X#ifndef NIXSEEK X hdrpos = ftell (fptr); X#endif X } /* end of while (fgets(...)) */ X X /* reach here if header not found -- this is an error */ X if (!silent) X printf ("%10s %s\n", "????", fname); X errcount++; X return; X} X X/* update file with CRC -- must be seekable */ Xupdatefile (fptr, hdrpos, crccode, fname) XFILE *fptr; Xlong hdrpos; Xlong crccode; Xchar *fname; X{ X char buf[LINESIZE]; X int buflen; /* will hold count of chars in buf */ X int chars_to_print; /* chars needed to fill in CRC */ X X /* X 1 for blank, CHARSINCRC for actual CRC, and possibly X 1 more for 'T' suffix if including trailing empty lines too X */ X chars_to_print = 1 + CHARSINCRC + (trailing ? 1 : 0); X X#ifndef NIXSEEK X /* hdrpos is already seek position of header */ X if (fseek (fptr, hdrpos, 0) != 0) { /* seek back */ X fprintf(stderr, X "brik: error: No CRC written, seek failed on %s\n",fname); X return; X } X XSEEKFIX X X fgets (buf, LINESIZE, fptr); X if (BRINCMP (buf, PATTERN, patlen) == 0) X goto foundit; X fprintf(stderr, X "brik: error: No CRC written, header lost in %s\n",fname); X return; X#else X /* Following code does fseeks in a non-ANSI-conformant way */ X /* hdrpos is seek position *after* header was read. Need to get back */ X if (hdrpos >= BACKSIZE) X hdrpos -= BACKSIZE; X else X hdrpos = 0L; X if (fseek (fptr, hdrpos, 0) != 0) { /* seek back first */ X fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname); X return; X } X /* now seek forward until we see CRC header again */ X hdrpos = ftell (fptr); X while (fgets (buf, LINESIZE, fptr) != NULL) { X if (BRINCMP (buf, PATTERN, patlen) == 0) X goto foundit; X hdrpos = ftell (fptr); X } X fprintf(stderr,"brik: error: No CRC written, header lost in %s\n",fname); X return; X#endif /* NIXSEEK */ X Xfoundit: /* hdrpos points to line with header */ X if (fseek (fptr, hdrpos, 0) != 0) { /* seek failed */ X fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname); X return; X } XSEEKFIX X /* we are seeked back to the line with the CRC header */ X X#ifdef CHECKSEEK /* triple-check seeks */ X { X char tmpbf1[LINESIZE]; X char tmpbf2[LINESIZE]; X fseek (fptr, hdrpos, 0); X assert (ftell (fptr) == hdrpos); XSEEKFIX X fgets (tmpbf1, LINESIZE, fptr); X fseek (fptr, 0L, 0); fseek (fptr, 0L, 2); /* exercise seeks */ X fseek (fptr, hdrpos, 0); X assert (ftell (fptr) == hdrpos); XSEEKFIX X fgets (tmpbf2, LINESIZE, fptr); X if (strcmp(tmpbf1,tmpbf2) != 0 || BRINCMP(tmpbf1,PATTERN,patlen) != 0) { X fprintf (stderr, X "brik: error: Bad seek on %s, abandoning this file\n", fname); X return; X } X fseek (fptr, hdrpos, 0); XSEEKFIX X } X#endif /* CHECKSEEK */ X X#ifdef DEBUG X if (debugging) { /* zap newline, print buffer, restore newline */ X int nlpos; char savech; X nlpos = strlen(buf) - 1; savech = buf[nlpos]; buf[nlpos] = '\0'; X fprintf (stderr, "read header [%s]\n", buf); X buf[nlpos] = savech; X } X#endif X X buflen = strlen (buf); X#ifdef DEBUG X if (debugging) /* need chars_to_print plus one trailing space or newline */ X fprintf(stderr,"need %d chars, have %d\n",chars_to_print+1,buflen-patlen); X#endif X if (buflen - patlen > chars_to_print) { /* if enough space */ X char sprbuf[1+CHARSINCRC+1+1+6]; /* blank+CRC+suffix+null+fudge */ X char *ptr; X int i; X ptr = &buf[patlen]; /* point to beyond header */ X sprintf (sprbuf, " %10lu%c", crccode, 'T'); X for (i = 0; i < chars_to_print; i++) /* trailing 'T' possibly ignored */ X ptr[i] = sprbuf[i]; X if (ptr[i] != '\n') X ptr[i] = ' '; /* terminate with newline or blank */ X fseek (fptr, 0L, 1); /* after read, must seek before write */ X if (fwrite (buf, 1, buflen, fptr) != buflen) { X fprintf(stderr, X "brik: error: Write failed while writing CRC to %s\n",fname); X } else if (verbose) X printf (fmtstr, crccode, suffix(), blank, fname); X /* printf ("%10lu %s\n", crccode, fname); */ X#ifdef DEBUG X buf[strlen(buf)-1] = '\0'; /* zap trailing newline */ X if (debugging) X fprintf (stderr, "wrote header [%s]\n", buf); X#endif X } else { X fprintf(stderr,"brik: error: Not enough space for CRC in %s\n",fname); X return; X } X} X Xvoid longhelp() X{ Xprintf (" Brik 1.0 (%s), a free CRC-32 program by Rahul Dhesi\n\n", X DATESTAMP); X Xprintf ("Usage: brik -cCgGsvWfbT [ file ] ...\n\n"); X Xprintf ("Brik 1.0 generates and verifies 32-bit CRC values (checksums). Optionally\n"); Xprintf ("it will read or update a \"Checksum: xxxxxxxxxx\" header at the beginning of\n"); Xprintf ("a line in which xxxxxxxxxx represents the CRC of all lines in the file\n"); Xprintf ("*after* this header. One of -c, -C, -g, or -G is required. If no\n"); X#ifdef WILDCARD Xprintf ("filename is given, or if a filename is -, standard input is read.\n"); Xprintf ("Wildcards are allowed on the command line and in files read with -f.\n\n"); X#else X/* extra newline */ Xprintf ("filename is given, or if a filename is -, standard input is read.\n\n"); X#endif X Xprintf (" -g look for Checksum: header, generate CRC for rest of file\n"); Xprintf (" -c get CRC from header, verify CRC of rest of file\n"); Xprintf (" -G generate CRC for entire file (add -b for binary files)\n"); Xprintf (" -C verify all file CRCs from output of -G (-f is not needed)\n"); Xprintf (" -b use binary mode--read file byte by byte, not line by line\n"); X X#ifdef WILDCARD Xprintf (" -f read filenames (wildcards ok) from specified files\n"); X#else Xprintf (" -f read filenames from specified files\n"); X#endif X Xprintf (" -v be verbose, report all results (else only errors are reported)\n"); Xprintf (" -s be silent, say nothing, just return status code\n"); Xprintf (" -W after generating CRC with -g, write it to original header\n"); Xprintf (" -T include trailing empty lines, normally ignored (text mode only)\n\n"); X X#ifndef EXITBUG Xprintf ("The exit code is the number of files with bad or missing CRCs.\n"); X#endif X Xexit (1); X} X X/* X** Generates CRC of an open file, from current file position to end X** Except in -T mode, will ignore all trailing empty lines in text X** files. Algorithm for this is: X** 1. After each nonempty line, save crccode so far. X** 2. At end of file, if last line was empty, use saved crccode rather X** than current one. X*/ X Xlong findcrc (fptr, fname) XFILE *fptr; Xchar *fname; X{ X int count; X char buf[LINESIZE]; X extern long crccode; X int warned = 0; X long savedcrc; /* save crccode here to handle trailing empty lines */ X int buflen; X X savedcrc = crccode = INITCRC; X X if (binary) { /* binary */ X while ((count = fread (buf, 1, LINESIZE, fptr)) > 0) { X#ifdef BRKTST X extern void brktst(); brktst(); X#endif X addbfcrc (buf, count); X } X return (crccode); X } else { /* text */ X buflen = 1; /* assume empty lines so far */ X while (fgets (buf, LINESIZE, fptr) != NULL) { X char *p; X char *limit; X#ifdef BRKTST X extern void brktst(); brktst(); X#endif X buflen = strlen (buf); X limit = buf + buflen; X for (p = buf; p != limit; p++) { X if (!warned && BINCHAR(*p)) { X fprintf (stderr, X "brik: warning: File %s is probably binary, don't trust text mode CRC\n", X fname); X warned = 1; X } X if (*p == '\n') X *p = MYNL; X } X addbfcrc (buf, buflen); X if (buflen != 1) X savedcrc = crccode; X } X if (!trailing && buflen == 1) X crccode = savedcrc; X return (crccode); X } X} X Xprinthdr () X{ X static int firsttime = 1; X if (firsttime) { X printf ("%c Whole file CRCs generated by Brik v1.0. Use \"brik -C\" to verify them.\n\n", X CMTCH); X printf ("%c CRC-32 filename\n", CMTCH); X printf ("%c ------ --------\n\n", CMTCH); X firsttime = 0; X } X} X X/* X** Prints error message via perror(). The message is printed in the X** format "brik: %s: %s" where the first %s is the level text ("warning", X** "error", or "fatal") and the second %s is the string supplied by X** perror(). X** X** superfluous right now because it is only called from efopen() X** and only with level = LVL_ERR. X*/ X Xvoid showerr (errmsg, level) Xchar *errmsg; Xint level; X{ X#define ERRSTRMAX 40 /* don't copy more than this many chars */ X static char leveltext[][7] = {"warning", "error", "fatal"}; X char errbuf[ERRBUFSIZ]; /* buffer for error message */ X strcpy (errbuf, "brik: "); X assert (level >= LVL_WARN && level <= LVL_FATAL); X strncat (errbuf, leveltext[level], ERRSTRMAX); X strcat (errbuf, ": "); X strncat (errbuf, errmsg, ERRSTRMAX); X perror (errbuf); X} X Xvoid shorthelp() X{ X fprintf (stderr, X "brik: fatal: One of -cCgG required, -svWfbT are optional (-h for help)\n"); X exit (1); X} SHAR_EOF echo "End of part 1, continue with part 2" exit 0