[comp.binaries.ibm.pc] v03i003: booz, a barebones zoo archive extractor

dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (05/27/89)

Checksum:   90299107  (Verify with "brik -cv")
Posting-number: Volume 03, Issue 003
Originally-from: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
Archive-name: booz/booz.shar

#! /bin/sh
# Future postings in this newsgroup will be mostly in zoo archive
# format.  Here is a small, relatively portable zoo archive extractor.
# It is written in portable C though it requires read(), write(), and
# lseek() system calls or their emulations to be available.  I will
# also be posting the MS-DOS zoo 2.01 executable.
#
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	addbfcrc.c
#	booz.c
#	booz.doc
#	booz.prj
#	func.h
#	lzd.c
#	makefile.msc
#	makefile.nix
#	oozext.c
#	oozio.h
#	options.h
#	portable.c
#	zoo.h
# This archive created: Fri Aug 26 02:41:13 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'addbfcrc.c'" '(2921 characters)'
if test -f 'addbfcrc.c'
then
	echo shar: "will not over-write existing file 'addbfcrc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'addbfcrc.c'
X/* adbfcrc.c */
X
X/*
Xaddbfcrc() accepts a buffer address and a count and adds the CRC for
Xall bytes in the buffer to the global variable crccode using
XCRC-16.
X
XCRC computation algorithm taken from source code for ARC 5.12, which
Xin turn took it from an article by David Schwaderer in the April 1985
Xissue of PC Tech Journal.
X
XI claim no copyright over the contents of this file.
X
X                                    -- Rahul Dhesi 1986/12/31
X*/
X
Xunsigned int crccode;
Xunsigned int crctab[] = {
X   0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 
X   0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 
X   0x0d80, 0xcd41, 0x0F00, 0xcFc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 
X   0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 
X   0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdF81, 0x1F40, 0xdd01, 
X   0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 
X   0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 
X   0x1040, 0xF001, 0x30c0, 0x3180, 0xF141, 0x3300, 0xF3c1, 0xF281, 0x3240, 
X   0x3600, 0xF6c1, 0xF781, 0x3740, 0xF501, 0x35c0, 0x3480, 0xF441, 0x3c00, 
X   0xFcc1, 0xFd81, 0x3d40, 0xFF01, 0x3Fc0, 0x3e80, 0xFe41, 0xFa01, 0x3ac0, 
X   0x3b80, 0xFb41, 0x3900, 0xF9c1, 0xF881, 0x3840, 0x2800, 0xe8c1, 0xe981, 
X   0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2F80, 0xeF41, 
X   0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 
X   0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 
X   0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 
X   0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 
X   0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaF01, 0x6Fc0, 0x6e80, 0xae41, 0xaa01, 
X   0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 
X   0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7F80, 
X   0xbF41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 
X   0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 
X   0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 
X   0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 
X   0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5F00, 0x9Fc1, 0x9e81, 0x5e40, 
X   0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 
X   0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 
X   0x8F81, 0x4F40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 
X   0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 
X   0x4100, 0x81c1, 0x8081, 0x4040 
X};
X
Xint addbfcrc(buffer,count)
Xchar *buffer;
Xint count;
X
X{
X   register unsigned int localcrc;
X   register int i;
X   localcrc = crccode;
X
X   for (i=0; i<count; i++)
X      localcrc = (localcrc>>8) ^ crctab[(localcrc ^ (buffer[i])) & 0x00ff];
X   crccode = localcrc;
X}
SHAR_EOF
if test 2921 -ne "`wc -c < 'addbfcrc.c'`"
then
	echo shar: "error transmitting 'addbfcrc.c'" '(should have been 2921 characters)'
fi
fi
echo shar: "extracting 'booz.c'" '(8123 characters)'
if test -f 'booz.c'
then
	echo shar: "will not over-write existing file 'booz.c'"
