[comp.sources.unix] v11i011: File archive program, Part02/07

rs@uunet.UU.NET (Rich Salz) (08/18/87)

Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
Posting-number: Volume 11, Issue 11
Archive-name: zoo/Part02

#! /bin/sh
#
# 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:
#	lzc.c
#	lzconst.h
#	lzd.c
#	machine.c
#	machine.h
#	makefile
#	makelist.c
#	misc.c
#	misc2.c
#	mkbsd
#	mkgenric
#	mksysv
#	mksysvsh
#	mkuport
#	mkx68
#	mkx86
#	mstime.i
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'lzc.c'
then
	echo shar: "will not over-write existing file 'lzc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lzc.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) lzc.c 1.4 87/05/29 12:53:58";
X#endif /* LINT */
X
X#include "options.h"
X/*
XLempel-Ziv compression.  Mostly based on Tom Pfau's assembly language
Xcode. 
X
XThe contents of this file are hereby released to the public domain.
X
X                                    -- Rahul Dhesi  1986/12/31
X*/
X
X#include <stdio.h>            /* just to define NULL */
X#include "various.h"
X#include "zoofns.h"           /* function definitions */
X/* zoomem.h defines IN_BUF_SIZE & OUT_BUF_SIZE */
X#include "zoomem.h"
X#include "debug.h"
X#include "assert.h"
X/* lzconst.h contains constants for lzd() and lzc() */
X#include "lzconst.h"
X
X/* interval at which to check ratio */
X#define CHECKGAP 4000
X#define NEXT_USE  1
X#define FIRST_USE 2
X#define FOUND 0
X
Xstruct   tabentry {
X   int first;
X   int next;
X   char z_ch;
X};
X
Xvoid init_ctab();
Xvoid wr_ccode();
Xint rd_cch();
Xint lukup_ccode();
Xvoid ad_ccode();
Xvoid check_ratio();
Xvoid flush_c();
Xextern char *out_buf_adr;
Xextern char *in_buf_adr;
Xextern char memflag;                    /* memory allocated? */
Xstruct tabentry *table;                 /* this table also used by lzd.c */
Xstatic unsigned int free_code;
Xstatic int nbits;
Xstatic unsigned int max_code;
Xstatic unsigned int bitsout;
Xstatic int bit_interval;
Xstatic unsigned int bytesin, ratio, ratflag;
Xstatic unsigned int in_offset, in_size;
Xstatic unsigned int bit_offset;
Xstatic int in_han, out_han;
X
Xint lzc(input_handle, output_handle)
Xint input_handle, output_handle;
X{
X   int nextch, prefix_code, k;
X   int status;
X   int where;
X
X   in_han = input_handle;
X   out_han = output_handle;
X
X   bit_offset = in_offset = in_size = 0;
X
X   if (memflag == 0) {
X     table = (struct tabentry *) emalloc((MAXMAX+10) * sizeof(struct tabentry));
X     memflag++;
X   }
X
X
X   init_ctab();
X   wr_ccode(CLEAR);
X   nextch = rd_cch();
X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
X      wr_ccode (Z_EOF);
X      return (0);                         /* normal return from compress */
X   }
X
X   /* compression loop begins here with nextch holding the next input char */
Xloop1:
X   if (ratflag != 0)
X      check_ratio();
X   nextch &= 0xff;                       /* turn character to code */
X   assert(nextch < 256);
Xloop2:
X   prefix_code = nextch;
X   nextch = rd_cch();
X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
X      wr_ccode (prefix_code);
X      wr_ccode (Z_EOF);
X      if (bit_offset != 0)
X         flush_c ((int) (bit_offset / 8 + 1));
X      return (0);                         /* normal return from compress */
X   }
X   nextch &= 0xff;                        /* force to 8 bits */
X   assert(nextch < 256);
X
X   k = nextch;
X   status = lukup_ccode (prefix_code, nextch, &where);
X   if (status == FOUND) {
X      nextch = where;                     /* where found */
X      goto loop2;
X   }
X   assert(status == FIRST_USE || status == NEXT_USE);
X
X   /* reach here with status = FIRST_USE or NEXT_USE */
X   ad_ccode (status, nextch, where);
X
X   wr_ccode (prefix_code);
X   nextch = k;
X
X   if (free_code <= max_code)
X      goto loop1;
X   assert(nbits >= 9 && nbits <= MAXBITS);
X   if (nbits >= MAXBITS) {
X   /* To continue using table after it is full, remove next two lines */
X      wr_ccode (CLEAR);
X      init_ctab();
X
X      goto loop1;
X   }
X
X   nbits++;
X   assert(nbits >= 9 && nbits <= MAXBITS);
X   max_code = max_code << 1;
X   goto loop1;
X} /* end lzc() */
X
Xvoid wr_ccode (code)
Xint code;
X{
X   unsigned int ofs_inbyte, hibits;
X   int byte_offset;
X
X#ifdef DEBUG
Xif (code == CLEAR)
X   printf(" CLEAR\n");
X#endif
X
X   assert(nbits >= 9 && nbits <= MAXBITS);
X   bitsout += nbits;                /* total number of bits written */
X   bit_interval -= nbits;
X   if (bit_interval < 0)
X      ratflag = 1;                  /* time to check ratio */
X
X   byte_offset = bit_offset / 8;
X   ofs_inbyte = bit_offset % 8;     /* offset within byte */
X   bit_offset += nbits;             /* allowing for new code */
X
X   if (byte_offset >= OUTBUFSIZ - 4) {
X      flush_c (byte_offset);
X      bit_offset = ofs_inbyte + nbits;
X      out_buf_adr[0] = out_buf_adr [byte_offset];
X      byte_offset = 0;
X   }
X
X   code = code & 0xffff;            /* force to 16 bits */
X
X   if (ofs_inbyte == 0)
X      out_buf_adr[byte_offset]  = code & 0xff;
X   else
X      out_buf_adr[byte_offset] |= (code << ofs_inbyte) & 0xff;
X
X   hibits = ((unsigned int) code) >> (8 - ofs_inbyte);
X   out_buf_adr[byte_offset+1] = hibits & 0xff;
X   out_buf_adr[byte_offset+2] = (((unsigned int) hibits) >> 8) & 0xff;
X
X   assert(nbits >= 9 && nbits <= MAXBITS);
X} /* end wr_ccode() */
X
Xvoid init_ctab()
X{
X   int i;
X   bytesin = bitsout = ratio = ratflag = 0;
X   bit_interval = CHECKGAP;
X   nbits = 9;
X   max_code = 512;
X#ifdef COMMENT
X   for (i = 0; i < 256; i++) {
X#endif
X   for (i = 0; i < MAXMAX+1; i++) {
X      table[i].z_ch = table[i].first = table[i].next = -1;
X   }
X#ifdef COMMENT
X   /*DEBUG*/ table[MAXMAX].first   = table[MAXMAX].next = -1;
X   /*DEBUG*/ table[MAXMAX-1].first = table[MAXMAX-1].next = -1;
X#endif
X   free_code = FIRST_FREE;
X} /* end init_ctab() */
X
Xint rd_cch()
X{
X   int count;
X   bytesin++;
X   if (in_offset == in_size) {
X      count = read (in_han, in_buf_adr, INBUFSIZ);
X      if (count == -1)
X         prterror ('f', "Error reading input file during compression.\n");
X      addbfcrc (in_buf_adr, count);
X      if (count == 0) {
X         debug((printf("\nEOF on input\n")))
X         return (EOF);              /* real EOF, not Z_EOF */
X      }
X      in_size = count;
X      debug((printf("\ninput %d chars\n", count)))
X      in_offset = 0;
X   }
X   in_offset++;
X   return (in_buf_adr[in_offset-1] & 0xff);
X} /* end rd_cch () */
X
Xvoid check_ratio()
X{
X#ifdef COMMENT
X   int rat;
X   if (bitsout > 16383) {     /* avoid overflow */
X      bitsout /= 4;
X      bytesin /= 4;
X   }
X   rat = (2 * bitsout) / bytesin;
X   if (1.1 * rat < ratio) {
X      printf("#");
X      wr_ccode (CLEAR);
X      init_ctab();
X      bit_interval = CHECKGAP;
X      bitsout = 0;
X      bytesin = 0;
X      ratio = 0;
X   } else
X      ratio = ((ratio << 2) + ((2 * bitsout) / bytesin)) / 5;
X#else
X   bit_interval = CHECKGAP;
X   bitsout = 0;
X   bytesin = 0;
X#endif
X} /* end check_ratio() */
X
Xvoid ad_ccode (status, ch, index)
Xint status, index, ch;
X{
X   assert(status == FIRST_USE || status == NEXT_USE);
X#ifdef COMMENT
X   if (free_code >= MAXMAX)      /* to fix apparent bug in original */
X      return;
X#endif
X#ifdef COMMENT
X   if (status == NEXT_USE)
X      table[index].next = free_code;
X   else                 /* else must be FIRST_USE */
X      table[index].first = free_code;
X#endif
X   if (status == NEXT_USE)
X      table[index].next = (free_code >= MAXMAX ? -1 : free_code);
X   else                 /* else must be FIRST_USE */
X      table[index].first = (free_code >= MAXMAX ? -1 : free_code);
X
X#ifdef COMMENT
X   if (free_code < MAXMAX) {
X#endif
X   if (free_code <= MAXMAX) {
X      table[free_code].first = table[free_code].next = -1;
X      table[free_code].z_ch = ch & 0xff;
X      free_code++;
X   }
X} /* end ad_ccode() */
X
Xint lukup_ccode (index, ch, where)
Xint index;                        /* where to start looking */
Xint ch;                             /* char to look for */
Xint *where;                       /* last entry looked at */
X{
X   *where = index;
X   index = table[index].first;
X   if (index == -1) {
X      return (FIRST_USE);           /* not found, first use */
X   } else {
X      while (1) {
X         if ((table[index].z_ch & 0xff) == (ch & 0xff)) {
X            *where = index;
X            return (FOUND);
X         }
X         *where = index;
X         index = table[index].next;
X         if (index == -1) {
X            return (NEXT_USE);
X         }
X      } /* end while */
X   } /* end else */
X} /* end lukup_ccode() */
X
Xvoid flush_c (count)
Xint count;
X{
X   int status;
X#ifdef DEBUG
Xprintf(" <flushed %d bytes> ", count);
X#endif
X   status = write (out_han, out_buf_adr, count);
X   if (status == -1)
X      prterror ('f', "Error writing during compression.\n");
X}
SHAR_EOF
fi
if test -f 'lzconst.h'
then
	echo shar: "will not over-write existing file 'lzconst.h'"
else
sed 's/^X//' << \SHAR_EOF > 'lzconst.h'
X/* @(#) lzconst.h 1.2 87/05/03 16:01:07 */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                    -- Rahul Dhesi  1986/12/31
X*/
X
X#define  INBUFSIZ    (IN_BUF_SIZE - 10)   /* avoid obo errors */
X#define  OUTBUFSIZ   (OUT_BUF_SIZE - 10)
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 */
SHAR_EOF
fi
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#ifndef LINT
X/* @(#) lzd.c 1.5 87/05/29 12:54:10 */
Xstatic char sccsid[]="@(#) lzd.c 1.5 87/05/29 12:54:10";
X#endif /* LINT */
X
X#include "options.h"
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
X*/
X
X#include <stdio.h>            /* just to define NULL */
X#include "various.h"
X#include "zoofns.h"           /* function definitions */
X/* zoomem.h defines IN_BUF_SIZE & OUT_BUF_SIZE */
X#include "zoomem.h"
X#include "debug.h"
X#include "assert.h"
X/* lzconst.h contains constants for lzd() and lzc() */
X#include "lzconst.h"
X
X#define  STACKSIZE   4000
X
Xstruct tabentry {
X   unsigned next;
X   char z_ch;
X};
X
Xvoid init_dtab();
Xunsigned rd_dcode();
X
X#ifdef LINT_ARGS
Xvoid wr_dchar (char);
X#else
Xvoid wr_dchar();
X#endif
X
Xvoid ad_dcode();
X
Xstatic unsigned stack_pointer = 0;
Xstatic unsigned *stack;
X
X#define  push(x)  {  \
X                     stack[stack_pointer++] = (x);                   \
X                     if (stack_pointer >= STACKSIZE)                 \
X                        prterror ('f', "Stack overflow in lzd().\n");\
X                  }
X#define  pop()    (stack[--stack_pointer])
X
Xextern char *out_buf_adr;        /* output buffer */
Xextern char *in_buf_adr;         /* input buffer */
X
Xchar memflag = 0;                /* memory allocated? flag */
Xextern struct tabentry *table;   /* hash table from lzc.c */
Xstatic unsigned cur_code;
Xstatic unsigned old_code;
Xstatic unsigned in_code;
X
Xstatic unsigned free_code;
Xstatic int nbits;
Xstatic unsigned max_code;
X
Xstatic char fin_char;
Xstatic char k;
Xstatic unsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
X                        0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
Xstatic unsigned bit_offset;
Xstatic unsigned output_offset;
Xstatic int 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   stack_pointer = 0;
X   bit_offset = 0;
X   output_offset = 0;
X
X   if (read(in_han, in_buf_adr, INBUFSIZ) == -1)
X      return(IOERR);
X   if (memflag == 0) {
X     table = (struct tabentry *) emalloc((MAXMAX+10) * sizeof(struct tabentry));
X     stack = (unsigned *) emalloc (sizeof (unsigned) * STACKSIZE + 20);
X     memflag++;
X   }
X
X   init_dtab();             /* initialize table */
X
Xloop:
X   cur_code = rd_dcode();
X   if (cur_code == Z_EOF) {
X      debug((printf ("lzd: Z_EOF\n")))
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         }
X         addbfcrc(out_buf_adr, output_offset);
X      }
X      return (0);
X   }
X
X   assert(nbits >= 9 && nbits <= 13);
X
X   if (cur_code == CLEAR) {
X      debug((printf ("lzd: CLEAR\n")))
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   assert(nbits >= 9 && nbits <= 13);
X
X   k = fin_char = cur_code;
X   push(k);
X   while (stack_pointer != 0) {
X      wr_dchar(pop());
X   }
X   assert(nbits >= 9 && nbits <= 13);
X   ad_dcode();
X   old_code = in_code;
X
X   assert(nbits >= 9 && nbits <= 13);
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   assert(nbits >= 9 && nbits <= 13);
X
X   if (byte_offset >= INBUFSIZ - 5) {
X      int space_left;
X
X      assert(byte_offset >= INBUFSIZ - 5);
X      debug((printf ("lzd: byte_offset near end of buffer\n")))
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      debug((printf ("rd_dcode: space_left = %d\n", space_left)))
X      while (space_left > 0) {
X         *ptra++ = *ptrb++;
X         space_left--;
X      }
X      assert(ptra - in_buf_adr == ptrb - (in_buf_adr + byte_offset));
X      assert(space_left == 0);
X      if (read(in_han, ptra, byte_offset) == -1)
X         prterror ('f', "I/O error in lzd:rd_dcode.\n");
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
Xvoid init_dtab()
X{
X   nbits = 9;
X   max_code = 512;
X   free_code = FIRST_FREE;
X}
X
Xvoid 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      }
X      addbfcrc(out_buf_adr, output_offset);     /* update CRC */
X      output_offset = 0;                  /* restore empty buffer */
X   }
X   assert(output_offset < OUTBUFSIZ);
X   out_buf_adr[output_offset++] = ch;        /* store character */
X} /* wr_dchar() */
X
X/* adds a code to table */
Xvoid ad_dcode()
X{
X   assert(nbits >= 9 && nbits <= 13);
X   assert(free_code <= MAXMAX+1);
X   table[free_code].z_ch = k;                /* save suffix char */
X   table[free_code].next = old_code;         /* save prefix code */
X   free_code++;
X   assert(nbits >= 9 && nbits <= 13);
X   if (free_code >= max_code) {
X      if (nbits < MAXBITS) {
X         debug((printf("lzd: nbits was %d\n", nbits)))
X         nbits++;
X         assert(nbits >= 9 && nbits <= 13);
X         debug((printf("lzd: nbits now %d\n", nbits)))
X         max_code = max_code << 1;        /* double max_code */
X         debug((printf("lzd: max_code now %d\n", max_code)))
X      }
X   }
X}
SHAR_EOF
fi
if test -f 'machine.c'
then
	echo shar: "will not over-write existing file 'machine.c'"
