Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!hoptoad!mejac!decwrl!labrea!husc6!ddl
From: ddl@husc6.UUCP
Newsgroups: alt.sources
Subject: arc repost (sort of) 4/4
Message-ID: <2594@husc6.UUCP>
Date: Thu, 23-Jul-87 23:57:29 EDT
Article-I.D.: husc6.2594
Posted: Thu Jul 23 23:57:29 1987
Date-Received: Sat, 25-Jul-87 12:04:38 EDT
Organization: Harvard University Computer Services
Lines: 1255
Keywords: arc UnSquash

#! /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 the files:
#	arcdos.c
#	arcm.h
#	arcsvc.c
#	arctst.c
#	arcunp.c
#	arcusq.c
#	arcvax.c
#	squash.c
# This archive created: Thu Jul 23 23:40:51 1987
export PATH; PATH=/bin:$PATH
if test -f 'arcdos.c'
then
	echo shar: will not over-write existing file "'arcdos.c'"
else
cat << \SHAR_EOF > 'arcdos.c'
static char *RCSid = "$Header: arcdos.c,v 1.2 86/07/15 07:53:02 turner Exp $";

/*
 * $Log:	arcdos.c,v $
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 *
 * Revision 1.2  86/07/15  07:53:02  turner
 * 
 * 
 * Revision 1.1  86/06/26  15:00:15  turner
 * initial version
 * 
 * 
 */

/*  ARC - Archive utility - ARCDOS

$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =1.43), created on $tag(
TED_DATE DB =11/09/85) at $tag(
TED_TIME DB =22:24:44))#
$undefine(tag)#
    $version

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

    By:  Thom Henderson

    Description:
         This file contains certain DOS level routines that assist
         in doing fancy things with an archive, primarily reading and
         setting the date and time last modified.

         These are, by nature, system dependant functions.  But they are
         also, by nature, very expendable.

    Language:
         Computer Innovations Optimizing C86
*/
#include 
#include "arc.h"
#if MSDOS
#include "fileio2.h"                   /* needed for filehand */
#endif
#if BSD
#include 
#include 
#endif

INT getstamp(f,date,time)                  /* get a file's date/time stamp */
FILE *f;                               /* file to get stamp from */
unsigned INT *date, *time;             /* storage for the stamp */
{
#if MSDOS
    struct {INT ax,bx,cx,dx,si,di,ds,es;} reg;

    reg.ax = 0x5700;                   /* get date/time */
    reg.bx = filehand(f);              /* file handle */
    if(sysint21(®,®)&1)          /* DOS call */
         printf("Get timestamp fail (%d)\n",reg.ax);

    *date = reg.dx;                    /* save date/time */
    *time = reg.cx;
#endif
#if BSD
    struct stat *buf;
    int day,hr,min,sec,yr,imon;
    static char mon[4],*mons[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
					"Aug","Sep","Oct","Nov","Dec"};

    buf = (struct stat *)malloc(sizeof(struct stat));
    fstat(f->_file,buf); 
/*
 * assume the UGLY ibm format for date and time
 */
    sscanf(ctime(&(buf->st_mtime)),"%*4s%3s%d%d:%d:%d%d"
	,mon,&day,&hr,&min,&sec,&yr);
    for(imon = 0; imon < 12 && strcmp(mon,mons[imon]); imon++);

    *date = (unsigned INT)(((yr-1980)<<9)+((imon+1)<<5)+day);
    *time = (unsigned INT)((hr<<11)+(min<<5)+sec/2);
#endif
}

INT setstamp(f,date,time)                  /* set a file's date/time stamp */
FILE *f;                               /* file to set stamp on */
unsigned INT date, time;               /* desired date, time */
{
#if MSDOS
    struct {INT ax,bx,cx,dx,si,di,ds,es;} reg;

    fflush(f);                         /* force any pending output */

    reg.ax = 0x5701;                   /* set date/time */
    reg.bx = filehand(f);              /* file handle */
    reg.cx = time;                     /* desired time */
    reg.dx = date;                     /* desired date */
    if(sysint21(®,®)&1)          /* DOS call */
         printf("Set timestamp fail (%d)\n",reg.ax);
#endif
}