else
sed 's/^X//' << \SHAR_EOF > 'booz.c'
X#define  VERSION  "Version 1.02 (1988/08/25)\n"
X
X/* booz.c -- small, memory-efficient Barebones Ooz to extract Zoo archives.
X
XFor maximum portability, Booz does not use the data type `unsigned long'.
X
XThe functions and system calls required by Tiny Booz are:
X   read()
X   write()
X   strlen()
X   exit()
X   malloc()
X   lseek()
X   open() and/or creat()
X   close()
X   unlink()                -- may be defined to be an empty function
X
X
XSmall Booz additionally uses the following functions:
X   strcat()
X   strcpy()
X
XBig Booz additionally use the following function:
X   strncat()
X*/
X
X/* 
XThe contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1988/08/25
X*/
X
X#include "options.h"
X#include "func.h"
X#include "zoo.h"
X
Xmain(argc,argv)
Xregister int argc;
Xregister char **argv;
X{
X#ifdef TINY
X   static char usage[]=
X      "Usage:  booz archive.zoo\n";
X   if (argc < 2) {
X      putstr ("Public domain Barebones Ooz\nZoo archive extractor (Tiny) by Rahul Dhesi\n");
X      putstr (VERSION);
X      putstr (usage);
X      exit (1);
X   }
X#endif
X
X#ifdef SMALL
X   static char usage[]=
X      "Usage:  booz archive[.zoo] [ file ... ]\n";
X   if (argc < 2) {
X      putstr ("Public domain Barebones Ooz\nZoo archive extractor (Small) by Rahul Dhesi\n");
X      putstr (VERSION);
X      putstr (usage);
X      exit (1);
X   }
X#endif
X
X#ifdef BIG
X   static char usage[]=
X      "Usage:  booz {lxt} archive[.zoo] [ file ... ]\n";
X   if (argc < 3) {
X      putstr ("Public domain Barebones Ooz\nZoo archive extractor/lister (Big) by Rahul Dhesi\n");
X      putstr (VERSION);
X      putstr (usage);
X      putstr ("l = list, x = extract, t = test\n");
X      exit (1);
X   }
X#endif
X
X#ifdef TINY
X   oozext (argv[1]);
X#endif
X
X#ifdef SMALL
X   oozext (argv[1], argc - 2, &argv[2]);
X#endif
X
X#ifdef BIG
X   {
X      char *p;
X      p = argv[1];
X      if (*p == 'L')
X         *p = 'l';
X      if (*p == 'X')
X         *p = 'x';
X      if (*p == 'T')
X         *p = 't';
X      if (*p != 'l' && *p != 'x' && *p != 't') {
X         putstr (usage);
X         exit (1);
X      }
X      oozext (argv[2], p, argc - 3, &argv[3]);
X   }
X#endif
X
X   exit (0);
X}
X
X/**********************/
X/* putstr()
XThis function prints a string to the standard output handle without
Xusing printf() or the standard I/O library.  If a null string, nothing 
Xis printed (not even the null character).
X*/
Xint putstr (str)
Xregister char *str;
X{
X   if (str != (char *) 0)
X      write (1, str, strlen(str));
X}
X
X/**********************/
X/* prterror()
XPrints an error message.  The first character controls the severity
Xof the error and the result.
X
X   'm'   informative message
X   'w'   warning     -- execution continues
X   'e'   error       -- execution continues
X   'f'   fatal error -- program exits
X*/
X
Xint prterror (level, a, b, c)
Xint level;
Xchar *a, *b, *c;
X
X{
X
X#ifdef DEBUG
X   {
X      char tmp[2];
X      tmp[0] = level & 0x7f;
X      tmp[1] = '\0';
X      putstr ("prterror:  level = ");
X      putstr (tmp);
X      putstr ("\n");
X   }
X#endif
X
X   switch (level & 0x7f) {
X      case 'm': break;
X      case 'w': putstr ("WARNING:  "); break;
X      case 'e': putstr ("ERROR:  "); break;
X      case 'f': putstr ("FATAL:  "); break;
X      default: prterror ('f', "Internal error\n", ((char *) 0), ((char *) 0));
X   }
X   putstr (a);
X   putstr (b);
X   putstr (c);
X
X   if (level == 'f')       /* and abort on fatal error 'f' but not 'F' */
X      exit (1);
X}
X
X/*************
XThis function copies count characters from the source file to the
Xdestination Function return value is 0 if no error, 2 if write error,
Xand 3 if read error.  
X
XThe global variable crccode is updated.
X*/
Xextern char out_buf_adr[];
X
Xint getfile(input_han, output_han, count)
Xint input_han, output_han;
Xlong count;
X{
X   register int how_much;
X
X   while (count > 0) {
X      if (count > OUT_BUF_SIZE)
X         how_much = OUT_BUF_SIZE;
X      else
X         how_much = count;
X      count -= how_much;
X      if (read (input_han, out_buf_adr, how_much) != how_much)
X         return (3);
X      addbfcrc (out_buf_adr, how_much);
X      if (output_han != -2 &&
X            write (output_han, out_buf_adr, how_much) != how_much)
X         return (2);
X   }
X   return (0);
X}
X
X#ifndef TINY
X
Xint needed (fname, argc, argv)
Xchar *fname;
Xint argc;
Xchar *argv[];
X{
X   register int i;
X   if (argc == 0)
X      return (1);
X   for (i = 0; i < argc; i++) {
X      if (match (fname, argv[i]))
X         return (1);
X   }
X   return (0);
X}
X
X/***********************/
X/*
Xmatch() compares a pattern with a string.  Wildcards accepted in
Xthe pattern are:  "*" for zero or more arbitrary characters;  "?"
Xfor any one characters.  Unlike the MS-DOS wildcard match, "*" is
Xcorrectly handled even if it isn't at the end of the pattern. ".'
Xis not special.
X
XOriginally written by Jeff Damens of Columbia University Center for
XComputing Activities.  Taken from the source code for C-Kermit version
X4C.
X*/
X
Xint match (string, pattern) 
Xregister char *string, *pattern;
X{
X   char *psave,*ssave;        /* back up pointers for failure */
X   psave = ssave = ((char *) 0);
X   while (1) {
X      for (; *pattern == *string; pattern++,string++)  /* skip first */
X         if (*string == '\0') 
X            return(1);                          /* end of strings, succeed */
X      if (*string != '\0' && *pattern == '?') {
X         pattern++;                             /* '?', let it match */
X         string++;
X      } else if (*pattern == '*') {             /* '*' ... */
X         psave = ++pattern;                     /* remember where we saw it */
X         ssave = string;                        /* let it match 0 chars */
X      } else if (ssave != ((char *) 0) && *ssave != '\0') {   /* if not at end  */
X         /* ...have seen a star */
X         string = ++ssave;                      /* skip 1 char from string */
X         pattern = psave;                       /* and back up pattern */
X      } else 
X         return(0);                             /* otherwise just fail */
X   }
X}
X
X#endif /* ndef TINY */
X
Xint memerr()
X{
X   prterror ('f', "Ran out of memory\n");
X}
X
X#ifdef BIG
X/* cfactor() calculates the compression factor given a directory entry */
Xint cfactor (org_size, size_now)
Xlong org_size, size_now;
X{
X   register int size_factor;
X
X   while (org_size > 10000) { /* avoid overflow below */
X      org_size = org_size >> 4;
X      size_now = size_now >> 4;
X   }
X   if (org_size == 0)         /* avoid division by zero */
X      size_factor = 0;
X   else {
X      size_factor = 
X         (
X            (1000 * 
X               (org_size - size_now)
X            ) / org_size + 5
X         ) / 10;
X   }
X   return (size_factor);
X}
X
X/******
XFunction itoa() converts a positive long integer into a text string of
Xdigits.  The buffer pointer buf must point to a buffer to receive the
Xdigit string.  The digit string is stored right justified in the
Xbuffer with leading blanks.  If the supplied number is negative, or if
Xoverflow occurs, a single '*' is returned.
X*/
X
Xchar *itoa (pad_ch, n, buf, buflen)
Xchar pad_ch;                  /* leading pad character */
Xlong n;                       /* positive long int to convert */
Xchar *buf;                    /* buffer to receive digit string */
Xint buflen;                   /* length of buffer */
X{
X   char *p;
X   int i;
X   for (i = 0;  i < buflen;  i++)         /* fill buffer with pad char */
X      buf[i] = pad_ch;
X   p = buf + buflen - 1;
X   *p-- = '\0';                           /* ensure null termination */
X   i = buflen - 1;
X   for (;;) {
X      if (n < 0) {                        /* can't handle negative n */
X         goto overflow;
X      } else {
X         *p-- = (int) (n % 10) + '0';     /* store a converted digit */
X         n = n / 10;
X         i--;
X         if (n == 0 || i == 0)
X            break;
X      } /* end of else of if (n < 0) */
X   } /* end while (buflen > 0) */
X   if (n != 0)                            /* buffer overflow */
X      goto overflow;
X   return (buf);
X
Xoverflow:                                 /* bad value filled with stars */
X   for (i = 0; i < buflen; i++)
X      buf[i] = '*';
X   buf[buflen-1] = '\0';
X   return (buf);
X}
X
X#endif /* BIG */
SHAR_EOF
if test 8123 -ne "`wc -c < 'booz.c'`"
then
	echo shar: "error transmitting 'booz.c'" '(should have been 8123 characters)'
fi
fi
echo shar: "extracting 'booz.doc'" '(6645 characters)'
if test -f 'booz.doc'
then
	echo shar: "will not over-write existing file 'booz.doc'"
