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