else
sed 's/^X//' << \SHAR_EOF > 'machine.c'
X#ifndef LINT
X/* @(#) machine.c 1.3 87/05/03 15:59:18 */
Xstatic char sccsid[]="@(#) machine.c 1.3 87/05/03 15:59:18";
X#endif /* LINT */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                    -- Rahul Dhesi  1986/12/31
X*/
X
X#include "options.h"
X#ifdef SYS_V
X#include "zoo.h"
X#include "sysv.c"
X#endif
X
X#ifdef GENERIC
X#include "zoo.h"
X#include <stdio.h>
X#include "generic.c"
X#endif
X
X#ifdef BSD4_3
X#include "bsd.c"
X#endif
X
X#ifdef DLC
X#include <stdio.h>
X#include "zoo.h"
X#include "generic.c"
X#endif
X
X#ifdef MSC
X#ifdef PORTABLE
X#include <stdio.h>
X#include "zoo.h"
X#include "zoofns.h"
X#include "generic.c"
X#else
X#include <stdio.h>
X#include "zoo.h"
X#include "zoofns.h"
X#include "msc.c"
X#endif
X#endif
SHAR_EOF
fi
if test -f 'machine.h'
then
	echo shar: "will not over-write existing file 'machine.h'"
else
sed 's/^X//' << \SHAR_EOF > 'machine.h'
X/* @(#) machine.h 1.2 87/05/03 15:59:21 */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                           -- Rahul Dhesi 1986/11/14
X*/
X
X/* 
XThis file holds definitions that usually do not change
Xbetween different systems, except when using REALLY strange systems.  But
Xoptions.h and machine.c hold stuff that does change quite a bit.
X*/
X
X/* 
XMAXLONG is the maximum size of a long integer.  Right now it doesn't have to
Xbe accurate since it's only used within zooext() to fake infinite disk space.
X*/
X#define  MAXLONG  ((unsigned long) (~0L))
X
X/* 
XType BYTE must hold exactly 8 bits.  The code will collapse badly if BYTE is
Xanything other than exactly 8 bits. To avoid sign extension when casting
XBYTE to a longer size, it must be declared unsigned.  For machine-
Xindependence, Zoo does all I/O of archive headers and directory entries 
Xin units of BYTE.  The actual file data are not written in units of
XBYTE, however, so portability may not be absolute.
X*/
Xtypedef  unsigned char BYTE;  /* type corresponding to an 8-bit byte */
X
SHAR_EOF
fi
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile'
X# @(#) makefile 1.6 87/05/03 15:59:23 
X#Make Zoo
X#
X#The contents of this makefile are hereby released to the public domain.
X#                                  -- Rahul Dhesi 1986/12/31
X#
X#This makefile should not be invoked directly, because different 
X#targets require different compilation switches.  The standard make
X#utility does not allow different switches to be specified for each target
X#(except through recursive invocation, which takes more memory than 
X#some systems have).  Invoke this makefile through one of the several
X#shell scripts supplied.  For non *NIX systems, convert the appropriate
X#shell script to one accepted by your system.
X#
X#This makefile expects two macro names, `cswitch' and `extra', to hold
X#all the switches to be supplied to the C compiler.  It also expects
X#a macro `ldswitch' to hold the switch for the loader when invoked.
X
X#Destination directory where `make install' will put the programs.
XDESTDIR = ../bin
X
XCC = cc
Xcswitch =
Xextra = -DBIG_MEM -DNDEBUG
X
X#List of all object files created for Zoo
XZOOOBJS = 	addbfcrc.o addfname.o basename.o comment.o crcdefs.o \
X		getfile.o lzc.o lzd.o machine.o makelist.o misc.o misc2.o \
X		nextfile.o needed.o options.o parse.o portable.o prterror.o \
X		version.o zoo.o zooadd.o zooadd2.o zoodel.o zooext.o zoolist.o \
X		zoopack.o
X
XFIZOBJS = fiz.o addbfcrc.o portable.o crcdefs.o
X
X.c.o :
X	$(CC) $(cswitch) $(extra) $*.c
X
X.c~.c:
X	get .z/s.$*.c
X
Xall : ERROR
X
Xlint: $(ZOOOBJS)
X	lint $(ZOOOBJS)
X
Xzoo: $(ZOOOBJS)
X	$(CC) $(ldswitch) $(ZOOOBJS)
X
Xfiz: $(FIZOBJS)
X	$(CC) $(ldswitch) $(FIZOBJS)
X
X#Install executable code into destination directory.  If your system
X#has the `install' program invoke it as:  install -s zoo $(DESTDIR)/zoo
X#
Xinstall : 
X	mv zoo $(DESTDIR)/zoo
X	mv fiz $(DESTDIR)/fiz
X
Xclean :
X	/bin/rm -f core a.out $(ZOOOBJS) $(FIZOBJS)
X
Xlzd.o : lzd.c zoomem.h
X	$(CC) $(cswitch) $(extra) $*.c
X
Xlzc.o : lzc.c zoomem.h
X	$(CC) $(cswitch) $(extra) $*.c
X
Xaddbfcrc.o : addbfcrc.c
X
Xaddfname.o : addfname.c
X
Xbasename.o : basename.c
X
Xcomment.o : comment.c 
X
Xcrcdefs.o : crcdefs.c
X
Xgetfile.o : getfile.c zoomem.h
X	$(CC) $(cswitch) $(extra) $*.c
X
Xmachine.o : machine.c nixtime.i
X	$(CC) $(cswitch) $(extra) $*.c
X
Xmakelist.o : makelist.c
X
Xmisc.o : misc.c 
X
Xmisc2.o : misc2.c zoomem.h
X	$(CC) $(cswitch) $(extra) $*.c
X
Xoptions.o : options.c
X
Xnextfile.o :  nextfile.c
X
Xneeded.o : needed.c
X
Xparse.o : parse.c
X
Xportable.o : portable.c
X
Xprterror.o : prterror.c
X
Xzoo.o :   zoo.c zoomem.h errors.i
X	$(CC) $(cswitch) $(extra) $*.c
X
Xzooadd.o : zooadd.c 
X
Xzooadd2.o : zooadd2.c
X
Xzoodel.o : zoodel.c 
X
Xzooext.o : zooext.c  errors.i
X	$(CC) $(cswitch) $(extra) $*.c
X
Xzoolist.o : zoolist.c 
X
Xzoopack.o : zoopack.c 
SHAR_EOF
fi
if test -f 'makelist.c'
then
	echo shar: "will not over-write existing file 'makelist.c'"
