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,×);
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