[comp.sources.unix] v11i010: File archiver programe, Part01/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 10
Archive-name: zoo/Part01

This is part 1 of 7 of the source distribution of zoo 1.51.

The zoo archiver provides most of the functionality of the utilities
"tar" and "cpio" with some restrictions (file protections and
multiple links are not currently preserved and archives cannot be
read from standard input or sent to standard ouput); in addition, it
supports storage of files in compressed form.  Long filenames of up
to 255 characters can be handled.

#!/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:
#	Bugs
#	Changes
#	Copyright
#	Install
#	addbfcrc.c
#	addfname.c
#	assert.h
#	basename.c
#	bsd.c
#	comment.c
#	crcdefs.c
#	debug.h
#	errors.i
#	fiz.c
#	generic.c
#	getfile.c
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Bugs'
then
	echo shar: "will not over-write existing file 'Bugs'"
else
sed 's/^X//' << \SHAR_EOF > 'Bugs'
X
X                               KNOWN BUGS
X
XThis is a summary of known bugs in zoo version 1.51.
X
X   - Attempted creation of a directory with a name of nearly 255
X     characters in length may fail.  This bug was deduced from an
X     inspection of the code, and no attempt has yet been made to confirm
X     it in practice or fix it.
X
X
X                                     -- Rahul Dhesi 1987/07/12
SHAR_EOF
fi
if test -f 'Changes'
then
	echo shar: "will not over-write existing file 'Changes'"
else
sed 's/^X//' << \SHAR_EOF > 'Changes'
X
X
X                                CHANGES
X
X
XThis is a summary of changes from Zoo version 1.41 to version 1.51.
X
X   - Zoo 1.41 always deleted an archived file if another file with the
X     same name was added to the archive, even if the two files had
X     different directory prefixs.  Zoo 1.51 works as follows.  If Zoo is
X     storing full pathnames during addition, then it deletes the old
X     file only if the old and new files have identical pathnames.  If
X     Zoo is not storing pathnames but only filenames, then it deletes
X     the old file if the old and new files have the same filename,
X     regardless of their pathnames.
X
X   - If a supplied argument matches no files, Zoo will now give an error
X     message.  Previous versions gave an error message only if no files
X     matched any argument.  However, this does not currently affect the
X     status code returned on exit.
X
X   - Zoo 1.41 did not archive a file whose filename (without path
X     prefix) was the same as the name of a subdirectory in the current
X     directory.   Similarly an archive of the form "xyz.zoo" was ignored
X     by the list command if a subdirectory "xyz" existed in the current
X     directory.  This bug is now fixed.
X
X   - Wildcard handling is now uniform across all operating systems.  "*"
X     matches zero or more characters and "?" matches any one character.
X     The dot is no longer special.  Thus "zoo a xyz *" will always add
X     all files to archive xyz.zoo on all systems.
X
X   - The new switch 'I' causes Zoo to read names of files to be archived
X     from standard input.
X
X   - The Novice commands no longer store the directory prefix for any
X     filename.  Thus Zoo's Novice commands simulate the behavior of
X     other archive programs.
X
X   - A bug was fixed that had caused the file date and time not to be
X     restored when full path was restored.
X
X   - A bug was fixed that had caused the directory prefix not to be
X     saved when a filename had no dot in it but directory prefix
X     contained a dot.
X
X   - A bug was fixed that had caused the totals line to be corrupted in
X     the "La" command.
X
X   - Packing now keeps the archive in the same directory.  Users with
X     limited disk space can still pack an archive from one disk to
X     another by using the . switch.
X
X   - A bug related to incorrect handling of timezones, when daylight
X     savings is in effect, was fixed.
X
X
X                                     -- Rahul Dhesi 1987/07/12
SHAR_EOF
fi
if test -f 'Copyright'
then
	echo shar: "will not over-write existing file 'Copyright'"
else
sed 's/^X//' << \SHAR_EOF > 'Copyright'
X
X                            COPYRIGHT
X
X
XCertain rules apply to the distribution of the Zoo archiver.
X
XThe following rules apply only to the zoo archiver itself.
XCurrently, all extract-only programs, and all supporting utili-
Xties, are fully in the public domain and are expected to remain so
Xfor the forseeable future.
X
X"This program" refers to version 1.50 and separately to each sub-
Xsequent version of the Zoo archiver and to all derivative works
Xthereof.  "Distribution right" refers to any copyright, compila-
Xtion copyright, license, or other right to control distribution or
Xcopying.  "Compiled code" refers to software that can be executed
Xby a computer system.
X
XThis program is copyrighted but its distribution for noncommercial
Xpurposes is permitted, with the following restrictions.
X
X   - You are prohibited from distributing this program as part of
X     any package over which you claim a distribution right.  This
X     restriction does not apply if any distribution right is
X     claimed only over individual items that you own or for which
X     the distribution right has been explicitly assigned to you,
X     and not over the package as a collection.
X
X   - You are prohibited from making this program available for
X     downloading via telecommunications if you charge a total of
X     more than $7.00 per hour at 1200 bps.
X
X   - You are prohibited from distributing this program as compiled
X     code unless you also distribute the source code from which
X     the compiled code was derived.  This restriction does not
X     apply if the compiled code was created by me.
X
X   - You are prohibited from creating, from this program, any
X     derivative work over which you claim a distribution right.
X
XThe above restrictions may be relaxed by special agreement;
Xplease contact me for details.
X
X                              -- Rahul Dhesi 1987/07/12
X                                 UUCP:    iuvax!bsu-cs!dhesi or
X                                          pur-ee!bsu-cs!dhesi
X                                 GEnie:   DHESI
X                                 Plink:   OLS806
X                                 Phone:   +1 317 285 8641 daytime EST
X                                 US mail: 720 W. Centennial Ave #15,
X                                          Muncie, Indiana 47303
SHAR_EOF
fi
if test -f 'Install'
then
	echo shar: "will not over-write existing file 'Install'"