else
sed 's/^X//' << \SHAR_EOF > 'booz.doc'
X                      Booz 1.02 -- Barebones Ooz
X                                  a
X                         Zoo Extractor/Lister
X                                  by
X                             Rahul Dhesi
X
XBooz 1.02 is a small, memory-efficient Zoo archive extractor/lister. 
XIt is not fancy.  It does not recognize the advanced features
Xavailable in current versions of Zoo, such as long filenames,
Xdirectory names, comments, and multiple file generations.  Extraction
Xalways uses a short MS-DOS format filename and all extracted files go
Xinto the current directory.
X
XBut Booz 1.02 is simple and portable and can be implemented in about
Xfifteen minutes on any system with a reasonably good C compiler that
Xprovides **IX-compatible read(), write(), and lseek() functions.
XAnd Booz 1.02 can extract and list all archives created by all
Xcurrently-existing versions of Zoo.
X
XAt compilation time, conditional compilation selects one of three
Xlevels of sophistication for Booz 1.02.  The three options are as
Xfollows.
X
XThe Tiny option:  Booz compiled with the Tiny option is very frugal
Xand should compile and run under CP/M and other systems with limited
Xmemory.  Tiny Booz always extracts an entire archive at a time and
Xdoes not attempt to prevent an exctracted file from overwriting
Xanother.  Tiny Booz requires you to type the entire filename of the
Xarchive being extracted, including the ".zoo" extension.
X
XThe Small option:  Booz compiled with the Small option is a little
Xmore sophisticated than Tiny Booz.  Small Booz assumes the default
Xextension ".zoo" for an archive if it is not specified.  It will let
Xyou specify which files should be extracted from an archive.  Small
XBooz accepts these wildcard symbols in the names of files to be
Xextracted:  "?" stands for any one character and "*" stands for any
Xsequence of zero or more characters.  Combinations of these are
Xpermitted so, for example, "*c?t*h" matches filenames ending with "h"
Xand containing "c" and "t" separated by one character.  Small Booz is
Xnearly as memory-efficient as Tiny Booz and it very likely that it
Xwill compile and run under CP/M.
X
XThe Big option:  Booz compiled with the Big option does everything
Xthat Small Booz does and in addition it can give the directory
Xlisting of a Zoo archive or test its integrity.  Despite its name,
XBig Booz is still quite frugal.  Under MS-DOS, when compiled with
Xthe Microsoft C compiler version 3.00, it runs in about 50 kilobytes
Xof free memory and occupies about 9.5 kilobytes on disk.
X
X
X                         COMPILING BOOZ 1.02
X
X1.
XMake sure that the two macros OPEN and CREATE are correctly defined
Xfor your system in file `oozio.h'.  Some sample macros are provided. 
XThe macros must be defined to open files in binary mode (i.e.,
Xwithout newline conversions).
X
XThe macro OPEN is supplied a filename and it must open the file for
Xreading and return an open file descriptor, or -1 if the open fails. 
XIt is used to open the archive being extracted or listed, and to test
Xthe existence of a file about to be extracted.
X
XThe macro CREATE is supplied a filename and it must create a new file
Xfor writing and return an open file descriptor, or -1 if the create
Xfails.  It is used for creating each file that is extracted.
X
X2.
XIf your C library does not provide the unlink() function (which
Xdeletes a file given its name), define an empty function by that
Xname, or define a suitable (possibly empty) macro by that name in
Xfile `oozio.h'.
X
X3.
XDecide which of the three options, Tiny, Small, or Big, you will use.
XIf memory is tight use the Tiny option first to get a Zoo extractor
Xquickly running on your system.  Then experiment with the other
Xoptions.  If memory is not tight, use the Big option.  Define any one
Xof the symbols TINY, SMALL, or BIG in the file `options.h' (or
Xalternatively define it on the command line that invokes your C
Xcompiler).  Exactly one of these three symbols must be defined.
X
X4.
XChoose appropriate sizes for the input/output buffers and for the
Xsize of the decompression stack in file `options.h'.  If memory
Xpermits, make the buffers 8192 each.   (Bigger sizes, perhaps up to
X16384, could be used but they have not been tested and could
Xconceivably cause overflow in certain bit-shift operations in file
X`lzd.c').  A reasonable stack size is 2000, but in pathological cases
Xextraction of a file could require a larger stack.
X
XIf memory is tight, decrease the input/output buffers to 1024 each
Xeach and the stack to 1000.
X
X5.
XCompile and link all the C files.  Two makefiles are supplied, one
Xsuitable for **IX systems and the other for Microsoft C 3.0 under
XMS-DOS.  Modify these as necessary for your system.  Also supplied is
Xa project file booz.prj for use with Turbo C 1.0 on MS-DOS.
X
X
X                          MACHINE DEPENDENCE
X
XBooz is relatively independent of machine architecture, except that
X(a) the machine must be a 2's complement machine (all modern machines
Xare) and (b) `char' must be exactly 8 bits, `int' must be 16 bits or
Xlarger, and `long' must be 32 bits or larger (though a `long' of a
Xlittle less than 32 bits may work).
X
XBooz makes no assumptions about the filename syntax of the host
Xmachine, except that Small and Big Booz assume that dot "." is used to
Xseparate the extension "zoo" from the rest of the name of the
Xarchive.  They will append ".zoo" to the archive name if it contains
Xno dot;  this fails if an archive name of the type "../junk" is
Xspecified.  
X
XIf your system uses a different filename syntax, you may need to
Xchange the code.  Also, if your system cannot accept some of the
Xcharacters legal in MS-DOS filenames, you may need to add a function
Xthat will fix the filename before extraction.  A sample function
X`fixfname()' is included in the file `oozext.c'.  It becomes activated
Xonly if the preprocessor symbol FIXFNAME is defined.
X
X				 NOTE
X
XThis program does not attempt to be case-insensitive.  Therefore you
Xwill need to type names of files to be extracted in the correct
Xcase.  Note, however, that some operating systems (possibly CP/M) may
Xfold command line arguments to uppercase.  If this happens, your
Xbest bet is to extract all files from an archive instead of
Xspecifying specific names.
X
X			   REVISION HISTORY
X
XVersion 1.00
X     Corresponded to just the Tiny booz 1.02
X
XVersion 1.01
X     Included TINY, SMALL, BIG compilation options.  Had a bug in
X     function needed() that sometimes cause file extraction to fail.
X
XVersion 1.02
X     Fixed bug in function needed().  Added support for Turbo C 1.0.
X     Revised this documentation and some comments in the source code.
X
X                                -- Rahul Dhesi 1988/08/25
SHAR_EOF
if test 6645 -ne "`wc -c < 'booz.doc'`"
then
	echo shar: "error transmitting 'booz.doc'" '(should have been 6645 characters)'
