Newsgroups: comp.sources.unix
From: hyc@umix.cc.umich.edu (Howard Chu)
Subject: v26i004: arc 5.21 (pl 8) - file archive/compression tool, Part01/03
Sender: unix-sources-moderator@pa.dec.com
Approved: vixie@pa.dec.com

Submitted-By: hyc@umix.cc.umich.edu (Howard Chu)
Posting-Number: Volume 26, Issue 4
Archive-Name: arc-5.21/part01

This program is based on the MSDOS ARC program, version 5.21, plus
a few enhancements... It compiles on UNIX(tm) and on the Atari ST.
 
 o ARC also performs Huffman Squeezing on data. The Huffman Squeeze
   algorithm was removed from MSDOS ARC after version 5.12. It turns
   out to be more efficient than Lempel-Ziv style compression when
   compressing graphic images. Squeeze analysis is always done now,
   and the best of packing, squeezing, or crunching is used.
 
 o Compresses and extracts Squashed files. "Squashing" was created
   by Phil Katz in his PKxxx series of ARC utility programs for
   MSDOS. Dan Lanciani wrote the original modifications to ARC's
   Crunch code to handle Squashing. I've made minor changes since
   then, mostly to reduce the amount of memory required. The 'q'
   option flag must be specified to Squash files. The Squashing
   algorithm will be used instead of the usual Crunch algorithm,
   and will be compared against packing and squeezing, as before.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  Arcinfo Changes.521 MANIFEST Makefile PATCHLEVEL README