else
sed 's/^X//' << \SHAR_EOF > 'Install'
X
X                              INSTALLATION
X
X
XThis document explains how to compile and install the zoo archiver.
X
XGenerally, you will not build zoo by directly invoking the supplied
Xmakefile.  Instead, you will execute one of the supplied scripts, or
Xcreate a suitable script.  Each supplied script has a name beginning
Xwith the characters "mk" and is executed with the command
X"sh scriptname" or "csh scriptname".  All the scripts listed below
Xworked correctly with version 1.50 of zoo, which was given only limited
Xdistribution.  The current version 1.51 differs from 1.50 only in the
Xfiles bsd.c, sysv.c, and version.c, so I expect the scripts to still
Xwork, with one exception that is noted.  The following scripts are sup-
Xplied.
X
Xmksysv    This is for any system running System V Release 2 or something
X          reasonably compatible.  It is known to work on the *T&T **IX
X          PC (also known as the 3B1 or the *T&T 7300) running software
X          revision 3.0.  It will also work on more recent versions of
X          Xenix.  On older machine architectures this script may need to
X          be revised to add a `-Ml' switch or equivalent to cause the
X          large memory model to be used.  For Microport System V/AT and
X          Xenix see also descriptions for mkuport, mkx86, and mkx68.
X
Xmkbsd     This is for 4.3BSD.  It is known to work on a VAX-11/785 run-
X          ning 4.3BSD straight from Berkeley.
X
Xmkuport   For Microport System V/AT.  This script includes the -Ml
X          switch so that the large memory model is used.
X
Xmksysvsh  This script first calls mksysv to build zoo, then it deletes
X          the executable program and re-loads it using the shareable
X          libraries available on the *T&T **IX PC.  It used to work but
X          I'm given to understand that it was broken by a reference to a
X          timezone-related variable that is absent from the shared
X          library.
X
Xmkx68     This script is for Xenix/68000.  It is known to work on a
X          Radio Shack Model 16 running Xenix version 3.01.01.  It takes
X          care of problems in the C compiler and in the include files
X          related to incorrect handling of the `void' data type.  How-
X          ever, since this version of Xenix does not have the memset()
X          library function, the line "#define MEMSET" must first be com-
X          mented out from the group of symbol definitions for SYS_V in
X          the file ``options.h''.
X
Xmkx86     This script is for Xenix for 80286 systems.  It is known to
X          work on an Intel 310/286 running Xenix 3.4 and an AT running
X          SCO Xenix 2.2.  It causes the large memory model to be used
X          and sufficient stack space to be allocated at load time.
X
XThe file ``options.h'' defines preprocessor symbols for the various sys-
Xtems.  In most cases, given a reasonably powerful C compiler and
Xlibrary, you will be able to find a combination of options that will
Xwork.
X
XOther machine-dependent code and definitions are in machine.h,
Xmachine.c, and portable.h.  Also, the amount of memory used for various
Xarrays can be customized by defining symbols that are described and used
Xin zoomem.h.
X
XThe low-level input/output routines are in portable.c.  In most cases
Xthese will not need to be modified.
X
XThe zoo source code largely conforms to the requirements of Kernighan
Xand Ritchie's book.  Some exceptions are as follows.
X
X   - Variables are unique in their initial 8 characters.  Systems that
X     distinguish fewer than 8 initial characters are currently not sup-
X     ported.
X
X   - Zoo code assumes that members of structures do not have global
X     scope.
X
X   - Long preprocessor symbols are occasionally used.
X
XTROUBLESHOOTING.
X
XThe zoo code uses strchr and strrchr, which are present on System V,
X4.3BSD, and Xenix, but may not be present on 4.2BSD. To get around this,
Xadd the C compiler switches "-Dstrchr=index" and "-Dstrrchr=rindex" to
Xthe make script or to the makefile.
X
XOptionally zoo can use the access() system call to check for file
Xexistence (see the definition for the symbol EXISTS in options.h).
XThere is some question about the appropriatenes of this, because
Xaccess() can give the wrong answer when used from a set-user-id program.
XIf EXISTS is left undefined, zoo uses its own function to test for file
Xexistence by trying to open the file for read and also for write.
X
XTwo common reasons for crashes when zoo is executed are the following.
X
X   - On machines with older (Intel-style) architectures zoo requires the
X     large memory model.  Compiling with the small memory model will
X     cause problems.  Also, systems that are limited to 64 kilobytes of
X     data and 64 kilobytes of code are not currently supported (but they
X     will be in the future).  Note that a small and memory-efficient
X     extract-only program, described below, is separately available that
X     should run on any system with a reasonable C compiler.
X
X   - Generous amounts of stack space is needed.  Depending on the sys-
X     tem, this will vary from about 15 kilobytes to about 33 kilobytes.
X     On systems that cannot expand the stack dynamically you will need
X     to specify the size of the stack area at load time.
X
XSPECIAL VERSIONS.  A version (currently 1.50) is available for MS-DOS
Xthat provides better performance due to assembly language routines and
Xalso includes some system-dependent features.  Another version
X(currently 1.42b) has been ported by J. Brian Waters for the Amiga.  It
Xincludes several AmigaDOS-dependent features such as preservation of
Xfile times and wildcard expansion.
X
XEXTRACT-ONLY VERSIONS.  For a new system, your first concern should be
Xthe ability to extract and list zoo archives.  For this purpose try com-
Xpiling booz (which stands for Barebones Ooz) (currently version 1.01),
Xwhich can be compiled with three different options requiring different
Xdegrees of compiler sophistication and offering different levels of
Xfeatures.  Unlike zoo, booz will work on systems with less than 64 kilo-
Xbytes of total available memory.  Also available, for VAX/VMS, is the
Xextract-only program vooz 1.00.  (Because of serious bugs in the VAX/VMS
Xinput/output routines, the full zoo archiver does not currently work
Xunder VAX/VMS.  Unfortunately, DEC documents these bugs as features, so
Xthey are unlikely to be fixed soon.  I hope to be eventually able to
Xwork around these bugs.)
X
XMachine-dependencies.
X
X   - Currently the only systems supported are those that can read and
X     write in 8-bit units.  The file ``machine.h'' contains a typedef of
X     BYTE, and it must be defined to be an 8-bit quantity.
X
X   - It is not known whether zoo code as it stands will work on a 1's-
X     complement machine.
X
X   - The code assumes that type `int' is at least 16 bits long and type
X     `long' is at least 32 bits long.  (The code may work if type `long'
X     is somewhat smaller than 32 bits but this has not been confirmed.)
X     There may be some implicit assumptions that type `char' is exactly
X     8 bits;  I am not sure if this is so.  However, type `BYTE' must be
X     exactly 8 bits long.
X
X   - In accordance with K&R (p 126), zoo code assumes that sizeof(char)
X     equals exactly 1.
X
X                                     -- Rahul Dhesi 1987/07/12
SHAR_EOF
fi
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#ifndef LINT
Xstatic char sccsid[]="@(#) addbfcrc.c 1.2 87/05/03 16:00:26";
X#endif /* LINT */
X
X#include "options.h"
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*/
X
Xextern unsigned int crccode;
Xextern unsigned crctab[];
X
Xvoid 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}
X
SHAR_EOF
fi
if test -f 'addfname.c'
then
	echo shar: "will not over-write existing file 'addfname.c'"
