[comp.binaries.ibm.pc] ARC for SYS V: Part 1 of 5

boneill@hawk.ulowell.edu (SoftXc Coordinator) (03/26/88)

This is version 1.1 of ARC for System V UNIX. It is a port of ARC 5.12 from
SEA. It consists of 5 shar files. The first three are the main files - the
other two are shars containing some replacement files, fixing some bugs. I
did not combine them, as this is exactly how they are on Simtel20.

============================================================================
Brian O'Neill					University of Lowell
boneill@hawk.ulowell.edu - boneill@hawk.UUCP ...!ulowell!hawk!boneill
MS-DOS Software Exchange Coordinator - E-mail for details

Article 3345 of net.sources:
Path: brl-smoke!brl-adm!rutgers!clyde!burl!codas!cpsc6a!cpsc6b!crs
From: crs@cpsc6b.cpsc6a.ATT.COM (C. R. Seaman)
Newsgroups: net.sources
Subject: System V ARC Ver. 1.1, Part 1 of 3
Message-ID: <247@cpsc6b.cpsc6a.ATT.COM>
Date: 30 Mar 87 23:44:31 GMT
Distribution: usa
Organization: AT&T (CPSC), Oakland, CA
Lines: 1538
Keywords: arc


[LINE EATER? I don't know no steenking LINE EATER!!]

The following three articles contain a new release of ARC for System V.
I have taken the code posted recently by Mike Stump, and reworked/added
a number of features, as well as performed some extensive debugging and
cleanup.  See the README file for more details.  Enjoy!

Chris Seaman
{ihnp4, rtech}!cpsc6a!crs

------------------------- CUT HERE!! -------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	Makefile
#	arc.h
#	arcs.h
#	arc.c
#	arcadd.c
#	arccode.c
#	arccvt.c
#	arcdel.c
#	arcdos.c
#	arcext.c
#	arcio.c
# This archive created: Sun Mar 22 10:45:32 1987
# By:	C. R. Seaman ()
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(3558 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	X
	XUnix System V ARC Version 1.1
	X
	X
	XThis is a COMPLETE (I hope!) version of PC ARC v5.12, ported to System V.
	XIt contains as much of the functionality of PC ARC as I could incorporate,
	Xand fixes all known bugs.
	X
	XVersion 1.1 is based on the version posted to the net by Mike Stump,
	Xwith several fixes and enhancements, as well as some general clean-up.
	X
	XSome enhancements:
	X
	X	Timestamping - arc will now stamp file upon extraction with the
	X	date and time contained in the header.  This feature may cause
	X	some discomfort with the recent change in Daylight Savings Time.
	X
	X
	X	Full wildcard/pattern matching - arc will take over for the shell
	X	if it receives standard shell-type wildcards and/or patterns.
	X	Remember, though, that the shell will always try to expand what
	X	it can FIRST, so if you explicitly want arc to do expansion,
	X	quote the arguments.  Also, arc will NOT search for real files
	X	based on wildcard matches.  I have left that under shell control;
	X	i.e., typing:
	X
	X			arc -v "*.c"<RETURN>
	X
	X	will work whether or not real files exist that match the pattern,
	X	but typing:
	X
	X			arc -a "*.c"<RETURN>
	X
	X	will report that file '*.c' was not found.
	X
	X
	X	14 character file name entries - by default arc now supports
	X	full 14 character file names in its entries.  This will, however,
	X	cause the archive to be incompatible with PC ARC, so I have
	X	added an option ('i') to truncate file names to the standard
	X	PC limit of 12 characters.  Archives created with this option are
	X	FULLY compatible with PC ARC.
	X
	X
	XSome Bug Fixes:
	X
	X	An archive will no longer try to archive itself, even if it is
	X	explicitly requested from the command line.  However, an archive
	X	with a similar name, but in a different directory, can be added.
	X
	X	Arguments passed to arc are now sorted, eliminating the
	X	possibility of duplicate entries for the same file in an archive.
	X	The arguments are also checked for duplicates, so it is impossible
	X	to add the same file name from multiple directories.  Only the
	X	first occurence is used.
	X
	X	Arc will not core dump if any of the file name arguments cannot
	X	be found.
	X
	X	Arc now cleans up after itself if it is aborted early.  Also,
	X	no damage will be done to the archive if arc is aborted.
	X
	X
	XCleanup:
	X
	X	I tried my best to make the code uniform, removed some unused
	X	variables and functions, and added/changed some of the comments.
	X
	X	I ran the resulting code through lint, which still considers
	X	the code somewhat inconsistent, but otherwise acceptible,
	X	with the exception of 'arclzw.c'.  Oh well, we can only do
	X	so much...
	X
	X
	XKnown limitations:
	X
	X	Ther is a REMOTE possibility that an archive can become corrupted
	X	if the IBM(TM) PC compatibility option ('i') is used/not used when it
	X	should/shouldn't be.  This only happened to me once out of 150+
	X	archives, and even that was during the early stages of the cleanup.
	X	As a rule, if I can't remember whether or not the 'i' option was
	X	used, I simply test the archive in questoion.  Testing an archive
	X	can do NO damage to it.
	X
	X
	XThis code has been thoroughly (if there is such a thing) tested on an
	XAT&T 3B5, 3B15, 3B2/300, and 3B2/400, running SYS V release 2 and release 3.
	X
	XI tried to keep things fairly portable, though I am not that familiar with
	XBSD.  I imagine that most things should work (I did change all the 'rindex'
	Xcalls to 'strrchr', sorry BSD), but I imagine that the setstamp() function
	Xis fairly System V dependent.  In any event, I will cheerfully listen to
	Xany reports of bugs and/or fixes, and will try to maintain the code as well
	Xas I can.
	X
	XChris Seaman
	X{ihnp4, rtech}!cpsc6a!crs
	X
SHAR_EOF
if test 3558 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 3558 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(524 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'Makefile'
	X#    Makefile for ARC
	X
	XCFLAGS = -O
	X
	XOBJS = arc.o arcadd.o arccode.o arccvt.o arcdel.o arcdos.o \
	X       arcext.o arcio.o arclst.o arclzw.o arcmatch.o arcmisc.o \
	X       arcpack.o arcsq.o arcsvc.o arctst.o arcunp.o arcusq.o
	X
	XSRCS = arc.c arcadd.c arccode.c arccvt.c arcdel.c arcdos.c \
	X       arcext.c arcio.c arclst.c arclzw.c arcmatch.c arcmisc.c \
	X       arcpack.c arcsq.c arcsvc.c arctst.c arcunp.c arcusq.c
	X
	Xarc:            ${OBJS}
	X	cc  ${CFLAGS} -o arc ${OBJS}
	X${OBJS}:        arc.h
	Xarc.h:          arcs.h
	X	touch arc.h
SHAR_EOF
if test 524 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 524 characters)'
fi
fi
echo shar: "extracting 'arc.h'" '(2185 characters)'
if test -f 'arc.h'
then
	echo shar: "will not over-write existing file 'arc.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'arc.h'
	X/*
	X *	arc.h	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X/*
	X * ARC - Archive utility - ARC Header
	X * 
	X * Version 2.14, created on 02/03/86 at 22:48:29
	X * 
	X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
	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#include <stdio.h>
	X#include <signal.h>
	X#include <ctype.h>
	X
	X#define EXTERN
	X#define INT short
	X
	X#define ARCMARK 26              /* special archive marker */
	X#define ARCVER 8                /* archive header version code */
	X#define STRLEN 100              /* system standard string length */
	X#define FNLEN1 15               /* file name length (UNIX) */
	X#define FNLEN2 13               /* file name length (DOS) */
	X#define MAXARG 25               /* maximum number of arguments */
	X
	X/*
	X * include the header structure
	X * (dependent on previously defined constants)
	X */
	X
	X#include "arcs.h"
	X
	XEXTERN INT keepbak;             /* true if saving the old archive */
	XEXTERN INT warn;                /* true to print warnings */
	XEXTERN INT note;                /* true to print comments */
	XEXTERN INT ibmpc;               /* true to make IBM compatibile */
	XEXTERN INT bose;                /* true to be verbose */
	XEXTERN INT nocomp;              /* true to suppress compression */
	XEXTERN char arctemp[STRLEN];    /* arc temp file prefix */
	XEXTERN char *password;          /* encryption password pointer */
	XEXTERN INT nerrs;               /* number of errors encountered */
	X
	XEXTERN char hdrver;             /* header version */
	X
	XEXTERN FILE *arc;               /* the old archive */
	XEXTERN FILE *new;               /* the new archive */
	X
	XEXTERN char arcname[STRLEN];    /* storage for archive name */
	XEXTERN char bakname[STRLEN];    /* storage for backup copy name */
	XEXTERN char newname[STRLEN];    /* storage for new archive name */
	XEXTERN unsigned INT arcdate;    /* archive date stamp */
	XEXTERN unsigned INT arctime;    /* archive time stamp */
SHAR_EOF
if test 2185 -ne "`wc -c < 'arc.h'`"
then
	echo shar: "error transmitting 'arc.h'" '(should have been 2185 characters)'
fi
fi
echo shar: "extracting 'arcs.h'" '(1950 characters)'
if test -f 'arcs.h'
then
	echo shar: "will not over-write existing file 'arcs.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcs.h'
	X/*
	X *	arcs.h	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	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 *     Description:
	X *          This file defines the format of an archive file header, excluding
	X *          the archive marker and the header version number.
	X * 
	X *          Each entry in an archive begins with a one byte archive marker,
	X *          which is set to 26.  The marker is followed by a one byte
	X *          header type code, from zero to 7.
	X * 
	X *          If the header type code is zero, then it is an end marker, and
	X *          no more data should be read from the archive.
	X * 
	X *          If the header type code is in the range 2 to 7, then it is
	X *          followed by a standard archive header, which is defined below.
	X * 
	X *          If the header type code is one, then it is followed by an older
	X *          format archive header.  The older format header does not contain
	X *          the true length.  A header should be read for a length of
	X *          sizeof(struct heads)-sizeof(long).  Then set length equal to size
	X *          and change the header version to 2.
	X * 
	X *     Programming note:
	X *          The crc value given in the header is based on the unpacked data.
	X */
	X
	Xstruct heads {                         /* archive entry header format */
	X    char name[FNLEN1];                 /* file name */
	X    long size;                         /* size of file, in bytes */
	X    unsigned INT date;                 /* creation date */
	X    unsigned INT time;                 /* creation time */
	X    INT crc;                           /* cyclic redundancy check */
	X    long length;                       /* true file length */
	X};
SHAR_EOF
if test 1950 -ne "`wc -c < 'arcs.h'`"
then
	echo shar: "error transmitting 'arcs.h'" '(should have been 1950 characters)'
fi
fi
echo shar: "extracting 'arc.c'" '(8232 characters)'
if test -f 'arc.c'
then
	echo shar: "will not over-write existing file 'arc.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arc.c'
	X/*
	X *	arc.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X#ifndef	lint
	Xstatic char	sccsid[] = "@(#)arc.c	1.1";
	X#endif	/* lint */
	X
	X
	X/*
	X * ARC - Archive utility
	X * 
	X * Version 5.12, created on 02/05/86 at 22:22:01
	X * 
	X * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
	X * 
	X *     Description:
	X *          This program is a general archive utility, and is used to maintain
	X *          an archive of files.  An "archive" is a single file that combines
	X *          many files, reducing storage space and allowing multiple files to
	X *          be handled as one.
	X * 
	X *     Instructions:
	X *          Run this program with no arguments for complete instructions.
	X * 
	X *     Programming notes:
	X *          ARC Version 2 differs from version 1 in that archive entries
	X *          are automatically compressed when they are added to the archive,
	X *          making a separate compression step unecessary.  The nature of the
	X *          compression is indicated by the header version number placed in
	X *          each archive entry, as follows:
	X * 
	X *          1 = Old style, no compression
	X *          2 = New style, no compression
	X *          3 = Compression of repeated characters only
	X *          4 = Compression of repeated characters plus Huffman SQueezing
	X *          5 = Lempel-Zev packing of repeated strings (old style)
	X *          6 = Lempel-Zev packing of repeated strings (new style)
	X *          7 = Lempel-Zev Williams packing with improved has function
	X *          8 = Dynamic Lempel-Zev packing with adaptive reset
	X * 
	X *          Type 5, Lempel-Zev packing, was added as of version 4.0
	X * 
	X *          Type 6 is Lempel-Zev packing where runs of repeated characters
	X *          have been collapsed, and was added as of version 4.1
	X * 
	X *          Type 7 is a variation of Lempel-Zev using a different hash
	X *          function which yields speed improvements of 20-25%, and was
	X *          added as of version 4.6
	X * 
	X *          Type 8 is a different implementation of Lempel-Zev, using a
	X *          variable code size and an adaptive block reset, and was added
	X *          as of version 5.0
	X * 
	X *          Verion 4.3 introduced a temporary file for holding the result
	X *          of the first crunch pass, thus speeding up crunching.
	X * 
	X *        { Version 4.4 introduced the ARCTEMP environment string, so that }
	X *        { the temporary crunch file may be placed on a ramdisk.  Also    }
	X *        { added was the distinction bewteen Adding a file in all cases,  }
	X *        { and Updating a file only if the disk file is newer than the    }
	X *        { corresponding archive entry.                                   }
	X *           (NOT USED IN THIS RELEASE OF THE SYSTEM V VERSION)
	X * 
	X *          The compression method to use is determined when the file is
	X *          added, based on whichever method yields the smallest result.
	X * 
	X */
	X#include "arc.h"
	X
	Xmain(argc,argv)                        /* system entry point */
	Xint argc;                              /* number of arguments */
	Xchar *argv[];                          /* pointers to arguments */
	X{
	X    char opt = 0;                      /* selected action */
	X    char *a;                           /* option pointer */
	X    char *upper();                     /* case conversion routine */
	X    INT n;                             /* argument index */
	X    INT dups = 0;                      /* duplicate argument counter */
	X    INT onintr();                      /* funtion to call when SIGNAL caught */
	X
	X    /* Basic signal trapping */
	X    signal(SIGHUP,SIG_IGN);
	X    signal(SIGINT,onintr);
	X    if (signal(SIGQUIT,SIG_IGN) != SIG_IGN) signal(SIGQUIT,onintr);
	X
	X    warn = 1;
	X    note = 1;
	X
	X    if (argc<3)
	X    {
	X        printf("%s - Archive Utility, 5.12\n",argv[0]);
	X        printf("System V Version 1.1, 3/21/87\n\n");
	X        printf("Usage: %s [-]{amufdxeplvtc}[biswn][g<password>]",argv[0]);
	X        printf(" <archive> [<filename> ... ]\n");
	X        printf("Where:   a   = add files to archive\n");
	X        printf("         m   = move files to archive\n");
	X        printf("         u   = update files in archive\n");
	X        printf("         f   = freshen files in archive\n");
	X        printf("         d   = delete files from archive\n");
	X        printf("         x,e = extract files from archive\n");
	X        printf("         p   = copy files from archive to standard output\n");
	X        printf("         l   = list files in archive\n");
	X        printf("         v   = verbose listing of files in archive\n");
	X        printf("         t   = test archive integrity\n");
	X        printf("         c   = convert entry to new packing method\n\n");
	X        printf("         b   = retain backup copy of archive\n");
	X        printf("         i   = maintain IBM(TM) PC compatible archive\n");
	X        printf("         s   = suppress compression (store only)\n");
	X        printf("         w   = suppress warning messages\n");
	X        printf("         n   = suppress notes and comments\n");
	X        printf("         g   = Encrypt/decrypt archive entry\n\n");
	X        exit(1);
	X    }
	X
	X    /* avoid any case problems with command options */
	X    upper(argv[1]);                /* convert it to uppercase */
	X
	X    /* parse the option argument */
	X
	X    for (a=argv[1]; *a; a++)
	X    {
	X        switch(*a)
	X        {
	X        case 'A':                       /* if a known command */
	X        case 'M':
	X        case 'U':
	X        case 'F':
	X        case 'D':
	X        case 'X':
	X        case 'E':
	X        case 'P':
	X        case 'L':
	X        case 'V':
	X        case 'T':
	X        case 'C':
	X            if (opt)                    /* do we have one yet? */
	X                abort("Cannot mix %c and %c",opt,*a);
	X            else
	X                opt = *a;               /* else remember it */
	X            break;
	X        case 'B':                       /* retain backup copy */
	X            keepbak = 1;
	X            break;
	X        case 'I':                       /* IBM compatibility */
	X            ibmpc = 1;
	X            break;
	X        case 'W':                       /* suppress warnings */
	X            warn = 0;
	X            break;
	X        case 'N':                       /* suppress notes and comments */
	X            note = 0;
	X            break;
	X        case 'G':                       /* garble */
	X            password = a+1;
	X            while (*a)
	X                a++;
	X            a--;
	X            break;
	X        case 'S':                       /* storage kludge */
	X            nocomp = 1;
	X            break;
	X        case '-':                       /* UNIX option marker */
	X            break;
	X        default:
	X            abort("%c is an unknown command",*a);
	X        }
	X    }
	X
	X    /* get out if no option made it through */
	X    if (!opt)
	X        abort("I don't know what to do!");
	X
	X    /* create archive names (arctemp, arcname, newname, bakname) */
	X    makenames(argv[2]);
	X
	X    /* strip off used args */
	X    argc -=3;
	X    argv +=3;
	X
	X    /* if file args, sort them */
	X    if (argc)
	X    {
	X        dups = sortarg(argc,argv);
	X        argc -= dups;
	X    }
	X
	X    /* act on whatever action command was given */
	X
	X    switch(opt)                        /* action depends on command */
	X    {
	X    case 'A':                          /* Add */
	X    case 'M':                          /* Move */
	X    case 'U':                          /* Update */
	X    case 'F':                          /* Freshen */
	X        addarc(argc,argv,(opt=='M'),(opt=='U'),(opt=='F'));
	X        break;
	X    case 'D':                          /* Delete */
	X        delarc(argc,argv);
	X        break;
	X    case 'E':                          /* Extract */
	X    case 'X':                          /* eXtract */
	X    case 'P':                          /* Print */
	X        extarc(argc,argv,(opt=='P'));
	X        break;
	X    case 'V':                          /* Verbose list */
	X        bose = 1;
	X    case 'L':                          /* List */
	X        lstarc(argc,argv);
	X        break;
	X    case 'T':                          /* Test */
	X        tstarc();
	X        break;
	X    case 'C':                          /* Convert */
	X        cvtarc(argc,argv);
	X    }
	X
	X    exit(nerrs);
	X}
SHAR_EOF
if test 8232 -ne "`wc -c < 'arc.c'`"
then
	echo shar: "error transmitting 'arc.c'" '(should have been 8232 characters)'
fi
fi
echo shar: "extracting 'arcadd.c'" '(6887 characters)'
if test -f 'arcadd.c'
then
	echo shar: "will not over-write existing file 'arcadd.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcadd.c'
	X/*
	X *	arcadd.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X/*
	X * ARC - Archive utility - ARCADD
	X * 
	X * Version 3.39, created on 02/05/86 at 22:21:53
	X * 
	X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
	X * 
	X *     Description:
	X *          This file contains the routines used to add files to an archive.
	X */
	X
	X#include "arc.h"
	X#include <sys/types.h>
	X#include <sys/stat.h>
	X
	XINT addarc(argc,argv,move,update,fresh)/* add files to archive */
	XINT argc;                              /* number of arguments */
	Xchar *argv[];                          /* pointers to arguments */
	XINT move;                              /* true if moving file */
	XINT update;                            /* true if updating */
	XINT fresh;                             /* true if freshening */
	X{
	X    char *buf;                         /* pathname buffer */
	X    char *i, *strrchr();               /* string indexing junk */
	X    INT n;                             /* indices */
	X    struct stat fbuf;                  /* file information structure */
	X    struct heads hdr;                  /* file header data storage */
	X    INT addfile();
	X
	X    openarc(1);                        /* open archive for changes */
	X
	X    for (n=0; n<argc; ++n)
	X    {
	X        stat(argv[n],&fbuf);           /* find out what kind of file it is */
	X
	X        /* if file is a regular file, try to add it */
	X        if (((fbuf.st_mode >> 12) == 8) || ((fbuf.st_mode >> 12) == 0))
	X        {
	X            if (i=strrchr(buf=argv[n], '/')) buf=i+1;
	X            addfile(argv[n],buf,update,fresh);
	X        }
	X        else
	X        {
	X            printf("Invalid file type: %s\n",argv[n]);
	X            ++nerrs;
	X        }
	X    }
	X
	X    /* quit if no changes to make */
	X    if (nerrs == argc)
	X    {
	X        fclose(arc);
	X        fclose(new);
	X        abort("I have no work to do!");
	X    }
	X
	X    /* now we must copy over all files that follow our additions */
	X
	X    while (readhdr(&hdr,arc))          /* while more entries to copy */
	X    {
	X        writehdr(&hdr,new);
	X        filecopy(arc,new,hdr.size);
	X    }
	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 (move) for (n=0; n<argc; ++n)   /* if this was a move */
	X    {
	X        stat(argv[n],&fbuf);           /* make sure file can be removed */
	X        if (((fbuf.st_mode >> 12) == 8) || ((fbuf.st_mode >> 12) == 0))
	X        {
	X            if (unlink(argv[n]) && warn)
	X            {
	X                printf("Cannot unsave %s\n",argv[n]);
	X                ++nerrs;
	X            }
	X        }
	X    }
	X}
	X
	Xstatic INT addfile(path,name,update,fresh) /* add named file to archive */
	Xchar *path;                            /* path name of file to add */
	Xchar *name;                            /* name of file to add */
	XINT update;                            /* true if updating */
	XINT fresh;                             /* true if freshening */
	X{
	X    struct heads nhdr;                 /* data regarding the new file */
	X    struct heads ohdr;                 /* data regarding an old file */
	X    FILE *f, *fopen();                 /* file to add, opener */
	X    long starts, ftell();              /* file locations */
	X    INT upd = 0;                       /* true if replacing an entry */
	X
	X    if (!(f=fopen(path,"r")))          /* quit if we can't open the file */
	X    {
	X        if (warn)
	X            printf("Cannot read file: %s\n",path);
	X        nerrs++;
	X        fclose(f);
	X        return;
	X    }
	X
	X    /* fill the header structure with information about the new file */
	X
	X    /* save filename, using 14 or 12 char template, based on ibmpc option */
	X    strncpy(nhdr.name,name,((ibmpc) ? FNLEN2 : FNLEN1)-1);
	X    nhdr.size = 0;                     /* clear out size storage */
	X    nhdr.crc = 0;                      /* clear out CRC check storage */
	X    getstamp(f,&nhdr.date,&nhdr.time);
	X
	X    /* position archive to spot for new file */
	X
	X    if (arc)                           /* if adding to existing archive */
	X    {
	X        starts = ftell(arc);           /* where are we? */
	X        while (readhdr(&ohdr,arc))     /* while more files to check */
	X        {
	X            if (strcmp(ohdr.name,nhdr.name) == 0)
	X            {
	X                upd = 1;               /* replace existing entry */
	X                if (update || fresh)   /* if updating or freshening */
	X                {
	X                    if (nhdr.date<ohdr.date ||
	X                       (nhdr.date == ohdr.date && nhdr.time <= ohdr.time))
	X                    {
	X                        fseek(arc,starts,0);
	X                        fclose(f);
	X                        return;        /* skip if not newer */
	X                    }
	X                }
	X            }
	X
	X            if (strcmp(ohdr.name,nhdr.name) >= 0)
	X                break;                 /* found our spot */
	X
	X            writehdr(&ohdr,new);       /* entry preceeds update; keep it */
	X            filecopy(arc,new,ohdr.size);
	X            starts = ftell(arc);       /* now where are we? */
	X        }
	X
	X        if (upd)                       /* if an update */
	X        {
	X            if (note)
	X            {
	X                printf("Updating file: %-14s  ",name);
	X                fflush(stdout);
	X            }
	X            fseek(arc,ohdr.size,1);
	X        }
	X        else if (fresh)                /* else if freshening */
	X        {
	X            fseek(arc,starts,0);       /* then do not add files */
	X            fclose(f);
	X            return;
	X        }
	X        else                           /* else adding a new file */
	X        {
	X            if (note)
	X            {
	X                printf("Adding file:   %-14s  ",name);
	X                fflush(stdout);
	X            }
	X            fseek(arc,starts,0);       /* reset for next time */
	X        }
	X    }
	X
	X    else                               /* no existing archive */
	X    {
	X        if (fresh)                     /* cannot freshen nothing */
	X        {
	X            fclose(f);
	X            return;
	X        }
	X        else if (note)                 /* else adding a file */
	X        {
	X            printf("Adding file:   %-14s  ",name);
	X            fflush(stdout);
	X        }
	X    }
	X
	X    starts = ftell(new);               /* note where header goes */
	X    hdrver = ARCVER;                   /* anything but end marker */
	X    writehdr(&nhdr,new);               /* write out header skeleton */
	X    pack(f,new,&nhdr);                 /* pack file into archive */
	X    fseek(new,starts,0);               /* move back to header skeleton */
	X    writehdr(&nhdr,new);               /* write out real header */
	X    fseek(new,nhdr.size,1);            /* skip over data to next header */
	X    fclose(f);                         /* all done with the file */
	X}
SHAR_EOF
if test 6887 -ne "`wc -c < 'arcadd.c'`"
then
	echo shar: "error transmitting 'arcadd.c'" '(should have been 6887 characters)'
fi
fi
echo shar: "extracting 'arccode.c'" '(1542 characters)'
if test -f 'arccode.c'
then
	echo shar: "will not over-write existing file 'arccode.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arccode.c'
	X/*
	X *	arccode.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	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 *     Description:
	X *          This file contains the routines used to encrypt and decrypt
	X *          data in an archive.  The encryption method is nothing fancy,
	X *          being just a routine XOR, but it is used on the packed data,
	X *          and uses a variable length key.  The end result is something
	X *          that is in theory crackable, but I'd hate to try it.  It should
	X *          be more than sufficient for casual use.
	X */
	X
	X#include "arc.h"
	X
	Xstatic char *p;                        /* password pointer */
	X
	XINT setcode()                          /* get set for encoding/decoding */
	X{
	X    p = password;                      /* reset password pointer */
	X}
	X
	XINT code(c)                            /* encode some character */
	XINT c;                                 /* character to encode */
	X{
	X    if (p)                             /* if password is in use */
	X    {
	X        if (!*p)                       /* if we reached the end */
	X            p = password;              /* then wrap back to the start */
	X        return(c^*p++);                /* very simple here */
	X    }
	X    else
	X        return(c);                     /* else no encryption */
	X}
SHAR_EOF
if test 1542 -ne "`wc -c < 'arccode.c'`"
then
	echo shar: "error transmitting 'arccode.c'" '(should have been 1542 characters)'
fi
fi
echo shar: "extracting 'arccvt.c'" '(4091 characters)'
if test -f 'arccvt.c'
then
	echo shar: "will not over-write existing file 'arccvt.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arccvt.c'
	X/*
	X *	arccvt.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	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 *     Description:
	X *          This file contains the routines used to convert archives to use
	X *          newer file storage methods.
	X */
	X
	X#include "arc.h"
	X
	Xstatic char tempname[STRLEN];          /* temp file name */
	X
	XINT cvtarc(argc,argv)                  /* convert archive */
	XINT argc;                              /* number of arguments */
	Xchar *argv[];                          /* 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    INT cvtfile();
	X
	X    sprintf(tempname,"%s.cvt",arctemp);
	X
	X    openarc(1);                        /* open archive for changes */
	X
	X    for (n=0; n<argc; n++)             /* for each argument */
	X         did[n] = 0;                   /* reset usage flag */
	X    rempath(argc,argv);                /* strip off paths */
	X
	X    if (argc)                          /* if files were named */
	X    {
	X        while (readhdr(&hdr,arc))      /* while more files to check */
	X        {
	X            cvt = 0;                   /* reset convert flag */
	X            for (n=0; n<argc; n++)     /* for each template given */
	X            {
	X                if (match(hdr.name,argv[n]))
	X                {
	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            {
	X                writehdr(&hdr,new);
	X                filecopy(arc,new,hdr.size);
	X            }
	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    {
	X        for (n=0; n<argc; n++)         /* report unused args */
	X        {
	X            if (!did[n])
	X            {
	X                printf("File not found: %s\n",argv[n]);
	X                nerrs++;
	X            }
	X        }
	X    }
	X}
	X
	Xstatic INT cvtfile(hdr)                /* convert a file */
	Xstruct 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+")))
	X        abort("Unable to create temporary file %s",tempname);
	X
	X    if (note)
	X    {
	X        printf("Converting file: %-14s   reading, ",hdr->name);
	X        fflush(stdout);
	X    }
	X
	X    unpack(arc,tmp,hdr);               /* unpack the entry */
	X    fseek(tmp,0L,0);                   /* reset temp for reading */
	X    starts = ftell(new);               /* note where header goes */
	X    hdrver = ARCVER;                   /* anything but end marker */
	X    writehdr(hdr,new);                 /* write out header skeleton */
	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    {
	X        printf("Cannot unsave %s\n",tempname);
	X        nerrs++;
	X    }
	X}
SHAR_EOF
if test 4091 -ne "`wc -c < 'arccvt.c'`"
then
	echo shar: "error transmitting 'arccvt.c'" '(should have been 4091 characters)'
fi
fi
echo shar: "extracting 'arcdel.c'" '(2722 characters)'
if test -f 'arcdel.c'
then
	echo shar: "will not over-write existing file 'arcdel.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcdel.c'
	X/*
	X *	arcdel.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	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 *     Description:
	X *          This file contains the routines used to delete entries
	X *          in an archive.
	X */
	X
	X#include "arc.h"
	X
	XINT delarc(argc,argv)                  /* remove files from archive */
	XINT argc;                              /* number of arguments */
	Xchar *argv[];                          /* 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 (!argc)                         /* she must specify which */
	X        abort("You must tell me which files to delete!");
	X
	X    for (n=0; n<argc; n++)             /* for each argument */
	X        did[n] = 0;                    /* reset usage flag */
	X    rempath(argc,argv);                /* strip off paths */
	X
	X    openarc(1);                        /* open archive for changes */
	X
	X    while (readhdr(&hdr,arc))          /* while more entries in archive */
	X    {
	X        del = 0;                       /* reset delete flag */
	X        for (n=0; n<argc; n++)         /* for each template given */
	X        {
	X            if (match(hdr.name,argv[n]))
	X            {
	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        {
	X            fseek(arc,hdr.size,1);
	X            if (note)
	X                printf("Deleting file: %s\n",hdr.name);
	X        }
	X        else                           /* else copy over file data */
	X        {
	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    {
	X        for (n=0; n<argc; n++)         /* report unused arguments */
	X        {
	X            if (!did[n])
	X            {
	X                printf("File not found: %s\n",argv[n]);
	X                nerrs++;
	X            }
	X        }
	X    }
	X}
SHAR_EOF
if test 2722 -ne "`wc -c < 'arcdel.c'`"
then
	echo shar: "error transmitting 'arcdel.c'" '(should have been 2722 characters)'
fi
fi
echo shar: "extracting 'arcdos.c'" '(3896 characters)'
if test -f 'arcdos.c'
then
	echo shar: "will not over-write existing file 'arcdos.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcdos.c'
	X/*
	X *	arcdos.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X/*
	X * ARC - Archive utility - ARCDOS
	X * 
	X * Version 1.43, created on 11/09/85 at 22:24:44
	X * 
	X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
	X * 
	X *     Description:
	X *          This file contains certain DOS level routines that assist
	X *          in doing fancy things with an archive, primarily reading and
	X *          setting the date and time last modified.
	X * 
	X *          These are, by nature, system dependant functions.  But they are
	X *          also, by nature, very expendable.
	X */
	X
	X#include "arc.h"
	X#include <sys/types.h>
	X#include <sys/stat.h>
	X#include <time.h>
	X
	XINT getstamp(f,date,time)              /* get a file's date/time stamp */
	XFILE *f;                               /* file to get stamp from */
	Xunsigned INT *date, *time;             /* storage for the stamp */
	X{
	X    struct stat buf;
	X    struct tm *tmbuf;
	X
	X    fstat(fileno(f),&buf);
	X    tmbuf=localtime(&buf.st_mtime);
	X    
	X    *date = ((tmbuf->tm_year-80)<<9) + ((tmbuf->tm_mon+1)<<5) + tmbuf->tm_mday;
	X    *time = (tmbuf->tm_hour<<11) + (tmbuf->tm_min<<5) + (tmbuf->tm_sec>>1);;
	X}
	X
	Xstruct utimbuf {
	X    time_t	actime;
	X    time_t	modtime;
	X};
	X
	XINT setstamp(file,date,time)           /* set a file's date/time stamp */
	Xchar *file;                            /* file to set stamp on */
	Xunsigned INT date, time;               /* desired date, time */
	X{
	X    struct utimbuf times;
	X    struct tm *tmbuf;
	X    long m_time;
	X    int yr, mo, dy, hh, mm, ss, leap, days = 0;
	X
	X    /*
	X     * These date conversions look a little wierd, so I'll explain.
	X     * UNIX bases all file modification times on the number of seconds
	X     * elapsed since Jan 1, 1970, 00:00:00 GMT.  Therefore, to maintain
	X     * compatibility with MS-DOS archives, which date from Jan 1, 1980,
	X     * with NO relation to GMT, the following conversions must be made:
	X     * 		the Year (yr) must be incremented by 10;
	X     *		the Date (dy) must be decremented by 1;
	X     *		and the whole mess must be adjusted by TWO factors:
	X     *			relationship to GMT (ie.,Pacific Time adds 8 hrs.),
	X     *			and whether or not it is Daylight Savings Time.
	X     * Also, the usual conversions must take place to account for leap years,
	X     * etc.
	X     *                                     C. Seaman
	X     */
	X
	X    yr = (((date >> 9) & 0x7f) + 10);  /* dissect the date */
	X    mo = ((date >> 5) & 0x0f);
	X    dy = ((date & 0x1f) - 1);
	X
	X    hh = ((time >> 11) & 0x1f);        /* dissect the time */
	X    mm = ((time >> 5) & 0x3f);
	X    ss = ((time & 0x1f) * 2);
	X
	X    leap = ((yr+1970)/4);              /* Leap year base factor */
	X
	X    /* How many days from 1970 to this year? */
	X    days = (yr * 365) + (leap - 492);
	X
	X    switch(mo)			       /* calculate expired days this year */
	X    {
	X    case 12:
	X        days += 30;
	X    case 11:
	X        days += 31;
	X    case 10:
	X        days += 30;
	X    case 9:
	X        days += 31;
	X    case 8:
	X        days += 31;
	X    case 7:
	X        days += 30;
	X    case 6:
	X        days += 31;
	X    case 5:
	X        days += 30;
	X    case 4:
	X        days += 31;
	X    case 3:
	X        days += 28;                    /* account for leap years */
	X        if ((leap * 4) == (yr+1970) && (yr+1970) != 2000)
	X            ++days;
	X    case 2:
	X        days += 31;
	X    }
	X
	X    /* convert date & time to seconds relative to 00:00:00, 01/01/1970 */
	X    m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
	X
	X    tmbuf = localtime(&m_time);        /* check for Daylight Savings Time */
	X    if (tmbuf->tm_isdst != 0)
	X        m_time -= 3600;
	X
	X    m_time += timezone;                /* account for timezone differences */
	X
	X    times.actime = m_time;             /* set the stamp on the file */
	X    times.modtime = m_time;
	X    utime(file,&times);
	X}
SHAR_EOF
if test 3896 -ne "`wc -c < 'arcdos.c'`"
then
	echo shar: "error transmitting 'arcdos.c'" '(should have been 3896 characters)'
fi
fi
echo shar: "extracting 'arcext.c'" '(4983 characters)'
if test -f 'arcext.c'
then
	echo shar: "will not over-write existing file 'arcext.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcext.c'
	X/*
	X *	arcext.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X/*
	X * ARC - Archive utility - ARCEXT
	X * 
	X * Version 2.18, created on 02/03/86 at 22:55:19
	X * 
	X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
	X * 
	X *     Description:
	X *          This file contains the routines used to extract files from
	X *          an archive.
	X */
	X
	X#include "arc.h"
	XINT extarc(argc,argv,prt)              /* extract files from archive */
	XINT argc;                              /* number of arguments */
	Xchar *argv[];                          /* pointers to arguments */
	XINT prt;                               /* true if printing */
	X{
	X    struct heads hdr;                  /* file header */
	X    INT save;                          /* true if current entry matches */
	X    INT did[MAXARG];                   /* true when argument was used */
	X    char *i, *strrchr();               /* string index */
	X    char *fbuf;                        /* temporary storage for name */
	X    INT n;                             /* index */
	X    INT extfile();
	X
	X    for (n=0; n<argc; n++)             /* for each argument */
	X        did[n] = 0;                    /* reset usage flag */
	X
	X    openarc(0);                        /* open archive for reading */
	X
	X    if (argc)                          /* if files were named */
	X    {
	X        while (readhdr(&hdr,arc))      /* while more files to check */
	X        {
	X            save = 0;
	X            for (n=0; n<argc; n++)     /* for each template given */
	X            {
	X                fbuf = argv[n];
	X                if (i = strrchr(argv[n],'/')) fbuf = i + 1;
	X                if (match(hdr.name,fbuf))
	X                {
	X                    save = 1;          /* turn on save flag */
	X                    did[n] = 1;        /* turn on usage flag */
	X                    extfile(&hdr,argv[n],prt); /* extract the file */
	X                    break;             /* stop looking */
	X                }
	X            }
	X
	X            if (!(save))               /* if not extracted, advance */
	X                fseek(arc,hdr.size,1); /* to next file */
	X        }
	X    }
	X
	X    else 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    {
	X        for (n=0; n<argc; n++)         /* report unused args */
	X        {
	X            if (!did[n])
	X            {
	X                printf("File not found: %s\n",argv[n]);
	X                nerrs++;
	X            }
	X        }
	X    }
	X}
	X
	XINT extfile(hdr,path,prt)              /* extract a file */
	Xstruct heads *hdr;                     /* pointer to header data */
	Xchar *path;                            /* pointer to path name */
	XINT 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 *fbuf;                        /* temporary pointer to path */
	X    char *i, *strrchr();               /* string index */
	X
	X    if (prt)                           /* printing is much easier */
	X    {
	X        unpack(arc,stdout,hdr);        /* unpack file from archive */
	X        printf("\f");                  /* eject the form */
	X        return;                        /* see? I told you! */
	X    }
	X
	X    strcpy(fix,path);                  /* note path name template */
	X    if (i=strrchr(fbuf=path,'/'))      /* find start of name */
	X    {
	X        fbuf = i + 1;
	X        fix[strlen(path)-strlen(fbuf)] = '\0';
	X        strcat(fix,hdr->name);         /* replace template with name */
	X    }
	X    else
	X        strcpy(fix,hdr->name);         /* replace template with name */
	X
	X    if (note)
	X        printf("Extracting file: %s\n",fix);
	X
	X    if (warn)
	X    {
	X        if (f=fopen(fix,"r"))          /* see if it exists */
	X        {
	X            fclose(f);
	X            printf("WARNING: File %s already exists!",fix);
	X            while (1)
	X            {
	X                printf("  Overwrite it (y/n)? ");
	X                fgets(buf,STRLEN,stdin);
	X                *buf = toupper(*buf);
	X                if (*buf=='Y' || *buf=='N')
	X                    break;
	X            }
	X            if (*buf=='N')
	X            {
	X                printf("%s not extracted.\n",fix);
	X                fseek(arc,hdr->size,1);
	X                return;
	X            }
	X        }
	X    }
	X
	X    if (!(f=fopen(fix,"w")))
	X    {
	X        if (warn)
	X        {
	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    setstamp(fix,hdr->date,hdr->time); /* set the proper date/time stamp */
	X}
SHAR_EOF
if test 4983 -ne "`wc -c < 'arcext.c'`"
then
	echo shar: "error transmitting 'arcext.c'" '(should have been 4983 characters)'
fi
fi
echo shar: "extracting 'arcio.c'" '(5551 characters)'
if test -f 'arcio.c'
then
	echo shar: "will not over-write existing file 'arcio.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'arcio.c'
	X/*
	X *	arcio.c	1.1
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	3/21/87
	X *
	X */
	X
	X/*
	X * ARC - Archive utility - ARCIO
	X * 
	X * Version 2.30, created on 02/03/86 at 22:56:00
	X * 
	X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
	X * 
	X *     Description:
	X *          This file contains the file I/O routines used to manipulate
	X *          an archive.
	X */
	X
	X#include "arc.h"
	X
	XINT readhdr(hdr,f)                     /* read a header from an archive */
	Xstruct heads *hdr;                     /* storage for header */
	XFILE *f;                               /* archive to read header from */
	X{
	X    INT i;                             /* misc. variables */
	X    int fnlen = (ibmpc) ? FNLEN2 : FNLEN1; /* file name length */
	X    unsigned char dummy[30];           /* dummy array for header storage */
	X    char name[FNLEN1];                 /* 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    if (feof(f))                       /* if no more data */
	X        return(0);                     /* then signal end of archive */
	X
	X    if (fgetc(f)!=ARCMARK)             /* check archive validity */
	X    {
	X        if (warn)
	X        {
	X            printf("An entry in %s has a bad header.\n",arcname);
	X            nerrs++;
	X        }
	X
	X        while (!feof(f))
	X        {
	X            try++;
	X            if (fgetc(f)==ARCMARK)
	X            {
	X                ungetc(hdrver=fgetc(f),f);
	X                if (hdrver>=0 && hdrver<=ARCVER)
	X                    break;
	X            }
	X        }
	X
	X        if (feof(f) && first)
	X            abort("%s is not an archive",arcname);
	X
	X        if (warn)
	X            printf("  %d bytes skipped.\n",try);
	X
	X        if (feof(f))
	X            return(0);
	X    }
	X
	X    hdrver = fgetc(f);                 /* get header version */
	X    if (hdrver<0)
	X        abort("Invalid header in archive %s",arcname);
	X    if (hdrver==0)
	X        return(0);                     /* note our end of archive marker */
	X    if (hdrver>ARCVER)
	X    {
	X        fread(name,sizeof(char),fnlen,f);
	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        abort("Archive error");
	X    }
	X
	X    /* amount to read depends on header type */
	X
	X    if (hdrver==1)                     /* old style is shorter */
	X    {
	X        fread(hdr,sizeof(struct heads)-sizeof(long),1,f);
	X        hdrver = 2;                    /* convert header to new format */
	X        hdr->length = hdr->size;       /* size is same when not packed */
	X    }
	X    else
	X    {
	X        fread(dummy,fnlen+14,1,f);
	X
	X        for (i=0;i<FNLEN1;hdr->name[i]='\0',i++);
	X        for (i=0;i<fnlen;hdr->name[i]=dummy[i],i++);
	X        hdr->size = (long)((dummy[fnlen+3]<<24) + (dummy[fnlen+2]<<16)
	X            + (dummy[fnlen+1]<<8) + dummy[fnlen]);
	X        hdr->date = (short)((dummy[fnlen+5]<<8) + dummy[fnlen+4]);
	X        hdr->time = (short)((dummy[fnlen+7]<<8) + dummy[fnlen+6]);
	X        hdr->crc  = (short)((dummy[fnlen+9]<<8) + dummy[fnlen+8]);
	X        hdr->length = (long)((dummy[fnlen+13]<<24) + (dummy[fnlen+12]<<16)
	X            + (dummy[fnlen+11]<<8) + dummy[fnlen+10]);
	X    }
	X
	X    first = 0;
	X    return(1);                         /* we read something */
	X}
	X
	XINT writehdr(hdr,f)                    /* write a header to an archive */
	Xstruct heads *hdr;                     /* header to write */
	XFILE *f;                               /* archive to write to */
	X{
	X    int i;
	X    int fnlen = (ibmpc) ? FNLEN2 : FNLEN1; /* file name length */
	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
	X    for (i = strlen(hdr->name);i < fnlen;i++)
	X        hdr->name[i] = '\0';
	X
	X    fwrite(hdr->name,1,fnlen,f);
	X    fputc(hdr->size&255,f);         fputc((hdr->size>>8)&255,f);
	X    fputc((hdr->size>>16)&255,f);   fputc((hdr->size>>24)&255,f);
	X    fputc(hdr->date&255,f);         fputc((hdr->date>>8)&255,f);
	X    fputc(hdr->time&255,f);         fputc((hdr->time>>8)&255,f);
	X    fputc(hdr->crc&255,f);          fputc((hdr->crc>>8)&255,f);
	X    fputc(hdr->length&255,f);       fputc((hdr->length>>8)&255,f);
	X    fputc((hdr->length>>16)&255,f); fputc((hdr->length>>24)&255,f);
	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    {
	X        arcdate = hdr->date;
	X        arctime = hdr->time;
	X    }
	X}
	X
	XINT filecopy(f,t,size)                 /* bulk file copier */
	XFILE *f, *t;                           /* from, to */
	Xlong size;                             /* number of bytes */
	X{
	X    INT putc_tst();
	X
	X    while (size--)                     /* while more bytes to move */
	X        putc_tst(fgetc(f),t);
	X}
	X
	XINT putc_tst(c,t)                      /* put a character, with tests */
	Xchar c;                                /* character to output */
	XFILE *t;                               /* file to write to */
	X{
	X    if (t)
	X        if (fputc(c,t)==EOF)
	X        {
	X            perror("system error:");
	X            abort("Write failed");
	X        }
	X}
SHAR_EOF
if test 5551 -ne "`wc -c < 'arcio.c'`"
then
	echo shar: "error transmitting 'arcio.c'" '(should have been 5551 characters)'
fi
fi
exit 0
#	End of shell archive