#   arc.h arccode.c arccvt.c arcdata.c arcdel.c arcdos.c arcext.c
#   arcio.c arclst.c arcmatch.c arcpack.c arcrun.c arcs.h arcsvc.c
#   arctst.c arcunp.c arcusq.c proto.h tmclock.c
# Wrapped by vixie@cognition.pa.dec.com on Sat Apr 11 13:54:34 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Arcinfo' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Arcinfo'\"
else
echo shar: Extracting \"'Arcinfo'\" \(5577 characters\)
sed "s/^X//" >'Arcinfo' <<'END_OF_FILE'
X
ARC-FILE.INF, created by Keith Petersen, W8SDZ, 21-Sep-86, extracted
from UNARC.INF by Robert A. Freed.
X
XFrom:     Robert A. Freed
Subject:  Technical Information for ARC files
Date:     June 24, 1986
X
Note: In the following discussion, UNARC refers to my CP/M-80 program
for extracting files from MSDOS ARCs.  The definitions of the ARC file
format are based on MSDOS ARC512.EXE.
X
ARCHIVE FILE FORMAT
X-------------------
X
Component files are stored sequentially within an archive.  Each entry
is preceded by a 29-byte header, which contains the directory
information.  There is no wasted space between entries.  (This is in
contrast to the centralized directory used by Novosielski libraries.
Although random access to subfiles within an archive can be noticeably
slower than with libraries, archives do have the advantage of not
requiring pre-allocation of directory space.)
X
Archive entries are normally maintained in sorted name order.  The
format of the 29-byte archive header is as follows:
X
Byte 1:  1A Hex.
X         This marks the start of an archive header.  If this byte is not found 
X         when expected, UNARC will scan forward in the file (up to 64K bytes) 
X         in an attempt to find it (followed by a valid compression version).  
X         If a valid header is found in this manner, a warning message is 
X         issued and archive file processing continues.  Otherwise, the file is 
X         assumed to be an invalid archive and processing is aborted.  (This is 
X         compatible with MS-DOS ARC version 5.12).  Note that a special 
X         exception is made at the beginning of an archive file, to accomodate 
X         "self-unpacking" archives (see below).
X
Byte 2:  Compression version, as follows:
X
X         0 = end of file marker (remaining bytes not present)
X         1 = unpacked (obsolete)
X         2 = unpacked
X         3 = packed
X         4 = squeezed (after packing)
X         5 = crunched (obsolete)
X         6 = crunched (after packing) (obsolete)
X         7 = crunched (after packing, using faster hash algorithm) (obsolete)
X         8 = crunched (after packing, using dynamic LZW variations)
X
Bytes 3-15:  ASCII file name, nul-terminated.
X
X(All of the following numeric values are stored low-byte first.)
X
Bytes 16-19:  Compressed file size in bytes.
X
Bytes 20-21:  File date, in 16-bit MS-DOS format:
X              Bits 15:9 = year - 1980
X              Bits  8:5 = month of year
X              Bits  4:0 = day of month
X              (All zero means no date.)
X
Bytes 22-23:  File time, in 16-bit MS-DOS format:
X              Bits 15:11 = hour (24-hour clock)
X              Bits 10:5  = minute
X              Bits  4:0  = second/2 (not displayed by UNARC)
X
Bytes 24-25:  Cyclic redundancy check (CRC) value (see below).
X
Bytes 26-29:  Original (uncompressed) file length in bytes.
X              (This field is not present for version 1 entries, byte 2 = 1.  
X              I.e., in this case the header is only 25 bytes long.  Because 
X              version 1 files are uncompressed, the value normally found in 
X              this field may be obtained from bytes 16-19.)
X
X
SELF-UNPACKING ARCHIVES
X-----------------------
X
A "self-unpacking" archive is one which can be renamed to a .COM file
and executed as a program.  An example of such a file is the MS-DOS
program ARC512.COM, which is a standard archive file preceded by a
three-byte jump instruction.  The first entry in this file is a simple
X"bootstrap" program in uncompressed form, which loads the subfile
ARC.EXE (also uncompressed) into memory and passes control to it.  In
anticipation of a similar scheme for future distribution of UNARC, the
program permits up to three bytes to precede the first header in an
archive file (with no error message).
X
X
CRC COMPUTATION
X---------------
X
Archive files use a 16-bit cyclic redundancy check (CRC) for error
control.  The particular CRC polynomial used is x^16 + x^15 + x^2 + 1,
which is commonly known as "CRC-16" and is used in many data
transmission protocols (e.g. DEC DDCMP and IBM BSC), as well as by
most floppy disk controllers.  Note that this differs from the CCITT
polynomial (x^16 + x^12 + x^5 + 1), which is used by the XMODEM-CRC
protocol and the public domain CHEK program (although these do not
adhere strictly to the CCITT standard).  The MS-DOS ARC program does
perform a mathematically sound and accurate CRC calculation.  (We
mention this because it contrasts with some unfortunately popular
public domain programs we have witnessed, which from time immemorial
have based their calculation on an obscure magazine article which
contained a typographical error!)
X
Additional note (while we are on the subject of CRC's): The validity
of using a 16-bit CRC for checking an entire file is somewhat
questionable.  Many people quote the statistics related to these
functions (e.g. "all two-bit errors, all single burst errors of 16 or
fewer bits, 99.997% of all single 17-bit burst errors, etc."), without
realizing that these claims are valid only if the total number of bits
checked is less than 32767 (which is why they are used in small-packet
data transmission protocols).  I.e., for file sizes in excess of about
X4K bytes, a 16-bit CRC is not really as good as what is often claimed.
This is not to say that it is bad, but there are more reliable methods
available (e.g. the 32-bit AUTODIN-II polynomial).  (End of lecture!)
X
X                           Bob Freed
X                           62 Miller Road
X                           Newton Centre, MA  02159
X                           Telephone (617) 332-3533
X
X
END_OF_FILE
if test 5577 -ne `wc -c <'Arcinfo'`; then
    echo shar: \"'Arcinfo'\" unpacked with wrong size!
fi
# end of 'Arcinfo'
fi
if test -f 'Changes.521' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Changes.521'\"
else
echo shar: Extracting \"'Changes.521'\" \(1892 characters\)
sed "s/^X//" >'Changes.521' <<'END_OF_FILE'
X                        CHANGES IN VERSION 5.21
X
X
The following changes have been made in ARC version 5.21, but have not
yet been included in the manual:
X
o   When adding files to an archive, ARC now shows the stowage facter
X    achieved on each file.
X
o   A bug was found that would keep an archive entry from being
X    encrypted if it was stored without compression.  This has now been
X    fixed.
X
o   If changes are made to a corrupted archive, the corrupted entries
X    are discarded.  This makes it possible to lose data accidentally.
X    ARC will now only make changes to a corrupted archive if the W
X    (suppress Warnings) option has been given.
X
o   The N (suppress Notes) option now suppresses the "Creating
X    archive" note when a new archive is being created.
X
o   The N (suppress Notes) option formerly did nothing useful when
X    used with the L (List files) command.  It now causes a terse
X    listing of filenames only, suitable for use with pipes and
X    redirection.
X
o   The list of filenames given to ARC may now include indirect
X    references.  If a filename begins with an "at sign" ("@"), it is
X    taken to be the name of a file which contains a list of file
X    names.  The list of file names may include further indirection.
X    If no extension is given, ".CMD" is assumed.  For example, the
X    command:
X
X         arc a waste junk.txt @trash
X
X    would cause ARC to add JUNK.TXT plus all files listed in the file
X    TRASH.CMD to an archive named WASTE.ARC.  If no file is specified,
X    then the list is read from standard input.  For example, the
X    command:
X
X         arc ln waste | arc a trash @
X
X    would cause ARC to add files to TRASH.ARC based on the names of
X    the files stored in WASTE.ARC.  It is probably a good idea to give
X    the O (Overwrite) option if you are extracting files this way.
X
X    Version 5.21 of MARC also allows for indirection.
END_OF_FILE
if test 1892 -ne `wc -c <'Changes.521'`; then
    echo shar: \"'Changes.521'\" unpacked with wrong size!
fi
# end of 'Changes.521'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(1119 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X Arc521.doc                 3	
X Arcinfo                    1	
X Changes.521                1	
X MANIFEST                   1	
X Makefile                   1	
X PATCHLEVEL                 1	
X README                     1	
X arc.1                      2	
X arc.c                      2	
X arc.h                      1	
X arcadd.c                   2	
X arccode.c                  1	
X arccvt.c                   1	
X arcdata.c                  1	
X arcdel.c                   1	
X arcdos.c                   1	
X arcext.c                   1	
X arcio.c                    1	
X arclst.c                   1	
X arclzw.c                   2	
X arcmatch.c                 1	
X arcmisc.c                  2	
X arcpack.c                  1	
X arcrun.c                   1	
X arcs.h                     1	
X arcsq.c                    2	
X arcsvc.c                   1	
X arctst.c                   1	
X arcunp.c                   1	
X arcusq.c                   1	
X marc.c                     2	
X proto.h                    1	
X tmclock.c                  1	
END_OF_FILE
if test 1119 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(3858 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# $Header: /var/local/hyc/src/arc/RCS/Makefile,v 2.0 1991/11/12 00:45:33 hyc Exp $
X#       Makefile for portable ARC
X#
X# Originals from Dan Lanciani, James Turner, and others...
X# This Makefile supports Atari ST and all Unix versions.
X#
X# I put SRCDIR on a real disk on the ST, but copy the makefile to a
X# RAMdisk and compile from there. Makes things go a bit quicker...
X# This has to be done in the shell, to get the trailing backslash
X# specified correctly. e.g., setenv SRCDIR='d:\src\arc\'
SRCDIR = 
X
HEADER = $(SRCDIR)arc.h $(SRCDIR)arcs.h
X
X# Add a ".TTP" suffix to the executable files on an ST.
X#PROG = .ttp
PROG =
X
X# SYSTEM defines your operating system:
X# MSDOS for IBM PCs or other MSDOS machines
X# GEMDOS for Atari ST (Predefined by MWC, so you don't need to define it.)
X# BSD for Berkeley Unix
X# SYSV for AT&T System V Unix
X# (_MTS for Michigan Terminal System, which requires a different makefile)
X# (_MTS also requires one of USEGFINFO or USECATSCAN for directory search)
X# NEEDMEMSET if your C library does not have the memset() routine and/or
X# your system include doesn't have <memory.h> (Most current systems don't
X# need this.)
X#SYSTEM = -DGEMDOS=1 -fstrength-reduce -fcombine-regs -fforce-mem -fomit-frame-pointer -finline-functions -fforce-addr
SYSTEM = -DBSD=1
X
OPT = -O
X# For MWC 3.0 on the Atari ST, use:
X#CFLAGS = -VCOMPAC -VPEEP
CFLAGS = $(OPT) $(SYSTEM)
X
X# GNU's gcc is very nice, if you've got it. Otherwise just cc.
X#CC = cgcc -mshort
CC = cc
X
X# tmclock is only needed on Unix systems...
TMCLOCK = tmclock.o
X
X# Files needed for System V 
X#SYSVOBJ =	getwd.o rename.o scandir.o utimes.o
SYSVOBJ =
X
OBJS = arc.o arcadd.o arccode.o arccvt.o arcdata.o arcdel.o arcdos.o \
arcext.o arcio.o arclst.o arclzw.o arcmatch.o arcpack.o arcrun.o \
arcsq.o arcsvc.o arctst.o arcunp.o arcusq.o arcmisc.o $(SYSVOBJ)
X
MOBJ = marc.o arcdata.o arcdos.o arcio.o arcmatch.o arcmisc.o $(SYSVOBJ)
X
all:	arc$(PROG) marc$(PROG)
X
arc$(PROG):	$(OBJS) $(TMCLOCK)
X	$(CC) -o arc$(PROG) $(OBJS) $(TMCLOCK)
X
marc$(PROG):	$(MOBJ) $(TMCLOCK)
X	$(CC) -o marc$(PROG) $(MOBJ) $(TMCLOCK)
X
clean:
X	-rm *.o arc$(PROG) marc$(PROG)
X
arc.o:	$(SRCDIR)arc.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arc.c
marc.o:	$(SRCDIR)marc.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)marc.c
arcadd.o:	$(SRCDIR)arcadd.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcadd.c
arccode.o:	$(SRCDIR)arccode.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arccode.c
arccvt.o:	$(SRCDIR)arccvt.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arccvt.c
arcdata.o:	$(SRCDIR)arcdata.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcdata.c
arcdel.o:	$(SRCDIR)arcdel.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcdel.c
arcdir.o:	$(SRCDIR)arcdir.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcdir.c
arcdos.o:	$(SRCDIR)arcdos.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcdos.c
arcext.o:	$(SRCDIR)arcext.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcext.c
arcio.o:	$(SRCDIR)arcio.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcio.c
arclst.o:	$(SRCDIR)arclst.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arclst.c
arclzw.o:	$(SRCDIR)arclzw.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arclzw.c
arcmatch.o:	$(SRCDIR)arcmatch.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcmatch.c
arcmisc.o:	$(SRCDIR)arcmisc.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcmisc.c
arcpack.o:	$(SRCDIR)arcpack.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcpack.c
arcrun.o:	$(SRCDIR)arcrun.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcrun.c
arcsq.o:	$(SRCDIR)arcsq.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcsq.c
arcsvc.o:	$(SRCDIR)arcsvc.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcsvc.c
arctst.o:	$(SRCDIR)arctst.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arctst.c
arcunp.o:	$(SRCDIR)arcunp.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcunp.c
arcusq.o:	$(SRCDIR)arcusq.c	$(HEADER)
X	$(CC) $(CFLAGS) -c $(SRCDIR)arcusq.c
X
tmclock.o:	$(SRCDIR)tmclock.c
X	$(CC) $(CFLAGS) -c $(SRCDIR)tmclock.c
END_OF_FILE
if test 3858 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'PATCHLEVEL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'PATCHLEVEL'\"
else
echo shar: Extracting \"'PATCHLEVEL'\" \(2 characters\)
sed "s/^X//" >'PATCHLEVEL' <<'END_OF_FILE'
X8
END_OF_FILE
if test 2 -ne `wc -c <'PATCHLEVEL'`; then
    echo shar: \"'PATCHLEVEL'\" unpacked with wrong size!
fi
# end of 'PATCHLEVEL'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5337 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Notes for ARC 5.21e					October 31, 1991
X
X	ARC 5.21 for Unix is currently at patch level 8. The code provided
here has been used on 4.3 BSD based Unix systems and on the Atari ST. (The
GNU C compiler, version 1.40, was used to make the ST version. It should
still compile with Mark Williams C, but I haven't bothered to try it.) The
current version is over twice as fast as previous releases, for all file
compression and decompression operations. It also fixes longstanding bugs
in the squash code and in the tmclock DST code.
X 
X	The Arcinfo file describes the ARC 5.xx directory format. The 6.xx
format contains additional information that is not supported here.
X
X	System V support in the shar file Sysvarcstuf was provided by Jon
Zeeff, Janet Walz, and Rich Salz. You will probably also need the dirent
directory library written by Doug Gwyn; this can be obtained from uunet or
many other comp.sources.unix archive sites.
X
X	The tmclock.c file was stolen from Jef Poskanzer's tws library,
as distributed in PHOON, PHase of the mOON, and slightly hacked by me.
X
X	The man page was originally from Leo Wilson, with updates by me.
X
X         /                 Howard Chu
X   ___  /_ , ,_.     Jet Propulsion Laboratory
X       / /(_/(__     hyc@hanauma.jpl.nasa.gov
X           /
X
Notes for ARC 5.21                                        June 6, 1988
X 
This program is based on the MSDOS ARC program, version 5.21, plus
a few enhancements... 
X 
X o ARC also performs Huffman Squeezing on data. The Huffman Squeeze
X   algorithm was removed from MSDOS ARC after version 5.12. It turns
X   out to be more efficient than Lempel-Ziv style compression when
X   compressing graphic images. Squeeze analysis is always done now,
X   and the best of packing, squeezing, or crunching is used.
X 
X o Compresses and extracts Squashed files. "Squashing" was created
X   by Phil Katz in his PKxxx series of ARC utility programs for
X   MSDOS. Dan Lanciani wrote the original modifications to ARC's
X   Crunch code to handle Squashing. I've made minor changes since
X   then, mostly to reduce the amount of memory required. The 'q'
X   option flag must be specified to Squash files. The Squashing
X   algorithm will be used instead of the usual Crunch algorithm,
X   and will be compared against packing and squeezing, as before.
X 
System specific notes:
X 
X   On MTS, an additional option flag, 'i' for "image mode," was
used. ARC assumes files are text, by default, and will translate
MTS files from EBCDIC to ASCII before storing in an archive, and
translates from ASCII to EBCDIC upon extraction. Specifying the
X'i' flag will inhibit this translation. This would most commonly
be used when shipping binary images such as TeX DVI files, other
X.ARC files stored within an archive, etc... The 'r' (run) command
is omitted. It just doesn't seem very useful. Also, ARC cannot
restore MTS files with their original time stamps. (Maybe in a
future release...)
X 
X   On Unix(tm) systems, the 'i' flag is also present. Unix ARC
assumes a binary file, by default. Here the only translation
involved is in end-of-line processing. When storing text files, ARC will
change '\n' to '\r\n', and does the opposite when extracting files.
Carriage returns in any other location are preserved when extracting.
This translation only occurs if the 'i' flag is given.
X
X   On the Atari ST, the 'h' (for "hold screen") option is present,
which simply delays exiting the program. This is typically used when
executing ARC from the desktop, to allow reading all of ARC's output
before the screen is cleared and the desktop is redrawn. The program
will prompt and wait for a keypress before exiting. Note that since
there are no "options" for the MARC program, the "hold screen" option
is always active for MARC.
X 
X   On both Unix and Atari systems, ARC & MARC will search for an
environment variable named "ARCTEMP" or "TMPDIR." If present, any
temporary files will be created in the specified directory. This is
probably insignificant for Unix users, but can be handy on the Atari,
in combination with a RAMdisk. Highly recommended for floppy users.
X(Unfortunately, you can only take advantage of this when running some
form of command shell that allows setting environment variables. Thus,
you won't see any speed gains when running from the desktop.)
X 
That about covers things. The enclosed documentation is taken directly
from the MSDOS distribution of ARC. Unless specified differently here,
the programs behave indentically. Note that ARC521.DOC is identical to
ARC520.DOC - the differences between the two versions are described in
the file CHANGES.521.
X 
Oh yeah - this program may be distributed freely so long as you don't
modify it in any way. You may not charge for distributing it. (Don't
feel bad, I can't charge for it either. }-) It'd be nice if you kept
this and the other enclosed doc files with it when distributing, but
I'm not going to make a fuss about it. Most people are so familiar
with the program by now that it wouldn't matter much anyway. You
should keep this README file around, so bug reports & such will find
their way back to me. (Bugs? What bugs? Nah, there aren't any bugs...)
X 
X         /                 Howard Chu
X   ___  /_ , ,_.     University of Michigan
X       / /(_/(__     hyc@umix.cc.umich.edu
X           /                umix!hyc
X          '     
END_OF_FILE
if test 5337 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'arc.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arc.h'\"
else
echo shar: Extracting \"'arc.h'\" \(3401 characters\)
sed "s/^X//" >'arc.h' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arc.h,v 2.0 1991/11/12 00:30:01 hyc Exp hyc $
X */
X
X#undef	DOS	/* Just in case... */
X#undef	UNIX
X
X/*
X * Assumptions:
X * char = 8 bits
X * short = 16 bits
X * long = 32 bits
X * int >= 16 bits
X */
X
X#if	MSDOS || GEMDOS
X#define	DOS	1
X#define	CUTOFF	'\\'
X#define	OPEN_R	"rb"
X#define	OPEN_W	"wb"
X#if	__GNUC__
X#include <types.h>
X#include <string.h>
X#endif
X#endif
X
X#if	!MSDOS
X#define	envfind	getenv
X#define	setmem(a, b, c)	memset(a, c, b)
X#endif
X
X#if	BSD || SYSV
X#define	UNIX	1
X#define	CUTOFF	'/'
X#define	OPEN_R	"r"
X#define	OPEN_W	"w"
X#include <ctype.h>
X#include <sys/types.h>
X#endif
X
X#if	_MTS
X#define	CUTOFF	sepchr[0]
X#define	OPEN_R	"rb"
X#define	OPEN_W	"wb"
X#endif
X
X#define	MYBUF	32766		/* Used for fopens and filecopy() */
X
X#if	_MTS || SYSV
X#define	rindex	strrchr
X#define	index	strchr
X#endif
X
X#if	__STDC__
X#include <stdlib.h>
X#define	VOID	void
X#define	PROTO(args)	args
X#else
X#define	VOID	int
X#define	PROTO(args)	()
X#endif
X
X/*  ARC - Archive utility - ARC Header
X  
X    Version 2.17, created on 04/22/87 at 13:09:43
X  
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X  
X    By:	 Thom Henderson
X  
X    Description: 
X	 This is the header file for the ARC archive utility.  It defines
X	 global parameters and the references to the external data.
X  
X  
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X
X#define ARCMARK 26		/* special archive marker        */
X#define ARCVER 9		/* archive header version code   */
X#define STRLEN 100		/* system standard string length */
X#define FNLEN 13		/* file name length              */
X#define MAXARG 400		/* maximum number of arguments   */
X
X#if	!UNIX
typedef unsigned int	u_int;
X#ifndef	__GNUC__
typedef unsigned char	u_char;
typedef unsigned short	u_short;
X#endif
X#endif
X#define	reg	register
X
X#ifndef DONT_DEFINE		/* Defined by arcdata.c */
X#include "arcs.h"
X
extern int      keepbak;	/* true if saving the old archive */
X#if	!DOS
extern int      image;		/* true to suppress CRLF/LF x-late */
X#endif
X#if	_MTS
extern char     sepchr[2];	/* Shared file separator, default = ':' */
extern char     tmpchr[2];	/* Temporary file prefix, default = '-' */
X#endif
X#if	GEMDOS
extern int      hold;		/* hold screen before exiting */
X#endif
extern int      warn;		/* true to print warnings */
extern int      note;		/* true to print comments */
extern int      bose;		/* true to be verbose */
extern int      nocomp;		/* true to suppress compression */
extern int      overlay;	/* true to overlay on extract */
extern int      kludge;		/* kludge flag */
extern char    *arctemp;	/* arc temp file prefix */
extern char    *password;	/* encryption password pointer */
extern int      nerrs;		/* number of errors encountered */
extern int      changing;	/* true if archive being modified */
X
extern char     hdrver;		/* header version */
X
extern FILE    *arc;		/* the old archive */
extern FILE    *new;		/* the new archive */
extern char     arcname[STRLEN];/* storage for archive name */
extern char     bakname[STRLEN];/* storage for backup copy name */
extern char     newname[STRLEN];/* storage for new archive name */
extern u_short	arcdate;	/* archive date stamp */
extern u_short	arctime;	/* archive time stamp */
extern u_short	olddate;	/* old archive date stamp */
extern u_short	oldtime;	/* old archive time stamp */
extern int      dosquash;	/* squash instead of crunch */
X#endif				/* DONT_DEFINE */
END_OF_FILE
if test 3401 -ne `wc -c <'arc.h'`; then
    echo shar: \"'arc.h'\" unpacked with wrong size!
fi
# end of 'arc.h'
fi
if test -f 'arccode.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arccode.c'\"
else
echo shar: Extracting \"'arccode.c'\" \(1147 characters\)
sed "s/^X//" >'arccode.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arccode.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCCODE
X * 
X * Version 1.02, created on 01/20/86 at 13:33:35
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:	Thom Henderson
X * 
X * Description: This file contains the routines used to encrypt and decrypt data
X * in an archive.  The encryption method is nothing fancy, being just a
X * routine XOR, but it is used on the packed data, and uses a variable length
X * key.	 The end result is something that is in theory crackable, but I'd
X * hate to try it.  It should be more than sufficient for casual use.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
static char    *p;		/* password pointer */
X
VOID
setcode()
X{				/* get set for encoding/decoding */
X	p = password;		/* reset password pointer */
X}
X
VOID
codebuf(buf, len)		/* encrypt a buffer */
X	reg char       *buf;
X	u_int		len;
X{
X	reg u_int	i;
X	reg char       *pasptr = p;
X
X	for (i = 0; i < len; i++) {
X		if (!*pasptr)
X			pasptr = password;
X		*buf++ ^= *pasptr++;
X	}
X	p = pasptr;
X}
END_OF_FILE
if test 1147 -ne `wc -c <'arccode.c'`; then
    echo shar: \"'arccode.c'\" unpacked with wrong size!
fi
# end of 'arccode.c'
fi
if test -f 'arccvt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arccvt.c'\"
else
echo shar: Extracting \"'arccvt.c'\" \(3539 characters\)
sed "s/^X//" >'arccvt.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arccvt.c,v 2.0 1991/11/12 00:52:07 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCCVT
X * 
X * Version 1.16, created on 02/03/86 at 22:53:02
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to convert archives to use
X * newer file storage methods.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#if	_MTS
X#include <mts.h>
X#endif
X#include "arc.h"
X
int	match(), readhdr(), unpack(), unlink();
VOID	openarc(), rempath(), closearc(), arcdie(), pack();
VOID	writehdr(), filecopy();
static	VOID	cvtfile();
X
static char     tempname[STRLEN];	/* temp file name */
X
VOID
cvtarc(num, arg)		/* convert archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* file header */
X	int             cvt;	/* true to convert current file */
X	int             did[MAXARG];/* true when argument was used */
X	int             n;	/* index */
X	char           *makefnam();	/* filename fixer */
X	FILE           *fopen();/* file opener */
X
X	if (arctemp)		/* use temp area if specified */
X		sprintf(tempname, "%s.CVT", arctemp);
X	else
X		makefnam("$ARCTEMP.CVT", arcname, tempname);
X#if	!DOS
X	image = 1;
X#endif
X
X	openarc(1);		/* open archive for changes */
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* while more files to check */
X			cvt = 0;/* reset convert flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, arg[n])) {
X					cvt = 1;	/* turn on convert flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (cvt)/* if converting this one */
X				cvtfile(&hdr);	/* then do it */
X			else {	/* else just copy it */
X				writehdr(&hdr, new);
X				filecopy(arc, new, hdr.size);
X			}
X		}
X	} else
X		while (readhdr(&hdr, arc))	/* else convert all files */
X			cvtfile(&hdr);
X
X	hdrver = 0;		/* archive EOF type */
X	writehdr(&hdr, new);	/* write out our end marker */
X	closearc(1);		/* close archive after changes */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
X
static	VOID
cvtfile(hdr)			/* convert a file */
X	struct heads   *hdr;	/* pointer to header data */
X{
X	long            starts, ftell();	/* where the file goes */
X	FILE           *tmp, *fopen();	/* temporary file */
X
X	if (!(tmp = fopen(tempname, "w+b")))
X		arcdie("Unable to create temporary file %s", tempname);
X
X	if (note) {
X		printf("Converting file: %-12s   reading, ", hdr->name);
X		fflush(stdout);
X	}
X	unpack(arc, tmp, hdr);	/* unpack the entry */
X	fseek(tmp, 0L, 0);	/* reset temp for reading */
X
X	starts = ftell(new);	/* note where header goes */
X	hdrver = ARCVER;		/* anything but end marker */
X	writehdr(hdr, new);	/* write out header skeleton */
X#if	_MTS
X	atoe(hdr->name, FNLEN);	/* writehdr translated this... */
X#endif
X	pack(tmp, new, hdr);	/* pack file into archive */
X	fseek(new, starts, 0);	/* move back to header skeleton */
X	writehdr(hdr, new);	/* write out real header */
X	fseek(new, hdr->size, 1);	/* skip over data to next header */
X	fclose(tmp);		/* all done with the file */
X	if (unlink(tempname) && warn) {
X		printf("Cannot unsave %s\n", tempname);
X		nerrs++;
X	}
X}
END_OF_FILE
if test 3539 -ne `wc -c <'arccvt.c'`; then
    echo shar: \"'arccvt.c'\" unpacked with wrong size!
fi
# end of 'arccvt.c'
fi
if test -f 'arcdata.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcdata.c'\"
else
echo shar: Extracting \"'arcdata.c'\" \(2097 characters\)
sed "s/^X//" >'arcdata.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcdata.c,v 2.0 1991/11/12 00:34:06 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCDATA
X
X    Version 2.17, created on 04/22/87 at 13:09:43
X
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description: 
X	 This file defines the external data storage used by the ARC
X	 archive utility.
X
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X
X#define DONT_DEFINE
X#include "arc.h"
X
int             keepbak = 0;	/* true if saving the old archive */
X#if	UNIX
int		image = 1;	/* true to suppress CRLF/LF x-late */
X#endif
X#if	_MTS
int             image = 0;	/* true to suppress EBCDIC/ASCII x-late */
char            sepchr[2] = ":";/* Shared file separator */
char            tmpchr[2] = "-";/* Temporary file prefix */
X#endif
X#if	GEMDOS
int		hold = 0;	/* true to pause before exit */
X#endif
int             warn = 1;	/* true to print warnings */
int             note = 1;	/* true to print comments */
int             bose = 0;	/* true to be verbose */
int             nocomp = 0;	/* true to suppress compression */
int             overlay = 0;	/* true to overlay on extract */
int             kludge = 0;	/* kludge flag */
char           *arctemp = NULL;	/* arc temp file prefix */
char           *password = NULL;/* encryption password pointer */
int             nerrs = 0;	/* number of errors encountered */
int		changing = 0;	/* true if archive being modified */
X
char            hdrver;		/* header version */
X
XFILE           *arc;		/* the old archive */
XFILE           *new;		/* the new archive */
char            arcname[STRLEN];	/* storage for archive name */
char            bakname[STRLEN];	/* storage for backup copy name */
char            newname[STRLEN];	/* storage for new archive name */
unsigned short  arcdate = 0;	/* archive date stamp */
unsigned short  arctime = 0;	/* archive time stamp */
unsigned short  olddate = 0;	/* old archive date stamp */
unsigned short  oldtime = 0;	/* old archive time stamp */
int		dosquash = 0;	/* true to squash instead of crunch */
END_OF_FILE
if test 2097 -ne `wc -c <'arcdata.c'`; then
    echo shar: \"'arcdata.c'\" unpacked with wrong size!
fi
# end of 'arcdata.c'
fi
if test -f 'arcdel.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcdel.c'\"
else
echo shar: Extracting \"'arcdel.c'\" \(2086 characters\)
sed "s/^X//" >'arcdel.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcdel.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCDEL
X * 
X * Version 2.09, created on 02/03/86 at 22:53:27
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to delete entries in an
X * archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
VOID	arcdie(), rempath(), openarc(), closearc(), writehdr(), filecopy();
int	match(), readhdr();
X
VOID
delarc(num, arg)		/* remove files from archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* header data */
X	int             del;	/* true to delete a file */
X	int             did[MAXARG];/* true when argument used */
X	int             n;	/* index */
X
X	if (!num)		/* she must specify which */
X		arcdie("You must tell me which files to delete!");
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	openarc(1);		/* open archive for changes */
X
X	while (readhdr(&hdr, arc)) {	/* while more entries in archive */
X		del = 0;	/* reset delete flag */
X		for (n = 0; n < num; n++) {	/* for each template given */
X			if (match(hdr.name, arg[n])) {
X				del = 1;	/* turn on delete flag */
X				did[n] = 1;	/* turn on usage flag */
X				break;	/* stop looking */
X			}
X		}
X
X		if (del) {	/* skip over unwanted files */
X			fseek(arc, hdr.size, 1);
X			if (note)
X				printf("Deleting file: %s\n", hdr.name);
X		} else {	/* else copy over file data */
X			writehdr(&hdr, new);	/* write out header and file */
X			filecopy(arc, new, hdr.size);
X		}
X	}
X
X	hdrver = 0;		/* special end of archive type */
X	writehdr(&hdr, new);	/* write out archive end marker */
X	closearc(1);		/* close archive after changes */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused arguments */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
END_OF_FILE
if test 2086 -ne `wc -c <'arcdel.c'`; then
    echo shar: \"'arcdel.c'\" unpacked with wrong size!
fi
# end of 'arcdel.c'
fi
if test -f 'arcdos.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcdos.c'\"
else
echo shar: Extracting \"'arcdos.c'\" \(4711 characters\)
sed "s/^X//" >'arcdos.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcdos.c,v 2.0 1991/11/12 00:34:06 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCDOS
X * 
X * Version 1.44, created on 07/25/86 at 14:17:38
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains certain DOS level routines that assist in
X * doing fancy things with an archive, primarily reading and setting the date
X * and time last modified.
X * 
X * These are, by nature, system dependant functions.  But they are also, by
X * nature, very expendable.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
X#if	MSDOS
X#include "fileio2.h"		/* needed for filehand */
X#endif
X
X#if	UNIX
X#include <sys/types.h>
X#include <sys/stat.h>
X#if	BSD
X#include <sys/time.h>
X#else	
X#include <time.h>		/* Sys V. Bleah. */
struct	timeval {
X	long	tv_sec;
X	long	tv_usec;
X};
X#endif	/* BSD vs SYSV */
X#endif
X
X#if	GEMDOS
X#include <osbind.h>
X#endif
X
X#include <string.h>
X#ifndef	__STDC__
char	*malloc();
X#endif
X
VOID
getstamp(f, date, time)		/* get a file's date/time stamp */
X#if	!_MTS
X	FILE           *f;	/* file to get stamp from */
X#else
X	char           *f;	/* filename "" "" */
X#endif
X	unsigned short   *date, *time;	/* storage for the stamp */
X{
X#if	MSDOS
X	struct {
X		int             ax, bx, cx, dx, si, di, ds, es;
X	}               reg;
X
X	reg.ax = 0x5700;	/* get date/time */
X	reg.bx = filehand(f);	/* file handle */
X	if (sysint21(&reg, &reg) & 1)	/* DOS call */
X		printf("Get timestamp fail (%d)\n", reg.ax);
X
X	*date = reg.dx;		/* save date/time */
X	*time = reg.cx;
X#endif
X#if	GEMDOS
X	int	fd, ret[2];
X
X	fd = fileno(f);
X	Fdatime(ret, fd, 0);
X	*date = ret[1];
X	*time = ret[0];
X#endif
X#if	UNIX
X	struct stat	buf;
X	struct tm	*localtime(), *t;
X
X	fstat(fileno(f), &buf);
X	t=localtime(&(buf.st_mtime));
X	*date = (unsigned short) (((t->tm_year - 80) << 9) +
X				((t->tm_mon + 1) << 5) + t->tm_mday);
X	*time = (unsigned short) ((t->tm_hour << 11) +
X				(t->tm_min << 5) + t->tm_sec / 2);
X#endif
X#if	_MTS
X	fortran         timein(),
X#if	USEGFINFO
X	                gfinfo();
X#else
X	                fileinfo();
X#endif
X	int             stclk[2];
X	char            name[24];
X	struct bigtime {
X		int             greg;
X		int             year;
X		int             mon;
X		int             day;
X		int             hour;
X		int             min;
X		int             sec;
X		int             usec;
X		int             week;
X		int             toff;
X		int             tzn1;
X		int             tzn2;
X	}               tvec;
X#if	USEGFINFO
X	static int      gfflag = 0x0009, gfdummy[2] = {
X						       0, 0
X	};
X	int             gfcinfo[18];
X#else
X	static int      cattype = 2;
X#endif
X
X	strcpy(name, f);
X	strcat(name, " ");
X#if	USEGFINFO
X	gfcinfo[0] = 18;
X	gfinfo(name, name, &gfflag, gfcinfo, gfdummy, gfdummy);
X	timein("*IBM MICROSECONDS*", &gfcinfo[16], &tvec);
X#else
X	fileinfo(name, &cattype, "CILCCT  ", stclk);
X	timein("*IBM MICROSECONDS*", stclk, &tvec);
X#endif
X
X	*date = (unsigned short) (((tvec.year - 1980) << 9) + ((tvec.mon) << 5) + tvec.day);
X	*time = (unsigned short) ((tvec.hour << 11) + (tvec.min << 5) + tvec.sec / 2);
X#endif
X}
X
VOID
setstamp(f, date, time)		/* set a file's date/time stamp */
X	char           *f;	/* filename to stamp */
X	unsigned short    date, time;	/* desired date, time */
X{
X#if	MSDOS
X	FILE	*ff;
X	struct {
X		int             ax, bx, cx, dx, si, di, ds, es;
X	}               reg;
X
X	ff = fopen(f, "w+");	/* How else can I get a handle? */
X
X	reg.ax = 0x5701;	/* set date/time */
X	reg.bx = filehand(f);	/* file handle */
X	reg.cx = time;		/* desired time */
X	reg.dx = date;		/* desired date */
X	if (sysint21(&reg, &reg) & 1)	/* DOS call */
X		printf("Set timestamp fail (%d)\n", reg.ax);
X	fclose(ff);
X#endif
X#if	GEMDOS
X	int	fd, set[2];
X
X	fd = Fopen(f, 0);
X	set[0] = time;
X	set[1] = date;
X	Fdatime(set, fd, 1);
X	Fclose(fd);
X#endif
X#if	UNIX
X	struct tm	tm;
X	struct timeval  tvp[2];
X	int	utimes();
X	long	tmclock();
X	tm.tm_sec = (time & 31) * 2;
X	tm.tm_min = (time >> 5) & 63;
X	tm.tm_hour = (time >> 11);
X	tm.tm_mday = date & 31;
X	tm.tm_mon = ((date >> 5) & 15) - 1;
X	tm.tm_year = (date >> 9) + 80;
X	tvp[0].tv_sec = tmclock(&tm);
X	tvp[1].tv_sec = tvp[0].tv_sec;
X	tvp[0].tv_usec = tvp[1].tv_usec = 0;
X	utimes(f, tvp);
X#endif
X}
X
X#if	MSDOS
int
filehand(stream)		/* find handle on a file */
X	struct bufstr  *stream;	/* file to grab onto */
X{
X	return stream->bufhand;	/* return DOS 2.0 file handle */
X}
X#endif
X
X#if	UNIX
int
izadir(filename)		/* Is filename a directory? */
X	char           *filename;
X{
X	struct stat     buf;
X
X	if (stat(filename, &buf) != 0)
X		return (0);	/* Ignore if stat fails since */
X	else
X		return (buf.st_mode & S_IFDIR);	/* bad files trapped later */
X}
X#endif
END_OF_FILE
if test 4711 -ne `wc -c <'arcdos.c'`; then
    echo shar: \"'arcdos.c'\" unpacked with wrong size!
fi
# end of 'arcdos.c'
fi
if test -f 'arcext.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcext.c'\"
else
echo shar: Extracting \"'arcext.c'\" \(4978 characters\)
sed "s/^X//" >'arcext.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcext.c,v 2.0 1991/11/12 02:32:55 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCEXT
X * 
X * Version 2.19, created on 10/24/86 at 14:53:32
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to extract files from an
X * archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X#if	!MSDOS
X#include <ctype.h>
X#endif
X#include <string.h>
X#if	BSD
X#include <strings.h>
X#endif
X
VOID	openarc(), closearc(), setstamp();
int	match(), readhdr(), unpack();
static	VOID	extfile();
X
X#ifndef	__STDC__
char	*malloc();
X#ifndef _AIX
VOID	free();
X#endif
X#endif
X
VOID
extarc(num, arg, prt)		/* extract files from archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X	int             prt;		/* true if printing */
X{
X	struct heads    hdr;	/* file header */
X	int             save;	/* true to save current file */
X	int             did[MAXARG];/* true when argument was used */
X	char           *i;	/* string index */
X	char          **name; 	/* name pointer list */
X	int             n;	/* index */
X
X	name = (char **) malloc(num * sizeof(char *));	/* get storage for name
X							 * pointers */
X
X	for (n = 0; n < num; n++) {	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X#if	!_MTS
X		if (!(i = rindex(arg[n], '\\')))	/* find start of name */
X			if (!(i = rindex(arg[n], '/')))
X				if (!(i = rindex(arg[n], ':')))
X					i = arg[n] - 1;
X#else
X		if (!(i = rindex(arg[n], sepchr[0])))
X			if (arg[n][0] != tmpchr[0])
X				i = arg[n] - 1;
X			else
X				i = arg[n];
X#endif
X		name[n] = i + 1;
X	}
X
X
X	openarc(0);		/* open archive for reading */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* while more files to check */
X			save = 0;	/* reset save flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, name[n])) {
X					save = 1;	/* turn on save flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (save)	/* extract if desired, else skip */
X				extfile(&hdr, arg[n], prt);
X			else
X				fseek(arc, hdr.size, 1);
X		}
X	} else
X		while (readhdr(&hdr, arc))	/* else extract all files */
X			extfile(&hdr, "", prt);
X
X	closearc(0);		/* close archive after reading */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X	free(name);
X}
X
static VOID
extfile(hdr, path, prt)		/* extract a file */
X	struct heads   *hdr;	/* pointer to header data */
X	char           *path;	/* pointer to path name */
X	int             prt;	/* true if printing */
X{
X	FILE           *f, *fopen();	/* extracted file, opener */
X	char            buf[STRLEN];	/* input buffer */
X	char            fix[STRLEN];	/* fixed name buffer */
X	char           *i;	/* string index */
X
X	if (prt) {		/* printing is much easier */
X		unpack(arc, stdout, hdr);	/* unpack file from archive */
X		printf("\f");	/* eject the form */
X		return;		/* see? I told you! */
X	}
X	strcpy(fix, path);	/* note path name template */
X#if	!_MTS
X	if (*path) {
X	if (!(i = rindex(fix, '\\')))	/* find start of name */
X		if (!(i = rindex(fix, '/')))
X			if (!(i = rindex(fix, ':')))
X				i = fix - 1;
X	} else i = fix -1;
X#else
X	if (!(i = rindex(fix, sepchr[0])))
X		if (fix[0] != tmpchr[0])
X			i = fix - 1;
X		else
X			i = fix;
X#endif
X	strcpy(i + 1, hdr->name);	/* replace template with name */
X
X	if (note)
X		printf("Extracting file: %s\n", fix);
X
X	if (warn && !overlay) {
X		if (f = fopen(fix, "r")) {	/* see if it exists */
X				fclose(f);
X				printf("WARNING: File %s already exists!", fix);
X				fflush(stdout);
X				while (1) {
X					printf("  Overwrite it (y/n)? ");
X					fflush(stdout);
X					fgets(buf, STRLEN, stdin);
X					*buf = toupper(*buf);
X					if (*buf == 'Y' || *buf == 'N')
X						break;
X				}
X				if (*buf == 'N') {
X					printf("%s not extracted.\n", fix);
X					fseek(arc, hdr->size, 1);
X					return;
X				}
X		}
X	}
X#if	!_MTS
X	if (!(f = fopen(fix, OPEN_W)))
X#else
X	{
X		fortran         create();
X		VOID		memset();
X		char            c_name[256];
X		struct crsize {
X			short           maxsize, cursize;
X		}               c_size;
X		char            c_vol[6];
X		int             c_type;
X		strcpy(c_name, fix);
X		strcat(c_name, " ");
X		c_size.maxsize = 0;
X		c_size.cursize = hdr->length / 4096 + 1;
X		memset(c_vol, 0, sizeof(c_vol));
X		c_type = 0x100;
X		create(c_name, &c_size, c_vol, &c_type);
X	}
X	if (image) {
X		f = fopen(fix, OPEN_W);
X	} else
X		f = fopen(fix, "w");
X	if (!f)
X#endif
X	{
X		if (warn) {
X			printf("Cannot create %s\n", fix);
X			nerrs++;
X		}
X		fseek(arc, hdr->size, 1);
X		return;
X	}
X
X	/* now unpack the file */
X
X	unpack(arc, f, hdr);	/* unpack file from archive */
X	fclose(f);		/* all done writing to file */
X#if	!_MTS
X	setstamp(fix, hdr->date, hdr->time);	/* use filename for stamp */
X#endif
X}
END_OF_FILE
if test 4978 -ne `wc -c <'arcext.c'`; then
    echo shar: \"'arcext.c'\" unpacked with wrong size!
fi
# end of 'arcext.c'
fi
if test -f 'arcio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcio.c'\"
else
echo shar: Extracting \"'arcio.c'\" \(6860 characters\)
sed "s/^X//" >'arcio.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcio.c,v 2.0 1991/11/12 02:34:42 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCIO
X
X    Version 2.50, created on 04/22/87 at 13:25:20
X
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description:
X	 This file contains the file I/O routines used to manipulate
X	 an archive.
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if	_MTS
X#include <mts.h>
X#endif
X#include <string.h>
X
VOID	arcdie();
X
int
readhdr(hdr, f)			/* read a header from an archive */
X	struct heads   *hdr;	/* storage for header */
X	FILE           *f;	/* archive to read header from */
X{
X#if	!MSDOS
X	unsigned char   dummy[28];
X	int             i;
X#endif
X	char            name[FNLEN];	/* filename buffer */
X	int             try = 0;/* retry counter */
X	static int      first = 1;	/* true only on first read */
X
X	if (!f)			/* if archive didn't open */
X		return 0;	/* then pretend it's the end */
X	hdrver = fgetc(f);
X	if (feof(f))		/* if no more data */
X		return 0;	/* then signal end of archive */
X
X	if (hdrver != ARCMARK) {	/* check archive validity */
X		if (warn) {
X			printf("An entry in %s has a bad header.\n", arcname);
X			nerrs++;
X		}
X		printf("hdrver: %x\n", hdrver);
X		while (!feof(f)) {
X			try++;
X			if (fgetc(f) == ARCMARK) {
X				ungetc(hdrver = fgetc(f), f);
X				if (!(hdrver & 0x80) && hdrver <= ARCVER)
X					break;
X			}
X		}
X
X		if (feof(f) && first)
X			arcdie("%s is not an archive", arcname);
X
X		if (changing && warn)
X			arcdie("%s is corrupted -- changes disallowed", arcname);
X
X		if (warn)
X			printf("  %d bytes skipped.\n", try);
X
X		if (feof(f))
X			return 0;
X	}
X	hdrver = fgetc(f);	/* get header version */
X	if (hdrver & 0x80)	/* sign bit? negative? */
X		arcdie("Invalid header in archive %s", arcname);
X	if (hdrver == 0)
X		return 0;	/* note our end of archive marker */
X	if (hdrver > ARCVER) {
X		fread(name, sizeof(char), FNLEN, f);
X#if	_MTS
X		atoe(name, strlen(name));
X#endif
X		printf("I don't know how to handle file %s in archive %s\n",
X		       name, arcname);
X		printf("I think you need a newer version of ARC.\n");
X		exit(1);
X	}
X	/* amount to read depends on header type */
X
X	if (hdrver == 1) {	/* old style is shorter */
X		fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f);
X		hdrver = 2;	/* convert header to new format */
X		hdr->length = hdr->size;	/* size is same when not
X						 * packed */
X	} else
X#if	MSDOS
X		fread(hdr, sizeof(struct heads), 1, f);
X#else
X		fread(dummy, 27, 1, f);
X
X	for (i = 0; i < FNLEN; hdr->name[i] = dummy[i], i++);
X#if	_MTS
X	(void) atoe(hdr->name, strlen(hdr->name));
X#endif
X	for (i = 0, hdr->size=0; i<4; hdr->size<<=8, hdr->size += dummy[16-i], i++);
X	hdr->date = (short) ((dummy[18] << 8) + dummy[17]);
X	hdr->time = (short) ((dummy[20] << 8) + dummy[19]);
X	hdr->crc = (short) ((dummy[22] << 8) + dummy[21]);
X	for (i = 0, hdr->length=0; i<4; hdr->length<<=8, hdr->length += dummy[26-i], i++);
X#endif
X
X	if (hdr->date > olddate
X	    || (hdr->date == olddate && hdr->time > oldtime)) {
X		olddate = hdr->date;
X		oldtime = hdr->time;
X	}
X	first = 0;
X	return 1;		/* we read something */
X}
X
VOID
put_int(number, f)		/* write a 2 byte integer */
X	short           number;
X	FILE           *f;
X{
X	fputc((char) (number & 255), f);
X	fputc((char) (number >> 8), f);
X}
X
VOID
put_long(number, f)		/* write a 4 byte integer */
X	long            number;
X	FILE           *f;
X{
X	put_int((short) (number & 0xFFFF), f);
X	put_int((short) (number >> 16), f);
X}
X
VOID
writehdr(hdr, f)		/* write a header to an archive */
X	struct heads   *hdr;	/* header to write */
X	FILE           *f;	/* archive to write to */
X{
X	fputc(ARCMARK, f);		/* write out the mark of ARC */
X	fputc(hdrver, f);	/* write out the header version */
X	if (!hdrver)		/* if that's the end */
X		return;		/* then write no more */
X#if	MSDOS
X	fwrite(hdr, sizeof(struct heads), 1, f);
X#else
X	/* byte/word ordering hassles... */
X#if	_MTS
X	etoa(hdr->name, strlen(hdr->name));
X#endif
X	fwrite(hdr->name, 1, FNLEN, f);
X	put_long(hdr->size, f);
X	put_int(hdr->date, f);
X	put_int(hdr->time, f);
X	put_int(hdr->crc, f);
X	put_long(hdr->length, f);
X#endif
X
X	/* note the newest file for updating the archive timestamp */
X
X	if (hdr->date > arcdate
X	    || (hdr->date == arcdate && hdr->time > arctime)) {
X		arcdate = hdr->date;
X		arctime = hdr->time;
X	}
X}
X
char	pinbuf[MYBUF];	/* general purpose input buffer */
X
X/*
X * NOTE:  The filecopy() function is used to move large numbers of bytes from
X * one file to another.  This particular version has been modified to improve
X * performance in Computer Innovations C86 version 2.3 in the small memory
X * model.  It may not work as expected with other compilers or libraries, or
X * indeed with different versions of the CI-C86 compiler and library, or with
X * the same version in a different memory model.
X * 
X * The following is a functional equivalent to the filecopy() routine that
X * should work properly on any system using any compiler, albeit at the cost
X * of reduced performance:
X * 
X * filecopy(f,t,size) 
X *      FILE *f, *t; long size; 
X * { 
X *      while(size--)
X *              putc_tst(fgetc(f),t); 
X * }
X */
X#if	MSDOS
X#include <fileio2.h>
X
filecopy(f, t, size)		/* bulk file copier */
X	FILE           *f, *t;	/* files from and to */
X	long            size;	/* bytes to copy */
X{
X	unsigned int    bufl;	/* buffer length */
X	unsigned int    coreleft();	/* space available reporter */
X	unsigned int    cpy;	/* bytes being copied */
X	long            floc, tloc, fseek();	/* file pointers, setter */
X	struct regval   reg;	/* registers for DOS calls */
X
X	bufl = (MYBUF > size) ? (u_int) size : MYBUF;
X
X	floc = fseek(f, 0L, 1);	/* reset I/O system */
X	tloc = fseek(t, 0L, 1);
X
X	segread(&reg.si);	/* set segment registers for DOS */
X
X	while (size > 0) {	/* while more to copy */
X		reg.ax = 0x3F00;/* read from handle */
X		reg.bx = filehand(f);
X		reg.cx = bufl < size ? bufl : size;	/* amount to read */
X		reg.dx = pinbuf;
X		if (sysint21(&reg, &reg) & 1)
X			arcdie("Read fail");
X
X		cpy = reg.ax;	/* amount actually read */
X		reg.ax = 0x4000;/* write to handle */
X		reg.bx = filehand(t);
X		reg.cx = cpy;
X		reg.dx = pinbuf;
X		sysint21(&reg, &reg);
X
X		if (reg.ax != cpy)
X			arcdie("Write fail (disk full?)");
X
X		size -= (long) cpy;
X	}
X}
X#else
X
VOID
filecopy(f, t, size)		/* bulk file copier */
X	FILE           *f, *t;	/* files from and to */
X	long            size;	/* bytes to copy */
X{
X	unsigned int    bufl;	/* buffer length */
X	unsigned int    cpy;	/* bytes being copied */
X
X	bufl = (MYBUF > size) ? (u_int) size : MYBUF;
X
X	while (size > 0) {
X		cpy = fread(pinbuf, sizeof(char), bufl, f);
X		if (fwrite(pinbuf, sizeof(char), cpy, t) != cpy)
X			arcdie("Write fail (no space?)");
X		size -= cpy;
X		if (bufl > size)
X			bufl = size;
X		if (ferror(f))
X			arcdie("Unexpected EOF copying archive");
X		if (!cpy) break;
X	}
X}
X#endif
END_OF_FILE
if test 6860 -ne `wc -c <'arcio.c'`; then
    echo shar: \"'arcio.c'\" unpacked with wrong size!
fi
# end of 'arcio.c'
fi
if test -f 'arclst.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arclst.c'\"
else
echo shar: Extracting \"'arclst.c'\" \(4518 characters\)
sed "s/^X//" >'arclst.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arclst.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCLST
X  
X    Version 2.39, created on 04/22/87 at 13:48:29
X  
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X  
X    By:	 Thom Henderson
X  
X    Description:
X	 This file contains the routines used to list the contents
X	 of an archive.
X  
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
VOID            rempath(), openarc(), closearc();
int             readhdr(), match();
static	VOID	lstfile();
X
VOID
lstarc(num, arg)		/* list files in archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* header data */
X	int             list;	/* true to list a file */
X	int             did[MAXARG];	/* true when argument was used */
X	long            tnum, tlen, tsize;	/* totals */
X	int             n;	/* index */
X
X	tnum = tlen = tsize = 0;/* reset totals */
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	if (note && !kludge) {
X		printf("Name          Length  ");
X		if (bose)
X			printf("  Stowage    SF   Size now");
X		printf("  Date     ");
X		if (bose)
X			printf("  Time    CRC");
X		printf("\n");
X
X		printf("============  ========");
X		if (bose)
X			printf("  ========  ====  ========");
X		printf("  =========");
X		if (bose)
X			printf("  ======  ====");
X		printf("\n");
X	}
X	openarc(0);		/* open archive for reading */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* process all archive files */
X			list = 0;	/* reset list flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, arg[n])) {
X					list = 1;	/* turn on list flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (list) {	/* if this file is wanted */
X				if (!kludge)
X					lstfile(&hdr);	/* then tell about it */
X				tnum++;	/* update totals */
X				tlen += hdr.length;
X				tsize += hdr.size;
X			}
X			fseek(arc, hdr.size, 1);	/* move to next header */
X		}
X	} else
X		while (readhdr(&hdr, arc)) {	/* else report on all files */
X			if (!kludge)
X				lstfile(&hdr);
X			tnum++;	/* update totals */
X			tlen += hdr.length;
X			tsize += hdr.size;
X			fseek(arc, hdr.size, 1);	/* skip to next header */
X		}
X
X	closearc(0);		/* close archive after reading */
X
X	if (note && !kludge) {
X		printf("        ====  ========");
X		if (bose)
X			printf("            ====  ========");
X		printf("\n");
X	}
X	if (note) {
X		printf("Total %6ld  %8ld", tnum, tlen);
X		if (bose) {
X			if (tlen)
X				printf("            %3ld%%", 100L - (100L * tsize) / tlen);
X			else
X				printf("            ---");
X			printf("  %8ld", tsize);
X		}
X		printf("\n");
X
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
X
static	VOID
lstfile(hdr)			/* tell about a file */
X	struct heads   *hdr;	/* pointer to header data */
X{
X	int             yr, mo, dy;	/* parts of a date */
X	int             hh, mm;	/* parts of a time */
X
X	static char    *mon[] =	/* month abbreviations */
X	{"???",			/* For month == 0 */
X	 "Jan", "Feb", "Mar", "Apr",
X	 "May", "Jun", "Jul", "Aug",
X	 "Sep", "Oct", "Nov", "Dec"
X	};
X
X	if (!note) {		/* no notes means short listing */
X		printf("%s\n", hdr->name);
X		return;
X	}
X
X	yr = (hdr->date >> 9) & 0x7f;	/* dissect the date */
X	mo = (hdr->date >> 5) & 0x0f;
X	if (mo > 12)		/* just in case... */
X		mo = 0;
X	dy = hdr->date & 0x1f;
X
X	hh = (hdr->time >> 11) & 0x1f;	/* dissect the time */
X	mm = (hdr->time >> 5) & 0x3f;
X/*	ss = (hdr->time & 0x1f) * 2;	seconds, not used. */
X
X	printf("%-12s  %8ld  ", hdr->name, hdr->length);
X
X	if (bose) {
X		switch (hdrver) {
X		case 1:
X		case 2:
X			printf("   --   ");
X			break;
X		case 3:
X			printf(" Packed ");
X			break;
X		case 4:
X			printf("Squeezed");
X			break;
X		case 5:
X		case 6:
X		case 7:
X			printf("crunched");
X			break;
X		case 8:
X			printf("Crunched");
X			break;
X		case 9:
X			printf("Squashed");
X			break;
X		default:
X			printf("Unknown!");
X		}
X
X		if (hdr->length)
X			printf("  %3ld%%", 100L - (100L * hdr->size) / hdr->length);
X		else
X			printf("  ---");
X		printf("  %8ld  ", hdr->size);
X	}
X	printf("%2d %3s %02d", dy, mon[mo], (yr + 80) % 100);
X
X	if (bose)
X		printf("  %2d:%02d%c  %04x",
X		       (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'),
X		       hdr->crc & 0xffff);
X
X	printf("\n");
X}
END_OF_FILE
if test 4518 -ne `wc -c <'arclst.c'`; then
    echo shar: \"'arclst.c'\" unpacked with wrong size!
fi
# end of 'arclst.c'
fi
if test -f 'arcmatch.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcmatch.c'\"
else
echo shar: Extracting \"'arcmatch.c'\" \(2999 characters\)
sed "s/^X//" >'arcmatch.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcmatch.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCMATCH
X * 
X * Version 2.17, created on 12/17/85 at 20:32:18
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains service routines needed to maintain an
X * archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
X#include <string.h>
X#if	BSD
X#include <strings.h>
X#endif
X
VOID	arcdie();
X
int
match(n, t)			/* test name against template */
X	char           *n;	/* name to test */
X	char           *t;	/* template to test against */
X{
X#if	_MTS
X	fortran         patbuild(), patmatch(), patfree();
X	static int      patlen = (-1);
X	static int      patwork = 0;
X	static int      patswch = 0;
X	char            patccid[4];
X	static char     patchar[2] = "?";
X	static char     oldtemp[16] = 0;
X	int             namlen, RETCODE;
X
X	if (strcmp(t, oldtemp)) {
X		if (patwork)
X			patfree(&patwork);
X		strcpy(oldtemp, t);
X		patlen = strlen(oldtemp);
X		patbuild(oldtemp, &patlen, &patwork, &patswch, patccid, patchar, _retcode RETCODE);
X		if (RETCODE > 8) {
X			printf("MTS: patbuild returned %d\n", RETCODE);
X			arcdie("bad wildcard in filename");
X		}
X	}
X	namlen = strlen(n);
X	patmatch(n, &namlen, &patwork, _retcode RETCODE);
X	switch (RETCODE) {
X	case 0:
X		return (1);
X	case 4:
X		return (0);
X	default:
X		arcdie("wildcard pattern match failed");
X	}
X}
X
X#else
X#if	!UNIX
X	upper(n);
X	upper(t);		/* avoid case problems */
X#endif	/* UNIX */
X
X	/* first match name part */
X
X	while ((*n && *n != '.') || (*t && *t != '.')) {
X		if (*n != *t && *t != '?') {	/* match fail? */
X			if (*t != '*')	/* wildcard fail? */
X				return 0;	/* then no match */
X			else {	/* else jump over wildcard */
X				while (*n && *n != '.')
X					n++;
X				while (*t && *t != '.')
X					t++;
X				break;	/* name part matches wildcard */
X			}
X		} else {	/* match good for this char */
X			n++;	/* advance to next char */
X			t++;
X		}
X	}
X
X	if (*n && *n == '.')
X		n++;		/* skip extension delimiters */
X	if (*t && *t == '.')
X		t++;
X
X	/* now match name part */
X
X	while (*n || *t) {
X		if (*n != *t && *t != '?') {	/* match fail? */
X			if (*t != '*')	/* wildcard fail? */
X				return 0;	/* then no match */
X			else
X				return 1;	/* else good enough */
X		} else {	/* match good for this char */
X			n++;	/* advance to next char */
X			t++;
X		}
X	}
X
X	return 1;		/* match worked */
X}
X#endif
X
VOID
rempath(nargs, arg)		/* remove paths from filenames */
X	int             nargs;	/* number of names */
X	char           *arg[];	/* pointers to names */
X{
X	char           *i;	/* string index, reverse indexer */
X	int             n;	/* index */
X
X	for (n = 0; n < nargs; n++) {	/* for each supplied name */
X		if (!(i = rindex(arg[n], '\\')))	/* search for end of
X							 * path */
X			if (!(i = rindex(arg[n], '/')))
X				i = rindex(arg[n], ':');
X		if (i)		/* if path was found */
X			arg[n] = i + 1;	/* then skip it */
X	}
X}
END_OF_FILE
if test 2999 -ne `wc -c <'arcmatch.c'`; then
    echo shar: \"'arcmatch.c'\" unpacked with wrong size!
fi
# end of 'arcmatch.c'
fi
if test -f 'arcpack.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcpack.c'\"
else
echo shar: Extracting \"'arcpack.c'\" \(6658 characters\)
sed "s/^X//" >'arcpack.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcpack.c,v 2.0 1991/11/12 00:34:06 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCPACK
X
X    Version 3.49, created on 04/21/87 at 11:26:51
X
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description:
X	 This file contains the routines used to compress a file
X	 when placing it in an archive.
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if	_MTS
X#include <ctype.h>
X#endif
X
X#include "proto.h"
X
VOID		setcode(), init_cm(), codebuf();
VOID		arcdie(), init_sq(), flsh_cm();
int		crcbuf();
u_int		ncr_buf();
X
int		lastc;
X
X/* stuff for non-repeat packing */
X
X#define DLE 0x90		/* repeat sequence marker */
X
u_char	state;		/* current packing state */
X
X/* non-repeat packing states */
X
X#define NOHIST	0		/* don't consider previous input */
X#define SENTCHAR 1		/* lastchar set, no lookahead yet */
X
extern	u_char	pinbuf[MYBUF];
u_char		pakbuf[2L*MYBUF];	/* worst case, 2*inbuf */
X
X/* packing results */
X
long		stdlen;		/* length for standard packing */
short		crcval;		/* CRC check value */
X
VOID
pack(f, t, hdr)			/* pack file into an archive */
X	FILE	       *f, *t;	/* source, destination */
X	struct heads   *hdr;	/* pointer to header data */
X{
X	long		ncrlen; /* length after packing */
X	long		huflen; /* length after squeezing */
X	long		lzwlen; /* length after crunching */
X	long		pred_sq(), head_sq(), huf_buf();	/* stuff for squeezing */
X	long		pred_cm();	/* dynamic crunching cleanup */
X	long		tloc, ftell();	/* start of output */
X	u_int		inbytes, pakbytes;
X
X	/* first pass - see which method is best */
X
X	tloc = ftell(t);	/* note start of output */
X
X	if (!nocomp) {		/* if storage kludge not active */
X		if (note) {
X			printf(" analyzing, ");
X			fflush(stdout);
X		}
X		state = NOHIST; /* initialize ncr packing */
X		stdlen = ncrlen = 0;	/* reset size counters */
X		huflen = lzwlen = 0;
X		crcval = 0;	/* initialize CRC check value */
X		setcode();	/* initialize encryption */
X		init_sq();	/* initialize for squeeze scan */
X
X		inbytes = getbuf(f);
X		if (inbytes) {
X
X			init_cm(pinbuf);
X
X			for (;; inbytes = getbuf(f)) {
X				pakbytes = ncr_buf(inbytes);
X				ncrlen += pakbytes;
X				hufb_tab(pakbuf, pakbytes);
X				if (dosquash)
X					lzw_buf(pinbuf, inbytes, t);
X				else
X					lzw_buf(pakbuf, pakbytes, t);
X				if (inbytes < MYBUF)
X					break;
X			}
X			lzwlen = pred_cm(t);
X			huflen = pred_sq();
X		}
X	} else {		/* else kludge the method */
X		stdlen = 0;	/* make standard look best */
X		ncrlen = huflen = lzwlen = 1;
X	}
X
X	/* standard set-ups common to all methods */
X
X	hdr->crc = crcval;	/* note CRC check value */
X	hdr->length = stdlen;	/* set actual file length */
X	if (stdlen > MYBUF) {
X		fseek(f, 0L, 0);/* rewind input */
X		state = NOHIST; /* reinitialize ncr packing */
X		setcode();	/* reinitialize encryption */
X	} else
X		inbytes = stdlen;
X
X	/* choose and use the shortest method */
X
X	if (kludge && note)
X		printf("\n\tS:%ld  P:%ld  S:%ld	 C:%ld,\t ",
X		       stdlen, ncrlen, huflen, lzwlen);
X
X	if (stdlen <= ncrlen && stdlen <= huflen && stdlen <= lzwlen) {
X		if (note) {
X			printf("storing, ");	/* store without compression */
X			fflush(stdout);
X		}
X		hdrver = 2;	/* note packing method */
X		fseek(t, tloc, 0);	/* reset output for new method */
X		if (nocomp || (stdlen > MYBUF)) {
X			stdlen = crcval = 0;
X			while ((inbytes = getbuf(f)) != 0)
X				putb_pak(pinbuf, inbytes, t); /* store it straight */
X		} else
X			putb_pak(pinbuf, inbytes, t);
X		hdr->crc = crcval;
X		hdr->length = hdr->size = stdlen;
X	} else if (ncrlen < lzwlen && ncrlen < huflen) {
X		if (note) {
X			printf("packing, ");	/* pack with repeat */
X			fflush(stdout); /* suppression */
X		}
X		hdrver = 3;	/* note packing method */
X		hdr->size = ncrlen;	/* set data length */
X		fseek(t, tloc, 0);	/* reset output for new method */
X		if (stdlen > MYBUF) {
X			do {
X				inbytes = getbuf(f);
X				pakbytes = ncr_buf(inbytes);
X				putb_pak(pakbuf, pakbytes, t);
X			} while (inbytes != 0);
X		} else
X			putb_pak(pakbuf, pakbytes, t);
X	} else if (huflen < lzwlen) {
X		if (note) {
X			printf("squeezing, ");
X			fflush(stdout);
X		}
X		hdrver = 4;	/* note packing method */
X		fseek(t, tloc, 0);	/* reset output for new method */
X		huflen = head_sq();
X		if (stdlen > MYBUF) {
X			do {
X				inbytes = getbuf(f);
X				pakbytes = ncr_buf(inbytes);
X				huflen += huf_buf(pakbuf, pakbytes, inbytes, t);
X			} while (inbytes != 0);
X		} else
X			huflen += huf_buf(pakbuf, pakbytes, 0, t);
X
X		hdr->size = huflen;	/* note final size */
X	} else {
X		if (note)
X			printf(dosquash ? "squashed, " : "crunched, ");
X		flsh_cm(t);
X		hdrver = dosquash ? 9 : 8;
X		hdr->size = lzwlen;	/* size should not change */
X	}
X
X	/* standard cleanups common to all methods */
X
X	if (note)
X		printf("done. (%ld%%)\n", hdr->length == 0 ?
X		       0L : 100L - (100L * hdr->size) / hdr->length);
X}
X
X/*
X * Non-repeat compression - text is passed through normally, except that a
X * run of more than two is encoded as:
X *
X * <char> <DLE> <count>
X *
X * Special case: a count of zero indicates that the DLE is really a DLE, not a
X * repeat marker.
X */
X
u_int
ncr_buf(inbytes)
X	u_int		inbytes;	/* number of bytes in inbuf */
X{
X	u_int		i;
X	int		c;
X	reg u_char     *inptr, *pakptr;
X	static int	cnt;
X
X	inptr = pinbuf;
X	pakptr = pakbuf;
X
X	if (state == NOHIST) {
X		lastc = (-1);
X		cnt = 1;
X		state = SENTCHAR;
X	}
X	for (i = 0; i < inbytes; i++) {
X		c = *inptr++;
X		if (c == lastc && cnt < 255)
X			cnt++;
X		else {
X			if (cnt == 2) {
X				*pakptr++ = lastc;
X			} else if (cnt > 2) {
X				*pakptr++ = DLE;
X				*pakptr++ = cnt;
X			}
X			*pakptr++ = c;
X			lastc = c;
X			cnt = 1;
X		}
X		if (c == DLE) {
X			*pakptr++ = '\0';
X			lastc = (-1);
X		}
X	}
X	if (inbytes < MYBUF && cnt > 1) {	/* trailing stuff */
X		if (cnt == 2)
X			*pakptr++ = lastc;
X		else {
X			*pakptr++ = DLE;
X			*pakptr++ = cnt;
X		}
X	}
X	return (pakptr - pakbuf);
X}
X
u_int
getbuf(f)
X	FILE	       *f;
X{
X	u_int		i;
X#if	!DOS
X	int		c;
X	static int	cr = 0;
X	register u_char *ptr;
X	if (image) {
X#endif
X		i = fread(pinbuf, 1, MYBUF, f);
X#if	!DOS
X	} else {
X		ptr = pinbuf;
X		for (i = 0, c = 0; (c != EOF) && (i < MYBUF); i++) {
X			if (cr) {
X				c = '\n';
X				cr = 0;
X			} else {
X				c = fgetc(f);
X				if (c == EOF)
X					break;
X				else if (c == '\n') {
X					c = '\r';
X					cr = 1;
X				}
X			}
X			*ptr++ = c;
X		}
X#if	_MTS
X		etoa(pinbuf, i);
X#endif				/* _MTS */
X	}
X#endif				/* !DOS */
X	crcval = crcbuf(crcval, i, pinbuf);
X	stdlen += i;
X	return (i);
X}
X
VOID
putb_pak(buf, len, f)
X	u_char	       *buf;
X	u_int		len;
X	FILE	       *f;
X{
X	u_int		i;
X
X	if (f && len) {
X		if (password)
X			codebuf(buf, len);
X		i = fwrite(buf, 1, len, f);
X		if (i != len)
X			arcdie("Write failed");
X	}
X}
END_OF_FILE
if test 6658 -ne `wc -c <'arcpack.c'`; then
    echo shar: \"'arcpack.c'\" unpacked with wrong size!
fi
# end of 'arcpack.c'
fi
if test -f 'arcrun.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcrun.c'\"
else
echo shar: Extracting \"'arcrun.c'\" \(3891 characters\)
sed "s/^X//" >'arcrun.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcrun.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCRUN
X * 
X * Version 1.20, created on 03/24/86 at 19:34:31
X * 
X * (C) COPYRIGHT 1985,85 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to "run" a file which is
X * stored in an archive.  At present, all we really do is (a) extract a
X * temporary file, (b) give its name as a system command, and then (c) delete
X * the file.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
VOID	rempath(), openarc(), closearc(), arcdie();
int	readhdr(), match(), unpack();
static	VOID	runfile();
char	*strcat();
X
VOID
runarc(num, arg)		/* run file from archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* file header */
X	char           *makefnam();	/* filename fixer */
X	char            buf[STRLEN];	/* filename buffer */
X	FILE           *fopen();/* file opener */
X	char	       *dummy[2];
X
X	dummy[0]="dummy";
X	dummy[1]=NULL;
X	rempath(num, arg);	/* strip off paths */
X
X	openarc(0);		/* open archive for reading */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* while more files to check */
X			if (match(hdr.name, makefnam(arg[0], ".*", buf)))
X				runfile(&hdr, num, arg);
X			else
X				fseek(arc, hdr.size, 1);
X		}
X	} else
X		while (readhdr(&hdr, arc))	/* else run all files */
X			runfile(&hdr, 1, dummy);
X
X	closearc(0);		/* close archive after changes */
X}
X
static  VOID
runfile(hdr, num, arg)		/* run a file */
X	struct heads   *hdr;	/* pointer to header data */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	FILE           *tmp, *fopen();	/* temporary file */
X	char           *dir, *gcdir();	/* directory stuff */
X	char            buf[STRLEN], *makefnam();	/* temp file name, fixer */
X#if	DOS
X	char		nbuf[64], *i, *rindex();
X#endif
X#if	!GEMDOS
X	int             n;	/* index */
X	char            sys[STRLEN];	/* invocation command buffer */
X#endif
X
X	/* makefnam("$ARCTEMP",hdr->name,buf); */
X#if	UNIX
X	sprintf(buf, "%s.RUN", arctemp);
X	strcpy(sys, buf);
X#else
X	strcpy(nbuf, arctemp);
X	makefnam(nbuf,hdr->name,buf);
X	i = rindex(buf,'.');
X#endif
X#if	MSDOS
X	if (!strcmp(i, ".BAS")) {
X		strcpy(sys, "BASICA ");
X		strcat(sys, buf);
X	}
X	else if (!strcmp(i, ".BAT")
X		 || !strcmp(i, ".COM")
X		 || !strcmp(i, ".EXE"))
X		strcpy(sys, buf);
X
X	else {
X		if (warn) {
X			printf("File %s is not a .BAS, .BAT, .COM, or .EXE\n",
X			       hdr->name);
X			nerrs++;
X		}
X		fseek(arc, hdr->size, 1);	/* skip this file */
X		return;
X	}
X#endif
X#if	GEMDOS
X      if (strcmp(i, ".PRG")
X              && strcmp(i, ".TTP")
X              && strcmp(i, ".TOS"))
X      {
X              if (warn) {
X                      printf("File %s is not a .PRG, .TOS, or .TTP\n",
X                              hdr->name);
X                      nerrs++;
X              }
X              fseek(arc, hdr->size, 1);       /* skip this file */
X              return;
X      }
X#endif
X
X	if (warn)
X		if (tmp = fopen(buf, "r"))
X			arcdie("Temporary file %s already exists", buf);
X	if (!(tmp = fopen(buf, OPEN_W)))
X		arcdie("Unable to create temporary file %s", buf);
X
X	if (note)
X		printf("Invoking file: %s\n", hdr->name);
X
X	dir = gcdir("");	/* see where we are */
X	unpack(arc, tmp, hdr);	/* unpack the entry */
X	fclose(tmp);		/* release the file */
X	chmod(buf, "700");	/* make it executable */
X#if	GEMDOS
X	execve(buf, arg, NULL);
X#else
X	for (n = 1; n < num; n++) {	/* add command line arguments */
X		strcat(sys, " ");
X		strcat(sys, arg[n]);
X	}
X	system(buf);		/* try to invoke it */
X#endif
X	chdir(dir);
X	free(dir);		/* return to whence we started */
X	if (unlink(buf) && warn) {
X		printf("Cannot unsave temporary file %s\n", buf);
X		nerrs++;
X	}
X}
END_OF_FILE
if test 3891 -ne `wc -c <'arcrun.c'`; then
    echo shar: \"'arcrun.c'\" unpacked with wrong size!