else
sed 's/^X//' << \SHAR_EOF > 'addfname.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) addfname.c 1.5 87/05/03 16:00:28";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X#include "options.h"
X
X/* Adds a filename to global list.  (This global list will eventually
Xbe searched by the inlist() function.)  The second through fourth 
Xparameters suppplied are stored with the name of the file and 
Xreturned by inlist. */
X
X#include <stdio.h>
X#include "various.h"
X#include "zoo.h"
X#include "zoofns.h"
X#include "zoomem.h" /* to get LIST_SIZE */
X
Xstatic struct item *fentry[LIST_SIZE];
Xstatic int lastname = 0;                  /* index of last name */
X
Xstruct item {              /* global filename list entry */
X   char *fname;
X   long position;
X   unsigned int date;
X   unsigned int time;
X};
X
Xvoid addfname(fname,position,date,time)
Xchar *fname;
Xlong position;
Xunsigned int date, time;
X{
X   if (lastname == 0)
X      fentry[lastname] = (struct item *) emalloc (sizeof(struct item));
X
X   /* keep a few empty spaces at end to avoid off by one errors */
X   if (lastname >= LIST_SIZE - 3)
X      memerr();
X
X   fentry[lastname]->fname = strdup(fname);
X   fentry[lastname]->position = position;
X   fentry[lastname]->date = date;
X   fentry[lastname]->time = time;
X   lastname++;
X   /* allocate memory for empty entry at end */
X   fentry[lastname] = (struct item *) emalloc (sizeof(struct item)); 
X} /* addfname */
X
X/* inlist() */
X/* Examines global list built by addfname() to see if supplied filename
Xis in the list.  
X
XIf found, returns the file's position within the archive as the function 
Xvalue and the date and time as parameters.  If not found, returns -1.
X
XA simple sequential search is done.
X
XIf justname is nonzero, then the search is for the filename only
Xwithout the directory prefix;  else it is for the full
Xpathname.
X*/
X
Xlong inlist (fname, date, time, justname)
Xchar *fname;
Xunsigned int *date, *time;
Xint justname;
X{
X   register int i = 0;
X	if (justname)
X		fname = nameptr (fname);					/* if directory wanted */
X   fentry[lastname]->fname = fname;          /* sentinel */
X
X#ifdef IGNORECASE
X#define	COMPARE	strcmpi
X#else
X#define	COMPARE	strcmp
X#endif
X
X   while (COMPARE(fname, 
X				(justname ? nameptr (fentry[i]->fname) : fentry[i]->fname)) != 0) {
X      i++;
X   }
X
X   if (i == lastname)
X      return (-1L);
X   else {
X      *date = fentry[i]->date;
X      *time = fentry[i]->time;
X      return (fentry[i]->position);
X   }
X} /* inlist() */
X
SHAR_EOF
fi
if test -f 'assert.h'
then
	echo shar: "will not over-write existing file 'assert.h'"
else
sed 's/^X//' << \SHAR_EOF > 'assert.h'
X/* @(#) assert.h 1.2 87/05/03 16:00:32 */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                           -- Rahul Dhesi 1986/11/14
X
XDefines a macro assert() that causes an assertion error if the assertion
Xfails.  For some useful information about this see "Reliable Data
XStructures in C" by Thomas Plum page 1-21.
X
XConditional compilation:
X
X   If NDEBUG is defined then
X      assert() is defined as null so all assertions vanish
X   else
X      if DUMB_ASS is defined then   -- use dumb assertions
X         assertions print a message but not the filename and line number
X      else
X         assertions print message including filename and line number
X      endif
X   endif
X
XNote:
X   DUMB_ASS should be defined if the preprocessor does not support the 
X   varying constants __FILE__ and __LINE__, which are supposed to hold the 
X   name of the current file and the number of the current line.
X
X*/
X
X#ifndef NDEBUG
X/* assert() macro defined only if NDEBUG is undefined */
X#ifdef DUMB_ASS
X#define assert(E) \
X   { if (!(E)) \
X      prterror ('w', "Assertion error.\n"); \
X   }
X#else
X/* else not DUMB_ASS */
X#define assert(E) \
X   { if (!(E)) \
X      prterror ('w',"Assertion error in %s:%d.\n", __FILE__, __LINE__); \
X   }
X#endif /* not DUMB_ASS */
X#else
X/* else NDEBUG */
X#define assert(E)
X#endif /* NDEBUG */
SHAR_EOF
fi
if test -f 'basename.c'
then
	echo shar: "will not over-write existing file 'basename.c'"
