[comp.binaries.ibm.pc] v08inf04: brik shar

ibmbin-request@crdgw1.crd.ge.com (09/06/90)

Checksum: 3477039163  (Verify with "brik -cv")
Posting-number: Volume 07, Issue inf04
Originally-from: dhesi@bsu-cs.bsu.edu
Archive-name: admin/briksrc.2
RKIV

#!/bin/sh
# This is part 02 of a multipart archive
# ============= brik.doc ==============
echo "x - extracting brik.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.doc &&
X                                 Brik  1.0
X                            A free CRC-32 program
X                                     by
X                                 Rahul Dhesi
X
XBrik 1.0 generates and verifies 32-bit CRC values (checksums).  It is
Xdesigned to generate CRCs for text files that are the same on all computer
Xsystems that use the ASCII character set, provided each text file is in the
Xusual text file format for each system.  Brik 1.0 will also optionally use
Xbinary CRCs calculated using every byte in a file.  Such binary CRCs are
Xportable across systems for binary files that are moved from system to system
Xwithout any newline conversion.
X
XThe general usage format is:
X
X     brik -gcGCbfvsWT [file] ...
X
XThe brackets mean that "file", which is the name of a file, is optional.  The
Xthree dots indicate that more than one filenames may be typed (separated by
Xblanks).  Exactly one of the options -c, -C, -g, -G, or -h is required.  The
X-h option gives a help screen.
X
XIn addition to -h, the brik options available (as they appear on the help
Xscreen) are:
X
X   -g     look for Checksum: header, generate CRC for rest of file
X   -c     get CRC from header, verify CRC of rest of file
X   -G     generate CRC for entire file (add -b for binary files)
X   -C     verify all file CRCs from output of -G (-f is not needed)
X   -b     use binary mode--read file byte by byte, not line by line
X   -f     read filenames (wildcards ok) from specified files
X   -v     be verbose, report all results (else only errors are reported)
X   -s     be silent, say nothing, just return status code
X   -W     after generating CRC with -g, write it to original header
X   -T     include trailing empty lines, normally ignored (text mode only)
X
X
XVERIFYING CRC HEADERS
X
XThe primary intended use of brik is to verify Checksum: headers in Usenet
Xpostings and in C and Pascal source files.  A Checksum: header looks like
Xthis:
X
X     Checksum: 9485762645   (verify or update this with "brik")
X
XThe word "Checksum:" must occur at the beginning of a line.  It is followed
Xby a colon, an optional blank, a ten-digit CRC-32 value, and any arbitrary
Xoptional string such as the comment shown above.  When brik is invoked with
Xthe syntax
X
X     brik -c file ...
X
Xit will search for the Checksum: header in each specified file, read the CRC
Xvalue from that header, calculate the CRC-32 for all lines in the file that
Xoccur *after* the header line, and report an error if the two values do not
Xmatch.  Brik ignores any trailing empty lines.
X
X
XCALCULATING CRC HEADERS
X
XThe command
X
X     brik -g file ...
X
Xtells brik to look for the Checksum: header in each specified file, calculate
Xthe CRC of the lines in the file following the header, and print the CRC and
Xfilename without changing the file in any way.  You can also ask brik to
Xupdate the Checksum: header with the following command:
X
X     brik -gW file ...
X
XThis causes brik to fill in the newly-calculated CRC in the Checksum: header.
XIf there is not enough space for the CRC value in the existing header, brik
Xreports an error and does not change the existing header.  To initially add
Xa Checksum: header to a file, insert a line of the following form into the
Xfile with a text editor:
X
X     Checksum: XXXXXXXXXX  -- this is an optional comment
X
XThe word "Checksum" must be at the beginning of a line.  The ten 'X'
Xcharacters shown can be any ten characters.  They will be later replaced by
Xthe calculated CRC value.  They do not need to be 'X'.  The comment
Xfollowing them is optional and can be any arbitrary string of characters
Xafter the CRC field, separated from it by a blank.  As an example, in a C
Xsource file called "main.c", you might have:
X
X     /*
X     Checksum: XXXXXXXXXX (verify or update this with brik)
X     */
X
XOnce a header like this exists in the file, invoke brik as follows:
X
X     brik -gW main.c
X
XThis will cause the ten 'X' characters to be replaced with the calculated
Xchecksum, giving something like this:
X
X     /*
X     Checksum: 1922837484 (verify or update this with brik)
X     */
X
XLater you can use the command
X
X     brik -c main.c
X
Xto verify that the contents of the file following the header have the same
XCRC as the stored value.
X
XIf brik is invoked with the -c or -g options and it cannot find a Checksum:
Xheader in a file, it prints a row of question marks.  If it is invoked with
Xthe -gW option and it does not find enough character positions after the
X"Checksum:" string to hold the CRC, it does not fill in the CRC and prints an
Xerror message.
X
XWhen calculating the CRC to fill in with the -gW option, brik ignores any
Xtrailing empty lines in the file.
X
X
XWHOLE-FILE CRCS
X
XA "whole-file" CRC calculation is done for the entire contents of a file,
Xwithout looking for a Checksum: header.  The command
X
X     brik -G file ...
X
Xasks brik to do this calculation for all specified files.  The output from
Xthis command is a list of files and their whole-file CRCs.  It is sent to the
Xstandard output stream, which in most cases is your screen.  The output
Xshould be saved in a file by redirecting it.  For example, the command
X"brik -G *.h *.c > crc.lst" on an MS-DOS system might yield the following in
Xthe output file "crc.lst":
X
X     # Whole file CRCs generated by Brik v1.0.  Use "brik -C" to verify them.
X
X     # CRC-32        filename
X     # ------        --------
X
X     2566277976      getopt.c
X      100594287      brik.c
X     1151475469      vms.c
X     3929503738      turboc.c
X     2424271922      addbfcrc.c
X     1943472856      assert.h
X     2601923477      brik.h
X
XThe output of the -G option is in free format.  The output file may be edited
Xby hand.  Empty lines and lines beginning with '#' will be ignored by brik
Xwhen it is later asked to read this file.
X
XThis list of filenames and whole-file CRCs may be verified by a command like
Xthis:
X
X     brik -C crc.lst
X
XThis makes brik read the file "crc.lst", get the CRCs and filenames from it,
Xdo the CRC calculation again for each file, and report an error if it does
Xnot match the CRC recorded inside "crc.lst".
X
X**IX and MS-DOS users (and others who can pipe the output of one command into
Xanother) could use a command like the following to see if brik's -G and -C
Xoptions are working:
X
X     brik -G file ... | brik -C
X
XThis invokes "brik -G" on some files, sending the output to a pipe where it
Xbecomes the input of "brik -C".  If no filename is specified, brik reads from
Xstandard input, so "brik -C" will read from the pipe and concurrently verify
Xall the CRCs that are being generated by "brik -G".
X
XWhole-file CRCs are normally generated in text mode, in which a file is
Xtreated as lines of text.  In this mode brik ignores any trailing empty lines
Xin a file.  You can also generate whole-file CRCs in binary mode.  See
Xbelow.
X
X
XBINARY VERSUS TEXT MODE 
X
XBrik can work in two different modes.  The most common mode, used by the -g,
X-c, and -G options, is text mode.  In this mode brik ignores all trailing
Xempty lines in files.  (See more about this below.)
X
XIn text mode, brik reads all files line by line, and forces lines to be
Xterminated by a newline character of constant value before doing a CRC
Xcalculation.  Thus, no matter what newline character is used by your system,
Xthe CRC calculation will be unaffected.  This means that whether your
Xoperating system uses linefeeds to terminate lines (e.g. **IX), or a carriage
Xreturn and a linefeed (e.g.  MS-DOS) or a carriage return only (e.g.
XMacintosh) or nothing but a record length field (e.g. VAX/VMS), the CRC
Xcalculation in text mode gives the same results.
X
XIf a file is not intended to be a text file, the text mode CRC calculated by
Xbrik may not be reliable or the same on all systems for the same file.  Brik
Xcan be asked to operate in binary mode by adding a -b option to the option. 
XBinary mode is applicable only to the -G option, which acts on whole files. 
XThus while "brik -G file..." finds whole-file CRCs of all specified files in
Xtext mode, "brik -Gb file ..." does the same in binary mode.  In binary mode
Xbrik attempts no newline compensation, but simply reads and calculates the
XCRC for all bytes in a file.  Provided a file is moved from one system to
Xanother without any changes, brik should calculate the same CRC for it on
Xboth systems.
X
XThe output from "brik -Gb" includes a trailing 'b' character in each CRC, so
X"brik -C" will correctly use text or binary mode as needed, and -Cb is
Xequivalent to just -C.
X
X
XTRAILING EMPTY LINES
X
XThe normal behavior of brik in text mode is to ignore any trailing empty lines
Xin a file when checking or updating the CRC in a Checksum: header.  An empty
Xline is a line that contains nothing, not even blanks or tabs.  (Just hitting
Xa carriage return when you are editing a text file usually produces an empty
Xline.)   If manipulating a text file causes trailing empty lines to be added
Xor deleted, the CRC calculated by brik will be unaffected.
X
XYou can override this if necessary with the -T option, which makes brik
Xinclude trailing empty lines in the CRC calculation.  For example,
X"brik -gWT" will update the Checksum: header with a CRC value that includes
Xall lines in a text file.  Similarly "brik -GT" will find whole-file CRCs
Xthat include all lines in a text file.
X
XWhen brik is given the -T option, it adds a 'T' suffix to each generated CRC
Xvalue.  Then, when the CRC is verified with "brik -c" or "brik -C", brik will
Xcorrectly include trailing empty lines without having to be explicitly told
Xto do so.
X
XIn binary mode brik always reads all bytes in a file, so it does not ignore
Xtrailing empty lines, and the -T switch is not needed.
X
XThe -T and -b options are mutually exclusive, since the first is used only
Xfor text mode and the second is used only for binary mode.  If both are
Xgiven, whichever is used later overrides the first.  This "-bT" is equivalent
Xto "-T" and "-Tb" is equivalent to "-T".
X
X
XFILENAME CONVENTIONS
X
XUnder MS-DOS and VAX/VMS, wildcards are allowed on the command line and will
Xbe expanded by brik.  Under **IX, wildcards are expected to be expanded by
Xthe shell and are not expanded by brik.
X
XIf no filename is given, brik reads its standard input.  By default this is
Xkeyboard input, but it is expected that input will usually be redirected to
Xcome from a file or a pipe.  Also, if a filename is explicitly specified as a
Xdash ("-"), it stands for standard input.
X
XThus the following five commands (valid under the **IX operating system)
X
X     brik -c myfile           # verify "myfile"
X     brik -c < myfile         # verify stdin, which is "myfile"
X     cat myfile | brik -c     # verify stdin, which is a pipe
X     brik -c - < myfile       # verify "-", which is stdin, which is "myfile"
X     cat myfile | brik -c -   # verify "-", which is stdin, which is a pipe
X
Xall have the effect of verifying the Checksum: header in the file "myfile".
X
XStandard input can also be read by "brik -C".  For example, suppose we have
Xalready given the command
X
X     brik -G *.c *.h > crc.lst
X
Xto create a file called "crc.lst" that contains a list of whole-file CRCs.  We
Xcan now verify the integrity of these files with any of the following
Xcommands:
X
X     brik -C crc.lst          # read "crc.lst"
X     brik -C < crc.lst        # read stdin, which is "crc.lst"
X     brik -C - < crc.lst      # read "-", which is stdin, which is "crc.lst"
X     cat crc.lst | brik -C    # read stdin, which is a pipe
X     cat crc.lst | brik -C -  # read "-" which is stdin which is a pipe
X
X
XINDIRECT FILE NAMING
X
XThe -f option allows you to have filenames in a list rather than on the
Xcommand line.  For example, suppose you want to generate whole-file CRCs of
Xfiles whose names are selected by some other program.  You could use "find"
X(under **IX) or "stuff" (under MS-DOS) to generate a list of filenames.  When
Xthe -f option is given, brik reads filenames, one per line, from the file(s)
Xspecified.  Thus you could do the following:
X
X     find . -mtime +3 -print > flist
X     brik -Gf flist > crc.lst
X
XThe first command asks "find" to generate a list of names of all files that
Xwere modified more than 3 days ago, and sends the output to the file "flist".
XThe contents of "flist" might now look like this, as an example:
X
X   ./sez.doc
X   ./brik.doc
X   ./stuff.doc
X   ./looz.doc
X   ./fiz.man
X
XThe second command above asks brik to read the file called "flist", get a 
Xlist of filenames from it, one per line, and generate the whole-file CRC of
Xeach of these files.  We additionally redirect the output of "brik -Gf" to
Xthe file called "crc.lst".  Given the above contents of "flist", the following
Xtwo commands are exactly equivalent:
X
X     brik -Gf flist > crc.lst
X     brik -G ./sez.doc ./brik.doc ./stuff.doc ./looz.doc ./fiz.man > crc.lst
X
XThe advantage of the -f option is that once you have filenames in a file,
Xyou need not type them again at the command line.  The -f option also allows
Xyou to feed brik filenames generated by another program through a pipe.
XConsider this command:
X
X     find . -mtime +3 -print | brik -Gf - > crc.lst
X
XUnder **IX this concurrently invokes both "find" and brik.  As find
Xgenerates a filename and sends it to its standard output (a pipe), brik reads
Xthe filename from its standard input and generates its whole-file CRC.
XThe following pipeline
X
X     find . -mtime +3 -print | brik -Gf - | brik -C -
X
Xinvokes "find" to generate filenames, brik to print the whole-file CRCs of
Xthose files, and brik again to immediately verify them.
X
XUnder MS-DOS and VAX/VMS (and any other operating system under which brik has
Xbeen installed to expand wildcards itself), a file specified by the -f option
Xcan itself contain wildcards in the filenames.  For example, suppose the file
X"wildfile" contains the following lines:
X
X     /bin/*.exe
X     /bin/*.com
X     /doc/*.doc
X
XNow if we invoke brik with the command
X
X     brik -Gf wildfile
X
Xit will read filespecs from "wildfile", expand wildcards in each filespec,
Xand generate whole-file CRCs for all matching files.
X
XIf you are checking whole-file CRCs with the -C option, you do *not* normally
Xneed to use the -f option, as the -f option introduces an additional level of
Xfile naming indirection.  For example, the command
X
X     brik -C crc.lst
X
Xtakes a list of CRCs and filenames from "crc.lst" and verifies them. 
XHowever, the command
X
X     brik -Cf master.lst
X
Xdoes not do the same thing.  Instead, it takes a list of files from
X"master.lst", looks inside each of *those* files for a list of CRCs and
Xfilenames, and verifies them.
X
XAs an example of the use of -Cf, consider this sequence:
X
X     brik -Gb /bin/*.exe > exelist
X     brik -Gb /bin/*.com > comlist
X     brik -GT /doc/*.doc > doclist
X     brik -G  /doc/*.man > manlist
X
XNow we have four files called "exelist", "comlist", "doclist", and "manlist"
Xcontaining whole-file CRCs of various types.  We can test the integrity of
Xfiles listed in these in four separate commands like this:
X
X     brik -C exelist
X     brik -C comlist
X     brik -C doclist
X     brik -C manlist
X
XBut we could also do this in a single step by first creating a file called
X"biglist" that contains the names of these four files:
X
X     exelist
X     comlist
X     doclist
X     manlist
X
Xand then use -Cf thus:
X
X     brik -Cf biglist
X
XThis causes brik to read filenames from "biglist", look inside each of those
Xfiles ("exelist", "comlist", "doclist", and "manlist") and check the CRCs
Xfound there.  A **IX example to do the same thing in a more compact
Xway might be:
X
X     cat exelist comlist doclist manlist | brik -Cf -
X
X
XSILENT VERSUS VERBOSE
X
XBrik accepts options -s and -v that cause it to be more silent or more
Xverbose than usual.
X
XNormally brik prints a message only if it detects an error.  For example,
Xif you give the command "brik -c *.c *.h" and brik finds that all Checksum:
Xheaders contain CRCs that match the calculated value, it prints nothing.
X
XThe -v switch makes brik print a message for each file tested that contains the
Xword "ok" if stored and calculated CRCs matched and "BAD" if they did not.
X
XIn all messages reporting file CRCs, brik prints the actual CRC it calculated,
Xor a row of question marks if it could not calculate one.  Brik fails to
Xcalculate a CRC if it is trying to calculate a header-based CRC (commands
X-c and -g) but does not find a Checksum: header in a file.
X
XThe -s switch tells brik to be silent.  This will cause nothing to be printed
Xif brik does not find a Checksum header or if CRCs don't match.  However, the
Xstatus code on exit is still set.  The -s option is useful for invoking brik
Xfrom within a shell script (**IX) or a batch file (MS-DOS) and later testing
Xthe error code it returned when it exited.
X
XThe -s switch does not suppress the error message printed if brik is given a
Xfilename and the file cannot be found.  For example, if the command
X"brik -cs myfile" is given but "myfile" does not exist, brik will print an
Xerror message even though the -s option was given.
X
X
XVAX/VMS BUGS
X
Xo    Under VAX/VMS, file manipulation is unpredictable and the VAX/VMS C
X     runtime library in particular is very unreliable.  One result is that
X     under VAX/VMS, the -gW option will work only for stream-LF files, which
X     are the only type of file that VAX/VMS seems to handle correctly.
X     Fortunately, the -c option will correctly work for VAX/VMS standard
X     text files.
X
Xo    The VAX/VMS implementation of brik 1.0 simply ignores filenames that
X     correspond to nonexistent files instead of giving an error message.
X     This bug will be fixed as soon as I figure out why wildcard expansion
X     code that used to work properly with VAX/VMS a year ago doesn't work
X     any more.
X
Xo    To avoid annoying error messages, brik under VAX/VMS always exits with
X     a status code of 1.
X
Xo    Due to a problem in the VAX/VMS command interpreter, if any uppercase
X     option characters are typed (e.g. -C, -G, -T), brik will not recognize
X     them as uppercase unless they are enclosed in double quotes.  An
X     example of a correct command under VAX/VMS:
X
X          brik "-GT" *.*
X
X     An example of a command that won't work:
X
X          brik -GT *.*
X
X
XPROGRAM LIMITATIONS
X
XBrik 1.0 is designed to work with computer systems that use the 7-bit ASCII
Xcharacter set and 8-bit bytes with the eighth (parity) bit set to zero.
X
XBrik 1.0 has not been tested with computer systems that use ASCII characters
Xwith the eighth bit set or those that use EBCDIC characters.  Although
Xit will calculate a CRC on such machines, the probability of this CRC being
Xthe same as the one calculated on machines that use 7-bit ASCII is
Xapproximately 0.00000000023.
X
X                                    -- Rahul Dhesi
X                                       1989/03/13
SHAR_EOF
# ============= brik.h ==============
echo "x - extracting brik.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.h &&
X/* ::[[ @(#) brik.h 1.26 89/03/11 16:54:08 ]]:: */
X
X/*
XChecksum:   48859975      (check or update this with "brik")
X*/
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1989/03/10
X*/
X
X/*
XBrik assumes eight-bit bytes and the ASCII character set.  There may also
Xbe some implicit assumptions that the parity bit in characters in text
Xfiles is always zero.
X
XOptions for compiling brik.c on various systems.
X
XTRAIL_TB    Define this if a trailing "t" or "b" is needed in the fopen mode
X            string to open files in text or binary mode respectively.  Can
X            probably be safely defined even for System V and 4.3BSD, since
X            compilers will typically just ignore it.
XWILDCARD    Define this if wildcards are to be expanded by this program.
X            If WILDCARD is defined, then a function nextfile() must also
X            be available that conforms to the specifications in turboc.c.
XUSEINDEX    Define this symbol to make brik use index() instead of strchr().
X            Probably needed only 4.2BSD and earlier.
XBRKTST      If defined, brik will explicitly test for user interrupts in
X            all long loops, so that the program can easily be interrupted
X            on microcomputers that don't accept user interrupts
X            asynchronously.  If BRKTST is defined, brik will call the
X            function brktst() periodically.  This function should check
X            for a user interrupt and abort the program if it has occurred.
XNIXSEEK     If seeks are UNIX-like, i.e., seeks are possible at any byte
X            offset even in text files, then NIXSEEK may be defined to make
X            the -gW option perform faster.  If NIXSEEK is not defined, all
X            seeks will be to line boundaries using an offset already
X            obtained from ftell().  Even on non-UNIX-like systems, it *may*
X            be possible to define NIXSEEK, since when brik seeks to an
X            arbitrary byte boundary, it always immediately reads
X            sequentially forward to a line boundary.  Seeks are needed only
X            for the -gW option, which causes brik to seek back to where
X            it found the Checksum: header so it can update the stored CRC.
XCHECKSEEK   If seeks are flaky despite NIXSEEK being defined, it may help
X            to define CHECKSEEK.  In this case brik will seek, read a line,
X            seek again, read the line again, compare the two, and proceed
X            only if both reads gave the checksum header it was looking for,
X            thus confirming that the seeks are working right.  This is
X            a very conservative strategy to minimize the risk of corrupting
X            a file by overwriting it at the wrong place due to a faulty
X            seek.
XBUG1,       If ftell() just after fgets() does not return the correct seek
XBUG2        offset of the next line, one of these two symbols can be defined
X            (but not both).  Each adds different bug fix code and one of them
X            may work for you.
XANSIPROTO   If defined, ANSI-style function prototypes will be used.
X            If using this symbol creates trouble because your stdio.h
X            has slightly different prototypes, don't define it.
XNDEBUG      If this symbol is defined, assert() macros throughout the
X            brik code will get nulled out, making the executable code
X            slightly smaller.
XDEBUG       If this symbol is defined, an undocumented -d switch will
X            be accepted that will cause information about Checksum:
X            header reads and writes to be printed.
XEXITBUG     Define this symbol if the exit() function has a bug causing
X            anomalous results if the exit code is not exactly 1.
XAVOID_MACROS  Brik uses macros for speed in case-insensitive string
X            comparisons.  If you get "macro too long" or "expression too
X            complex" or similar compilation errors, you can define the
X            symbol AVOID_MACROS.  This will cause slower but more compact
X            code to be used that does not use long macros, possibly
X            allowing compilation.
XLOWERIT     If a fast macro or function call is available that will accept
X            a single parameter of type "int" and return its lowercase
X            value, the symbol LOWERIT may be defined to invoke it.  This
X            macro or function must accept any int value, whether or not
X            it represents an uppercase character.  Since LOWERIT is
X            never called with side-effects, it can safely be a macro.
X            If any include file is needed, include it here.  For example,
X            if a tolower() macro or function is available that requires
X            <ctype.h> to be included, use "#include <ctype.h>" followed
X            by "#define LOWERIT tolower" somewhere in brik.h.
XSTRNICMP    If a case-insensitive implementation of strncmp is available,
X            define STRNICMP to be equivalent to it.  If STRNICMP is not
X            defined, brik uses its own case-insensitive string comparison
X            function.  STRNICMP must accept the same arguments as strncmp.
XBINCHAR     Brik uses a simple range test to detect binary characters and
X            warn the user if a text mode CRC is being used on a binary file.
X            The user may optionally define his own BINCHAR(c) macro, which
X            must return nonzero if c should be considered a binary character.
XNOCASE      This symbol should be defined if the filesystem is case-
X            insensitive.  It will cause all filenames printed to be in
X            lowercase.  This will help make a list of files generated by
X            the -G option to be more easily usable on systems with case-
X            sensitive filesystems, as most file transfer mechanisms (e.g.
X            zmodem, kermit, zoo archives) will be compatible with this.
X
X                                     -- Rahul Dhesi
X                                        1989/03/11
X                                        UUCP:      iuvax!bsu-cs!dhesi
X                                        Internet:  dhesi@bsu-cs.bsu.edu
X*/
X
X#ifdef TURBOC
X# define TRAIL_T
X# define WILDCARD
X# define ANSIPROTO
X# define BRKTST
X# define BUG1
X# define NOCASE
X# define STRNICMP    strnicmp
X  int strnicmp (char *, char *, unsigned);
X# include <ctype.h>
X# define LOWERIT tolower
X#endif /* TURBOC */
X
X#ifdef SYS_V
X# define NIXSEEK
X#endif /* SYS_V */
X
X#ifdef BSD
X# define NIXSEEK
X# define USEINDEX
X#endif /* BSD */
X
X#ifdef VMS
X# define WILDCARD
X# define CHECKSEEK
X# define BUG2
X# define EXITBUG
X# define NOCASE
X#endif /* VMS */
X
X#ifdef BUG1
X# define SEEKFIX  \
X fgetc(fptr);while(lowerit(fgetc(fptr))!='c')fseek(fptr,-2L,1);fseek(fptr,-1L,1);
X#endif
X
X
X#ifdef BUG2
X# define SEEKFIX  \
X   fseek(fptr,-2L,1);while(fgetc(fptr)!='\n');
X#endif
X
X#ifndef BUG1
X# ifndef BUG2
X#  define SEEKFIX
X# endif
X#endif
X
X/* another thing to try */
X/* fseek(fptr,-2L,1);while(lowerit(fgetc(fptr))!='C');fseek(fptr,-1L,1); */
X
X#ifdef EXITBUG
X# define exit bugexit
X#endif
SHAR_EOF
# ============= brik.prj ==============
echo "x - extracting brik.prj (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.prj &&
Xaddbfcrc.c
Xbrik.c		(assert.h brik.h)
Xgetopt.c
Xturboc.c	(assert.h)
SHAR_EOF
# ============= descrip.mms ==============
echo "x - extracting descrip.mms (Text)"
sed 's/^X//' << 'SHAR_EOF' > descrip.mms &&
X# Makefile for brik -- for VAX/VMS "mms".  If you don't have mms,
X#  use the "makebrik.com" command file instead.
X#
X# Don't forget to define a symbol "brik" like this:
X#  $ brik:==$disk:[dir]brik.exe
X# where "disk" is your device name and "dir" is the directory in which
X# brik.exe is kept.
X
X# ::[[ @(#) descrip.mms 1.1 89/03/09 20:46:04 ]]::
X
X# Please see brik.h for configuration options.
X
XCFLAGS = /define=VMS
XOBJS = brik.obj, addbfcrc.obj, getopt.obj, vms.obj
XCC = cc
X
X.c.obj :
X	$(CC) $(CFLAGS) $*.c
X
Xbrik.exe : $(OBJS)
X	link/executable=brik.exe  $(OBJS), options/opt
X
Xbrik.obj : brik.c brik.h assert.h
X
Xaddbfcrc.obj : addbfcrc.c
X
Xvms.obj : vms.c
X
Xgetopt.obj : getopt.c
X
SHAR_EOF
# ============= getopt.c ==============
echo "x - extracting getopt.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > getopt.c &&
X/* ::[[ @(#) getopt.c 1.5 89/03/11 05:40:23 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) getopt.c 1.5 89/03/11 05:40:23 ]]::";
X#endif
X
X/*
XChecksum: 1099544938      (check or update this with "brik")
X*/
X
X/*
X * Here's something you've all been waiting for:  the AT&T public domain
X * source for getopt(3).  It is the code which was given out at the 1985
X * UNIFORUM conference in Dallas.  I obtained it by electronic mail
X * directly from AT&T.  The people there assure me that it is indeed
X * in the public domain.
X *
X * There is no manual page.  That is because the one they gave out at
X * UNIFORUM was slightly different from the current System V Release 2
X * manual page.  The difference apparently involved a note about the
X * famous rules 5 and 6, recommending using white space between an option
X * and its first argument, and not grouping options that have arguments.
X * Getopt itself is currently lenient about both of these things White
X * space is allowed, but not mandatory, and the last option in a group can
X * have an argument.  That particular version of the man page evidently
X * has no official existence, and my source at AT&T did not send a copy.
X * The current SVR2 man page reflects the actual behavor of this getopt.
X * However, I am not about to post a copy of anything licensed by AT&T.
X */
X
X/*
XMinor modifications by Rahul Dhesi 1989/03/06
X*/
X
X#include "brik.h"
X
X#ifdef ANSIPROTO
Xint strcmp (char *, char *);
Xchar *strchr (char *, char);
X#endif
X
X#include <stdio.h>
X
X/* Avoid possible compiler warning if we simply redefine NULL or EOF */
X#define XNULL   0
X#define XEOF (-1)
X
X#define ERR(szz,czz) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);}
X
Xextern int strcmp();
Xextern char *strchr();
X
Xint   opterr = 1;
Xint   optind = 1;
Xint   optopt;
Xchar  *optarg;
X
Xint
Xgetopt(argc, argv, opts)
Xint   argc;
Xchar  **argv, *opts;
X{
X   static int sp = 1;
X   register int c;
X   register char *cp;
X
X   if(sp == 1)
X      if(optind >= argc ||
X         argv[optind][0] != '-' || argv[optind][1] == '\0')
X         return(XEOF);
X      else if(strcmp(argv[optind], "--") == XNULL) {
X         optind++;
X         return(XEOF);
X      }
X   optopt = c = argv[optind][sp];
X   if(c == ':' || (cp=strchr(opts, c)) == XNULL) {
X      ERR(": illegal option -- ", c);
X      if(argv[optind][++sp] == '\0') {
X         optind++;
X         sp = 1;
X      }
X      return('?');
X   }
X   if(*++cp == ':') {
X      if(argv[optind][sp+1] != '\0')
X         optarg = &argv[optind++][sp+1];
X      else if(++optind >= argc) {
X         ERR(": option requires an argument -- ", c);
X         sp = 1;
X         return('?');
X      } else
X         optarg = argv[optind++];
X      sp = 1;
X   } else {
X      if(argv[optind][++sp] == '\0') {
X         sp = 1;
X         optind++;
X      }
X      optarg = XNULL;
X   }
X   return(c);
X}
SHAR_EOF
# ============= makebrik.com ==============
echo "x - extracting makebrik.com (Text)"
sed 's/^X//' << 'SHAR_EOF' > makebrik.com &&
X$! This command file compiles brik for VAX/VMS and also defines a
X$! symbol so you can type "brik" to execute the program.
X$!
X$! ::[[ @(#) makebrik.com 1.1 89/03/09 15:25:56 ]]::
X$!
X$ cc /define=VMS addbfcrc
X$ cc /define=VMS brik.c
X$ cc /define=VMS vms.c
X$ cc /define=VMS getopt.c
X$ link/executable=brik.exe  brik,addbfcrc,vms,getopt, options/opt
X$ brik:==$'f$trnlnm("sys$disk")''f$directory()'brik.exe
SHAR_EOF
# ============= makefile ==============
echo "x - extracting makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > makefile &&
X# Makefile for brik
X# ::[[ @(#) makefile 1.7 89/03/09 02:47:07 ]]::
X
X# Please see brik.h for configuration options.
X
X# "make brik"     -- makes brik in current directory
X# "make install"  -- makes brik, then moves it into DESTDIR defined below
X# "make clean"    -- deletes object files and executable brik from current dir
X
X# Directory where we want to move executable brik on "make install"
XDESTDIR=/usr/local/bin/.
X
X# CFLAGS are flags for the C compiler.  LDFLAGS are flags for the loader.
X# They are defined by the mk* scripts, so they need not be changed here.
X
XCFLAGS=
XLDFLAGS=
X
XCC=cc
X
X.c.o :
X	$(CC) -c $(CFLAGS) $*.c
X
XOBJS = brik.o addbfcrc.o
X
Xbrik: $(OBJS)
X	cc $(LDFLAGS) -o brik $(OBJS)
X
Xbrik.o: brik.c brik.h assert.h
X
Xaddbfcrc.o: addbfcrc.c
X
Xinstall: brik
X	mv brik $(DESTDIR)/brik
X
Xclean:
X	/bin/rm -f $(OBJS) core brik
SHAR_EOF
# ============= mkbsd ==============
echo "x - extracting mkbsd (Text)"
sed 's/^X//' << 'SHAR_EOF' > mkbsd &&
X# ::[[ @(#) mkbsd 1.1 89/03/09 02:41:21 ]]::
X# For 4.xBSD
Xmake "CFLAGS=-DBSD -O" brik
SHAR_EOF
# ============= mksysv ==============
echo "x - extracting mksysv (Text)"
sed 's/^X//' << 'SHAR_EOF' > mksysv &&
X# ::[[ @(#) mksysv 1.1 89/03/09 02:41:22 ]]::
X# For System V.  (See "mkuport" for Microport System V/AT.) 
Xmake "CFLAGS=-DSYS_V -O" brik
SHAR_EOF
# ============= mkuport ==============
echo "x - extracting mkuport (Text)"
sed 's/^X//' << 'SHAR_EOF' > mkuport &&
X# ::[[ @(#) mkuport 1.1 89/03/09 02:41:23 ]]::
X# For Microport System V/AT.
Xmake "CFLAGS=-Ml -DSYS_V -O" "LDFLAGS=-Ml" install
SHAR_EOF
# ============= options.opt ==============
echo "x - extracting options.opt (Text)"
sed 's/^X//' << 'SHAR_EOF' > options.opt &&
Xsys$share:vaxcrtl.exe/share
SHAR_EOF
# ============= turboc.c ==============
echo "x - extracting turboc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > turboc.c &&
X/* nextfile.c */
X/* ::[[ @(#) turboc.c 1.4 89/03/10 19:10:15 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) turboc.c 1.4 89/03/10 19:10:15 ]]::";
X#endif
X
X/*
XThis file is used only for MS-DOS & Turbo C.
X*/
X
X/*
XChecksum: 2196257943      (check or update this with "brik")
X*/
X
X/*
Xnextfile() is a general wildcard expansion function that may be used
Xwith other programs.  Usage instructions are below.  It does not
Xsimply expand wildcards in an entire argument list.  Instead, it is
Xcalled in a loop as described below, and returns one matching
Xfilename each time it is called.
X
XThese functions are for the SMALL MEMORY MODEL ONLY.
X*/
X
X#include "assert.h"
X#include "brik.h"
X
X#define  FMAX  2        /* Number of different filename patterns */
X#define  PATHSIZE 200   /* Size of MS-DOS pathname */
X#define  NULL  0
X
X#ifdef ANSIPROTO
Xchar *strtcpy (char *, char *);
Xint strlen (char *);
Xchar *strcpy (char *, char *);
X#endif
X
X
X/* Structure definitions for MS-DOS software interrupt intdos() */
X
Xstruct WORD_REGISTERS {
X   unsigned int ax, bx, cx, dx, si, di, carry, flags;
X};
X
X/* byte registers */
X
Xstruct BYTE_REGISTERS {
X   unsigned char al, ah, bl, bh, cl, ch, dl, dh;
X};
X
Xunion REGS {
X   struct WORD_REGISTERS x;
X   struct BYTE_REGISTERS h;
X};
X
Xint intdos (union REGS *, union REGS *);
X
X/*
Xformat of disk transfer address after MS-DOS calls FindFirst and
XFindNext
X*/
Xstruct dta_t {
X   char junk[22];
X   int time;
X   int date;
X   long size;
X   char fname[13];
X   char just_in_case[4];   /* in case MS-DOS writes too much */
X};
X
Xvoid setdta (struct dta_t *);
Xvoid fcbpath (struct dta_t *, char *, char *);
X
X/*******************/
X/*
Xnextfile() returns the name of the next source file matching a filespec.
X
XINPUT
X   what: A flag specifying what to do.  If "what" is 0, nextfile()
X      initializes itself.  If "what" is 1, nextfile() returns the next
X      matching filename.
X   filespec:  The filespec, usually containing wildcard characters, that
X      specifies which files are needed.  If "what" is 0, filespec must be
X      the filespec for which matching filenames are needed.  If "what" is 1,
X      nextfile() does not use "filespec" and "filespec" should be NULL to
X      avoid an assertion error during debugging.
X   fileset:  nextfile() can keep track of more than one set of filespecs.
X      The fileset specifies which filespec is being matched and therefore
X      which set of files is being considered.  "fileset" can be in the
X      range 0:FMAX.  Initialization of one fileset does not affect the
X      other filesets.
X
XOUTPUT
X   IF what == 0 THEN
X      return value is NULL
X   ELSE IF what == 1 THEN
X      IF a matching filename is found THEN
X         return value is pointer to matching filename including supplied path
X      ELSE
X         IF at least one file matched previously but no more match THEN
X            return value is NULL
X         ELSE IF supplied filespec never matched any filename THEN
X            IF this is the first call with what == 1 THEN
X               return value is pointer to original filespec
X            ELSE
X               return value is NULL
X            END IF
X         END IF
X      END IF
X   END IF
X
XNOTE
X
X   Initialization done when "what"=0 is not dependent on the correctness
X   of the supplied filespec but simply initializes internal variables
X   and makes a local copy of the supplied filespec.  If the supplied
X   filespec was illegal, the only effect is that the first time that
X   nextfile() is called with "what"=1, it will return the original
X   filespec instead of a matching filename.  That the filespec was
X   illegal will become obvious when the caller attempts to open the
X   returned filename for input/output and the open attempt fails.
X
XUSAGE HINTS
X
Xnextfile() can be used in the following manner:
X
X      char *filespec;                  -- will point to filespec
X      char *this_file;                 -- will point to matching filename
X      filespec = parse_command_line(); -- may contain wildcards
X      FILE *stream;
X
X      nextfile (0, filespec, 0);          -- initialize fileset 0
X      while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
X         stream = fopen (this_file, "whatever");
X         if (stream == NULL)
X            printf ("could not open %s\n", this_file);
X         else
X            perform_operations (stream);
X      }
X*/
X
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
X   static int first_time [FMAX+1];
X   static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
X   static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
X   union REGS regs;
X
X   assert(fileset >= 0 && fileset <= FMAX);
X   if (what == 0) {
X      assert(filespec != NULL);
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return ((char *) NULL);
X   }
X
X   setdta (&new_dta[fileset]);   /* set new dta -- our very own */
X   assert(what == 1);
X   assert(filespec == NULL);
X   assert(first_time[fileset] == 0 || first_time[fileset] == 1);
X
X   if (first_time[fileset]) {             /* first time -- initialize etc. */
X      /* find first matching file */
X      regs.h.ah = 0x4e;                   /* FindFirst MS-DOS call    */
X      regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
X      regs.x.cx = 0;                      /* search attributes       */
X      intdos (&regs, &regs);
X   } else {
X      /* find next matching file */
X      regs.h.ah = 0x4f;                   /* FindNext MS-DOS call     */
X      intdos (&regs, &regs);
X   }
X
X   if (regs.x.carry != 0) {            /* if error status                  */
X      if (first_time[fileset]) {       /*   if file never matched then     */
X         first_time[fileset] = 0;
X         return (saved_fspec[fileset]);/*      return original filespec    */
X      } else {                         /*   else                           */
X         first_time[fileset] = 0;      /*                                  */
X         return ((char *) NULL);         /*      return (NULL) for no more   */
X      }
X   } else {                                        /* a file matched */
X      first_time[fileset] = 0;
X      /* add path info  */
X      fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]);
X      return (pathholder[fileset]);                /* matching path  */
X   }
X} /* nextfile */
X
X/*******************/
X/* This function sets the dta to a new dta */
Xvoid setdta (dta)
Xstruct dta_t *dta;
X{
X   union REGS regs;
X   regs.h.ah = 0x1a;                /* SetDTA Call       */
X   regs.x.dx = (unsigned int) dta;  /* new DTA address   */
X   intdos (&regs, &regs);
X}
X
X/*******************/
X/*
Xfcbpath() accepts a pointer to the Disk Transfer Area, a character
Xpointer to a pathname that may contain wildcards, and a character
Xpointer to a buffer.  It copies into the buffer the path prefix from
Xthe pathname and the filename prefix from the DTA so that it forms a
Xcomplete path.
X*/
X
Xvoid fcbpath (dta, old_path, new_path)
Xstruct dta_t *dta;
Xchar *old_path;
Xregister char *new_path;
X{
X   register int i;
X   int length, start_pos;
X
X   strcpy(new_path, old_path);               /* copy the whole thing first */
X   length = strlen(new_path);
X   i = length - 1;                           /* i points to end of path */
X   while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
X      i--;
X   /* either we found a "/", "\", or ":", or we reached the beginning of
X      the name.  In any case, i points to the last character of the
X      path part. */
X   start_pos = i + 1;
X   for (i = 0; i < 13; i++)
X      new_path[start_pos+i] = dta->fname[i];
X   new_path[start_pos+13] = '\0';
X}
X/* -- END OF nextfile() and related functions -- */
X
Xextern unsigned _stklen = 10000;
X
X#include <conio.h>
Xbrktst() { kbhit(); }      /* test for user interrupt */
SHAR_EOF
# ============= vms.c ==============
echo "x - extracting vms.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > vms.c &&
X/*
X**   A wildcard expansion function for VAX/VMS
X**   -- Rahul Dhesi
X*/
X/* ::[[ @(#) vms.c 1.5 89/03/10 19:09:28 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) vms.c 1.5 89/03/10 19:09:28 ]]::";
X#endif
X
X/*
XChecksum: 3221488897     (verify or update with "brik")
X*/
X
X#include <descrip.h>
X
X#define  FMAX  3        /* Number of different filename patterns */
X#define  PATHSIZE 1024  /* buffer area to store pathname */
X
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   int status;
X   char *p;                      /* temp ptr */
X   struct dsc$descriptor_s d_fwild, d_ffound;
X   static int first_time [FMAX+1];
X   static char saved_fspec [FMAX+1][PATHSIZE];  /* our own copy of filespec */
X   static char found_fspec [FMAX+1][PATHSIZE];  /* matched filename */
X   static unsigned long context [FMAX+1]; /* needed by VMS */
X   if (what == 0) {
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return (0);
X   }
X
X   /* Reach here if what is not 0, so it must be 1 */
X
X   /* Create a descriptor for the wildcarded filespec */
X   d_fwild.dsc$w_length = strlen (saved_fspec[fileset]);
X   d_fwild.dsc$a_pointer = saved_fspec[fileset];
X   d_fwild.dsc$b_class = DSC$K_CLASS_S;
X   d_fwild.dsc$b_dtype = DSC$K_DTYPE_T;
X
X   d_ffound.dsc$w_length = sizeof (found_fspec[fileset]);
X   d_ffound.dsc$a_pointer = found_fspec[fileset];
X   d_ffound.dsc$b_class = DSC$K_CLASS_S;
X   d_ffound.dsc$b_dtype = DSC$K_DTYPE_T;
X
X   if (first_time[fileset]) {
X      first_time[fileset] = 0;
X      context[fileset] = 0L;   /* tell VMS this is first search */
X   }
X   status = LIB$FIND_FILE (&d_fwild, &d_ffound, &context[fileset]);
X   status = status & 1; /* use only lowest bit */
X
X   if (status == 0) {
X      LIB$FIND_FILE_END (&context[fileset]);
X      return ((char *) 0);
X   } else {
X      found_fspec[fileset][d_ffound.dsc$w_length] = '\0'; /* just in case */
X      p = found_fspec[fileset];
X      while (*p != ' ' && *p != '\0')
X         p++;
X      if (*p != '\0')
X         *p = '\0';
X      return (found_fspec[fileset]);
X   }
X}
X
X/* Compensate for bug in VAX/VMS C exit() function */
X
X#ifdef exit
X# undef exit
X#endif
X
Xint bugexit (n)
Xint n;
X{
X   exit (1);
X}
SHAR_EOF
exit 0