fi
# end of 'arcrun.c'
fi
if test -f 'arcs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcs.h'\"
else
echo shar: Extracting \"'arcs.h'\" \(1674 characters\)
sed "s/^X//" >'arcs.h' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcs.h,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - Archive file header format
X * 
X * Version 2.12, created on 12/17/85 at 14:40:26
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file defines the format of an archive file header,
X * excluding the archive marker and the header version number.
X * 
X * Each entry in an archive begins with a one byte archive marker, which is set
X * to 26.  The marker is followed by a one byte header type code, from zero
X * to 7.
X * 
X * If the header type code is zero, then it is an end marker, and no more data
X * should be read from the archive.
X * 
X * If the header type code is in the range 2 to 7, then it is followed by a
X * standard archive header, which is defined below.
X * 
X * If the header type code is one, then it is followed by an older format
X * archive header.  The older format header does not contain the true length.
X * A header should be read for a length of sizeof(struct heads)-sizeof(long).
X * Then set length equal to size and change the header version to 2.
X * 
X * Programming note: The crc value given in the header is based on the unpacked
X * data.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X
struct heads {			/* archive entry header format */
X    char    name[FNLEN];		/* file name */
X            long size;		/* size of file, in bytes */
X    unsigned    short date;	/* creation date */
X    unsigned    short time;	/* creation time */
X                short crc;	/* cyclic redundancy check */
X                long length;	/* true file length */
X};
END_OF_FILE
if test 1674 -ne `wc -c <'arcs.h'`; then
    echo shar: \"'arcs.h'\" unpacked with wrong size!