else
sed 's/^X//' << \SHAR_EOF > 'basename.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) basename.c 1.4 87/05/29 12:53:28";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X
X#include "zoo.h"
X#include "options.h"
X#include "parse.h"
X#include <stdio.h>
X#include "various.h"
X#include "zoofns.h"
X#include "debug.h"
X#include "assert.h"
X
X/* This function strips device/directory information from
Xa pathname and returns just the plain filename */
Xvoid basename (pathname, fname)
Xchar *pathname;
Xchar fname[];
X{
X   strcpy (fname, nameptr (pathname));
X}
X
X/* Set of legal MSDOS filename characters.  The working of cvtchr() depends
Xon the order of the first few characters here.  In particular, '_' is
Xpositioned so '.' gets converted to it. */
Xstatic char legal[] = 
X"tabcdefghijklmnopqrs_uvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@^`{}~!#$%&'()-";
X
X/****************
Xcvtchr() converts a character to a lowercase alphabetic character in
Xa somewhat random way.  
X*/
X#define  cvtchr(ch)        legal[(ch & 0xff) % 26]
X
X/***************
Xcleanup() cleans up a string so it contains only legal MSDOS filename
Xcharacters.  Any other characters are converted to an underscore.
XIf the filename is null or if it begins with a dot, it is fixed.
XAll dots are also converted.
X*/
Xvoid cleanup (p)
Xchar *p;
X{
X   assert(p != NULL);
X   if (*p == '\0')
X      strcpy (p, "X");
X   if (*p == '.')
X      *p = '_';
X   while (*p != '\0') {
X      if (strchr (legal, *p) == NULL) {   /* if invalid character */
X         *p = cvtchr(*p);
X      }
X      p++;
X   }
X}
X/* This function strips device/directory information from a pathname,
Xforces the remaining filename to MSDOS format, and returns it.  Any
Xillegal characters are fixed.
X*/
Xvoid dosname (pathname, fname)
Xchar *pathname;
Xchar fname[];
X{
X   struct path_st path_st;
X   parse (&path_st, pathname);
X   strcpy (fname, path_st.fname);
X   cleanup (fname);
X   if (path_st.ext[0] != '\0') {
X      strcat (fname, ".");
X      cleanup (path_st.ext);
X      strcat (fname, path_st.ext);
X   }
X}
X
X/* 
XThis function accepts a pathname and returns the extension.  If there is
Xnone, it returns a null string
X*/
X
Xvoid extension (pathname, ext)
Xchar *pathname;
Xregister char ext[];
X{
X   struct path_st path_st;
X   parse (&path_st, pathname);
X   strcpy (ext, path_st.ext);
X}
X
X/* rootname() */
X/* Accepts a pathname.  Returns the root filename, i.e., with both the
Xdirectory path and the extension stripped. */
X
Xvoid rootname (path, root)
Xchar *path, *root;
X{
X   char *p;
X   static char dot[] = {EXT_CH, '\0'};
X   strcpy(root, nameptr(path));           /* copy all but path prefix */
X   p = findlast(root, dot);               /* find last dot */
X   if (p != NULL)                         /* if found ... */
X      *p = '\0';                          /* ... null it out */
X}
X
X/* nameptr() */
X/* Accepts a pathname.  Returns a pointer to the filename within
Xthat pathname.
X*/
X
Xchar *nameptr (path)
Xchar *path;
X{
X   char *t;
X   t = findlast (path, PATH_SEP);   /* last char separating device/directory */
X   debug ((printf ("nameptr:  findlast returned ptr to string [%s].\n",t)))
X   if (t == NULL)                /* no separator */
X      return (path);
X   else {
X      return (t+1);
X   }
X}
SHAR_EOF
fi
if test -f 'bsd.c'
then
	echo shar: "will not over-write existing file 'bsd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bsd.c'
X#ifndef LINT
Xstatic char bsdid[]="@(#) bsd.c 1.4 87/07/12 15:05:42";
X#endif /* LINT */
X
X/* machine.c for 4.3BSD. */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                    -- Rahul Dhesi  1986/12/31
X*/
X
Xlong tell();
X
X/****************
Xfunction trunc() truncates a file.
X*/
X
Xint trunc (handle)
Xint handle;
X{
X   ftruncate (handle, tell(handle));
X}
X
X/****************
XFunction fixfname() converts the supplied filename to a syntax
Xlegal for the host system.  It is used during extraction.
X*/
X
Xchar *fixfname(fname)
Xchar *fname;
X{
X   return (fname); /* default is no-op */
X}
X
X/****************
XDate and time functions are standard UNIX-style functions.  "nixtime.i"
Xwill be included by machine.c.
X*/
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/time.h>
X
X/* Function isadir() returns 1 if the supplied handle is a directory, 
Xelse it returns 0.  
X*/
X
Xint isadir (handle)
Xint handle;
X{
X   struct stat buf;           /* buffer to hold file information */
X   if (fstat (handle, &buf) == -1) {
X      return (0);             /* inaccessible -- assume not dir */
X   } else {
X      if (buf.st_mode & S_IFDIR)
X         return (1);
X      else
X         return (0);
X   }
X}
X
X/* Function gettz(), returns the offset from GMT in seconds */
Xlong gettz()
X{
X   struct timeval tp;
X   struct timezone tzp;
X   gettimeofday (&tp, &tzp);              /* specific to 4.3BSD */
X
X   /* return (tzp.tz_minuteswest * 60); */ /* old incorrect code fixed below */
X	/*
X	Timezone fix thanks to Bill Davidsen <wedu@ge-crd.ARPA>
X	{uunet | philabs | seismo!rochester}!steinmetz!crdos1!davidsen
X	*/
X   return (tzp.tz_minuteswest * 60 - tzp.tz_dsttime * 3600L);
X}
X
X/* Standard UNIX-compatible time routines */
X#include "nixtime.i"
SHAR_EOF
fi
if test -f 'comment.c'
then
	echo shar: "will not over-write existing file 'comment.c'"