else
sed 's/^X//' << \SHAR_EOF > 'makelist.c'
X#ifndef LINT
X/* @(#) makelist.c 1.21 87/05/30 18:50:05 */
Xstatic char sccsid[]="@(#) makelist.c 1.21 87/05/30 18:50:05";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X
X#include "options.h"
X#include "portable.h"
X#include "errors.i"
X
X/* for low-level I/O */
X#ifdef NOFCNTL
X#include <file.h>
X#else
X#include <fcntl.h>
X#endif
X
X#ifdef FLAT
X#include <types.h>
X#include <stat.h>
X#else
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X
X#include "zoo.h"
X#include <stdio.h>
X#include "various.h"
X
X#include "zoofns.h"
X#include "assert.h"
X#include "debug.h"
X
X#ifdef LINT_ARGS
Xchar *nameptr (char *);
X#else
Xchar *nameptr();
X#endif
X
X/*******************/
X/*
Xmakelist() gets all pathnames corresponding to a set of filespecs and
Xadds them to a list.  Not more than "flistsize" pathnames are added.
XInto `longest' it returns the length of the longest name added, or
Xzero if none added.
X
XFiles ignore1, ignore2, and ignore3 are not added to the list.
XA file that is a device/directory is also not added to the list.
X
XHowever, if ignore1 is NULL, both these tests are skipped and all files
Xwill be added to the list.
X*/
X
Xvoid makelist (argc, argv, flist, flistsize, ignore1, ignore2, ignore3, longest)
Xint argc;               /* number of filespec supplied */
Xchar *argv[];           /* array of pointers to supplied filespecs */
Xregister char *flist[]; /* array of pointers to filenames we will add */
Xint flistsize;          /* home many names we can use */
Xchar *ignore1, *ignore2, *ignore3; /* files to exclude from list */
Xint *longest;        /* length of longest name in list */
X{
X   char *this_path;        /* current pathname */
X   int fptr;               /* pointer to within flist */
X   register int i, j;      /* loop counters */
X   char *pat_name;         /* filename part of pattern */
X   int gap;                /* for Shell sort */
X   
X   flistsize--;            /* allow for one terminating NULL entry */
X   fptr = *longest = 0;
X
X   assert(argc > 0);
X
X#define WCLEN	4	/* length needed for wildcard, and a little extra */
X
X   while (argc > 0) {
X#ifdef WILDCARD
X		int argok = 0;											/* arg not matched yet */
X#endif
X      char *this_arg;
X		this_arg = emalloc (strlen (*argv) + WCLEN);
X		strcpy (this_arg, *argv);
X
X      /* Initialize fileset 0.  Select all files -- we will later
X	 		filter out the ones wanted */
X#ifdef FOLD
X      strlwr (this_arg);
X#endif
X      pat_name = strdup (nameptr (this_arg));		/* pattern without path */
X
X#ifdef WILDCARD
X		/* 
X		replace filename by wildcard;  however, if argument ends in slash, 
X		then simply append wildcard so we get all files in that directory
X		*/
X#ifdef FORCESLASH
X			fixslash (this_arg);				/* convert backslashes to slashes */
X#endif
X
X		if (*lastptr(this_arg) == *PATH_CH) {
X			strcat (this_arg, WILDCARD);
X			pat_name = "*";					/* and select all files */
X		} else
X      	strcpy (nameptr (this_arg), WILDCARD);
X#endif
X
X      nextfile (0, this_arg, 0);
X      while (fptr < flistsize && 
X            (this_path = nextfile(1, (char *) NULL, 0)) != NULL) {
X         char *this_name = nameptr (this_path);
X			modpath (this_path);					/* do any needed changes to path */
X
X#ifdef IGNORECASE
X#define	COMPARE	strcmpi
X#else
X#define	COMPARE	strcmp
X#endif
X			if (ignore1 != NULL) {
X				if (!COMPARE(this_name,ignore1)  ||    /* exclude ignored files */
X					 !COMPARE(this_name,ignore2)  ||
X					 !COMPARE(this_name,ignore3))
X					continue;
X#ifdef CHEKDIR
X				{
X					int skip, han;  
X					han=OPEN(this_path, F_READ);
X					skip = isadir(han);  close(han);
X					if (skip)
X						continue;
X				}
X#endif
X      
X#ifdef CHEKUDIR
X				if (isuadir(this_path))
X					continue;
X#endif
X			} /* end if ignore1 ! = NULL */
X
X/* 
XIf WILDCARD is defined (e.g. AmigaDOS, MS-DOS), then nextfile() returns 
Xall filenames and we must now select the ones we need by pattern matching.  
XIf WILDCARD is not defined (e.g. **IX), filenames have already been selected 
Xby the shell and need not be tested again.
X*/
X#ifdef WILDCARD
X			if (match_half (this_name,pat_name) ||
X				match_half (pat_name, "?-?") &&     /* character range */
X					*this_name >= *pat_name && *this_name <= pat_name[2])
X#endif
X			{
X#ifdef WILDCARD
X				argok = 1;									/* remember arg matched */
X#endif
X				flist[fptr++] = strdup (this_path);
X				if (*longest < strlen(this_path))
X					*longest = strlen(this_path);
X			}
X
X		} /* end while */
X#ifdef WILDCARD
X		if (argok == 0) {									/* no match for argument */
X			prterror ('e', "Could not open %s\n", *argv);
X		}
X#endif
X      argc--;
X      argv++;
X   }
X   /* fptr is now 1 + index of last item in array */
X
X   if (this_path != NULL && fptr >= flistsize)
X      prterror ('w', too_many_files, flistsize);
X#ifndef  DONT_SORT
X   /* Shell sort -- K&R p. 58 */
X   for (gap = fptr/2; gap > 0; gap /= 2)
X      for (i = gap; i < fptr; i++)
X         for (j = i - gap; j >= 0 && 
X            strcmp(flist[j],flist[j+gap]) > 0; j -= gap) {
X            char *t = flist[j]; flist[j] = flist[j+gap]; flist[j+gap] = t;
X         }
X#endif /* DONT_SORT */
X
X   fptr--;     /* fptr is now index of last item in array */
X
X   /* Remove duplicates */
X   for (i = 0; i < fptr; i++) {
X      while (i<fptr && COMPARE(flist[i],flist[i+1]) == 0) {
X         for (j = i; j < fptr; j++)
X            flist[j] = flist[j+1];
X         fptr--;
X      }
X   }
X
X   flist[++fptr] = NULL;      /* NULL entry terminates list */
X}
X
X/*******
Xmodpath() makes any changes needed before pathname is stored;
Xcurrently these could involve folding it to lower case and
Xconverting backslashes to forward slashes
X*/
X
Xmodpath (path)
Xchar *path;
X{
X#ifdef FOLD
X	strlwr (path);
X#endif
X
X#ifdef FORCESLASH
X	fixslash (path);				/* convert backslashes to slashes */
X#endif
X}
SHAR_EOF
fi
if test -f 'misc.c'
then
	echo shar: "will not over-write existing file 'misc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc.c'