fi
# end of 'arcs.h'
fi
if test -f 'arcsvc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcsvc.c'\"
else
echo shar: Extracting \"'arcsvc.c'\" \(5488 characters\)
sed "s/^X//" >'arcsvc.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcsvc.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCSVC
X
X    Version 2.23, created on 04/22/87 at 13:10:10
X
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description:
X	 This file contains service routines needed to maintain an archive.
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if	_MTS
X#include <mts.h>
X#endif
X
VOID	arcdie(), setstamp();
int	unlink();
X
VOID
openarc(chg)			/* open archive */
X	int             chg;	/* true to open for changes */
X{
X	FILE           *fopen();/* file opener */
X
X	if (!(arc = fopen(arcname, OPEN_R))) {
X		if (chg) {
X			if (note)
X				printf("Creating new archive: %s\n", arcname);
X		}
X		else
X			arcdie("Archive not found: %s", arcname);
X	}
X#if	_MTS	/* allow reading archives of max MTS record length */
X	{
X		char *buf, *malloc();
X		int inlen;
X		struct GDDSECT *region;
X
X		region=gdinfo(arc->_fd._fdub);
X		inlen=region->GDINLEN;
X		buf=malloc(inlen);
X		setbuffer(arc, buf, inlen);
X	}
X#endif
X	if (chg) {		/* if opening for changes */
X		if (!(new = fopen(newname, OPEN_W)))
X			arcdie("Cannot create archive copy: %s", newname);
X
X	changing = chg;		/* note if open for changes */
X	}
X}
X
VOID
closearc(chg)			/* close an archive */
X	int             chg;	/* true if archive was changed */
X{
X	if (arc) {		/* if we had an initial archive */
X		fclose(arc);
X#if	!_MTS
X		if (kludge)	/* kludge to update timestamp */
X			setstamp(arcname, olddate, oldtime);
X#endif
X	}
X	if (chg) {		/* if things have changed */
X		fclose(new);	/* close the new copy */
X		if (arc) {	/* if we had an original archive */
X#if      _MTS
X                                {
X                                 fortran VOID permit();
X                                 char what[FNLEN+2];
X/* copy permissions  */          char who[FNLEN+6];
X/* of old archive to */          int how,whotyp,wholen,info;
X/* new copy...       */          strcpy(what, newname);
X                                 strcat(what," ");
X                                 whotyp=9;
X                                 sprintf(who,"like %s",arcname);
X                                 wholen=strlen(who);
X                                 info=0;
X                                 permit(what,&how,&whotyp,&wholen,who,&info);
X                                }
X#endif
X			if (keepbak) {	/* if a backup is wanted */
X				unlink(bakname);	/* erase any old copies */
X				if (move(arcname, bakname))
X					arcdie("Cannot rename %s to %s", arcname, bakname);
X				printf("Keeping backup archive: %s\n", bakname);
X			} else if (unlink(arcname))
X				arcdie("Cannot delete old archive: %s", arcname);
X		}
X		if (move(newname, arcname))
X			arcdie("Cannot move %s to %s", newname, arcname);
X#if	!_MTS
X		setstamp(arcname, arcdate, arctime);
X#endif
X	}
X}
X
X/*
X * CRC computation logic
X * 
X * The logic for this method of calculating the CRC 16 bit polynomial is taken
X * from an article by David Schwaderer in the April 1985 issue of PC Tech
X * Journal.
X */
X
static short      crctab[] =	/* CRC lookup table */
X{
X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
X};
X
X/*
X * Update a CRC check on the given buffer.
X */
X
int
crcbuf(crc, len, buf)
X	register int	crc;	/* running CRC value */
X	register u_int	len;
X	register u_char	*buf;
X{
X	register u_int	i;
X
X	for (i=0; i<len; i++)
X		crc = ((crc >> 8) & 0xff) ^ crctab[(crc ^ *buf++) & 0xff];
X	
X	return (crc);
X}
END_OF_FILE
if test 5488 -ne `wc -c <'arcsvc.c'`; then
    echo shar: \"'arcsvc.c'\" unpacked with wrong size!