else
sed 's/^X//' << \SHAR_EOF > 'comment.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) comment.c 1.5 87/05/29 12:53:35";
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/* comment() */
X/* Updates comments */
X
X/* buffer size for any one comment line */
X#define  COMMENT_LINE_SIZE 77
X
X#define  MAX_COMMENT_SIZE  65535
X#include <stdio.h>
X#include "various.h"
X
X#ifndef NOSIGNAL
X#include <signal.h>
X#endif
X
X#include "zoo.h"
X#include "zoofns.h"
X#include "errors.i"
X
X#ifdef LINT_ARGS
Xvoid show_comment (struct direntry *, FILE *, int, char *);
Xget_comment (struct direntry *, FILE *, char *);
X#else
Xvoid show_comment ();
Xget_comment ();
X#endif
X
Xvoid comment(zoo_path, option)
Xchar *zoo_path, *option;
X{
X#ifndef NOSIGNAL  
Xint (*oldsignal)();
X#endif
XFILE *zoo_file;                           /* stream for open archive */
Xlong next_ptr;                            /* pointers to within archive */
Xlong this_dir_offset;                     /* pointers to within archive */
Xstruct direntry direntry;                 /* directory entry */
Xstruct zoo_header zoo_header;
Xint matched = 0;                          /* any files matched? */
Xunsigned int zoo_date, zoo_time;          /* for restoring archive timestamp */
X
X/* on entry option points to first letter */
X++option;
Xif (*option != '\0')
X   prterror ('f', inv_option, *option);
X
Xif ((zoo_file = fopen (zoo_path, FRWSTR)) == NULL)
X   prterror ('f', could_not_open, zoo_path);
X
X/* save archive timestamp */
X#ifdef GETUTIME
Xgetutime (zoo_path, &zoo_date, &zoo_time);
X#else
Xgettime (fileno(zoo_file), &zoo_date, &zoo_time);
X#endif
X
X/* read header and rewrite with updated version numbers */
Xrwheader (&zoo_header, zoo_file);
X
X/* Loop through and add comments for matching files */
Xwhile (1) {
X   this_dir_offset = ftell (zoo_file);    /* save pos'n of this dir entry */
X   readdir (&direntry, zoo_file, 1);      /* read directory entry */
X   next_ptr = direntry.next;              /* ptr to next dir entry */
X
X   /* exit on end of directory chain or end of file */
X   if (next_ptr == 0L || feof(stdin))
X      break;
X
X   /* add comments for matching non-deleted files */
X   if (!direntry.deleted && needed (direntry.fname)) {
X      matched++;
X      show_comment (&direntry, zoo_file, 1, direntry.fname);
X      get_comment (&direntry, zoo_file, direntry.fname);
X      fseek (zoo_file, this_dir_offset, 0);
X#ifndef NOSIGNAL
X      oldsignal = signal (SIGINT, SIG_IGN);
X#endif
X      fwr_dir (&direntry, zoo_file);
X      /* fwrite ((char *) &direntry, sizeof(direntry), 1, zoo_file); */
X#ifndef NOSIGNAL
X      signal (SIGINT, oldsignal);
X#endif
X   }
X   fseek (zoo_file, next_ptr, 0);   /* ..seek to next dir entry */
X} /* end while */
X
X#ifdef NIXTIME
Xfclose (zoo_file);
Xsetutime (zoo_path, zoo_date, zoo_time); /* restore timestamp */
X#else
Xsettime (fileno(zoo_file), zoo_date, zoo_time); /* restore timestamp */
Xfclose (zoo_file);
X#endif
X
Xif (!matched)
X   printf ("Zoo:  %s", no_match);
X} /* comment */
X
X/* show_comment() */
X/* shows comment on screen.  If show=1, says "Current comment is..." */
X
Xvoid show_comment (direntry, zoo_file, show, name)
Xstruct direntry *direntry;
XFILE *zoo_file;
Xint show;
Xchar *name;       /* name of file for which comment is being added */
X{
X   if (direntry->cmt_size != 0) {
X      unsigned int i;
X      char ch;
X      int newline = 1;
X      fseek (zoo_file, direntry->comment, 0);   
X      if (show)
X         printf ("Current comment for %s is:\n", name);
X      for (i = 0; i < direntry->cmt_size; i++) {/* show it */
X         ch = fgetc (zoo_file) & 0x7f;          /* 7 bits only */
X         if (newline)
X            printf (" |");    /* indent and mark comment lines thus */
X         fputchar (ch);
X         if (ch == '\n')
X            newline = 1;
X         else
X            newline = 0;
X      }
X      if (!newline)              /* always terminate with newline */
X         fputchar ('\n');
X   }
X} /* show_comment() */
X
X
X/* get_comment() */
X/* Shows user old comment and updates it */
X
X/* INPUT:
X   direntry points to current directory entry.
X   zoo_file is archive file.
X   this_path is full pathname of file being updated/added.
X
X   OUTPUT:
X   Comment is added to file and supplied directory entry is updated
X   with comment size and seek position but directory entry is
X   not written to file.  Exceptions:  If RETURN is hit as first line,
X   previous comment is left unchanged.  If /END is hit, previous
X   comment is superseded, even if new comment is null.
X*/
X
Xget_comment (direntry, zoo_file, this_path)  /* update comment */
Xregister struct direntry *direntry;
XFILE *zoo_file;
Xchar *this_path;
X{
X   unsigned int line_count = 0;        /* count of new comment lines */
X
X   fseek (zoo_file, 0L, 2);            /* ready to append new comment */
X   fprintf (stderr, "[Enter comment for %s then type /END]\n", this_path);
X   while (1) {
X      char cmt_line[COMMENT_LINE_SIZE];
X      int cmt_size;
X      if (fgets (cmt_line, sizeof(cmt_line), stdin) == NULL)
X         break;
X      line_count++;
X      if (line_count == 1) {                 /* first line typed */
X         if (!strcmp (cmt_line, "\n"))   /* exit if first line blank */
X            break;
X         direntry->comment = ftell (zoo_file);
X         direntry->cmt_size = 0;
X      }
X      if (!strcmpi (cmt_line, "/end\n"))
X         break;
X      cmt_size = strlen (cmt_line);
X      if (MAX_COMMENT_SIZE - direntry->cmt_size > cmt_size) {
X         direntry->cmt_size += (unsigned int) cmt_size;
X         if (fwrite (cmt_line, cmt_size, 1, zoo_file) < 1)
X            prterror ('f', disk_full);
X      }
X   } /* end while */
X} /* get_comment() */
X
SHAR_EOF
fi
if test -f 'crcdefs.c'
then
	echo shar: "will not over-write existing file 'crcdefs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'crcdefs.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) crcdefs.c 1.2 87/05/03 16:00:46";