X#ifndef LINT
X/* @(#) misc.c 1.7 87/05/03 15:59:33 */
Xstatic char sccsid[]="@(#) misc.c 1.7 87/05/03 15:59:33";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X#include "options.h"
X/* Miscellaneous functions needed by Zoo but not by Ooz */
X
X#include "zoo.h"
X#include <stdio.h>
X#include "various.h"
X
X#include "errors.i"
X#include "zoofns.h"
X#ifndef NOSIGNAL
X#include <signal.h>
X#endif
X
X#ifdef NEEDCTYP
X#include <ctype.h>
X#endif
X
X/*
Xcalc_ofs() is given a string that (supposedly) begins with a string
Xof digits.  It returns a corresponding numeric value.  If no such
Xstring, it returns zero.
X*/
Xlong calc_ofs(str)
Xchar *str;
X{
X   long retval;
X   int status;
X   char *p;
X   retval = 0L;
X   p = str; /* save for error message */
X   while (isdigit(*str)) {
X      retval = retval * 10L + (*str-'0');
X      str++;
X   }
X   if (*str != '\0')
X      prterror ('f', "Invalid number %s\n", p);
X   return (retval);
X}
X
X/*
Xchoosefname() decides which filename to use.  If a long filename is present,
Xand if the syntax is that of UNIX, MS-DOS or the portable form, we use it;
Xelse we use the short filename. 
X*/
X
Xchar *choosefname(direntry)
Xstruct direntry *direntry;
X{
X   char *retptr;                 /* pointer to name that we will return */
X   switch (direntry->system_id) {
X      case SYSID_NIX:
X      case SYSID_PORTABLE:
X      case SYSID_MS:
X         retptr = (direntry->namlen > 0) ? direntry->lfname : direntry->fname;
X         break;
X      default:
X         retptr = direntry->fname;
X         break;
X   }
X   return (retptr);
X} /* choosefname() */
X
X/* 
Xcombine() combines a directory name and a filename, making sure the
Xtwo are separated by a path separator 
X*/
Xchar *combine(result, dirname, fname)
Xchar result[], *dirname, *fname;
X{
X   *result = '\0';
X   if (*dirname != '\0') {
X      strcpy(result, dirname);
X      if (*lastptr(result) != *PATH_CH)
X         strcat(result, PATH_CH);
X   }
X   strcat(result, fname);
X   return (result);
X}
X
X/*
Xfullpath() accepts a pointer to a directory entry and returns the
Xcombined directory name + filename.  The long filename is used
Xif available, else the short filename is used.
X*/
Xchar *fullpath (direntry)
Xstruct direntry *direntry;
X{
X	static char result[PATHSIZE];
X	combine (result,
X				direntry->dirlen > 0 ? direntry->dirname : "", 
X				(direntry->namlen > 0) ? direntry->lfname : direntry->fname
X			  );
X	return (result);
X}
X
X/* 
Xver_too_high returns true if version of provided archive header is
Xtoo high for us to manipulate archive 
X*/
X
Xint ver_too_high (header)
Xstruct zoo_header *header;
X{
X   return (header->major_ver > MAJOR_VER ||
X            (header->major_ver == MAJOR_VER &&
X             header->minor_ver > MINOR_VER));
X}
X
X/* 
Xrwheader() reads archive header, checks consistency, makes sure its
Xversion number is not too high, updates it if too low, and seeks to
Xbeginning of first directory entry 
X*/
X
Xrwheader (header, zoo_file)
Xregister struct zoo_header *header;
XFILE *zoo_file;
X{
X
X   frd_zooh (header, zoo_file);
X
X   if ((header->zoo_start + header->zoo_minus) != 0L)
X      prterror ('f', failed_consistency);
X   if (ver_too_high (header))
X      prterror ('f', wrong_version, header->major_ver, header->minor_ver);
X
X   /* We reach here if the archive version is not too high.  Now, if it
X   isn't the same as ours, we bring it up to ours so the modified archive 
X   will be safe from previous versions of Zoo */
X
X   if (header->major_ver != MAJOR_VER || header->minor_ver != MINOR_VER) {
X      header->major_ver = MAJOR_VER;
X      header->minor_ver = MINOR_VER;
X      fseek (zoo_file, 0L, 0);            /* seek to beginning */
X      fwr_zooh (header, zoo_file);
X   }
X   fseek (zoo_file, header->zoo_start, 0); /* seek to where data begins */
X} /* rwheader */
X
X/*
Xwritedir() write a directory entry with keyboard interrupt disabled
X*/
Xvoid writedir (direntry, zoo_file)
Xstruct direntry *direntry;
XFILE *zoo_file;
X{
X#ifndef NOSIGNAL  
X   int (*oldsignal)();
X   oldsignal = signal (SIGINT, SIG_IGN);
X#endif
X   if (fwr_dir (direntry, zoo_file) == -1)
X      prterror ('f', disk_full);
X#ifndef NOSIGNAL
X   signal (SIGINT, oldsignal);
X#endif
X}
X
X/* 
Xreaddir() reads a directory entry from an archive.  If the directory
Xentry is invalid and if fail is 1, it causes a fatal error;
Xelse it returns.  Return value is 0 if no error else -1;
X*/
X
Xint readdir (direntry, zoo_file, fail)    /* read directory entry */
Xregister struct direntry *direntry;
XFILE *zoo_file;
Xint fail;                              /* 0 -> return, 1 -> abort on error */
X{
X   if (frd_dir (direntry, zoo_file) < 0) {
X      if (fail)
X         prterror ('f', bad_directory);
X      else
X         return (-1);
X   }
X   if (direntry->zoo_tag != ZOO_TAG) {
X      if (fail)
X         prterror ('f', bad_directory);
X      else
X         return (-1);
X   }
X   return (0);
X}
X
X/* use pointer version below */
X#ifdef COMMENT
X/* instr() searches a string for a substring */
Xinstr (s, t)      /* return index of string t in string s, -1 if none */
Xchar s[], t[];    /*  .. from K&R page 67 */
X{
X   int i;
X   register int j, k;
X   for (i = 0; s[i] != '\0'; i++) {
X      for (j = i, k = 0; t[k] != '\0' && s[j]==t[k]; j++, k++)
X         ;
X      if (t[k] == '\0')
X         return (i);
X   }
X   return (-1);
X}
X#endif COMMENT
X
X/* instr() searches a string for a substring */
X/* from J. Brian Waters */
Xint instr (s, t)   		/* return the position of t in s, -1 if none */
Xchar *s, *t;				/*  a pointer version of K&R index function p.67 */
X{               /* renamed to instr() to avoid conflicts with C RTL - JBW */
X
X   register char *i, *j, *k;
X
X   for (i = s; *i; i++) {
X      for (j = i, k = t; (*k) && (*j++ == *k); k++)
X         ;
X       if (!*k)
X         return ((int) (i - s));
X   }
X   return(-1);
X}
X
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   if ((unsigned long) org_size > 1000000) { /* avoid later overflow */
X      org_size = (unsigned long) org_size / 1024;
X      size_now = (unsigned long) size_now / 1024;
X   }
X   if (org_size == 0)         /* avoid division by zero */
X      size_factor = 0;
X   else {
X      size_factor = 
X         (
X            (1000 * 
X               ((unsigned long) org_size - (unsigned long) size_now)
X            ) / org_size + 5
X         ) / 10;
X   }
X   return (size_factor);
X}
X
X#ifndef STRDUP
X/***********
Xstrdup() duplicates a string using dynamic memory.
X*/
X
Xchar *strdup (str)
Xregister char *str;
X{
X   return (strcpy (emalloc (strlen(str)+1), str));
X}
X#endif /* STRDUP */
X
X/**************
Xcmpnum() compares two pairs of unsigned integers and returns a negative,
Xzero, or positive value as the comparison yields less than, equal, or
Xgreater than result.  Each pair of unsigned integers is considered to be the
Xmore significant and the less significant half of a longer unsigned number.
X
XNote:  cmpnum is used to compare dates and times.
X*/
X
Xint cmpnum (hi1, lo1, hi2, lo2)
Xregister unsigned int hi1, hi2;
Xunsigned int lo1, lo2;
X{
X   if (hi1 != hi2)
X      return ((int) hi1 - hi2);
X   else
X      return ((int) lo1 - lo2);
X}
X
X/*******************/
X/* writenull() */
X/* writes a null directory entry to the archive whose handle is supplied */
Xvoid writenull(handle, length)
Xint handle, length;
X{
X#ifndef NOSIGNAL
X   int (*oldsignal)();
X#endif
X   struct direntry newentry;
X   memset ((char *) &newentry, 0, sizeof (newentry));
X   newentry.zoo_tag = ZOO_TAG;
X   newentry.type = 2;
X   /* Force entry to be the required length plus possibly 2 stray bytes
X   by dividing up the needed padding into dirlen and namlen. */
X   if (length > SIZ_DIRL)
X      newentry.dirlen = newentry.namlen = (length-SIZ_DIRL)/2 + 2;
X   else
X      newentry.dirlen = newentry.namlen = 0;
X#ifndef NOSIGNAL
X   oldsignal = signal (SIGINT, SIG_IGN);
X#endif
X   if (wr_dir (&newentry, handle) == -1)
X      prterror ('f', disk_full);
X#ifndef NOSIGNAL
X   signal (SIGINT, oldsignal);
X#endif
X}
X
X#ifdef FORCESLASH
X/*******************/
X/*
Xfixslash() changes all "\" characters in the supplied string to "/".
X*/
X
Xvoid fixslash (str)
Xchar *str;
X{
X   register char *p;
X   for (p = str; *p != '\0'; p++)
X      if (*p == '\\')
X         *p = '/';
X}
X#endif /* FORCESLASH */
X
X/* Currently using portable directory I/O for MSC also */
X#ifdef COMMENT
X#ifndef PORTABLE  
X/* portable implementations are elsewhere */
X/***********************
XFunction fwr_dir() writes a directory entry to a FILE.  Return value is -1 on
Xerror, else 0.
X*/
Xint fwr_dir(direntry, zoo_file)
Xstruct direntry *direntry;
XFILE *zoo_file;
X{
X   if (fwrite ((char *) direntry, SIZ_DIR, 1, zoo_file) != 1)
X      return (-1);
X   else
X      return (0);
X}
X
X/***********************
XFunction wr_dir() writes a directory entry to a handle.  Return value is -1
Xon error else 0.
X*/
Xint wr_dir(direntry, zoo_han)
Xstruct direntry *direntry;
Xint zoo_han;
X{
X   if (write (zoo_han, (char *) direntry, SIZ_DIR) != SIZ_DIR)
X      return (-1);
X   else
X      return (0);
X}
X
X/***********************
XFunction wr_zooh() writes an archive header to a handle.  Return value -1 if
Xerror else 0.
X*/
Xint wr_zooh(zoo_header, zoo_han)
Xstruct zoo_header *zoo_header;
Xint zoo_han;
X{
X   if (write (zoo_han, (char *) zoo_header, SIZ_ZOOH) != SIZ_ZOOH)
X      return (-1);
X   else
X      return (0);
X}
X
X/***********************
XFunction fwr_zooh() writes an archive header to a FILE.  Return value is -1
Xif error else 0.
X*/
Xint fwr_zooh(zoo_header, zoo_file)
Xstruct zoo_header *zoo_header;
XFILE *zoo_file;
X{
X   if (fwrite ((char *) zoo_header, SIZ_ZOOH, 1, zoo_file) != 1)
X      return (-1);
X   else
X      return (0);
X}
X#endif /* end of not PORTABLE */
X#endif /* COMMENT */
X
SHAR_EOF
fi
if test -f 'misc2.c'
then
	echo shar: "will not over-write existing file 'misc2.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc2.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) misc2.c 1.8 87/05/29 12:54:33";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X#include "options.h"