fi
fi
echo shar: "extracting 'booz.prj'" '(138 characters)'
if test -f 'booz.prj'
then
	echo shar: "will not over-write existing file 'booz.prj'"
else
sed 's/^X//' << \SHAR_EOF > 'booz.prj'
Xbooz.c		(options.h zoo.h func.h)
Xaddbfcrc.c
Xlzd.c		(options.h func.h)
Xoozext.c	(options.h zoo.h oozio.h func.h)
Xportable.c	(func.h zoo.h)
SHAR_EOF
if test 138 -ne "`wc -c < 'booz.prj'`"
then
	echo shar: "error transmitting 'booz.prj'" '(should have been 138 characters)'
fi
fi
echo shar: "extracting 'func.h'" '(505 characters)'
if test -f 'func.h'
then
	echo shar: "will not over-write existing file 'func.h'"
else
sed 's/^X//' << \SHAR_EOF > 'func.h'
X/* 
XThe contents of this file are hereby released to the public domain.
X                                   -- Rahul Dhesi 1987/02/08
X*/
X
X/* Functions defined by Booz */
X
Xint getfile ();
Xint lzd ();
Xint readdir ();
Xint rd_zooh ();
Xint rd_dir ();
Xint addbfcrc();
Xint prterror();
Xint oozext ();
Xint putstr ();
Xchar *itoa ();
Xint fixfname ();
X
X/* Standard functions */
X
Xchar *malloc ();
Xint close ();
Xint creat ();
Xint open ();
Xint read ();
Xint unlink ();
Xint write ();
Xlong lseek ();
Xunsigned int strlen ();
SHAR_EOF
if test 505 -ne "`wc -c < 'func.h'`"
then
	echo shar: "error transmitting 'func.h'" '(should have been 505 characters)'
fi
fi
echo shar: "extracting 'lzd.c'" '(5823 characters)'
if test -f 'lzd.c'
then
	echo shar: "will not over-write existing file 'lzd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lzd.c'
X/*
XLempel-Ziv decompression.  Mostly based on Tom Pfau's assembly language
Xcode.  The contents of this file are hereby released to the public domain.
X                                 -- Rahul Dhesi 1986/11/14, 1987/02/08
X*/
X
X#include "func.h"
X#include "options.h"
X
X#define  INBUFSIZ    (IN_BUF_SIZE - SPARE)
X#define  OUTBUFSIZ   (OUT_BUF_SIZE - SPARE)
X#define  MEMERR      2
X#define  IOERR       1
X#define  MAXBITS     13
X#define  CLEAR       256         /* clear code */
X#define  Z_EOF       257         /* end of file marker */
X#define  FIRST_FREE  258         /* first free code */
X#define  MAXMAX      8192        /* max code + 1 */
X
X#define  SPARE       5
X
Xstruct tabentry {
X   unsigned next;
X   char z_ch;
X};
X
Xstruct tabentry *table;
Xint   gotmem = 0;
X
Xint init_dtab();
Xunsigned rd_dcode();
Xint wr_dchar();
Xint ad_dcode();
X
Xunsigned lzd_sp = 0;
Xunsigned lzd_stack[STACKSIZE + SPARE];
X
Xint push(ch)
Xint ch;
X{
X   lzd_stack[lzd_sp++] = ch;
X   if (lzd_sp >= STACKSIZE)
X      prterror ('f', "Stack overflow in lzd()\n", (char *) 0, (char *) 0);
X}
X   
X#define  pop()    (lzd_stack[--lzd_sp])
X
Xchar out_buf_adr[IN_BUF_SIZE + SPARE];
Xchar in_buf_adr[OUT_BUF_SIZE + SPARE];
X
Xchar memflag = 0;                /* memory allocated? flag */
X
Xunsigned cur_code;
Xunsigned old_code;
Xunsigned in_code;
X
Xunsigned free_code;
Xint nbits;
Xunsigned max_code;
X
Xchar fin_char;
Xchar k;
Xunsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
X                        0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
Xunsigned bit_offset;
Xunsigned output_offset;
Xint in_han, out_han; 
X
Xint lzd(input_handle, output_handle)
Xint input_handle, output_handle;          /* input & output file handles */
X{
X   in_han = input_handle;                 /* make it avail to other fns */
X   out_han = output_handle;               /* ditto */
X   nbits = 9;
X   max_code = 512;
X   free_code = FIRST_FREE;
X   lzd_sp = 0;
X   bit_offset = 0;
X   output_offset = 0;
X
X   if (gotmem == 0) {
X      table = (struct tabentry *) 
X         malloc (MAXMAX * sizeof (struct tabentry) + SPARE);
X      gotmem++;
X   }
X   if (table == (struct tabentry *) 0)
X      memerr();
X
X   if (read(in_han, in_buf_adr, INBUFSIZ) == -1)
X      return(IOERR);
X
X   init_dtab();             /* initialize table */
X
Xloop:
X   cur_code = rd_dcode();
X   if (cur_code == Z_EOF) {
X      if (output_offset != 0) {
X         if (out_han != -2) {
X            if (write(out_han, out_buf_adr, output_offset) != output_offset)
X               prterror ('f', "Output error in lzd()\n", 
X						(char *) 0, (char *) 0);
X         }
X         addbfcrc(out_buf_adr, output_offset);
X      }
X      return (0);
X   }
X
X   if (cur_code == CLEAR) {
X      init_dtab();
X      fin_char = k = old_code = cur_code = rd_dcode();
X      wr_dchar(k);
X      goto loop;
X   }
X
X   in_code = cur_code;
X   if (cur_code >= free_code) {        /* if code not in table (k<w>k<w>k) */
X      cur_code = old_code;             /* previous code becomes current */
X      push(fin_char);
X   }
X
X   while (cur_code > 255) {               /* if code, not character */
X      push(table[cur_code].z_ch);         /* push suffix char */
X      cur_code = table[cur_code].next;    /* <w> := <w>.code */
X   }
X
X   k = fin_char = cur_code;
X   push(k);
X   while (lzd_sp != 0) {
X      wr_dchar(pop());
X   }
X   ad_dcode();
X   old_code = in_code;
X
X   goto loop;
X} /* lzd() */
X
X/* rd_dcode() reads a code from the input (compressed) file and returns
Xits value. */
Xunsigned rd_dcode()
X{
X   register char *ptra, *ptrb;    /* miscellaneous pointers */
X   unsigned word;                     /* first 16 bits in buffer */
X   unsigned byte_offset;
X   char nextch;                           /* next 8 bits in buffer */
X   unsigned ofs_inbyte;               /* offset within byte */
X
X   ofs_inbyte = bit_offset % 8;
X   byte_offset = bit_offset / 8;
X   bit_offset = bit_offset + nbits;
X
X   if (byte_offset >= INBUFSIZ - 5) {
X      int space_left;
X
X      bit_offset = ofs_inbyte + nbits;
X      space_left = INBUFSIZ - byte_offset;
X      ptrb = byte_offset + in_buf_adr;          /* point to char */
X      ptra = in_buf_adr;
X      /* we now move the remaining characters down buffer beginning */
X      while (space_left > 0) {
X         *ptra++ = *ptrb++;
X         space_left--;
X      }
X      if (read(in_han, ptra, byte_offset) == -1)
X         prterror ('f', "I/O error in lzd:rd_dcode\n", 
X				(char *) 0, (char *) 0);
X      byte_offset = 0;
X   }
X   ptra = byte_offset + in_buf_adr;
X   /* NOTE:  "word = *((int *) ptra)" would not be independent of byte order. */
X   word = (unsigned char) *ptra; ptra++;
X   word = word | ((unsigned char) *ptra) << 8; ptra++;
X
X   nextch = *ptra;
X   if (ofs_inbyte != 0) {
X      /* shift nextch right by ofs_inbyte bits */
X      /* and shift those bits right into word; */
X      word = (word >> ofs_inbyte) | (((unsigned)nextch) << (16-ofs_inbyte));
X   }
X   return (word & masks[nbits]); 
X} /* rd_dcode() */
X
Xint init_dtab()
X{
X   nbits = 9;
X   max_code = 512;
X   free_code = FIRST_FREE;
X}
X
Xint wr_dchar (ch)
Xchar ch;
X{
X   if (output_offset >= OUTBUFSIZ) {      /* if buffer full */
X      if (out_han != -2) {
X         if (write(out_han, out_buf_adr, output_offset) != output_offset)
X            prterror ('f', "Write error in lzd:wr_dchar\n", 
X					(char *) 0, (char *) 0);
X      }
X      addbfcrc(out_buf_adr, output_offset);     /* update CRC */
X      output_offset = 0;                  /* restore empty buffer */
X   }
X   out_buf_adr[output_offset++] = ch;        /* store character */
X} /* wr_dchar() */
X
X/* adds a code to table */
Xint ad_dcode()
X{
X   table[free_code].z_ch = k;                /* save suffix char */
X   table[free_code].next = old_code;         /* save prefix code */
X   free_code++;
X   if (free_code >= max_code) {
X      if (nbits < MAXBITS) {
X         nbits++;
X         max_code = max_code << 1;        /* double max_code */
X      }
X   }
X}
SHAR_EOF
if test 5823 -ne "`wc -c < 'lzd.c'`"
then
	echo shar: "error transmitting 'lzd.c'" '(should have been 5823 characters)'