fi
# end of 'arcsvc.c'
fi
if test -f 'arctst.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arctst.c'\"
else
echo shar: Extracting \"'arctst.c'\" \(1313 characters\)
sed "s/^X//" >'arctst.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arctst.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCTST
X * 
X * Version 2.12, created on 02/03/86 at 23:00:40
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to test archive integrity.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
VOID	openarc();
int	readhdr(), unpack();
X
VOID
tstarc()
X{				/* test integrity of an archive */
X	struct heads    hdr;	/* file header */
X	long            arcsize, ftell();	/* archive size */
X
X	openarc(0);		/* open archive for reading */
X	fseek(arc, 0L, 2);	/* move to end of archive */
X	arcsize = ftell(arc);	/* see how big it is */
X	fseek(arc, 0L, 0);	/* return to top of archive */
X
X	while (readhdr(&hdr, arc)) {
X		if (ftell(arc) + hdr.size > arcsize) {
X			printf("Archive truncated in file %s\n", hdr.name);
X			nerrs++;
X			break;
X		} else {
X			printf("Testing file: %-12s  ", hdr.name);
X			fflush(stdout);
X			if (unpack(arc, NULL, &hdr))
X				nerrs++;
X			else
X				printf("okay\n");
X		}
X	}
X
X	if (nerrs < 1)
X		printf("No errors detected\n");
X	else if (nerrs == 1)
X		printf("One error detected\n");
X	else
X		printf("%d errors detected\n", nerrs);
X}
END_OF_FILE
if test 1313 -ne `wc -c <'arctst.c'`; then
    echo shar: \"'arctst.c'\" unpacked with wrong size!