ibmbin-request@crdgw1.crd.ge.com (11/18/90)

Checksum: 1548012502  (Verify with "brik -cv")
Posting-number: Volume 08, Issue inf04
Originally-from: dhesi@bsu-cs.bsu.edu
Archive-name: admin/briksrc.2
RKIV

#!/bin/sh
# This is part 02 of a multipart archive
# ============= brik.doc ==============
echo "x - extracting brik.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.doc &&
X                                 Brik  1.0
X                            A free CRC-32 program
X                                     by
X                                 Rahul Dhesi
X
XBrik 1.0 generates and verifies 32-bit CRC values (checksums).  It is
Xdesigned to generate CRCs for text files that are the same on all computer
Xsystems that use the ASCII character set, provided each text file is in the
Xusual text file format for each system.  Brik 1.0 will also optionally use
Xbinary CRCs calculated using every byte in a file.  Such binary CRCs are
Xportable across systems for binary files that are moved from system to system
Xwithout any newline conversion.
X
XThe general usage format is:
X
X     brik -gcGCbfvsWT [file] ...
X
XThe brackets mean that "file", which is the name of a file, is optional.  The
Xthree dots indicate that more than one filenames may be typed (separated by
Xblanks).  Exactly one of the options -c, -C, -g, -G, or -h is required.  The
X-h option gives a help screen.
X
XIn addition to -h, the brik options available (as they appear on the help
Xscreen) are:
X
X   -g     look for Checksum: header, generate CRC for rest of file
X   -c     get CRC from header, verify CRC of rest of file
X   -G     generate CRC for entire file (add -b for binary files)
X   -C     verify all file CRCs from output of -G (-f is not needed)
X   -b     use binary mode--read file byte by byte, not line by line
X   -f     read filenames (wildcards ok) from specified files
X   -v     be verbose, report all results (else only errors are reported)
X   -s     be silent, say nothing, just return status code
X   -W     after generating CRC with -g, write it to original header
X   -T     include trailing empty lines, normally ignored (text mode only)
X
X
XVERIFYING CRC HEADERS
X
XThe primary intended use of brik is to verify Checksum: headers in Usenet
Xpostings and in C and Pascal source files.  A Checksum: header looks like
Xthis:
X
X     Checksum: 9485762645   (verify or update this with "brik")
X
XThe word "Checksum:" must occur at the beginning of a line.  It is followed
Xby a colon, an optional blank, a ten-digit CRC-32 value, and any arbitrary
Xoptional string such as the comment shown above.  When brik is invoked with
Xthe syntax
X
X     brik -c file ...
X
Xit will search for the Checksum: header in each specified file, read the CRC
Xvalue from that header, calculate the CRC-32 for all lines in the file that
Xoccur *after* the header line, and report an error if the two values do not
Xmatch.  Brik ignores any trailing empty lines.
X
X
XCALCULATING CRC HEADERS
X
XThe command
X
X     brik -g file ...
X
Xtells brik to look for the Checksum: header in each specified file, calculate
Xthe CRC of the lines in the file following the header, and print the CRC and
Xfilename without changing the file in any way.  You can also ask brik to
Xupdate the Checksum: header with the following command:
X
X     brik -gW file ...
X
XThis causes brik to fill in the newly-calculated CRC in the Checksum: header.
XIf there is not enough space for the CRC value in the existing header, brik
Xreports an error and does not change the existing header.  To initially add
Xa Checksum: header to a file, insert a line of the following form into the
Xfile with a text editor:
X
X     Checksum: XXXXXXXXXX  -- this is an optional comment
X
XThe word "Checksum" must be at the beginning of a line.  The ten 'X'
Xcharacters shown can be any ten characters.  They will be later replaced by
Xthe calculated CRC value.  They do not need to be 'X'.  The comment
Xfollowing them is optional and can be any arbitrary string of characters
Xafter the CRC field, separated from it by a blank.  As an example, in a C
Xsource file called "main.c", you might have:
X
X     /*
X     Checksum: XXXXXXXXXX (verify or update this with brik)
X     */
X
XOnce a header like this exists in the file, invoke brik as follows:
X
X     brik -gW main.c
X
XThis will cause the ten 'X' characters to be replaced with the calculated
Xchecksum, giving something like this:
X
X     /*
X     Checksum: 1922837484 (verify or update this with brik)
X     */
X
XLater you can use the command
X
X     brik -c main.c
X
Xto verify that the contents of the file following the header have the same
XCRC as the stored value.
X
XIf brik is invoked with the -c or -g options and it cannot find a Checksum:
Xheader in a file, it prints a row of question marks.  If it is invoked with
Xthe -gW option and it does not find enough character positions after the
X"Checksum:" string to hold the CRC, it does not fill in the CRC and prints an
Xerror message.
X
XWhen calculating the CRC to fill in with the -gW option, brik ignores any
Xtrailing empty lines in the file.
X
X
XWHOLE-FILE CRCS
X
XA "whole-file" CRC calculation is done for the entire contents of a file,
Xwithout looking for a Checksum: header.  The command
X
X     brik -G file ...
X
Xasks brik to do this calculation for all specified files.  The output from
Xthis command is a list of files and their whole-file CRCs.  It is sent to the
Xstandard output stream, which in most cases is your screen.  The output
Xshould be saved in a file by redirecting it.  For example, the command
X"brik -G *.h *.c > crc.lst" on an MS-DOS system might yield the following in
Xthe output file "crc.lst":
X
X     # Whole file CRCs generated by Brik v1.0.  Use "brik -C" to verify them.
X
X     # CRC-32        filename
X     # ------        --------
X
X     2566277976      getopt.c
X      100594287      brik.c
X     1151475469      vms.c
X     3929503738      turboc.c
X     2424271922      addbfcrc.c
X     1943472856      assert.h
X     2601923477      brik.h
X
XThe output of the -G option is in free format.  The output file may be edited
Xby hand.  Empty lines and lines beginning with '#' will be ignored by brik
Xwhen it is later asked to read this file.
X
XThis list of filenames and whole-file CRCs may be verified by a command like
Xthis:
X
X     brik -C crc.lst
X
XThis makes brik read the file "crc.lst", get the CRCs and filenames from it,
Xdo the CRC calculation again for each file, and report an error if it does
Xnot match the CRC recorded inside "crc.lst".
X
X**IX and MS-DOS users (and others who can pipe the output of one command into
Xanother) could use a command like the following to see if brik's -G and -C
Xoptions are working:
X
X     brik -G file ... | brik -C
X
XThis invokes "brik -G" on some files, sending the output to a pipe where it
Xbecomes the input of "brik -C".  If no filename is specified, brik reads from
Xstandard input, so "brik -C" will read from the pipe and concurrently verify
Xall the CRCs that are being generated by "brik -G".
X
XWhole-file CRCs are normally generated in text mode, in which a file is
Xtreated as lines of text.  In this mode brik ignores any trailing empty lines
Xin a file.  You can also generate whole-file CRCs in binary mode.  See
Xbelow.
X
X
XBINARY VERSUS TEXT MODE 
X
XBrik can work in two different modes.  The most common mode, used by the -g,
X-c, and -G options, is text mode.  In this mode brik ignores all trailing
Xempty lines in files.  (See more about this below.)
X
XIn text mode, brik reads all files line by line, and forces lines to be
Xterminated by a newline character of constant value before doing a CRC
Xcalculation.  Thus, no matter what newline character is used by your system,
Xthe CRC calculation will be unaffected.  This means that whether your
Xoperating system uses linefeeds to terminate lines (e.g. **IX), or a carriage
Xreturn and a linefeed (e.g.  MS-DOS) or a carriage return only (e.g.
XMacintosh) or nothing but a record length field (e.g. VAX/VMS), the CRC
Xcalculation in text mode gives the same results.
X
XIf a file is not intended to be a text file, the text mode CRC calculated by
Xbrik may not be reliable or the same on all systems for the same file.  Brik
Xcan be asked to operate in binary mode by adding a -b option to the option. 
XBinary mode is applicable only to the -G option, which acts on whole files. 
XThus while "brik -G file..." finds whole-file CRCs of all specified files in
Xtext mode, "brik -Gb file ..." does the same in binary mode.  In binary mode
Xbrik attempts no newline compensation, but simply reads and calculates the
XCRC for all bytes in a file.  Provided a file is moved from one system to
Xanother without any changes, brik should calculate the same CRC for it on
Xboth systems.
X
XThe output from "brik -Gb" includes a trailing 'b' character in each CRC, so
X"brik -C" will correctly use text or binary mode as needed, and -Cb is
Xequivalent to just -C.
X
X
XTRAILING EMPTY LINES
X
XThe normal behavior of brik in text mode is to ignore any trailing empty lines
Xin a file when checking or updating the CRC in a Checksum: header.  An empty
Xline is a line that contains nothing, not even blanks or tabs.  (Just hitting
Xa carriage return when you are editing a text file usually produces an empty
Xline.)   If manipulating a text file causes trailing empty lines to be added
Xor deleted, the CRC calculated by brik will be unaffected.
X
XYou can override this if necessary with the -T option, which makes brik
Xinclude trailing empty lines in the CRC calculation.  For example,
X"brik -gWT" will update the Checksum: header with a CRC value that includes
Xall lines in a text file.  Similarly "brik -GT" will find whole-file CRCs
Xthat include all lines in a text file.
X
XWhen brik is given the -T option, it adds a 'T' suffix to each generated CRC
Xvalue.  Then, when the CRC is verified with "brik -c" or "brik -C", brik will
Xcorrectly include trailing empty lines without having to be explicitly told
Xto do so.
X
XIn binary mode brik always reads all bytes in a file, so it does not ignore
Xtrailing empty lines, and the -T switch is not needed.
X
XThe -T and -b options are mutually exclusive, since the first is used only
Xfor text mode and the second is used only for binary mode.  If both are
Xgiven, whichever is used later overrides the first.  This "-bT" is equivalent
Xto "-T" and "-Tb" is equivalent to "-T".
X
X
XFILENAME CONVENTIONS
X
XUnder MS-DOS and VAX/VMS, wildcards are allowed on the command line and will
Xbe expanded by brik.  Under **IX, wildcards are expected to be expanded by
Xthe shell and are not expanded by brik.
X
XIf no filename is given, brik reads its standard input.  By default this is
Xkeyboard input, but it is expected that input will usually be redirected to
Xcome from a file or a pipe.  Also, if a filename is explicitly specified as a
Xdash ("-"), it stands for standard input.
X
XThus the following five commands (valid under the **IX operating system)
X
X     brik -c myfile           # verify "myfile"
X     brik -c < myfile         # verify stdin, which is "myfile"
X     cat myfile | brik -c     # verify stdin, which is a pipe
X     brik -c - < myfile       # verify "-", which is stdin, which is "myfile"
X     cat myfile | brik -c -   # verify "-", which is stdin, which is a pipe
X
Xall have the effect of verifying the Checksum: header in the file "myfile".
X
XStandard input can also be read by "brik -C".  For example, suppose we have
Xalready given the command
X
X     brik -G *.c *.h > crc.lst
X
Xto create a file called "crc.lst" that contains a list of whole-file CRCs.  We
Xcan now verify the integrity of these files with any of the following
Xcommands:
X
X     brik -C crc.lst          # read "crc.lst"
X     brik -C < crc.lst        # read stdin, which is "crc.lst"
X     brik -C - < crc.lst      # read "-", which is stdin, which is "crc.lst"
X     cat crc.lst | brik -C    # read stdin, which is a pipe
X     cat crc.lst | brik -C -  # read "-" which is stdin which is a pipe
X
X
XINDIRECT FILE NAMING
X
XThe -f option allows you to have filenames in a list rather than on the
Xcommand line.  For example, suppose you want to generate whole-file CRCs of
Xfiles whose names are selected by some other program.  You could use "find"
X(under **IX) or "stuff" (under MS-DOS) to generate a list of filenames.  When
Xthe -f option is given, brik reads filenames, one per line, from the file(s)
Xspecified.  Thus you could do the following:
X
X     find . -mtime +3 -print > flist
X     brik -Gf flist > crc.lst
X
XThe first command asks "find" to generate a list of names of all files that
Xwere modified more than 3 days ago, and sends the output to the file "flist".
XThe contents of "flist" might now look like this, as an example:
X
X   ./sez.doc
X   ./brik.doc
X   ./stuff.doc
X   ./looz.doc
X   ./fiz.man
X
XThe second command above asks brik to read the file called "flist", get a 
Xlist of filenames from it, one per line, and generate the whole-file CRC of
Xeach of these files.  We additionally redirect the output of "brik -Gf" to
Xthe file called "crc.lst".  Given the above contents of "flist", the following
Xtwo commands are exactly equivalent:
X
X     brik -Gf flist > crc.lst
X     brik -G ./sez.doc ./brik.doc ./stuff.doc ./looz.doc ./fiz.man > crc.lst
X
XThe advantage of the -f option is that once you have filenames in a file,
Xyou need not type them again at the command line.  The -f option also allows
Xyou to feed brik filenames generated by another program through a pipe.
XConsider this command:
X
X     find . -mtime +3 -print | brik -Gf - > crc.lst
X
XUnder **IX this concurrently invokes both "find" and brik.  As find
Xgenerates a filename and sends it to its standard output (a pipe), brik reads
Xthe filename from its standard input and generates its whole-file CRC.
XThe following pipeline
X
X     find . -mtime +3 -print | brik -Gf - | brik -C -
X
Xinvokes "find" to generate filenames, brik to print the whole-file CRCs of
Xthose files, and brik again to immediately verify them.
X
XUnder MS-DOS and VAX/VMS (and any other operating system under which brik has
Xbeen installed to expand wildcards itself), a file specified by the -f option
Xcan itself contain wildcards in the filenames.  For example, suppose the file
X"wildfile" contains the following lines:
X
X     /bin/*.exe
X     /bin/*.com
X     /doc/*.doc
X
XNow if we invoke brik with the command
X
X     brik -Gf wildfile
X
Xit will read filespecs from "wildfile", expand wildcards in each filespec,
Xand generate whole-file CRCs for all matching files.
X
XIf you are checking whole-file CRCs with the -C option, you do *not* normally
Xneed to use the -f option, as the -f option introduces an additional level of
Xfile naming indirection.  For example, the command
X
X     brik -C crc.lst
X
Xtakes a list of CRCs and filenames from "crc.lst" and verifies them. 
XHowever, the command
X
X     brik -Cf master.lst
X
Xdoes not do the same thing.  Instead, it takes a list of files from
X"master.lst", looks inside each of *those* files for a list of CRCs and
Xfilenames, and verifies them.
X
XAs an example of the use of -Cf, consider this sequence:
X
X     brik -Gb /bin/*.exe > exelist
X     brik -Gb /bin/*.com > comlist
X     brik -GT /doc/*.doc > doclist
X     brik -G  /doc/*.man > manlist
X
XNow we have four files called "exelist", "comlist", "doclist", and "manlist"
Xcontaining whole-file CRCs of various types.  We can test the integrity of
Xfiles listed in these in four separate commands like this:
X
X     brik -C exelist
X     brik -C comlist
X     brik -C doclist
X     brik -C manlist
X
XBut we could also do this in a single step by first creating a file called
X"biglist" that contains the names of these four files:
X
X     exelist
X     comlist
X     doclist
X     manlist
X
Xand then use -Cf thus:
X
X     brik -Cf biglist
X
XThis causes brik to read filenames from "biglist", look inside each of those
Xfiles ("exelist", "comlist", "doclist", and "manlist") and check the CRCs
Xfound there.  A **IX example to do the same thing in a more compact
Xway might be:
X
X     cat exelist comlist doclist manlist | brik -Cf -
X
X
XSILENT VERSUS VERBOSE
X
XBrik accepts options -s and -v that cause it to be more silent or more
Xverbose than usual.
X
XNormally brik prints a message only if it detects an error.  For example,
Xif you give the command "brik -c *.c *.h" and brik finds that all Checksum:
Xheaders contain CRCs that match the calculated value, it prints nothing.
X
XThe -v switch makes brik print a message for each file tested that contains the
Xword "ok" if stored and calculated CRCs matched and "BAD" if they did not.
X
XIn all messages reporting file CRCs, brik prints the actual CRC it calculated,
Xor a row of question marks if it could not calculate one.  Brik fails to
Xcalculate a CRC if it is trying to calculate a header-based CRC (commands
X-c and -g) but does not find a Checksum: header in a file.
X
XThe -s switch tells brik to be silent.  This will cause nothing to be printed
Xif brik does not find a Checksum header or if CRCs don't match.  However, the
Xstatus code on exit is still set.  The -s option is useful for invoking brik
Xfrom within a shell script (**IX) or a batch file (MS-DOS) and later testing
Xthe error code it returned when it exited.
X
XThe -s switch does not suppress the error message printed if brik is given a
Xfilename and the file cannot be found.  For example, if the command
X"brik -cs myfile" is given but "myfile" does not exist, brik will print an
Xerror message even though the -s option was given.
X
X
XVAX/VMS BUGS
X
Xo    Under VAX/VMS, file manipulation is unpredictable and the VAX/VMS C
X     runtime library in particular is very unreliable.  One result is that
X     under VAX/VMS, the -gW option will work only for stream-LF files, which
X     are the only type of file that VAX/VMS seems to handle correctly.
X     Fortunately, the -c option will correctly work for VAX/VMS standard
X     text files.
X
Xo    The VAX/VMS implementation of brik 1.0 simply ignores filenames that
X     correspond to nonexistent files instead of giving an error message.
X     This bug will be fixed as soon as I figure out why wildcard expansion
X     code that used to work properly with VAX/VMS a year ago doesn't work
X     any more.
X
Xo    To avoid annoying error messages, brik under VAX/VMS always exits with
X     a status code of 1.
X
Xo    Due to a problem in the VAX/VMS command interpreter, if any uppercase
X     option characters are typed (e.g. -C, -G, -T), brik will not recognize
X     them as uppercase unless they are enclosed in double quotes.  An
X     example of a correct command under VAX/VMS:
X
X          brik "-GT" *.*
X
X     An example of a command that won't work:
X
X          brik -GT *.*
X
X
XPROGRAM LIMITATIONS
X
XBrik 1.0 is designed to work with computer systems that use the 7-bit ASCII
Xcharacter set and 8-bit bytes with the eighth (parity) bit set to zero.
X
XBrik 1.0 has not been tested with computer systems that use ASCII characters
Xwith the eighth bit set or those that use EBCDIC characters.  Although
Xit will calculate a CRC on such machines, the probability of this CRC being
Xthe same as the one calculated on machines that use 7-bit ASCII is
Xapproximately 0.00000000023.
X
X                                    -- Rahul Dhesi
X                                       1989/03/13
SHAR_EOF
# ============= brik.h ==============
echo "x - extracting brik.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.h &&
X/* ::[[ @(#) brik.h 1.26 89/03/11 16:54:08 ]]:: */
X
X/*
XChecksum:   48859975      (check or update this with "brik")
X*/
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1989/03/10
X*/
X
X/*
XBrik assumes eight-bit bytes and the ASCII character set.  There may also
Xbe some implicit assumptions that the parity bit in characters in text
Xfiles is always zero.
X
XOptions for compiling brik.c on various systems.
X
XTRAIL_TB    Define this if a trailing "t" or "b" is needed in the fopen mode
X            string to open files in text or binary mode respectively.  Can
X            probably be safely defined even for System V and 4.3BSD, since
X            compilers will typically just ignore it.
XWILDCARD    Define this if wildcards are to be expanded by this program.
X            If WILDCARD is defined, then a function nextfile() must also
X            be available that conforms to the specifications in turboc.c.
XUSEINDEX    Define this symbol to make brik use index() instead of strchr().
X            Probably needed only 4.2BSD and earlier.
XBRKTST      If defined, brik will explicitly test for user interrupts in
X            all long loops, so that the program can easily be interrupted
X            on microcomputers that don't accept user interrupts
X            asynchronously.  If BRKTST is defined, brik will call the
X            function brktst() periodically.  This function should check
X            for a user interrupt and abort the program if it has occurred.
XNIXSEEK     If seeks are UNIX-like, i.e., seeks are possible at any byte
X            offset even in text files, then NIXSEEK may be defined to make
X            the -gW option perform faster.  If NIXSEEK is not defined, all
X            seeks will be to line boundaries using an offset already
X            obtained from ftell().  Even on non-UNIX-like systems, it *may*
X            be possible to define NIXSEEK, since when brik seeks to an
X            arbitrary byte boundary, it always immediately reads
X            sequentially forward to a line boundary.  Seeks are needed only
X            for the -gW option, which causes brik to seek back to where
X            it found the Checksum: header so it can update the stored CRC.
XCHECKSEEK   If seeks are flaky despite NIXSEEK being defined, it may help
X            to define CHECKSEEK.  In this case brik will seek, read a line,
X            seek again, read the line again, compare the two, and proceed
X            only if both reads gave the checksum header it was looking for,
X            thus confirming that the seeks are working right.  This is
X            a very conservative strategy to minimize the risk of corrupting
X            a file by overwriting it at the wrong place due to a faulty
X            seek.
XBUG1,       If ftell() just after fgets() does not return the correct seek
XBUG2        offset of the next line, one of these two symbols can be defined
X            (but not both).  Each adds different bug fix code and one of them
X            may work for you.
XANSIPROTO   If defined, ANSI-style function prototypes will be used.
X            If using this symbol creates trouble because your stdio.h
X            has slightly different prototypes, don't define it.
XNDEBUG      If this symbol is defined, assert() macros throughout the
X            brik code will get nulled out, making the executable code
X            slightly smaller.
XDEBUG       If this symbol is defined, an undocumented -d switch will
X            be accepted that will cause information about Checksum:
X            header reads and writes to be printed.
XEXITBUG     Define this symbol if the exit() function has a bug causing
X            anomalous results if the exit code is not exactly 1.
XAVOID_MACROS  Brik uses macros for speed in case-insensitive string
X            comparisons.  If you get "macro too long" or "expression too
X            complex" or similar compilation errors, you can define the
X            symbol AVOID_MACROS.  This will cause slower but more compact
X            code to be used that does not use long macros, possibly
X            allowing compilation.
XLOWERIT     If a fast macro or function call is available that will accept
X            a single parameter of type "int" and return its lowercase
X            value, the symbol LOWERIT may be defined to invoke it.  This
X            macro or function must accept any int value, whether or not
X            it represents an uppercase character.  Since LOWERIT is
X            never called with side-effects, it can safely be a macro.
X            If any include file is needed, include it here.  For example,
X            if a tolower() macro or function is available that requires
X            <ctype.h> to be included, use "#include <ctype.h>" followed
X            by "#define LOWERIT tolower" somewhere in brik.h.
XSTRNICMP    If a case-insensitive implementation of strncmp is available,
X            define STRNICMP to be equivalent to it.  If STRNICMP is not
X            defined, brik uses its own case-insensitive string comparison
X            function.  STRNICMP must accept the same arguments as strncmp.
XBINCHAR     Brik uses a simple range test to detect binary characters and
X            warn the user if a text mode CRC is being used on a binary file.
X            The user may optionally define his own BINCHAR(c) macro, which
X            must return nonzero if c should be considered a binary character.
XNOCASE      This symbol should be defined if the filesystem is case-
X            insensitive.  It will cause all filenames printed to be in
X            lowercase.  This will help make a list of files generated by
X            the -G option to be more easily usable on systems with case-
X            sensitive filesystems, as most file transfer mechanisms (e.g.
X            zmodem, kermit, zoo archives) will be compatible with this.
X
X                                     -- Rahul Dhesi
X                                        1989/03/11
X                                        UUCP:      iuvax!bsu-cs!dhesi
X                                        Internet:  dhesi@bsu-cs.bsu.edu
X*/
X
X#ifdef TURBOC
X# define TRAIL_T
X# define WILDCARD
X# define ANSIPROTO
X# define BRKTST
X# define BUG1
X# define NOCASE
X# define STRNICMP    strnicmp
X  int strnicmp (char *, char *, unsigned);
X# include <ctype.h>
X# define LOWERIT tolower
X#endif /* TURBOC */
X
X#ifdef SYS_V
X# define NIXSEEK
X#endif /* SYS_V */
X
X#ifdef BSD
X# define NIXSEEK
X# define USEINDEX
X#endif /* BSD */
X
X#ifdef VMS
X# define WILDCARD
X# define CHECKSEEK
X# define BUG2
X# define EXITBUG
X# define NOCASE
X#endif /* VMS */
X
X#ifdef BUG1
X# define SEEKFIX  \
X fgetc(fptr);while(lowerit(fgetc(fptr))!='c')fseek(fptr,-2L,1);fseek(fptr,-1L,1);
X#endif
X
X
X#ifdef BUG2
X# define SEEKFIX  \
X   fseek(fptr,-2L,1);while(fgetc(fptr)!='\n');
X#endif
X
X#ifndef BUG1
X# ifndef BUG2
X#  define SEEKFIX
X# endif
X#endif
X
X/* another thing to try */
X/* fseek(fptr,-2L,1);while(lowerit(fgetc(fptr))!='C');fseek(fptr,-1L,1); */
X
X#ifdef EXITBUG
X# define exit bugexit
X#endif
SHAR_EOF
# ============= brik.prj ==============
echo "x - extracting brik.prj (Text)"
sed 's/^X//' << 'SHAR_EOF' > brik.prj &&
Xaddbfcrc.c
Xbrik.c		(assert.h brik.h)
Xgetopt.c
Xturboc.c	(assert.h)
SHAR_EOF
# ============= descrip.mms ==============
echo "x - extracting descrip.mms (Text)"
sed 's/^X//' << 'SHAR_EOF' > descrip.mms &&
X# Makefile for brik -- for VAX/VMS "mms".  If you don't have mms,
X#  use the "makebrik.com" command file instead.
X#
X# Don't forget to define a symbol "brik" like this:
X#  $ brik:==$disk:[dir]brik.exe
X# where "disk" is your device name and "dir" is the directory in which
X# brik.exe is kept.
X
X# ::[[ @(#) descrip.mms 1.1 89/03/09 20:46:04 ]]::
X
X# Please see brik.h for configuration options.
X
XCFLAGS = /define=VMS
XOBJS = brik.obj, addbfcrc.obj, getopt.obj, vms.obj
XCC = cc
X
X.c.obj :
X	$(CC) $(CFLAGS) $*.c
X
Xbrik.exe : $(OBJS)
X	link/executable=brik.exe  $(OBJS), options/opt
X
Xbrik.obj : brik.c brik.h assert.h
X
Xaddbfcrc.obj : addbfcrc.c
X
Xvms.obj : vms.c
X
Xgetopt.obj : getopt.c
X
SHAR_EOF
# ============= getopt.c ==============
echo "x - extracting getopt.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > getopt.c &&
X/* ::[[ @(#) getopt.c 1.5 89/03/11 05:40:23 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) getopt.c 1.5 89/03/11 05:40:23 ]]::";
X#endif
X
X/*
XChecksum: 1099544938      (check or update this with "brik")
X*/
X
X/*
X * Here's something you've all been waiting for:  the AT&T public domain
X * source for getopt(3).  It is the code which was given out at the 1985
X * UNIFORUM conference in Dallas.  I obtained it by electronic mail
X * directly from AT&T.  The people there assure me that it is indeed
X * in the public domain.
X *
X * There is no manual page.  That is because the one they gave out at
X * UNIFORUM was slightly different from the current System V Release 2
X * manual page.  The difference apparently involved a note about the
X * famous rules 5 and 6, recommending using white space between an option
X * and its first argument, and not grouping options that have arguments.
X * Getopt itself is currently lenient about both of these things White
X * space is allowed, but not mandatory, and the last option in a group can
X * have an argument.  That particular version of the man page evidently
X * has no official existence, and my source at AT&T did not send a copy.
X * The current SVR2 man page reflects the actual behavor of this getopt.
X * However, I am not about to post a copy of anything licensed by AT&T.
X */
X
X/*
XMinor modifications by Rahul Dhesi 1989/03/06
X*/
X
X#include "brik.h"
X
X#ifdef ANSIPROTO
Xint strcmp (char *, char *);
Xchar *strchr (char *, char);
X#endif
X
X#include <stdio.h>
X
X/* Avoid possible compiler warning if we simply redefine NULL or EOF */
X#define XNULL   0
X#define XEOF (-1)
X
X#define ERR(szz,czz) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);}
X
Xextern int strcmp();
Xextern char *strchr();
X
Xint   opterr = 1;
Xint   optind = 1;
Xint   optopt;
Xchar  *optarg;
X
Xint
Xgetopt(argc, argv, opts)
Xint   argc;
Xchar  **argv, *opts;
X{
X   static int sp = 1;
X   register int c;
X   register char *cp;
X
X   if(sp == 1)
X      if(optind >= argc ||
X         argv[optind][0] != '-' || argv[optind][1] == '\0')
X         return(XEOF);
X      else if(strcmp(argv[optind], "--") == XNULL) {
X         optind++;
X         return(XEOF);
X      }
X   optopt = c = argv[optind][sp];
X   if(c == ':' || (cp=strchr(opts, c)) == XNULL) {
X      ERR(": illegal option -- ", c);
X      if(argv[optind][++sp] == '\0') {
X         optind++;
X         sp = 1;
X      }
X      return('?');
X   }
X   if(*++cp == ':') {
X      if(argv[optind][sp+1] != '\0')
X         optarg = &argv[optind++][sp+1];
X      else if(++optind >= argc) {
X         ERR(": option requires an argument -- ", c);
X         sp = 1;
X         return('?');
X      } else
X         optarg = argv[optind++];
X      sp = 1;
X   } else {
X      if(argv[optind][++sp] == '\0') {
X         sp = 1;
X         optind++;
X      }
X      optarg = XNULL;
X   }
X   return(c);
X}
SHAR_EOF
# ============= makebrik.com ==============
echo "x - extracting makebrik.com (Text)"
sed 's/^X//' << 'SHAR_EOF' > makebrik.com &&
X$! This command file compiles brik for VAX/VMS and also defines a
X$! symbol so you can type "brik" to execute the program.
X$!
X$! ::[[ @(#) makebrik.com 1.1 89/03/09 15:25:56 ]]::
X$!
X$ cc /define=VMS addbfcrc
X$ cc /define=VMS brik.c
X$ cc /define=VMS vms.c
X$ cc /define=VMS getopt.c
X$ link/executable=brik.exe  brik,addbfcrc,vms,getopt, options/opt
X$ brik:==$'f$trnlnm("sys$disk")''f$directory()'brik.exe
SHAR_EOF
# ============= makefile ==============
echo "x - extracting makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > makefile &&
X# Makefile for brik
X# ::[[ @(#) makefile 1.7 89/03/09 02:47:07 ]]::
X
X# Please see brik.h for configuration options.
X
X# "make brik"     -- makes brik in current directory
X# "make install"  -- makes brik, then moves it into DESTDIR defined below
X# "make clean"    -- deletes object files and executable brik from current dir
X
X# Directory where we want to move executable brik on "make install"
XDESTDIR=/usr/local/bin/.
X
X# CFLAGS are flags for the C compiler.  LDFLAGS are flags for the loader.
X# They are defined by the mk* scripts, so they need not be changed here.
X
XCFLAGS=
XLDFLAGS=
X
XCC=cc
X
X.c.o :
X	$(CC) -c $(CFLAGS) $*.c
X
XOBJS = brik.o addbfcrc.o
X
Xbrik: $(OBJS)
X	cc $(LDFLAGS) -o brik $(OBJS)
X
Xbrik.o: brik.c brik.h assert.h
X
Xaddbfcrc.o: addbfcrc.c
X
Xinstall: brik
X	mv brik $(DESTDIR)/brik
X
Xclean:
X	/bin/rm -f $(OBJS) core brik
SHAR_EOF
# ============= mkbsd ==============
echo "x - extracting mkbsd (Text)"
sed 's/^X//' << 'SHAR_EOF' > mkbsd &&
X# ::[[ @(#) mkbsd 1.1 89/03/09 02:41:21 ]]::
X# For 4.xBSD
Xmake "CFLAGS=-DBSD -O" brik
SHAR_EOF
# ============= mksysv ==============
echo "x - extracting mksysv (Text)"
sed 's/^X//' << 'SHAR_EOF' > mksysv &&
X# ::[[ @(#) mksysv 1.1 89/03/09 02:41:22 ]]::
X# For System V.  (See "mkuport" for Microport System V/AT.) 
Xmake "CFLAGS=-DSYS_V -O" brik
SHAR_EOF
# ============= mkuport ==============
echo "x - extracting mkuport (Text)"
sed 's/^X//' << 'SHAR_EOF' > mkuport &&
X# ::[[ @(#) mkuport 1.1 89/03/09 02:41:23 ]]::
X# For Microport System V/AT.
Xmake "CFLAGS=-Ml -DSYS_V -O" "LDFLAGS=-Ml" install
SHAR_EOF
# ============= options.opt ==============
echo "x - extracting options.opt (Text)"
sed 's/^X//' << 'SHAR_EOF' > options.opt &&
Xsys$share:vaxcrtl.exe/share
SHAR_EOF
# ============= turboc.c ==============
echo "x - extracting turboc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > turboc.c &&
X/* nextfile.c */
X/* ::[[ @(#) turboc.c 1.4 89/03/10 19:10:15 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) turboc.c 1.4 89/03/10 19:10:15 ]]::";
X#endif
X
X/*
XThis file is used only for MS-DOS & Turbo C.
X*/
X
X/*
XChecksum: 2196257943      (check or update this with "brik")
X*/
X
X/*
Xnextfile() is a general wildcard expansion function that may be used
Xwith other programs.  Usage instructions are below.  It does not
Xsimply expand wildcards in an entire argument list.  Instead, it is
Xcalled in a loop as described below, and returns one matching
Xfilename each time it is called.
X
XThese functions are for the SMALL MEMORY MODEL ONLY.
X*/
X
X#include "assert.h"
X#include "brik.h"
X
X#define  FMAX  2        /* Number of different filename patterns */
X#define  PATHSIZE 200   /* Size of MS-DOS pathname */
X#define  NULL  0
X
X#ifdef ANSIPROTO
Xchar *strtcpy (char *, char *);
Xint strlen (char *);
Xchar *strcpy (char *, char *);
X#endif
X
X
X/* Structure definitions for MS-DOS software interrupt intdos() */
X
Xstruct WORD_REGISTERS {
X   unsigned int ax, bx, cx, dx, si, di, carry, flags;
X};
X
X/* byte registers */
X
Xstruct BYTE_REGISTERS {
X   unsigned char al, ah, bl, bh, cl, ch, dl, dh;
X};
X
Xunion REGS {
X   struct WORD_REGISTERS x;
X   struct BYTE_REGISTERS h;
X};
X
Xint intdos (union REGS *, union REGS *);
X
X/*
Xformat of disk transfer address after MS-DOS calls FindFirst and
XFindNext
X*/
Xstruct dta_t {
X   char junk[22];
X   int time;
X   int date;
X   long size;
X   char fname[13];
X   char just_in_case[4];   /* in case MS-DOS writes too much */
X};
X
Xvoid setdta (struct dta_t *);
Xvoid fcbpath (struct dta_t *, char *, char *);
X
X/*******************/
X/*
Xnextfile() returns the name of the next source file matching a filespec.
X
XINPUT
X   what: A flag specifying what to do.  If "what" is 0, nextfile()
X      initializes itself.  If "what" is 1, nextfile() returns the next
X      matching filename.
X   filespec:  The filespec, usually containing wildcard characters, that
X      specifies which files are needed.  If "what" is 0, filespec must be
X      the filespec for which matching filenames are needed.  If "what" is 1,
X      nextfile() does not use "filespec" and "filespec" should be NULL to
X      avoid an assertion error during debugging.
X   fileset:  nextfile() can keep track of more than one set of filespecs.
X      The fileset specifies which filespec is being matched and therefore
X      which set of files is being considered.  "fileset" can be in the
X      range 0:FMAX.  Initialization of one fileset does not affect the
X      other filesets.
X
XOUTPUT
X   IF what == 0 THEN
X      return value is NULL
X   ELSE IF what == 1 THEN
X      IF a matching filename is found THEN
X         return value is pointer to matching filename including supplied path
X      ELSE
X         IF at least one file matched previously but no more match THEN
X            return value is NULL
X         ELSE IF supplied filespec never matched any filename THEN
X            IF this is the first call with what == 1 THEN
X               return value is pointer to original filespec
X            ELSE
X               return value is NULL
X            END IF
X         END IF
X      END IF
X   END IF
X
XNOTE
X
X   Initialization done when "what"=0 is not dependent on the correctness
X   of the supplied filespec but simply initializes internal variables
X   and makes a local copy of the supplied filespec.  If the supplied
X   filespec was illegal, the only effect is that the first time that
X   nextfile() is called with "what"=1, it will return the original
X   filespec instead of a matching filename.  That the filespec was
X   illegal will become obvious when the caller attempts to open the
X   returned filename for input/output and the open attempt fails.
X
XUSAGE HINTS
X
Xnextfile() can be used in the following manner:
X
X      char *filespec;                  -- will point to filespec
X      char *this_file;                 -- will point to matching filename
X      filespec = parse_command_line(); -- may contain wildcards
X      FILE *stream;
X
X      nextfile (0, filespec, 0);          -- initialize fileset 0
X      while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
X         stream = fopen (this_file, "whatever");
X         if (stream == NULL)
X            printf ("could not open %s\n", this_file);
X         else
X            perform_operations (stream);
X      }
X*/
X
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
X   static int first_time [FMAX+1];
X   static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
X   static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
X   union REGS regs;
X
X   assert(fileset >= 0 && fileset <= FMAX);
X   if (what == 0) {
X      assert(filespec != NULL);
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return ((char *) NULL);
X   }
X
X   setdta (&new_dta[fileset]);   /* set new dta -- our very own */
X   assert(what == 1);
X   assert(filespec == NULL);
X   assert(first_time[fileset] == 0 || first_time[fileset] == 1);
X
X   if (first_time[fileset]) {             /* first time -- initialize etc. */
X      /* find first matching file */
X      regs.h.ah = 0x4e;                   /* FindFirst MS-DOS call    */
X      regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
X      regs.x.cx = 0;                      /* search attributes       */
X      intdos (&regs, &regs);
X   } else {
X      /* find next matching file */
X      regs.h.ah = 0x4f;                   /* FindNext MS-DOS call     */
X      intdos (&regs, &regs);
X   }
X
X   if (regs.x.carry != 0) {            /* if error status                  */
X      if (first_time[fileset]) {       /*   if file never matched then     */
X         first_time[fileset] = 0;
X         return (saved_fspec[fileset]);/*      return original filespec    */
X      } else {                         /*   else                           */
X         first_time[fileset] = 0;      /*                                  */
X         return ((char *) NULL);         /*      return (NULL) for no more   */
X      }
X   } else {                                        /* a file matched */
X      first_time[fileset] = 0;
X      /* add path info  */
X      fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]);
X      return (pathholder[fileset]);                /* matching path  */
X   }
X} /* nextfile */
X
X/*******************/
X/* This function sets the dta to a new dta */
Xvoid setdta (dta)
Xstruct dta_t *dta;
X{
X   union REGS regs;
X   regs.h.ah = 0x1a;                /* SetDTA Call       */
X   regs.x.dx = (unsigned int) dta;  /* new DTA address   */
X   intdos (&regs, &regs);
X}
X
X/*******************/
X/*
Xfcbpath() accepts a pointer to the Disk Transfer Area, a character
Xpointer to a pathname that may contain wildcards, and a character
Xpointer to a buffer.  It copies into the buffer the path prefix from
Xthe pathname and the filename prefix from the DTA so that it forms a
Xcomplete path.
X*/
X
Xvoid fcbpath (dta, old_path, new_path)
Xstruct dta_t *dta;
Xchar *old_path;
Xregister char *new_path;
X{
X   register int i;
X   int length, start_pos;
X
X   strcpy(new_path, old_path);               /* copy the whole thing first */
X   length = strlen(new_path);
X   i = length - 1;                           /* i points to end of path */
X   while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
X      i--;
X   /* either we found a "/", "\", or ":", or we reached the beginning of
X      the name.  In any case, i points to the last character of the
X      path part. */
X   start_pos = i + 1;
X   for (i = 0; i < 13; i++)
X      new_path[start_pos+i] = dta->fname[i];
X   new_path[start_pos+13] = '\0';
X}
X/* -- END OF nextfile() and related functions -- */
X
Xextern unsigned _stklen = 10000;
X
X#include <conio.h>
Xbrktst() { kbhit(); }      /* test for user interrupt */
SHAR_EOF
# ============= vms.c ==============
echo "x - extracting vms.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > vms.c &&
X/*
X**   A wildcard expansion function for VAX/VMS
X**   -- Rahul Dhesi
X*/
X/* ::[[ @(#) vms.c 1.5 89/03/10 19:09:28 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) vms.c 1.5 89/03/10 19:09:28 ]]::";
X#endif
X
X/*
XChecksum: 3221488897     (verify or update with "brik")
X*/
X
X#include <descrip.h>
X
X#define  FMAX  3        /* Number of different filename patterns */
X#define  PATHSIZE 1024  /* buffer area to store pathname */
X
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   int status;
X   char *p;                      /* temp ptr */
X   struct dsc$descriptor_s d_fwild, d_ffound;
X   static int first_time [FMAX+1];
X   static char saved_fspec [FMAX+1][PATHSIZE];  /* our own copy of filespec */
X   static char found_fspec [FMAX+1][PATHSIZE];  /* matched filename */
X   static unsigned long context [FMAX+1]; /* needed by VMS */
X   if (what == 0) {
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return (0);
X   }
X
X   /* Reach here if what is not 0, so it must be 1 */
X
X   /* Create a descriptor for the wildcarded filespec */
X   d_fwild.dsc$w_length = strlen (saved_fspec[fileset]);
X   d_fwild.dsc$a_pointer = saved_fspec[fileset];
X   d_fwild.dsc$b_class = DSC$K_CLASS_S;
X   d_fwild.dsc$b_dtype = DSC$K_DTYPE_T;
X
X   d_ffound.dsc$w_length = sizeof (found_fspec[fileset]);
X   d_ffound.dsc$a_pointer = found_fspec[fileset];
X   d_ffound.dsc$b_class = DSC$K_CLASS_S;
X   d_ffound.dsc$b_dtype = DSC$K_DTYPE_T;
X
X   if (first_time[fileset]) {
X      first_time[fileset] = 0;
X      context[fileset] = 0L;   /* tell VMS this is first search */
X   }
X   status = LIB$FIND_FILE (&d_fwild, &d_ffound, &context[fileset]);
X   status = status & 1; /* use only lowest bit */
X
X   if (status == 0) {
X      LIB$FIND_FILE_END (&context[fileset]);
X      return ((char *) 0);
X   } else {
X      found_fspec[fileset][d_ffound.dsc$w_length] = '\0'; /* just in case */
X      p = found_fspec[fileset];
X      while (*p != ' ' && *p != '\0')
X         p++;
X      if (*p != '\0')
X         *p = '\0';
X      return (found_fspec[fileset]);
X   }
X}
X
X/* Compensate for bug in VAX/VMS C exit() function */
X
X#ifdef exit
X# undef exit
X#endif
X
Xint bugexit (n)
Xint n;
X{
X   exit (1);
X}
SHAR_EOF
exit 0