X/* Miscellaneous routines needed by both Zoo and Ooz */
X#ifdef NOFCNTL
X#include <file.h>
X#else
X#include <fcntl.h>
X#endif
X
X#ifdef FLAT
X#include <types.h>
X#include <stat.h>
X#else
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X
X#include "portable.h"
X#include <stdio.h>
X#include "various.h"
X#include "zoofns.h"     /* only for malloc */
X#include "errors.i"
X#include "zoomem.h"
X#include "zoo.h"
X
X/**********************/
X/* memerr() */
X/* Give error message on memory error and abort */
Xvoid memerr()
X{
X#ifdef OOZ
X   prterror ('f', no_memory, "", "");
X#else
X   prterror ('f', no_memory);
X#endif
X}
X
X/**********************/
X/*
Xemalloc() allocates memory like malloc() does, except that it automatically
Xcalls the error function memerr() if memory couldn't be allocated.  It also
Xassumes (unless small memory allocation is being done) that memory will
Xnever be freed and conserves it by allocating memory in large chunks
Xand then partitioning it out with no administrative overhead.
X*/
X
Xchar *emalloc (size)
Xunsigned int size;
X{
X#define  BLOCK_SIZE  512      /* memory allocation granularity */
X
X#ifdef USE_MALLOC
X/* Pass on memory requests to malloc() */
X   char *ptr;
X   if ((ptr = malloc (size)) == NULL)
X      memerr();
X   return (ptr);
X#else
X   static char *memptr;
X   static unsigned avail = 0;
X   unsigned malloc_incr;
X   char *retval;
X
X   if (size == 0)
X      return (NULL);
X
X   /* if not enough space avail get some more */
X   if (avail < size) {
X      malloc_incr = BLOCK_SIZE;
X      if (malloc_incr < size)
X         malloc_incr = size;
X      while (malloc_incr >= size && (memptr = malloc (malloc_incr)) == NULL)
X         malloc_incr = (malloc_incr / 6) * 5;
X      avail = malloc_incr;
X   }
X
X   if (avail < size)
X      memerr();
X   else {
X      retval = memptr;
X      memptr += size;
X      avail -= size;
X      return (retval);
X   }
X#endif  /* end of not USE_MALLOC */
X}
X
X/**********************/
X/* putstr()
XThis function prints a string to standard output without using printf().
XIf a null string, nothing is printed (not even the null character).
X*/
Xputstr (str)
Xregister char *str;
X{
X   if (str == NULL)
X      return;
X   while (*str) {
X      fputchar (*str++);
X   }
X}
X
X/**********************/
X/* exists()
XThis function checks the existence of a file.  
X
XIf the symbol EXISTS is defined, that is called as a macro and
Xsupplied the filename.  It must return 1 if the file exists and
X0 if it does not.
X
XIf EXISTS is not defined, exists() tests to see if the file can be 
Xopened for either reading or writing;  if so, it returns 1 else it 
Xreturns 0. 
X
XBecause of the delay between the time existence is checked and the time Zoo
Xcreates a files, a race condition exists.  It would be better to
Xuse open() with the O_EXCL flag but that will not work for many
Xsystems.
X*/
X
Xint exists (fname)
Xchar *fname;
X{
X#ifdef EXISTS
X	return EXISTS(fname);
X#else
X   int han;
X
X#ifdef PORTABLE
X   if ((han = OPEN(fname,F_READ)) != -1 || (han = OPEN(fname,F_WRITE)) != -1)
X#else
X   /* Under MS-DOS, all files are readable */
X   if ((han = OPEN(fname,F_READ)) != -1)
X#endif /* ifdef PORTABLE */
X	{
X      close (han);
X      return (1);
X   } else
X      return (0);
X#endif /* ifdef EXISTS */
X}
X
X/************************************************************************
XThe following MS-DOS-specific functions read directory entries and zoo
Xheaders.  Portable versions are elsewhere.
X
XNote:  At some future time, it will be better to make the MS-DOS versions
Xof these into macros.
X*/
X
X/* Currently using portable I/O for MSC too */
X#ifdef COMMENT
X#ifndef PORTABLE
X/**********************
XFunction frd_zooh() reads the header of a Zoo archive from a FILE.
X*/
Xint frd_zooh(zoo_header, zoo_file)
Xstruct zoo_header *zoo_header;
XFILE *zoo_file;
X{
X   if (fread ((char *) zoo_header, SIZ_ZOOH, 1, zoo_file) != 1)
X      return (-1);
X   else
X      return (0);
X}
X
X/**********************
XFunction frd_dir() reads a directory entry from a FILE.
X*/
Xint frd_dir(direntry, zoo_file)
Xstruct direntry *direntry;
XFILE *zoo_file;
X{
X   if (fread ((char *) direntry, SIZ_DIR, 1, zoo_file) != 1)
X      return (-1);
X   else
X      return (0);
X}
X
X/**********************
XFunction rd_zooh() reads a Zoo archive header from a file handle.
X*/
Xint rd_zooh (header, zoo_han)
Xstruct zoo_header *header;
Xint zoo_han;
X{
X   return (read (zoo_han, (char *) header, SIZ_ZOOH));
X}
X
X/**********************
XFunction rd_dir() reads a directory entry from a file handle */
Xint rd_dir(direntry, zoo_han)
Xstruct direntry *direntry;
Xint zoo_han;
X{
X   return (read (zoo_han, (char *) direntry, SIZ_DIR));
X}
X
X#endif /* end of not PORTABLE */
X#endif /* COMMENT */
X
X/****************
Xnewcat() allocates enough space to concatenate two strings then returns
Xa pointer to the concatenated result */
X
Xchar *newcat (r, s)
Xchar *r, *s;
X{
X   char *temp = emalloc (strlen (r) + strlen (s) + 2); /* 1 spare */
X   strcpy (temp, r);
X   strcat (temp, s);
X   return (temp);
X}
X
X
X/* Creates a path */
Xint makepath(path)
Xchar *path;
X{
X   char tmppath[PATHSIZE];
X   char *slashpos;
X   if (path == NULL)
X      return;
X   while (*lastptr(path) == *PATH_CH)     /* remove trailing slashes */
X      *lastptr(path) = '\0';
X   if (*path == '\0')
X      return;
X
X   slashpos = findlast(path, PATH_CH);    /* find last slash */
X   if (slashpos == NULL) {                /* if not, just create dir. */
X      MKDIR(path);
X      return;
X   } else {                               /* otherwise...         */
X      if (slashpos == path) {             /* if leading slash */
X         MKDIR(slashpos);                 /* make that directory */
X         return;                          /* and done */
X      } else {
X         strcpy(tmppath,path);            /* save path */
X         *slashpos = '\0';                /* split into prefix & suffix */
X#ifdef DEBUG
X         printf("making path from [%s]\n", path);
X#endif
X         makepath(path);                     /* make path from prefix */
X#ifdef DEBUG
X         printf("making dir from [%s]\n", tmppath);
X#endif
X         MKDIR(tmppath);                  /* make dir from suffix */
X      }
X   }
X} /* makepath() */
X
X/*
XIf no extension in filename add supplied extension
X*/
Xchar *addext (fname, ext)
Xchar *fname;
Xchar *ext;
X{
X   if (strchr (nameptr (fname), EXT_CH) == NULL)
X      return (newcat (fname, ext));
X   else
X      return (fname);
X}
SHAR_EOF
fi
if test -f 'mkbsd'
then
	echo shar: "will not over-write existing file 'mkbsd'"