static INT filehand(stream)            /* find handle on a file */
struct bufstr *stream;                 /* file to grab onto */
{
#if MSDOS
    return stream->bufhand;            /* return DOS 2.0 file handle */
#endif
}

INT izadir(filename)			/* Is filename a directory? */
char *filename;
{
#if MSDOS
    return 0;
#else
struct stat buf;

    if (stat(filename,&buf)!=0) return 0;   /* Ignore if stat fails since we */
    else return (buf.st_mode & S_IFDIR);    /* trap for bad file elsewhere.  */

#endif
}
SHAR_EOF
chmod +x 'arcdos.c'
fi # end of overwriting check
if test -f 'arcm.h'
then
	echo shar: will not over-write existing file "'arcm.h'"
else
cat << \SHAR_EOF > 'arcm.h'
/*
 * $Header: arcm.h,v 1.2 86/07/15 07:53:40 turner Exp $
 */

/*
 * $Log:	arcm.h,v $
 * Revision 1.2  86/07/15  07:53:40  turner
 * 
 * 
 * Revision 1.1  86/06/26  15:01:25  turner
 * initial version
 * 
 * 
 */

/*
 *
 * ARC archive utility - standard MACRO insert file.
 *
 * parameters:
 *
 */

#define ARCMARK 26 /*                   special archive marker        */
#define ARCVER 9   /*                   archive header version code   */
#define STRLEN 100 /*                   system standard string length */
#define FNLEN 13   /*                   file name length              */
#define MAXARG 25  /*                   maximum number of arguments   */

#define ARC 1
#define XARC 0
SHAR_EOF
chmod +x 'arcm.h'
fi # end of overwriting check
if test -f 'arcsvc.c'
then
	echo shar: will not over-write existing file "'arcsvc.c'"
else
cat << \SHAR_EOF > 'arcsvc.c'
static char *RCSid = "$Header: arcsvc.c,v 1.2 86/07/15 07:54:19 turner Exp $";

/*
 * $Log:	arcsvc.c,v $
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 *
 * Revision 1.2  86/07/15  07:54:19  turner
 * 
 * 
 * Revision 1.1  86/06/26  15:00:57  turner
 * initial version
 * 
 * 
 */

/*  ARC - Archive utility - ARCSVC

$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =2.15), created on $tag(
TED_DATE DB =12/17/85) at $tag(
TED_TIME DB =15:17:16))#
$undefine(tag)#
    $version

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

    By:  Thom Henderson

    Description:
         This file contains service routines needed to maintain an archive.

    Language:
         Computer Innovations Optimizing C86
*/
#include 
#include "arc.h"

INT openarc(chg)                           /* open archive */
INT chg;                               /* true to open for changes */
{
    FILE *fopen();                     /* file opener */

    if(!(arc=fopen(arcname,"r")))
    {    if(chg)
              printf("Creating new archive: %s\n",arcname);
         else abort("Cannot read archive: %s",arcname);
    }

    if(chg)                            /* if opening for changes */
         if(!(new=fopen(newname,"w")))
              abort("Cannot create archive copy: %s",newname);
}

INT closearc(chg)                          /* close an archive */
INT chg;                               /* true if archive was changed */
{
    if(arc)                            /* if we had an initial archive */
         fclose(arc);                  /* then close it */

    if(chg)                            /* if things have changed */
    {    setstamp(new,arcdate,arctime);/* archive matches newest file */
         fclose(new);                  /* close the new copy */

         if(arc)                       /* if we had an original archive */
         {    if(keepbak)              /* if a backup is wanted */
              {    unlink(bakname);    /* erase any old copies */
                   if(rename(arcname,bakname))
                        abort("Cannot rename %s to %s",arcname,bakname);
                   printf("Keeping backup archive: %s\n",bakname);
              }
              else if(unlink(arcname))
                   abort("Cannot delete old archive: %s",arcname);
         }

         if(rename(newname,arcname))
              abort("Cannot rename %s to %s",newname,arcname);
    }
}