X#endif /* LINT */
X
X#include "options.h"
X
X/* Global definitions for CRC calculation, adapted from the source code
Xfor ARC.EXE 5.12.
X
XWHEREAS
X
X   Algorithms cannot be copyrighted;
X   
X   And whereas this table of values, being determined by the needs of the 
X   algorithm and being expressible in no other substantially dissimilar 
X   manner, cannot be copyrighted either;
X
X   And whereas I claim no copyright over the contents of this file;
X
XNOW THEREFORE
X
X   It appears that the contents of this file are in the public domain.
X
X                                 -- Rahul Dhesi
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
SHAR_EOF
fi
if test -f 'debug.h'
then
	echo shar: "will not over-write existing file 'debug.h'"
else
sed 's/^X//' << \SHAR_EOF > 'debug.h'
X/* @(#) debug.h 1.2 87/05/03 16:00:48 */
X
X/* 
XThe contents of this file are hereby released to the public domain.
X
X                           -- Rahul Dhesi 1986/11/14
X
Xdefines conditional function calls 
X
XUsage:  The statement
X
X   debug((printf("y = %d\n", y)))
X
Xmay be placed anywhere where two or more statements could be used.  It will 
Xprint the value of y at that point.
X
XConditional compilation:
X
X   if DEBUG is defined
X      define the macro debug(X) to execute statement X
X   else
X      define the macro debug(X) to be null
X   endif
X*/
X
X#ifdef DEBUG
X#define  debug(x)    x;
X#else
X#define  debug(x)
X#endif
X
SHAR_EOF
fi
if test -f 'errors.i'
then
	echo shar: "will not over-write existing file 'errors.i'"
else
sed 's/^X//' << \SHAR_EOF > 'errors.i'
X/* @(#) errors.i 1.5 87/05/21 11:37:33 */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                           -- Rahul Dhesi 1986/11/14
X*/
X
X/* defines all the errors as externs.  Declarations must be
Xequivalent to those in prterror.c */
X
X/* These declarations must be equivalent to those in prterror.c */
Xextern char no_match[];
Xextern char failed_consistency[];
Xextern char invalid_header[];
Xextern char internal_error[];
Xextern char disk_full[];
Xextern char bad_directory[];
Xextern char no_memory[];
Xextern char too_many_files[];
X
X#ifndef OOZ
Xextern char wrong_version[];
Xextern char cant_process[];
Xextern char option_ignored[];
Xextern char inv_option[];
Xextern char bad_crc[];
X#endif
X
Xextern char could_not_open[];
X
SHAR_EOF
fi
if test -f 'fiz.c'
then
	echo shar: "will not over-write existing file 'fiz.c'"