fi
# end of 'arctst.c'
fi
if test -f 'arcunp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcunp.c'\"
else
echo shar: Extracting \"'arcunp.c'\" \(5073 characters\)
sed "s/^X//" >'arcunp.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcunp.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCUNP
X * 
X * Version 3.17, created on 02/13/86 at 10:20:08
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to expand a file when
X * taking it out of an archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X#if	_MTS
X#include <mts.h>
X#endif
X
VOID	setcode(), init_usq(), init_ucr(), decomp();
VOID	arcdie(), codebuf();
X
X#include "proto.h"
X
X/* stuff for repeat unpacking */
X
X#define DLE 0x90		/* repeat byte flag */
X
extern u_char   state;		/* repeat unpacking state */
extern int	lastc;
X
X/* repeat unpacking states */
X
X#define NOHIST 0		/* no relevant history */
X#define INREP 1			/* sending a repeated value */
X
short    crcval;		/* CRC check value */
long     stdlen;		/* bytes to read */
X#if	!DOS
static int	gotcr;		/* got a carriage return? */
X#endif
X
extern u_char	pinbuf[MYBUF], pakbuf[2L*MYBUF];
extern u_char	outbuf[MYBUF];
X
int
unpack(f, t, hdr)		/* unpack an archive entry */
X	FILE           *f, *t;	/* source, destination */
X	struct heads   *hdr;	/* pointer to file header data */
X{
X	u_int		len;
X
X	/* setups common to all methods */
X#if	!DOS
X	gotcr = 0;
X#endif
X	crcval = 0;		/* reset CRC check value */
X	stdlen = hdr->size;	/* set input byte counter */
X	state = NOHIST;		/* initial repeat unpacking state */
X	setcode();		/* set up for decoding */
X
X	/* use whatever method is appropriate */
X
X	switch (hdrver) {	/* choose proper unpack method */
X	case 1:		/* standard packing */
X	case 2:
X		do {
X			len = getb_unp(f);
X			putb_unp(pinbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 3:		/* non-repeat packing */
X		do {
X			len = getb_unp(f);
X			putb_ncr(pinbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 4:		/* Huffman squeezing */
X		init_usq(f);
X		do {
X			len = getb_usq(f);
X			putb_ncr(outbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 5:		/* Lempel-Zev compression */
X		init_ucr(0, f);
X		do {
X			len = getb_ucr(f);
X			putb_unp(outbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 6:		/* Lempel-Zev plus non-repeat */
X		init_ucr(0, f);
X		do {
X			len = getb_ucr(f);
X			putb_ncr(outbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 7:		/* L-Z plus ncr with new hash */
X		init_ucr(1, f);
X		do {
X			len = getb_ucr(f);
X			putb_ncr(outbuf, len, t);
X		} while (len == MYBUF);
X		break;
X
X	case 8:		/* dynamic Lempel-Zev */
X		decomp(0, f, t);
X		break;
X
X	case 9:		/* Squashing */
X		decomp(1, f, t);
X		break;
X
X	default:		/* unknown method */
X		if (warn) {
X			printf("I don't know how to unpack file %s\n", hdr->name);
X			printf("I think you need a newer version of ARC\n");
X			nerrs++;
X		}
X		fseek(f, hdr->size, 1);	/* skip over bad file */
X		return 1;	/* note defective file */
X	}
X
X	/* cleanups common to all methods */
X
X	if (crcval != hdr->crc) {
X		if (warn || kludge) {
X			printf("WARNING: File %s fails CRC check\n", hdr->name);
X			nerrs++;
X		}
X		return 1;	/* note defective file */
X	}
X	return 0;		/* file is okay */
X}
X
X/*
X * This routine is used to put bytes in the output file.  It also performs
X * various housekeeping functions, such as maintaining the CRC check value.
X */
X
VOID
putb_unp(buf, len, t)
X	u_char	*buf;
X	u_int	len;
X	FILE	*t;
X{
X	u_int i, j;
X
X	crcval = crcbuf(crcval, len, buf);
X
X	if (!t)
X		return;
X#if	!DOS
X	if (!image) {
X#if	_MTS
X		atoe(buf, len);
X#endif
X		if (gotcr) {
X			gotcr = 0;
X			if (buf[0] != '\n')
X				putc('\r', t);
X		}
X
X		for (i=0,j=0; i<len; i++)
X			if (buf[i] != '\r' || buf[i+1] != '\n')
X				buf[j++] = buf[i];
X		len = j;
X
X		if (buf[len-1] == '\r') {
X			len--;
X			gotcr = 1;
X		}
X	}
X#endif	/* !DOS */
X	i=fwrite(buf, 1, len, t);
X	if (i != len)
X		arcdie("Write fail");
X}
X
X/*
X * This routine is used to decode non-repeat compression.  Bytes are passed
X * one at a time in coded format, and are written out uncoded. The data is
X * stored normally, except that runs of more than two characters are
X * represented as:
X * 
X * <char> <DLE> <count>
X * 
X * With a special case that a count of zero indicates a DLE as data, not as a
X * repeat marker.
X */
X
VOID
putb_ncr(buf, len, t)		/* put NCR coded bytes */
X	u_char	*buf;
X	u_int	len;
X	FILE	*t;		/* file to receive data */
X{
X	u_char	*pakptr=pakbuf;
X	u_int	i;
X
X	for (i=0; i<len; i++) {
X		if (state == INREP) {
X			if (buf[i])
X				while (--buf[i])
X					*pakptr++ = lastc;
X			else
X				*pakptr++ = DLE;
X			state = NOHIST;
X		} else {
X			if (buf[i] != DLE)
X				*pakptr++ = lastc = buf[i];
X			else
X				state = INREP;
X		}
X
X		if (pakptr - pakbuf > MYBUF) {
X			putb_unp(pakbuf, (u_int) (pakptr-pakbuf), t);
X			pakptr = pakbuf;
X		}
X	}
X	putb_unp(pakbuf, (u_int) (pakptr-pakbuf), t);
X}
X
X/*
X * This routine reads a buffer of data from an archive.
X */
X
u_int
getb_unp(f)
X	FILE		*f;
X{
X	register u_int len;
X
X	if (stdlen) {
X		len = (stdlen < MYBUF) ? stdlen : MYBUF;
X
X		len = fread(pinbuf, 1, len, f);
X
X		if (password)
X			codebuf(pinbuf, len);
X	
X		stdlen -= len;
X	} else
X		len = 0;
X	
X	return (len);
X}
END_OF_FILE
if test 5073 -ne `wc -c <'arcunp.c'`; then
    echo shar: \"'arcunp.c'\" unpacked with wrong size!
fi
# end of 'arcunp.c'
fi
if test -f 'arcusq.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'arcusq.c'\"
else
echo shar: Extracting \"'arcusq.c'\" \(2743 characters\)
sed "s/^X//" >'arcusq.c' <<'END_OF_FILE'
X/*
X * $Header: /var/local/hyc/src/arc/RCS/arcusq.c,v 2.0 1991/11/12 00:30:01 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCUSQ
X * 
X * Version 3.14, created on 07/25/86 at 13:04:19
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:	Thom Henderson
X * 
X * Description: This file contains the routines used to expand a file which was
X * packed using Huffman squeezing.
X * 
X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
X * adapted to CI-C86 by Robert J. Beilstein.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
X#include "proto.h"
X
VOID		arcdie();
X
X/* stuff for Huffman unsqueezing */
X
X#define ERROR (-1)
X
X#define SPEOF 256		/* special endfile token */
X#define NUMVALS 257		/* 256 data values plus SPEOF */
X
extern struct nd {		/* decoding tree */
X	int		child[2];	/* left, right */
X}		node[NUMVALS];	/* use large buffer */
X
extern char	pinbuf[MYBUF];
extern u_char	outbuf[MYBUF], *outbeg, *outend;
X
static int	bpos;		/* last bit position read */
extern int	curin;		/* last byte value read */
static int	numnodes;	/* number of nodes in decode tree */
X
extern char  *inbeg, *inend;
X
X/* get a 16bit integer */
X#define GET_INT(x)	\
X{	x = (u_char) (*inbeg++); \
X	x |= *inbeg++ << 8;}
X
VOID
init_usq(f)			/* initialize Huffman unsqueezing */
X	FILE	       *f;	/* file containing squeezed data */
X{
X	int		i;	/* node index */
X	u_int		inlen;
X
X	bpos = 99;		/* force initial read */
X
X	inlen = getb_unp(f);
X	inbeg = pinbuf;
X	inend = &pinbuf[inlen];
X
X	GET_INT(numnodes);
X
X	if (numnodes < 0 || numnodes >= NUMVALS)
X		arcdie("File has an invalid decode tree");
X
X	/* initialize for possible empty tree (SPEOF only) */
X
X	node[0].child[0] = -(SPEOF + 1);
X	node[0].child[1] = -(SPEOF + 1);
X
X	for (i = 0; i < numnodes; ++i) {	/* get decoding tree from
X						 * file */
X		GET_INT(node[i].child[0]);
X		GET_INT(node[i].child[1]);
X	}
X}
X
u_int
getb_usq(f)			/* get byte from squeezed file */
X	FILE	       *f;	/* file containing squeezed data */
X{
X	int		i;	/* tree index */
X	u_int		j;
X
X	outbeg = outbuf;
X	for (j = 0; j < MYBUF; j++) {
X		/* follow bit stream in tree to a leaf */
X
X		for (i = 0; i >= 0;) {	/* work down(up?) from root */
X			if (++bpos > 7) {
X				if (inbeg >= inend) {
X					inend = &pinbuf[getb_unp(f)];
X					inbeg = pinbuf;
X					if (inend == inbeg) {
X						if (!curin)
X							j--;
X						return(j);
X					}
X				}
X				curin = *inbeg++;
X				bpos = 0;
X
X				/* move a level deeper in tree */
X				i = node[i].child[1 & curin];
X			} else
X				i = node[i].child[1 & (curin >>= 1)];
X		}
X
X		/* decode fake node index to original data value */
X
X		i = -(i + 1);
X
X		if (i != SPEOF)
X			*outbeg++ = i;
X		else
X			break;
X	}
X	/*NOTREACHED*/
X	return (j);
X}
END_OF_FILE
if test 2743 -ne `wc -c <'arcusq.c'`; then
    echo shar: \"'arcusq.c'\" unpacked with wrong size!
fi
# end of 'arcusq.c'
fi
if test -f 'proto.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'proto.h'\"
else
echo shar: Extracting \"'proto.h'\" \(410 characters\)
sed "s/^X//" >'proto.h' <<'END_OF_FILE'
u_int	getbuf PROTO ((FILE *f));
u_int	getb_ucr PROTO ((FILE *f));
u_int	getb_usq PROTO ((FILE *f));
u_int	getb_unp PROTO ((FILE *f));
VOID	hufb_tab PROTO ((u_char *buf, u_int len));
VOID	 lzw_buf PROTO ((u_char *buf, u_int len, FILE *f));
VOID	putb_unp PROTO ((u_char *buf, u_int len, FILE *f));
VOID	putb_ncr PROTO ((u_char *buf, u_int len, FILE *f));
VOID	putb_pak PROTO ((u_char *buf, u_int len, FILE *f));
END_OF_FILE
if test 410 -ne `wc -c <'proto.h'`; then
    echo shar: \"'proto.h'\" unpacked with wrong size!
fi
# end of 'proto.h'
fi
if test -f 'tmclock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tmclock.c'\"
else
echo shar: Extracting \"'tmclock.c'\" \(2332 characters\)
sed "s/^X//" >'tmclock.c' <<'END_OF_FILE'
X/*
X * Stolen from Jef Poskanzer's tws time library, which was stolen from
X * Marshall Rose's MH Message Handling system...
X *
X * tmclock() will convert time from a tm struct back to a clock value.
X * tmjuliandate() converts a tm struct to its julian day number.
X * tmsubdayclock() takes hours, minutes, and seconds from a tm struct
X * and returns the number of seconds since midnight of that day. (?)
X *  -- Howard Chu, August 1 1988      hyc@umix.cc.umich.edu, umix!hyc
X */
X
X/* $Header: /var/local/hyc/src/arc/RCS/tmclock.c,v 2.0 1991/11/12 08:02:25 hyc Exp $ */
X
X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */
X#define JD1970 2440587L
X#define	CENTURY	19
X#if	BSD
X#include <sys/time.h>
X#else
X#include <time.h>
extern long	timezone;	/* should be in <time.h>, but isn't on Sun */
X#endif
X
long	tzone;
X
long
tmjuliandate( tm )
struct tm *tm;
X    {
X    register int mday, mon, year;
X    register long a, b;
X    double jd;
X
X    if ( (mday = tm -> tm_mday) < 1 || mday > 31 ||
X	    (mon = tm -> tm_mon + 1) < 1 || mon > 12 ||
X	    (year = tm -> tm_year) < 1 || year > 10000 )
X	return ( -1L );
X    if ( year < 100 )
X	year += CENTURY * 100;
X
X    if ( mon == 1 || mon == 2 )
X	{
X	--year;
X	mon += 12;
X	}
X    if ( year < 1583 )
X	return ( -1L );
X    a = year / 100;
X    b = 2 - a + a / 4;
X    b += (long) ( (double) year * 365.25 );
X    b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
X    jd = mday + b + 1720994.5;
X    return ( (long) jd );
X    }
X
X
long
tmsubdayclock( tm )
struct tm *tm;
X    {
X    register int sec, min, hour;
X    register long result;
X#if	BSD
X    {
X       struct timezone tzp;
X
X       gettimeofday(0L, &tzp);
X       tzone = tzp.tz_minuteswest*(-60);
X    }
X#else
X    tzone=timezone;
X#endif
X    if ( (sec = tm -> tm_sec) < 0 || sec > 59 ||
X	    (min = tm -> tm_min) < 0 || min > 59 ||
X	    (hour = tm -> tm_hour) < 0 || hour > 23 )
X	return ( -1L );
X
X    result = ( hour * 60 + min ) * 60 + sec;
X    result -= tzone;
X
X    return ( result );
X    }
X
X
long
tmclock( tm )
struct tm *tm;
X    {
X    register long jd, sdc;
X    long result;
X
X    if ( ( jd = tmjuliandate( tm ) ) == -1L )
X	return ( -1L );
X    if ( ( sdc = tmsubdayclock( tm ) ) == -1L )
X	return ( -1L );
X
X    result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
X
X    if ( localtime( &result )->tm_isdst )
X	result -= 60L * 60L;
X
X    return ( result );
X    }
END_OF_FILE
if test 2332 -ne `wc -c <'tmclock.c'`; then
    echo shar: \"'tmclock.c'\" unpacked with wrong size!
fi
# end of 'tmclock.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