fi
fi
echo shar: "extracting 'makefile.msc'" '(414 characters)'
if test -f 'makefile.msc'
then
	echo shar: "will not over-write existing file 'makefile.msc'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.msc'
X#Make Booz -- makefile for Microsoft C 3.0.  Rename to `makefile' before use.
X
XOOZOBJS = addbfcrc.obj lzd.obj booz.obj oozext.obj portable.obj
X
Xcswitch = -c -Oas -DMSC
X
X.c.obj :
X	cl $(cswitch) $*.c
X
Xbooz.exe : $(OOZOBJS)
X	cl $(OOZOBJS) -o booz
X
Xbooz.obj : options.h zoo.h func.h booz.c
X
Xlzd.obj : options.h func.h lzd.c
X
Xoozext.obj : options.h zoo.h oozio.h func.h oozext.c
X
Xportable.obj : func.h zoo.h portable.c
SHAR_EOF
if test 414 -ne "`wc -c < 'makefile.msc'`"
then
	echo shar: "error transmitting 'makefile.msc'" '(should have been 414 characters)'
fi
fi
echo shar: "extracting 'makefile.nix'" '(380 characters)'
if test -f 'makefile.nix'
then
	echo shar: "will not over-write existing file 'makefile.nix'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.nix'
X#Make Booz -- makefile for **IX.  Rename to `makefile' before use.
X
XOOZOBJS = addbfcrc.o lzd.o booz.o oozext.o portable.o
X
Xcswitch = -c -O -DNIX_IO
X
X.c.o :
X	cc $(cswitch) $*.c
X
Xbooz : $(OOZOBJS)
X	cc $(OOZOBJS) -o booz
X
Xbooz.o : options.h zoo.h func.h booz.c
X
Xlzd.o : options.h func.h lzd.c
X
Xoozext.o : options.h zoo.h oozio.h func.h oozext.c
X
Xportable.o : func.h zoo.h portable.c
SHAR_EOF
if test 380 -ne "`wc -c < 'makefile.nix'`"
then
	echo shar: "error transmitting 'makefile.nix'" '(should have been 380 characters)'
fi
fi
echo shar: "extracting 'oozext.c'" '(8196 characters)'
if test -f 'oozext.c'
then
	echo shar: "will not over-write existing file 'oozext.c'"