else
sed 's/^X//' << \SHAR_EOF > 'fiz.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) fiz.c 1.4 87/05/29 12:53:42";
X#endif /* LINT */
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1987/02/06
X*/
X
X/*
XSearches for all directory entries in an archive and prints their
Xoffsets.  Zoo 1.41 and later may then be asked to extract a specific
Xfile by supplying the offset of the file.
X*/
X
X#include "options.h"
X#include <stdio.h>
X#include "various.h"
X#include "zoofns.h"
X#include "portable.h"         /* I/O definitions */
X#include "zoo.h"
X
X#ifdef LINT_ARGS
Xvoid prtctrl (char *);
Xvoid prtch (unsigned int);
X#else
Xvoid prtctrl ();
Xvoid prtch ();
X#endif
X
Xmain(argc,argv)
Xregister int argc;
Xregister char **argv;
X{
X   char *zooname;          /* name of archive to be read */
X   FILE *zoo_file;         /* the archive opened as a FILE */
X   int column;             /* column currently printing */
X   int state;              /* to keep track of how much of tag seen */
X   int inch;               /* char just read from archive */
X
X   static char usage1[] = "Fiz 1.0 (1987/01/30) public domain Zoo archive repair utility by Rahul Dhesi\n";
X   static char usage2[] = "Usage:  fiz archive[.zoo]  (\"fiz -h\" for help)\n";
X
X#ifdef SETBUF
X/* set stdout to unbuffered */
Xsetbuf (stdout, (char *) NULL);
X#endif
X
X   if (argc < 2) {
X      printf("%s%s", usage1, usage2);
X      exit (1);
X   }
X
X   if (strcmp(argv[1],"-h") == 0)
X      goto givehelp;
X
X   zooname = argv[1];
X
X   /* Add default extension if none supplied */
X   {
X      char *p, *q;
X      p = zooname + strlen(zooname);         /* point to last char */
X      while (p != zooname && *p != EXT_CH)
X         --p;
X      /* either found EXT_CH or reached beginning of zooname */
X      if (*p != EXT_CH) {
X         q = malloc(strlen(zooname) + strlen(EXT_DFLT) + 2);
X         if (q == NULL) {
X            printf("Fiz:  Ran out of memory.\n");
X            exit(1);
X         }
X         strcpy(q, zooname);
X         strcat(q, EXT_DFLT);
X         zooname = q;
X      }
X   }
X
X   zoo_file = fopen (zooname, FRDSTR);
X   if (zoo_file == NULL) {
X      printf("Fiz:  FATAL:  Could not open %s.\n", zooname);
X      exit(1);
X   }
X
X#define  NOTHING  1
X#define  CHAR_1   0xdc
X#define  CHAR_2   0xa7
X#define  CHAR_3   0xc4
X#define  CHAR_4   0xfd
X
X   column = 0;
X   state = NOTHING;
X   while ((inch = getc(zoo_file)) != EOF) {
X      inch = inch & 0xff;
X      if (state == NOTHING && inch == CHAR_1)
X         state = CHAR_1;
X      else if (state == CHAR_1 && inch == CHAR_2)
X         state = CHAR_2;
X      else if (state == CHAR_2 && inch == CHAR_3)
X         state = CHAR_3;
X      else if (state == CHAR_3 && inch == CHAR_4)
X         state = CHAR_4;
X      else
X         state = NOTHING;
X
X      if (state == CHAR_4) {           /* found tag */
X         long save_pos;
X         struct direntry direntry;
X         save_pos = ftell(zoo_file);
X         fseek(zoo_file, save_pos-4L, 0);          /* back to tag pos */
X         frd_dir(&direntry, zoo_file);             /* read dir entry */
X         printf("****************\n");
X
X         printf ("%8lu:  ", save_pos-4L);
X
X         if (direntry.dirlen > 0) {
X            printf ("[");
X            prtctrl (direntry.dirname);
X            printf ("]");
X         }
X
X         printf(" [");
X         prtctrl (direntry.fname);
X         printf ("]");
X
X         if (direntry.namlen > 0) {
X            printf (" [");
X            prtctrl (direntry.lfname);
X            printf ("]");
X         }
X         if (direntry.dir_crc != 0)
X            printf (" [*bad CRC*]");
X         printf ("\n");
X         fseek (zoo_file, save_pos, 0);         /* try again from there */
X      }
X   }
Xexit (0);      /* don't fall through */
X
Xgivehelp:
X
X   printf ("Fiz is used to help you recover data from a damaged archive.  Fiz\n");
X   printf ("searches the specified archive and prints the position (a decimal\n");
X   printf ("number) of each directory entry found and the directory name and\n");
X   printf ("filename associated with it.\n\n");
X
X   printf ("Make a record of the output of Fiz by redirecting it to a file.  Then\n");
X   printf ("use Zoo version 1.41 or higher to list or extract files in the\n");
X   printf ("damaged archives starting at a chosen position.  For example, you can\n");
X   printf ("start extracting files from archive \"badarc.zoo\" at position 1098\n");
X   printf ("with the command\n\n");
X
X   printf ("     zoo x@1098 badarc\n\n");
X
X   printf ("Zoo will ignore the first 1097 bytes of the damaged archive and you\n"); 
X   printf ("should be able to recover the undamaged files from the rest of the\n");
X   printf ("archive.\n\n");
X   printf ("The position supplied to Zoo should have been obtained from Fiz and\n");
X   printf ("must correspond to an undamaged directory entry in the archive.\n");
X
X   exit(1);
X}
X
X/*
Xprtctrl() prints a string with all unprintable characters converted
Xto printable form.  To avoid the program running astray trying to
Xprint damaged data, no more than MAXPRT characters are printed.
XCharacters with the 8th bit set are printed preceded with ~.  Control
Xcharacters are printed preceded with ^.  Both ~ and ^ may preced
Xthe character if a control character has the 8th bit set.
X*/
X#define  MAXPRT      50
X
Xvoid prtctrl (str)
Xchar *str;
X{
X   unsigned int ch;
X   int count;
X   count = 0;
X
X   while (count < MAXPRT && *str != '\0') {
X      ch = (unsigned) *str;
X      prtch(ch);
X      str++;
X      count++;
X   }
X}
X
X/*
XDoes the actual character printing for prtctrl()
X*/
Xvoid prtch(ch)
Xunsigned int ch;
X{
X   /* assumes ASCII character set */
X   if (ch < ' ') {                        /* ^@ through ^_ */
X      printf("^%c", ch + 0x40);
X   } else if (ch == 0x7f) {               /* DEL */
X      printf("^?");
X   } else if (ch > 0x7f) {                /* 8th bit set */
X      printf("~");                        /* .. so precede with ~ */
X      prtch(ch & 0x7f);                   /* slick recursive call */
X   } else
X      printf("%c", ch);                   /* plain char */
X}
SHAR_EOF
fi
if test -f 'generic.c'
then
	echo shar: "will not over-write existing file 'generic.c'"