else
sed 's/^X//' << \SHAR_EOF > 'mkbsd'
X# @(#) mkbsd 1.2 87/05/03 15:59:46
X#4.3BSD -- make Zoo and Fiz
Xmake "cswitch=-c -O -DBSD4_3" "ldswitch = -o zoo" zoo
Xmake "cswitch=-c -O -DBSD4_3" "ldswitch = -o fiz" fiz
SHAR_EOF
fi
if test -f 'mkgenric'
then
	echo shar: "will not over-write existing file 'mkgenric'"
else
sed 's/^X//' << \SHAR_EOF > 'mkgenric'
X# @(#) mkgenric 1.2 87/05/03 15:59:48
X#Generic Zoo and Fiz
Xmake "cswitch=-c -O -DGENERIC" "ldswitch = -o zoo" zoo
Xmake "cswitch=-c -O -DGENERIC" "ldswitch = -o fiz" fiz
SHAR_EOF
fi
if test -f 'mksysv'
then
	echo shar: "will not over-write existing file 'mksysv'"
else
sed 's/^X//' << \SHAR_EOF > 'mksysv'
X# @(#) mksysv 1.2 87/05/03 15:59:51
X#System V
Xmake "cswitch=-c -O -DSYS_V" "ldswitch=-s -o zoo" zoo
Xmake "cswitch=-c -O -DSYS_V" "ldswitch=-s -o fiz" fiz
SHAR_EOF
fi
if test -f 'mksysvsh'
then
	echo shar: "will not over-write existing file 'mksysvsh'"