else
sed 's/^X//' << \SHAR_EOF > 'oozext.c'
X/* oozext.c -- extracts files from archive */
X
X/* The contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1987/02/08
X
XThe function fixfname() is currently defined to be empty but may be
Xactivated if needed to fix filename syntax to be legal for your
Xcomputer system.  Look near the end of this file for instructions and
Xa sample implementation of fixfname().  Currently, fixfname() is used
Xonly if the symbol FIXFNAME is defined.
X*/
X
X#include "options.h"
X#include "zoo.h"
X#include "oozio.h"
X#include "func.h"
X
Xextern unsigned int crccode;
X
X#ifndef TINY
Xint needed ();
X#endif
X
X#ifdef TINY
Xint oozext (zoo_path)
Xchar *zoo_path;
X#endif
X
X#ifdef SMALL
Xint oozext (zoo_path, argc, argv)
Xchar *zoo_path;
Xint argc;
Xchar *argv[];
X#endif
X
X#ifdef BIG
Xint oozext (zoo_path, option, argc, argv)
Xchar *zoo_path;
Xchar *option;
Xint argc;
Xchar *argv[];
X#endif
X
X{
Xint zoo_han;                              /* handle for open archive */
Xint this_han;                             /* handle of file to extract */
Xlong next_ptr;                            /* pointer to within archive */
Xstruct zoo_header zoo_header;             /* header for archive */
Xint status;                               /* error status */
Xstruct direntry direntry;                 /* directory entry */
Xint all = 0;                              /* overwrite all? */
Xstatic char vermsg[] = "A higher version of Ooz is needed to extract ";
Xint exitstat = 0;                         /* return code */
X
X#ifdef BIG
Xint first_time = 1;
Xstatic char *month_list="000JanFebMarAprMayJunJulAugSepOctNovDec";
X#endif
X
X#ifndef TINY
X{
X   /* If no dot in name, add ".zoo" extension */
X   char *p;
X   p = zoo_path;
X   while (*p != '\0' && *p != '.')
X      p++;
X   if (*p != '.') {  /* no dot found */
X      p = malloc (strlen (zoo_path) + 5);
X      if (p == (char *) 0)
X         memerr();
X      strcpy (p, zoo_path);
X      strcat (p, ".zoo");
X      zoo_path = p;
X   }
X}
X#endif
X
Xzoo_han = OPEN(zoo_path);
X
Xif (zoo_han == -1)
X   prterror ('f', "Could not open ", zoo_path, "\n");
X
X/* read header */
Xrd_zooh (&zoo_header, zoo_han);
Xlseek (zoo_han, zoo_header.zoo_start, 0); /* seek to where data begins */
X
Xwhile (1) {
X   rd_dir (&direntry, zoo_han);
X
X   if (direntry.lo_tag != LO_TAG || direntry.hi_tag != HI_TAG)
X         prterror ('f', "Bad entry in archive\n", 
X            ((char *) 0), ((char *) 0));
X   if (direntry.next == 0L) {                /* END OF CHAIN */
X      break;                                 /* EXIT on end of chain */
X   }
X   next_ptr = direntry.next;                 /* ptr to next dir entry */
X
X#ifndef TINY
X      /* See if this file is wanted */
X      if (!needed (direntry.fname, argc, argv)) {
X         goto loop_again;
X      }
X#endif
X
X#ifdef BIG
X  /* If list needed, give information and loop again */
X   if (*option == 'l') {
X      char outstr[80];
X      char buf[20];
X      int year, month, day, hours, min, sec;
X      int size_factor;
X      size_factor = cfactor (direntry.org_size, direntry.size_now);
X   
X      year  =  ((unsigned int) direntry.date >> 9) & 0x7f;
X      month =  ((unsigned int) direntry.date >> 5) & 0x0f;
X      day   =  direntry.date        & 0x1f;
X      
X      hours =  ((unsigned int) direntry.time >> 11)& 0x1f;
X      min   =  ((unsigned int) direntry.time >> 5) & 0x3f;
X      sec   =  ((unsigned int) direntry.time & 0x1f) * 2;
X
X      if (first_time) {
X         putstr ("Length    CF  Size Now  Date      Time\n");
X         putstr ("--------  --- --------  --------- --------\n");
X         first_time = 0;
X      }
X      strcpy (outstr, itoa(' ', direntry.org_size, buf, 9));
X      strcat (outstr, itoa(' ',(long) size_factor, buf, 5));
X      strcat (outstr, "% ");
X      strcat (outstr, itoa(' ',direntry.size_now, buf, 9));
X      strcat (outstr, "  ");
X      strcat (outstr, itoa(' ',(long) day, buf, 3));
X      strcat (outstr, " ");
X      strncat (outstr, &month_list[month*3], 3);
X      strcat (outstr, " ");
X      if (day && month)
X         strcat (outstr, itoa(' ',(long) (year+80) % 100, buf, 3));
X      else
X         strcat (outstr, itoa(' ',0L, buf, 3));
X      strcat (outstr, " ");
X      strcat (outstr, itoa('0',(long) hours, buf, 3));
X      strcat (outstr, ":");
X      strcat (outstr, itoa('0',(long) min, buf, 3));
X      strcat (outstr, ":");
X      strcat (outstr, itoa('0',(long) sec, buf, 3));
X      strcat (outstr, "  ");
X      strcat (outstr, direntry.fname);
X      strcat (outstr, "\n");
X      putstr (outstr);
X
X#ifdef COMMENT
X      printf ("%8lu %3u%% %8lu  %2d %-.3s %02d %02d:%02d:%02d  ",  
X               direntry.org_size, 
X               size_factor, direntry.size_now, 
X               day, &month_list[month*3], 
X               (day && month) ?  (year+80) % 100 : 0,
X               hours, min, sec);
X      printf ("%s\n", direntry.fname);
X#endif
X
X     goto loop_again;
X   }
X#endif /* SMALL */
X
X
X   if (direntry.major_ver > 1 ||
X         (direntry.major_ver == 1 && direntry.minor_ver > 0)) {
X      prterror ('e', vermsg, direntry.fname, "\n");
X      goto loop_again;
X   }
X
X#ifdef FIXFNAME
X   /* Make the filename syntax acceptable to the host system */
X   fixfname (direntry.fname);
X#endif
X
X
X#ifndef TINY
X   /* See if this file already exists */
X
X#ifdef BIG
X   if (*option != 't' && !all)
X#else
X   if (!all)
X#endif
X   {
X
X      this_han = OPEN(direntry.fname);
X      if (this_han != -1) {
X         char ans[2];
X         char ans2[2];
X         close (this_han);
X   
X         do {
X            prterror ('m', "Overwrite ", direntry.fname, " (Yes/No/All)? ");
X            read (0, ans, 1);
X            do {
X               read (0, ans2, 1);
X            } while (*ans2 != '\n');
X         }  while (*ans != 'y' && *ans != 'Y' && 
X                   *ans != 'n' && *ans != 'N' &&
X                   *ans != 'a' && *ans != 'A');    
X   
X         if (*ans == 'a' || *ans == 'A')
X            all++;
X         if (*ans == 'n' || *ans == 'N') {
X            prterror ('m', "Skipping ", direntry.fname, "\n");
X            goto loop_again;
X         }
X      }
X   }
X#endif /* ndef TINY */
X
X
X#ifdef BIG
X   if (*option == 't')
X      this_han = -2;
X   else
X#endif
X      this_han = CREATE(direntry.fname);
X
X   if (this_han == -1) {
X      prterror ('e', "Could not open ", direntry.fname, " for output.\n");
X   } else {
X      lseek (zoo_han, direntry.offset, 0);
X      crccode = 0;      /* Initialize CRC before extraction */
X      prterror ('m', direntry.fname, " ", ((char *) 0));
X
X      if (direntry.packing_method == 0)
X         status = getfile (zoo_han, this_han, direntry.size_now);
X      else if (direntry.packing_method == 1)
X         status = lzd (zoo_han, this_han); /* uncompress */
X      else
X         prterror ('e', vermsg, direntry.fname, "\n");
X      if (status != 0) {
X         unlink(direntry.fname);
X         if (status == 1) {
X            memerr();
X         } else 
X            prterror ('e', "I/O error writing ", direntry.fname, "\n");
X      } else {
X         if (direntry.file_crc != crccode) {
X            putstr ("<--\007WARNING:  Bad CRC.\n");
X            exitstat = 1;
X         } else
X            putstr ("\n");
X      } /* end if */
X   } /* end if */
X
X#ifdef BIG
X   if (*option != 't')
X#endif
X      close (this_han);
X
Xloop_again:
X   lseek (zoo_han, next_ptr, 0); /* ..seek to next dir entry */
X} /* end while */
Xclose (zoo_han);
Xexit (exitstat);
X} /* end oozext */
X
X/*
XFunction fixfname() fixes the syntax of the supplied filename so it is
Xacceptable to the host system.  We call the standard string function 
Xstrchr(s, c) which searches a string s for a character c and returns
Xa pointer to it or returns NULL if not found.  The scheme below
Xstrips the 8th bit and changes control characters to corresponding 
Xprintable characters (e.g.  ^A becomes A).
X
XAs supplied, fixfname() is activated only if the symbol FIXFNAME
Xis defined.
X*/
X
X
X#ifdef FIXFNAME
X/* set of all characters legal for our system */
Xchar legal[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.";
X
Xchar *strchr ();
X
Xint fixfname (fname)
Xchar *fname;
X{
X   char *p;
X   for (p = fname;  *p != '\0';  p++) {
X      *p &= 0x7f;
X      if (strchr (legal, *p) == (char *) 0) {
X         *p = legal[(*p) % 26];
X      }
X   }
X}
X#endif /* FIXFNAME */
SHAR_EOF
if test 8196 -ne "`wc -c < 'oozext.c'`"
then
	echo shar: "error transmitting 'oozext.c'" '(should have been 8196 characters)'
fi
fi
echo shar: "extracting 'oozio.h'" '(1325 characters)'
if test -f 'oozio.h'
then
	echo shar: "will not over-write existing file 'oozio.h'"
else
sed 's/^X//' << \SHAR_EOF > 'oozio.h'
X/* oozio.h */
X/* Definitions for portable I/O.
X
XDefinitions are:
X
XOPEN(x)     open file x for read
XCREATE(x)   create file x for read/write
X
XNote that files opened by OPEN() and CREATE() must be opened in
Xbinary mode (not involving any LF <-> CR/LF translation).
X
XThe contents of this file are hereby released to the public domain.
X                                   -- Rahul Dhesi 1987/02/08
X*/
X
X/* MIX C compiler for CP/M. */
X#ifdef   MIXC
X#define  CREATE(x)      (iofilter(0,0), creat (x, 0))
X#define  OPEN(x)        (iofilter (0,0), open (x, 0))
X#endif
X
X/* Microsoft C 3.0 under MS-DOS */
X#ifdef   MSC
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <io.h>
X#define  CREATE(x) \
X   open (x, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE)
X#define  OPEN(x)     open (x, O_RDONLY|O_BINARY)
X#endif
X
X/* Turbo C 1.0 under MS-DOS */
X#ifdef   TURBOC
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <io.h>
X#define  CREATE(x) \
X   open (x, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE)
X#define  OPEN(x)     open (x, O_RDONLY|O_BINARY)
X#endif
X
X/* **IX family I/O */
X#ifdef   NIX_IO
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#define  CREATE(x) \
X   open (x, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE)
X#define  OPEN(x)     open (x, O_RDONLY)
X#endif
SHAR_EOF
if test 1325 -ne "`wc -c < 'oozio.h'`"
then
	echo shar: "error transmitting 'oozio.h'" '(should have been 1325 characters)'
fi
fi
echo shar: "extracting 'options.h'" '(1559 characters)'
if test -f 'options.h'
then
	echo shar: "will not over-write existing file 'options.h'"
else
sed 's/^X//' << \SHAR_EOF > 'options.h'
X/* Compile-time options for Booz to allow custom versions to be built */
X
X/* 
XUse buffer sizes of at least 1024, larger if enough memory is
Xavailable.  Buffer sizes of over 8192 have not been confirmed to work.
X*/
X#define  IN_BUF_SIZE       1024
X#define  OUT_BUF_SIZE      1024
X
X/* 
XDecompression stack.  Except in pathological cases, 2000 bytes should
Xbe enough.  Rare files may need a bigger stack to decompress.
XMay be decreased to 1000 bytes if memory is tight.
X*/
X#define  STACKSIZE   2000        /* adjust to conserve memory */
X
X/* 
XDefine one of the symbols TINY, SMALL, and BIG.  Do not define more than
Xone of these symbols.  The effects are:
X
X   Symbol      Effect
X
X   TINY        A very tiny barebones version that always extracts an entire
X               archive at a time.  Should compile and run under CP/M.
X
X   SMALL       A slightly bigger version that will let the user specify
X               which files are to be extracted from the archive.  Wildcards
X               "?" and "*" are accepted in any combination.  Still quite
X               small.  Will probably compile and run under CP/M.
X
X   BIG         Does everything that the SMALL version does.  In addition, 
X               it will list and test archives.  May or may not compile 
X               and run under CP/M.
X*/
X
X/* Only one of the three following symbols should be defined */
X#define TINY
X/* #define SMALL */
X/* #define BIG */
X
X/* Define FIXFNAME to activate the fixfname() function that converts
Xfilename syntax to be acceptable to the host system */
X/* #define FIXFNAME */
SHAR_EOF
if test 1559 -ne "`wc -c < 'options.h'`"
then
	echo shar: "error transmitting 'options.h'" '(should have been 1559 characters)'
fi
fi
echo shar: "extracting 'portable.c'" '(3351 characters)'
if test -f 'portable.c'
then
	echo shar: "will not over-write existing file 'portable.c'"
else
sed 's/^X//' << \SHAR_EOF > 'portable.c'
X/* 
XThe contents of this file are hereby released to the public domain.
X                                   -- Rahul Dhesi 1987/02/08
X*/
X
Xtypedef char BYTE;      /* MUST be an 8-bit value */
X
X#include "func.h"
X#include "zoo.h"
X
Xlong to_long ();
Xint to_int ();
Xint b_to_zooh();
Xint b_to_dir();
Xint splitlong();
Xint splitint();
X
X/**********************
Xto_long() converts four consecutive bytes, in order of increasing
Xsignificance, to a long integer.  It is used to make Zoo independent of the
Xbyte order of the system.  
X*/
Xlong to_long(data)
XBYTE data[];
X{
X   int i;
X   long retval;
X   retval = ((unsigned) data[2] & 0xff) | 
X      (((unsigned) data[3] & 0xff) << 8);
X   retval <<= 16;
X   retval |= (((unsigned) data[0] & 0xff) | 
X      (((unsigned) data[1] & 0xff) << 8));
X   return (retval);
X}
X
X/**********************
Xto_int() converts two consecutive bytes, in order of increasing
Xsignificance, to an integer, in a machine-independent manner
X*/
Xint to_int(data)
XBYTE data[];
X{
X   return (int) (((unsigned) data[0] & 0xff) | 
X      ((unsigned) (data[1] & 0xff) << 8));
X}
X
X/**********************
XFunction rd_zooh() reads a Zoo archive header in a machine-dependent manner,
Xfrom a file handle.
X*/
Xint rd_zooh (header, zoo_han)
Xstruct zoo_header *header;
Xint zoo_han;
X{
X   int status;
X   BYTE bytes[SIZ_ZOOH];
X   status = read (zoo_han, (char *) bytes, SIZ_ZOOH);
X   b_to_zooh (header, bytes);
X   return (status);
X}
X
X/**********************
XFunction rd_dir() reads a directory entry in a machine-independent manner
Xfrom a handle.
X*/
Xint rd_dir(direntry, zoo_han)
Xstruct direntry *direntry;
Xint zoo_han;
X{
X   int status;
X   BYTE bytes[SIZ_DIR];
X   status = read (zoo_han, (char *) bytes, SIZ_DIR);
X   b_to_dir (direntry, bytes);
X   return (status);
X}
X
X/***********************
Xb_to_zooh() converts an array of BYTE to a zoo_header structure.
X*/
Xint b_to_zooh (zoo_header, bytes)
Xstruct zoo_header *zoo_header;
XBYTE bytes[];
X{
X   int i;
X   for (i = 0; i < SIZ_TEXT; i++)
X      zoo_header->text[i] = bytes[TEXT_I + i];
X   zoo_header->lo_tag = to_int(&bytes[ZTAG_I]);
X   zoo_header->hi_tag = to_int(&bytes[ZTAG_I+2]);
X   /* zoo_header->zoo_tag = to_long(&bytes[ZTAG_I]); */
X   zoo_header->zoo_start = to_long(&bytes[ZST_I]);
X   zoo_header->zoo_minus = to_long(&bytes[ZSTM_I]);
X   zoo_header->major_ver = bytes[MAJV_I];
X   zoo_header->minor_ver = bytes[MINV_I];
X}
X
X/* b_to_dir() converts bytes to directory entry structure */
Xint b_to_dir(direntry, bytes)
Xstruct direntry *direntry;
XBYTE bytes[];
X{
X   int i;
X   direntry->lo_tag = to_int(&bytes[DTAG_I]);
X   direntry->hi_tag = to_int(&bytes[DTAG_I+2]);
X   /* direntry->zoo_tag = to_long(&bytes[DTAG_I]); */
X   direntry->type = bytes[DTYP_I];
X   direntry->packing_method = bytes[PKM_I];
X   direntry->next = to_long(&bytes[NXT_I]);
X   direntry->offset = to_long(&bytes[OFS_I]);
X   direntry->date = to_int(&bytes[DAT_I]);
X   direntry->time = to_int(&bytes[TIM_I]);
X   direntry->file_crc = to_int(&bytes[CRC_I]);
X   direntry->org_size = to_long(&bytes[ORGS_I]);
X   direntry->size_now = to_long(&bytes[SIZNOW_I]);
X   direntry->major_ver = bytes[DMAJ_I];
X   direntry->minor_ver = bytes[DMIN_I];
X   direntry->deleted = bytes[DEL_I];
X   direntry->comment = to_long(&bytes[CMT_I]);
X   direntry->cmt_size = to_int(&bytes[CMTSIZ_I]);
X   for (i = 0; i < FNM_SIZ; i++)
X      direntry->fname[i] = bytes[FNAME_I + i];
X}
SHAR_EOF
if test 3351 -ne "`wc -c < 'portable.c'`"
then
	echo shar: "error transmitting 'portable.c'" '(should have been 3351 characters)'
fi
fi
echo shar: "extracting 'zoo.h'" '(1900 characters)'
if test -f 'zoo.h'
then
	echo shar: "will not over-write existing file 'zoo.h'"
else
sed 's/^X//' << \SHAR_EOF > 'zoo.h'
X/* zoo.h */
X
X/* 
XThe contents of this file are hereby released to the public domain.
X                                   -- Rahul Dhesi 1987/02/08
X*/
X
X#define SIZ_TEXT  20
X#define FNAMESIZE 13
X#define MAX_PACK 1
X#define LO_TAG (0xa7dc)
X#define HI_TAG (0xfdc4)
X
Xstruct zoo_header {
X   char text[SIZ_TEXT];
X   unsigned lo_tag;
X   unsigned hi_tag;
X   long zoo_start;
X   long zoo_minus;
X   char major_ver;
X   char minor_ver;
X};
X
Xstruct direntry {
X   unsigned lo_tag;
X   unsigned hi_tag;
X   char type;
X   char packing_method;       /* 0 = no packing, 1 = normal LZW */
X   long next;                 /* pos'n of next directory entry */
X   long offset;               /* position of this file */
X   unsigned int date;         /* DOS format date */
X   unsigned int time;         /* DOS format time */
X   unsigned int file_crc;     /* CRC of this file */
X   long org_size;
X   long size_now;
X   char major_ver;
X   char minor_ver;            /* minimum version needed to extract */
X   char deleted;              /* will be 1 if deleted, 0 if not */
X   long comment;              /* points to comment;  zero if none */
X   unsigned int cmt_size; /* length of comment, 0 if none */
X   char fname[FNAMESIZE]; /* filename */
X};
X
X/* offsets of items within the canonical zoo archive header */
X#define  SIZ_ZOOH 34
X#define  TEXT_I   0
X#define  ZTAG_I   20
X#define  ZST_I    24
X#define  ZSTM_I   28
X#define  MAJV_I   32
X#define  MINV_I   33
X
X/* offsets of items within the canonical directory entry structure */
X#define  SIZ_DIR  51
X#define  DTAG_I   0
X#define  DTYP_I   4
X#define  PKM_I    5
X#define  NXT_I    6
X#define  OFS_I    10 
X#define  DAT_I    14 
X#define  TIM_I    16 
X#define  CRC_I    18 
X#define  ORGS_I   20 
X#define  SIZNOW_I 24 
X#define  DMAJ_I   28 
X#define  DMIN_I   29 
X#define  DEL_I    30 
X#define  SPARE_I  31 
X#define  CMT_I    32 
X#define  CMTSIZ_I 36 
X#define  FNAME_I  38 
X
X#define  FNM_SIZ  13
SHAR_EOF
if test 1900 -ne "`wc -c < 'zoo.h'`"
then
	echo shar: "error transmitting 'zoo.h'" '(should have been 1900 characters)'
fi
fi
exit 0
#	End of shell archive