/* CRC computation logic

   The logic for this method of calculating the CRC 16 bit polynomial
   is taken from an article by David Schwaderer in the April 1985
   issue of PC Tech Journal.
*/

static INT crctab[] =                  /* CRC lookup table */
{   0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
INT addcrc(crc,c)                      /* update a CRC check */
INT crc;                               /* running CRC value */
unsigned char c;                       /* character to add */
{
    return (((crc>>8)&0x00ff) ^ crctab[(crc^c)&0x00ff]) & 0x0000ffff;
}
SHAR_EOF
chmod +x 'arcsvc.c'
fi # end of overwriting check
if test -f 'arctst.c'
then
	echo shar: will not over-write existing file "'arctst.c'"
else
cat << \SHAR_EOF > 'arctst.c'
static char *RCSid = "$Header: arctst.c,v 1.1 86/06/26 15:01:02 turner Exp $";

/*
 * $Log:	arctst.c,v $
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 *
 * Revision 1.1  86/06/26  15:01:02  turner
 * initial version
 * 
 * 
 */

/*  ARC - Archive utility - ARCTST

$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =2.12), created on $tag(
TED_DATE DB =02/03/86) at $tag(
TED_TIME DB =23:00:40))#
$undefine(tag)#
    $version

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

    By:  Thom Henderson

    Description:
         This file contains the routines used to test archive integrity.

    Language:
         Computer Innovations Optimizing C86
*/
#include 
#include "arc.h"

INT tstarc()                               /* test integrity of an archive */
{
    struct heads hdr;                  /* file header */
    long arcsize, ftell();             /* archive size */

    openarc(0);                        /* open archive for reading */
    fseek(arc,0L,2);                   /* move to end of archive */
    arcsize = ftell(arc);              /* see how big it is */
    fseek(arc,0L,0);                   /* return to top of archive */

    printf ("Testing archive...\n");
    while(readhdr(&hdr,arc))
    {    if(ftell(arc)+hdr.size>arcsize)
         {    printf("Archive truncated in file %s\n",hdr.name);
              nerrs++;
              break;
         }

         else
         {    printf("    File: %-12s  ",hdr.name);
              fflush(stdout);
              if(unpack(arc,NULL,&hdr))
                   nerrs++;
              else printf("okay\n");
         }
    }

    if(nerrs<1)
         printf("No errors detected\n");
    else if(nerrs==1)
         printf("One error detected\n");
    else printf("%d errors detected\n",nerrs);
}
SHAR_EOF
chmod +x 'arctst.c'
fi # end of overwriting check
if test -f 'arcunp.c'
then
	echo shar: will not over-write existing file "'arcunp.c'"
else
cat << \SHAR_EOF > 'arcunp.c'
static char *RCSid = "$Header: arcunp.c,v 1.2 86/07/15 07:54:25 turner Exp $";

/*
 * $Log:	arcunp.c,v $
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 *
 * Revision 1.2  86/07/15  07:54:25  turner
 * 
 * 
 * Revision 1.1  86/06/26  15:01:04  turner
 * initial version
 * 
 * 
 */

/*  ARC - Archive utility - ARCUNP

$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =3.16), created on $tag(
TED_DATE DB =02/03/86) at $tag(
TED_TIME DB =23:01:16))#
$undefine(tag)#
    $version

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

    By:  Thom Henderson

    Description:
         This file contains the routines used to expand a file
         when taking it out of an archive.

    Language:
         Computer Innovations Optimizing C86
*/
#include 
#include "arc.h"

/* stuff for repeat unpacking */

#define DLE 0x90                       /* repeat byte flag */

static INT state;                      /* repeat unpacking state */

/* repeat unpacking states */

#define NOHIST 0                       /* no relevant history */
#define INREP 1                        /* sending a repeated value */

static INT crcval;                     /* CRC check value */
static long size;                      /* bytes to read */

INT unpack(f,t,hdr)                    /* unpack an archive entry */
FILE *f, *t;                           /* source, destination */
struct heads *hdr;                     /* pointer to file header data */
{
 INT c;                             /* one char of stream */
    INT putc_unp();
    INT putc_ncr();
    INT getc_unp();

    /* setups common to all methods */

    crcval = 0;                        /* reset CRC check value */
    size = hdr->size;                  /* set input byte counter */
    state = NOHIST;                    /* initial repeat unpacking state */
    setcode();                         /* set up for decoding */

    /* use whatever method is appropriate */

    switch(hdrver)                     /* choose proper unpack method */
    {
    case 1:                            /* standard packing */
    case 2:
         while((c=getc_unp(f))!=EOF)
              putc_unp(c,t);
         break;

    case 3:                            /* non-repeat packing */
         while((c=getc_unp(f))!=EOF)
              putc_ncr(c,t);
         break;

    case 4:                            /* Huffman squeezing */
         init_usq(f);
         while((c=getc_usq(f))!=EOF)
              putc_ncr(c,t);
         break;

    case 5:                            /* Lempel-Zev compression */
         init_ucr(0);
         while((c=getc_ucr(f))!=EOF)
              putc_unp(c,t);
         break;

    case 6:                            /* Lempel-Zev plus non-repeat */
         init_ucr(0);
         while((c=getc_ucr(f))!=EOF)
              putc_ncr(c,t);
         break;

    case 7:                            /* L-Z plus ncr with new hash */
         init_ucr(1);
         while((c=getc_ucr(f))!=EOF)
              putc_ncr(c,t);
         break;

    case 8:                            /* dynamic Lempel-Zev */
         decomp(f,t);
         break;

    case 9:
	 sqdecomp(f,t);
	 break;

    default:                           /* unknown method */
         if(warn)
         {    printf("I don't know how to unpack file %s\n",hdr->name);
              printf("I think you need a newer version of ARC\n");
              nerrs++;
         }
         fseek(f,hdr->size,1);         /* skip over bad file */
         return 1;                     /* note defective file */
    }

    /* cleanups common to all methods */

    if((crcval&0xffff)!=(hdr->crc&0x0000ffff))
    {    if(warn)
         {    printf("WARNING: File %s fails CRC check\n",hdr->name);
              nerrs++;
         }
         return 1;                     /* note defective file */
    }
    return 0;                          /* file is okay */
}

/*  This routine is used to put bytes in the output file.  It also
    performs various housekeeping functions, such as maintaining the
    CRC check value.
*/

INT putc_unp(c,t)                   /* output an unpacked byte */
char c;                                /* byte to output */
FILE *t;                               /* file to output to */
{
    crcval = addcrc(crcval,c);         /* update the CRC check value */
    putc_tst(c,t);
}

/*  This routine is used to decode non-repeat compression.  Bytes are
    passed one at a time in coded format, and are written out uncoded.
    The data is stored normally, except that runs of more than two
    characters are represented as:

           

    With a special case that a count of zero indicates a DLE as data,
    not as a repeat marker.
*/

INT putc_ncr(c,t)                          /* put NCR coded bytes */
unsigned char c;                       /* next byte of stream */
FILE *t;                               /* file to receive data */
{
    static INT lastc;                  /* last character seen */

    switch(state)                      /* action depends on our state */
    {
    case NOHIST:                       /* no previous history */
         if(c==DLE)                    /* if starting a series */
              state = INREP;           /* then remember it next time */
         else putc_unp(lastc=c,t);     /* else nothing unusual */
         return;

    case INREP:                        /* in a repeat */
         if(c)                         /* if count is nonzero */
              while(--c)               /* then repeatedly ... */
                   putc_unp(lastc,t);  /* ... output the byte */
         else putc_unp(DLE,t);         /* else output DLE as data */
         state = NOHIST;               /* back to no history */
         return;

    default:
         abort("Bad NCR unpacking state (%d)",state);
    }
}

/*  This routine provides low-level byte input from an archive.  This
    routine MUST be used, as end-of-file is simulated at the end of
    the archive entry.
*/

INT getc_unp(f)                        /* get a byte from an archive */
FILE *f;                               /* archive file to read */
{
    if(!size)                          /* if no data left */
         return EOF;                   /* then pretend end of file */

    size--;                            /* deduct from input counter */
    return code(fgetc(f));             /* and return next decoded byte */
}
SHAR_EOF
chmod +x 'arcunp.c'
fi # end of overwriting check
if test -f 'arcusq.c'
then
	echo shar: will not over-write existing file "'arcusq.c'"
else
cat << \SHAR_EOF > 'arcusq.c'
static char *RCSid = "$Header: arcusq.c,v 1.2 86/07/15 07:54:30 turner Exp $";

/*
 * $Log:	arcusq.c,v $
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 *
 * Revision 1.2  86/07/15  07:54:30  turner
 * 
 * 
 * Revision 1.1  86/06/26  15:01:07  turner
 * initial version
 * 
 * 
 */

/*  ARC - Archive utility - ARCUSQ

$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =3.13), created on $tag(
TED_DATE DB =01/30/86) at $tag(
TED_TIME DB =20:11:42))#
$undefine(tag)#
    $version

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

    By:  Thom Henderson

    Description:
         This file contains the routines used to expand a file
         which was packed using Huffman squeezing.

         Most of this code is taken from an USQ program by Richard
         Greenlaw, which was adapted to CI-C86 by Robert J. Beilstein.

    Language:
         Computer Innovations Optimizing C86
*/
#include 
#include "arc.h"

/* stuff for Huffman unsqueezing */

#define ERROR (-1)

#define SPEOF 256                      /* special endfile token */
#define NUMVALS 257                    /* 256 data values plus SPEOF */

EXTERN struct nd                       /* decoding tree */
{ INT child[2];                      /* left, right */
}   node[NUMVALS];                     /* use large buffer */

static INT bpos;                       /* last bit position read */
static INT curin;                      /* last byte value read */
static INT numnodes;                   /* number of nodes in decode tree */

static INT get_int(f)                  /* get an integer */
FILE *f;                               /* file to get it from */
{
    INT i;

    i = getc_unp(f);
    return (short)(i | (getc_unp(f)<<8));
}

INT init_usq(f)                            /* initialize Huffman unsqueezing */
FILE *f;                               /* file containing squeezed data */
{
 INT i;                             /* node index */

    bpos = 99;                         /* force initial read */

    numnodes = get_int(f);

    if(numnodes<0 || numnodes>=NUMVALS)
         abort("File has an invalid decode tree");

    /* initialize for possible empty tree (SPEOF only) */

    node[0].child[0] = -(SPEOF + 1);
    node[0].child[1] = -(SPEOF + 1);

    for(i=0; i=0; )                   /* work down(up?) from root */
    {    if(++bpos>7)
         {    if((curin=getc_unp(f)) == ERROR)
                   return(ERROR);
              bpos = 0;

              /* move a level deeper in tree */
              i = node[i].child[1&curin];
         }
         else i = node[i].child[1 & (curin >>= 1)];
    }

    /* decode fake node index to original data value */

    i = -(i + 1);

    /* decode special endfile token to normal EOF */

    i = (i==SPEOF) ? EOF : i;
    return i;
}
SHAR_EOF
chmod +x 'arcusq.c'
fi # end of overwriting check
if test -f 'arcvax.c'
then
	echo shar: will not over-write existing file "'arcvax.c'"
else
cat << \SHAR_EOF > 'arcvax.c'
#include 
#include 
#include "arc.h"

/*
 * Misc routines to emulate IBM MSDOS functions under BSD
 *
 * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
 * 	Bludgeoned into submission for VAX 11/780 BSD4.2
 *	(ugly code, but fewer core dumps)
 */
INT upper(string)
char *string;
{
    char *p;

    for(p = string; *p != NULL; p++)
	if(islower(*p))
	    *p = toupper(*p);
}
char *setmem(dest,size,c)
char *dest,c;
INT size;
{
 INT i;

    for(i = 0; i < size; dest[i] = c, i++);
    return(&dest[0]);
}
char *gcdir(dirname)
char *dirname;

{
	if(dirname == NULL || strlen(dirname) == 0)
		dirname = (char *)malloc(1024);

	getwd(dirname);
}
INT abort(s,arg1,arg2,arg3)
char *s;
{
    fprintf(stderr,"ARC: ");
    fprintf(stderr,s,arg1,arg2,arg3);
    fprintf(stderr,"\n");
#if BSD
    perror("BSD");
#endif
    exit(1);
}
SHAR_EOF
chmod +x 'arcvax.c'
fi # end of overwriting check
if test -f 'squash.c'
then
	echo shar: will not over-write existing file "'squash.c'"
else
cat << \SHAR_EOF > 'squash.c'
/*  ARC - Archive utility - SQUASH

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

	This is a quick hack to ARCLZW to make it handle squashed archives.
	Dan Lanciani (ddl@harvard.*) July 87

*/
#include 
#include "arc.h"

/* definitions for the new dynamic Lempel-Zev crunching */

#define BITS   13                      /* maximum bits per code */
#define HSIZE  10007                    /* 80% occupancy */
#define INIT_BITS 9                    /* initial number of bits/code */

static INT n_bits;                     /* number of bits/code */
static INT maxcode;                    /* maximum code, given n_bits */
#define MAXCODE(n)      ((1<<(n)) - 1) /* maximum code calculation */
static INT maxcodemax =  1 << BITS;    /* largest possible code (+1) */

static unsigned char buf[BITS];        /* input/output buffer */

static unsigned char lmask[9] =        /* left side masks */
{   0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
static unsigned char rmask[9] =        /* right side masks */
{   0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

static INT offset;                     /* byte offset for code output */
static long in_count;                  /* length of input */
static long bytes_out;                 /* length of compressed output */
static unsigned INT ent;

static long htab[HSIZE];               /* hash code table   (crunch) */
static unsigned INT codetab[HSIZE];    /* string code table (crunch) */

static unsigned INT *prefix = codetab; /* prefix code table (uncrunch) */

static unsigned char suffix[HSIZE];    /* suffix table (uncrunch) */
static INT free_ent;                   /* first unused entry */
static INT firstcmp;                   /* true at start of compression */
static unsigned char stack[HSIZE];     /* local push/pop stack */

/*
 * block compression parameters -- after all codes are used up,
 * and compression rate changes, start over.
 */

static INT clear_flg;
static long ratio;
#define CHECK_GAP 10000                /* ratio check interval */
static long checkpoint;

/*
 * the next two codes should not be changed lightly, as they must not
 * lie within the contiguous general code space.
 */
#define FIRST   257                    /* first free entry */
#define CLEAR   256                    /* table clear output code */

static INT cl_block(t)                     /* table clear for block compress */
FILE *t;                               /* our output file */
{
    long rat;
    INT putcode();

    checkpoint = in_count + CHECK_GAP;

    if(in_count > 0x007fffff)          /* shift will overflow */
    {    rat = bytes_out >> 8;
         if(rat == 0)                  /* Don't divide by zero */
              rat = 0x7fffffff;
         else rat = in_count / rat;
    }
    else rat = (in_count<<8)/bytes_out;/* 8 fractional bits */

    if(rat > ratio)
         ratio = rat;
    else
    {    ratio = 0;
         setmem	(htab,HSIZE*sizeof(long),0xff);
         free_ent = FIRST;
         clear_flg = 1;
         putcode(CLEAR,t);
    }
}

/*****************************************************************
 *
 * Output a given code.
 * Inputs:
 *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
 *              that n_bits =< (long)wordsize - 1.
 * Outputs:
 *      Outputs code to the file.
 * Assumptions:
 *      Chars are 8 bits long.
 * Algorithm:
 *      Maintain a BITS character long buffer (so that 8 codes will
 * fit in it exactly).  When the buffer fills up empty it and start over.
 */

static INT putcode(code,t)                 /* output a code */
INT code;                              /* code to output */
FILE *t;                               /* where to put it */
{
 INT r_off = offset;                /* right offset */
 INT bits = n_bits;                 /* bits to go */
 unsigned char *bp = buf;           /* buffer pointer */
 INT n;                             /* index */

    if(code >= 0)                      /* if a real code */
    {    /*
          * Get to the first byte.
          */
         bp += (r_off >> 3);
         r_off &= 7;

         /*
          * Since code is always >= 8 bits, only need to mask the first
          * hunk on the left.
          */
         *bp = (*bp&rmask[r_off]) | (code<>= (8 - r_off);

         /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
         if(bits >= 8)
         {    *bp++ = code;
              code >>= 8;
              bits -= 8;
         }

         /* Last bits. */
         if(bits)
              *bp = code;

         offset += n_bits;

         if(offset == (n_bits << 3))
         {    bp = buf;
              bits = n_bits;
              bytes_out += bits;
              do
                   putc_pak(*bp++,t);
              while(--bits);
              offset = 0;
         }

         /*
          * If the next entry is going to be too big for the code size,
          * then increase it, if possible.
          */
         if(free_ent>maxcode || clear_flg>0)
         {    /*
               * Write the whole buffer, because the input side won't
               * discover the size increase until after it has read it.
               */
              if(offset > 0)
              {    bp = buf;           /* reset pointer for writing */
                   bytes_out += n = n_bits;
                   while(n--)
                        putc_pak(*bp++,t);
              }
              offset = 0;

              if(clear_flg)            /* reset if clearing */
              {    maxcode = MAXCODE(n_bits = INIT_BITS);
                   clear_flg = 0;
              }
              else                     /* else use more bits */
              {    n_bits++;
                   if(n_bits == BITS)
                        maxcode = maxcodemax;
                   else
                        maxcode = MAXCODE(n_bits);
              }
         }
    }

    else                               /* dump the buffer on EOF */
    {    bytes_out += n = (offset+7) / 8;

         if(offset > 0)
              while(n--)
                   putc_pak(*bp++,t);
         offset = 0;
    }
}

/*****************************************************************
 *
 * Read one code from the standard input.  If EOF, return -1.
 * Inputs:
 *      cmpin
 * Outputs:
 *      code or -1 is returned.
 */

static INT getcode(f)                  /* get a code */
FILE *f;                               /* file to get from */
{
 INT code;
    static INT offset = 0, size = 0;
 INT r_off, bits;
    unsigned char *bp = buf;

    if(clear_flg > 0 || offset >= size || free_ent > maxcode)
    {    /*
          * If the next entry will be too big for the current code
          * size, then we must increase the size.  This implies reading
          * a new buffer full, too.
          */
         if(free_ent > maxcode)
         {    n_bits++;
              if(n_bits == BITS)
                   maxcode = maxcodemax;    /* won't get any bigger now */
              else maxcode = MAXCODE(n_bits);
         }
         if(clear_flg > 0)
         {    maxcode = MAXCODE(n_bits = INIT_BITS);
              clear_flg = 0;
         }

         for(size=0; size> 3);
    r_off &= 7;

    /* Get first part (low order bits) */
    code = (*bp++ >> r_off);
    bits -= 8 - r_off;
    r_off = 8 - r_off;                 /* now, offset into code word */

    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
    if(bits >= 8)
    {    code |= *bp++ << r_off;
         r_off += 8;
         bits -= 8;
    }
    /* high order bits. */
    code |= (*bp & rmask[bits]) << r_off;
    offset += n_bits;

    return code;
}

/*
 * compress a file
 *
 * Algorithm:  use open addressing double hashing (no chaining) on the
 * prefix code / next character combination.  We do a variant of Knuth's
 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 * secondary probe.  Here, the modular division first probe is gives way
 * to a faster exclusive-or manipulation.  Also do block compression with
 * an adaptive reset, where the code table is cleared when the compression
 * ratio decreases, but after the table fills.  The variable-length output
 * codes are re-sized at this point, and a special CLEAR code is generated
 * for the decompressor.
 */

INT sqinit_cm(f,t)                           /* initialize for compression */
FILE *f;                               /* file we will be compressing */
FILE *t;                               /* where we will put it */
{
    offset = 0;
    bytes_out = 0;
    clear_flg = 0;
    ratio = 0;
    in_count = 1;
    checkpoint = CHECK_GAP;
    maxcode = MAXCODE(n_bits = INIT_BITS);
    free_ent = FIRST;
    setmem(htab,HSIZE*sizeof(long),0xff);
    n_bits = INIT_BITS;                /* set starting code size */

    firstcmp = 1;                      /* next byte will be first */
}

INT sqputc_cm(c,t)                           /* compress a character */
unsigned char c;                       /* character to compress */
FILE *t;                               /* where to put it */
{
    static long fcode;
    static INT hshift;
 INT i;
 INT disp;

    if(firstcmp)                       /* special case for first byte */
    {    ent = c;                      /* remember first byte */

         hshift = 0;
         for(fcode=(long)HSIZE;  fcode<65536L; fcode*=2L)
              hshift++;
         hshift = 8 - hshift;          /* set hash code range bund */

         firstcmp = 0;                 /* no longer first */
         return;
    }

    in_count++;
    fcode =(long)(((long)c << BITS)+ent);
    i = (c< 0)
         goto probe;

nomatch:
    putcode(ent,t);
    ent = c;
    if(free_ent < maxcodemax)
    {    codetab[i] = free_ent++;      /* code -> hashtable */
         htab[i] = fcode;
    }
    else if((long)in_count >= checkpoint)
         cl_block(t);
}

long sqpred_cm(t)                        /* finish compressing a file */
FILE *t;                               /* where to put it */
{
    putcode(ent,t);                    /* put out the final code */
    putcode(-1,t);                     /* tell output we are done */

    return bytes_out;                  /* say how big it got */
}

/*
 * Decompress a file.  This routine adapts to the codes in the file
 * building the string table on-the-fly; requiring no table to be stored
 * in the compressed file.  The tables used herein are shared with those of
 * the compress() routine.  See the definitions above.
 */

INT sqdecomp(f,t)                            /* decompress a file */
FILE *f;                               /* file to read codes from */
FILE *t;                               /* file to write text to */
{
    unsigned char *stackp;
 INT finchar;
 INT code, oldcode, incode;

    n_bits = INIT_BITS;                /* set starting code size */
    clear_flg = 0;

    /*
     * As above, initialize the first 256 entries in the table.
     */
    maxcode = MAXCODE(n_bits=INIT_BITS);
    for(code = 255; code >= 0; code--)
    {    prefix[code] = 0;
         suffix[code] = (unsigned char)code;
    }
    free_ent = FIRST;

    finchar = oldcode = getcode(f);
    if(oldcode == -1)                  /* EOF already? */
         return;                       /* Get out of here */
    putc_unp((char)finchar,t);         /* first code must be 8 bits=char */
    stackp = stack;

    while((code = getcode(f))> -1)
    {    if(code==CLEAR)
         {    for(code = 255; code >= 0; code--)
                   prefix[code] = 0;
              clear_flg = 1;
              free_ent = FIRST - 1;
              if((code=getcode(f))==-1)/* O, untimely death! */
                   break;
         }
         incode = code;
         /*
          * Special case for KwKwK string.
          */
         if(code >= free_ent)
         {    *stackp++ = finchar;
              code = oldcode;
         }

         /*
          * Generate output characters in reverse order
          */
         while(code >= 256)
         {    *stackp++ = suffix[code];
              code = prefix[code];
         }
         *stackp++ = finchar = suffix[code];

         /*
          * And put them out in forward order
          */
         do
              putc_unp(*--stackp,t);
         while(stackp > stack);

         /*
          * Generate the new entry.
          */
         if((code=free_ent) < maxcodemax)
         {    prefix[code] = (unsigned short)oldcode;
              suffix[code] = finchar;
              free_ent = code+1;
         }
         /*
          * Remember previous code.
          */
         oldcode = incode;
    }
}
SHAR_EOF
chmod +x 'squash.c'
fi # end of overwriting check
#	End of shell archive
exit 0