else
sed 's/^X//' << \SHAR_EOF > 'mksysvsh'
X# @(#) mksysvsh 1.3 87/06/04 12:38:45
X#This script first calls `mksysvsh' to build zoo and fiz without
X#the shared libraries.  Then it deletes zoo and fiz and reloads
X#them with the shared libraries.
Xsh mksysv
X/bin/rm -f zoo fiz
Xmake CC=ld ldswitch="/lib/crt0s.o /lib/shlib.ifile -o zoo" zoo
Xmake CC=ld ldswitch="/lib/crt0s.o /lib/shlib.ifile -o fiz" fiz
SHAR_EOF
fi
if test -f 'mkuport'
then
	echo shar: "will not over-write existing file 'mkuport'"
else
sed 's/^X//' << \SHAR_EOF > 'mkuport'
X# @(#) mkuport 1.3 87/05/03 15:59:55
X#Microport UNIX on AT.  -Ml = large memory model.
Xmake "cswitch = -O -c -Ml -DSYS_V" "ldswitch = -Ml -o zoo" zoo
Xmake "cswitch = -O -c -Ml -DSYS_V" "ldswitch = -Ml -o fiz" fiz
SHAR_EOF
fi
if test -f 'mkx68'
then
	echo shar: "will not over-write existing file 'mkx68'"