else
sed 's/^X//' << \SHAR_EOF > 'generic.c'
X#ifndef LINT
Xstatic char genericid[]="@(#) generic.c 1.5 87/05/29 12:53:52";
X#endif /* LINT */
X
X/* Generic template for machine-dependent functions. */
X
X/****************
Xfunction trunc() truncates a file.
X*/
X
Xint trunc (handle)
Xint handle;
X{
X   /* code to truncate file goes here -- may be left empty */
X}
X
X/*****************
XFunction gettime() or getutime() gets the date and time of the file handle 
Xor filename supplied.  Date and time is in MSDOS format.
X*/
X#ifdef GETUTIME
Xgetutime (fname, date, time)
Xchar *fname;
X#else
Xgettime (handle,date,time)
Xint handle;
X#endif
Xint *date, *time;
X{
X   *date = *time = 0; /* not yet implemented */
X}
X
X/*****************
XFunction settime() or setutime() sets the date and time of the file handle
Xor filename supplied.  Date and time is in MSDOS format.
X*/
X#ifdef NIXTIME
Xint setutime(path,date,time)
Xchar *path;
X#else
Xint settime(handle, date, time)
Xint handle;
X#endif
Xunsigned int date, time;
X{
X   /* not yet implemented */
X}
X
X/*****************
XFunction mktemp() accepts a template of the form `baseXXXXXX' where
Xbase is an arbitrary string, and returns a unique temporary filename.
XIf template is not correct, it is returned unchanged.
X*/
Xchar *mktemp(template)
Xchar *template;
X{
X
X#ifndef NDEBUG
X   if (instr(template, "XXXXXX") == -1)
X      prterror ('w', "Incorrect template [%s] supplied to mktemp().\n",
X         template);
X#endif
X
X   strcpy(&template[instr(template, "XXXXXX")],"{zoo}.@@@");
X   return (template);
X}
X
X/*****************
XFunction isadir() or isuadir() returns 1 if supplied handle or 
Xfilename is a directory or other special file that should not be 
Xarchived, else it returns 0.
X*/
X
X#ifdef CHEKDIR
Xint isadir(han)
Xint han;
X{
X   return (0); /* by default assume never a directory */
X}
X#endif
X
X#ifdef CHEKUDIR
Xint isuadir(path)
Xchar *path;
X{
X   return (0); /* by default assume never a directory */
X}
X#endif
X
X/****************
XFunction fixfname() converts the supplied filename to a syntax
Xlegal for the host system.  It is used during extraction to make sure
Xthat a file can be extracted even if a badly-implemented archiver
Xstored it with an illegal filename.
X*/
X
Xchar *fixfname(fname)
Xchar *fname;
X{
X   return (fname); /* default is no-op */
X}
X
X/*****************
XFunction nextfile() is effectively a no-op.  Any wildcard expansion 
Xmust have been done before Zoo receives the arguments.
X*/
X
X#define FMAX 1
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   static int first_time [FMAX+1];
X   static char saved_fspec [FMAX+1][PATHSIZE];  /* our own copy of filespec */
X
X   if (what == 0) {
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return (NULL);
X   }
X
X   if (first_time[fileset]) {
X      first_time[fileset] = 0;
X      return (saved_fspec[fileset]);
X   } else {
X      return (NULL);
X   }
X}
SHAR_EOF
fi
if test -f 'getfile.c'
then
	echo shar: "will not over-write existing file 'getfile.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getfile.c'
X#ifndef LINT
Xstatic char sccsid[]="@(#) getfile.c 1.2 87/05/03 16:00:59";
X#endif /* LINT */
X
X/*
XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
X*/
X
X#include "options.h"
X/* 
XThis function copies n characters from the source file to the destination
X
XInput:   output_han:    handle of destination file.
X         input_han:     handle of source file.
X         count:         count of characters to copy.
X         docrc:         0 if crc not wanted
X
XIf count is -1, copying is done until eof is encountered.
X
XThe source file is transferred to the current file pointer position in the
Xdestination file, using the handles provided.  Function return value is 0 
Xif no error, 2 if write error, and 3 if read error.  
X
XNote, however, that if the output handle is -2, it is taken to be the
Xnull device and no output actually occurs.  
X
XIf docrc is not 0, the global variable crccode is updated via addbfcrc().
XThis is done even if the output is to the null device.
X*/
X
X#include <stdio.h>
X#include "various.h"
X#include "zoofns.h"
X#include "zoomem.h"
X
Xint getfile(input_han, output_han, count, docrc)
Xint input_han, output_han;
Xlong count;
Xint docrc;
X{
X   register int how_much;
X
X   if (count == -1) {
X      while ((how_much = read (input_han, out_buf_adr, MEM_BLOCK_SIZE)) > 0) {
X         if (how_much == -1 || 
X               write (output_han, out_buf_adr, how_much) != how_much)
X            return (2);
X         if (docrc)
X            addbfcrc (out_buf_adr,how_much);
X      }
X      return (0);
X   }
X
X   while (count > 0) {
X      if (count > MEM_BLOCK_SIZE)
X         how_much = MEM_BLOCK_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      if (docrc)
X         addbfcrc (out_buf_adr, how_much);
X      if (output_han != -2)
X         if (write (output_han, out_buf_adr, how_much) != how_much)
X            return (2);
X   }
X   return (0);
X}
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.net