else
sed 's/^X//' << \SHAR_EOF > 'mkx68'
X# @(#) mkx68 1.2 87/05/03 15:59:58
X#Radio Shack Model 16 with Xenix/68000 3.01.01. "-DM_VOID" tells not 
X#to try to do a typedef of `void'. "-Dvoid=int" because compiler doesn't 
X#know about `void'.  `-s -n' strips and makes it shareable.
Xmake "cswitch=-c -O -DSYS_V -DM_VOID -Dvoid=int" "ldswitch=-s -n -o zoo" zoo
Xmake "cswitch=-c -O -DSYS_V -DM_VOID -Dvoid=int" "ldswitch=-s -n -o fiz" fiz
SHAR_EOF
fi
if test -f 'mkx86'
then
	echo shar: "will not over-write existing file 'mkx86'"
else
sed 's/^X//' << \SHAR_EOF > 'mkx86'
X# @(#) mkx86 1.4 87/06/04 12:33:47
X# Make Zoo and Fiz
X# This script is believed to work on:
X#    Xenix 3.4 on Greg Laskin's Intel 310/286
X#    SCO Xenix 2.2 on Robert Cliff's AT.
X#`-Ml' for large memory model, `-M2' to generate code for 80286 cpu,
X#`-F 8000' for 0x8000 bytes of stack space
Xmake "cswitch=-c -O -DSYS_V -Ml -M2" "ldswitch=-Ml -o zoo -F 8000" zoo
Xmake "cswitch=-c -O -DSYS_V -Ml -M2" "ldswitch=-Ml -o fiz" fiz
SHAR_EOF
fi
if test -f 'mstime.i'
then
	echo shar: "will not over-write existing file 'mstime.i'"
else
sed 's/^X//' << \SHAR_EOF > 'mstime.i'
X#ifndef LINT
Xstatic char mstimeid[]="@(#) mstime.i 1.2 87/05/03 16:00:02";
X#endif /* LINT */
X
X#define BASEYEAR 1970
X
X/****************
XFunction mstime() converts time in seconds since January 1 of BASEYEAR
Xto MS-DOS format date and time.
X*/
Xmstime(longtime, date, time)
Xlong longtime;       /* input:  seconds since Jan 1, BASEYEAR   */
Xint *date, *time;    /* output: MS-DOS format date and time */
X
X{
X   static int daysinmo[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
X#define FEBRUARY 1
X   int year, month, day, hour, min, sec;
X   long secsinhour, secsinday, secsinyear, secsinleapyear;
X
X   int leapyear;                             /* is this a leap year? */
X   int done;                                 /* control variable */
X
X   secsinhour = (long) (60 * 60);            /* seconds in an hour */
X   secsinday  = 24 * secsinhour;             /* seconds in a day */
X   secsinyear = 365 * secsinday;             /* seconds in a year */
X   secsinleapyear = secsinyear + secsinday;  /* seconds in a leap year */
X
X#ifdef DEBUG
Xprintf("mstime:  input longtime = %ld\n", longtime);
X#endif
X
X   /* We can't handle dates before 1970 so force longtime positive */
X   if (longtime < 0)
X      longtime = 0;
X
X   /* 
X   Step through years from BASEYEAR onwards, subtracting number of
X   seconds in each, stopping just before longtime would become negative.
X   */
X   year = BASEYEAR;
X   done = 0;
X   while (!done) {
X      long yearlength;
X      leapyear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
X      if (leapyear)
X         yearlength = secsinleapyear;
X      else
X         yearlength = secsinyear;
X
X      if (longtime >= yearlength) {
X         longtime -= yearlength;
X         year++;
X      } else
X         done++;
X   }
X
X   /* Now `year' contains year and longtime contains remaining seconds */
X   daysinmo[FEBRUARY] = leapyear ? 29 : 28;
X
X   month = 0; /* range is 0:11 */
X   while (longtime > daysinmo[month] * secsinday) {
X      longtime = longtime - daysinmo[month] * secsinday;
X      month++;
X   }
X   month++; /* range now 1:12 */
X
X   day = longtime / secsinday;     /* day of month, range 0:30 */
X   longtime = longtime % secsinday;
X   day++;                         /* day of month, range 1:31 */
X
X   hour = longtime / secsinhour;       /* hours, range 0:23 */
X   longtime = longtime % secsinhour;
X
X   min = longtime / 60L;               /* minutes, range 0:59 */
X   longtime = longtime % 60L;
X
X   sec = longtime;                     /* seconds, range 0:59 */
X
X#ifdef DEBUG
Xprintf("mstime:  date = %4d/%02d/%02d   time = %02d:%02d:%02d\n",
X      year, month, day, hour, min, sec);
Xif (leapyear)
X   printf("(leap year)\n");
X#endif
X
X   if (year < 1980)
X      year = 1980;
X   *date = day + (month << 5) + ((year - 1980) << 9);
X   *time = (sec / 2) + (min << 5) + (hour << 11);
X}
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi

-- 

Rich $alz
Cronus Project, BBN Labs			rsalz@bbn.com
Moderator, comp.sources.unix			sources@uunet.uu.nest