[comp.sources.unix] v15i079: ARC

rsalz@uunet.uu.net (Rich Salz) (07/02/88)

Submitted-by: hyc@math.lsa.umich.edu
Posting-number: Volume 15, Issue 79
Archive-name: arc5.21/part03

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--  1 hyc         11146 Jun 17 17:03 arc.c
# -rw-r--r--  1 hyc          3318 Jun  1 19:59 arc.h
# -rw-r--r--  1 hyc          9286 Jun 13 00:31 arcadd.c
# -rw-r--r--  1 hyc          1204 Jun  1 15:16 arccode.c
# -rw-r--r--  1 hyc          3396 Jun  1 19:18 arccvt.c
# -rw-r--r--  1 hyc          2070 Jun 13 04:26 arcdata.c
# -rw-r--r--  1 hyc          2055 Apr 19 01:39 arcdel.c
# -rw-r--r--  1 hyc          5008 Jun 13 14:08 arcdos.c
# -rw-r--r--  1 hyc          4898 Jun 13 14:06 arcext.c
# -rw-r--r--  1 hyc          7418 Jun 13 13:48 arcio.c
# -rw-r--r--  1 hyc          4418 Jun  1 18:06 arclst.c
#
echo 'x - arc.c'
if test -f arc.c; then echo 'shar: not overwriting arc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arc.c
X/*
X * $Header: arc.c,v 1.10 88/06/17 15:22:48 hyc Locked $
X */
X
X/*  ARC - Archive utility
X  
X    Version 5.21, created on 04/22/87 at 15:05:21
X  
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X  
X    By:	 Thom Henderson
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 hash function
X	 8 = Dynamic Lempel-Zev packing with adaptive reset
X	 9 = Dynamic Lempel-Zev packing, larger hash table
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	 Type 9 is a slight modification of type 8, first used by Phil
X	 Katz in his PKARC utilites. The primary difference is the use
X	 of a hash table twice as large as for type 8, and that this
X	 algorithm called Squashing, doesn't perform run-length encoding
X	 on the input data.
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  
X	 The compression method to use is determined when the file is
X	 added, based on whichever method yields the smallest result.
X  
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xint		strlen();
Xvoid		addarc(), delarc(), extarc(), lstarc(), tstarc(), cvtarc(), runarc();
Xvoid		abort();
X#if	MTS
Xvoid		etoa();
X#endif
X#if	GEMDOS
Xlong		_stksize = 24576;
X#endif
Xchar		*strcpy(), *strcat();
X
Xstatic char   **lst;		/* files list */
Xstatic int	lnum;		/* length of files list */
X
Xmain(num, arg)			/* system entry point */
X	int		num;	/* number of arguments */
X	char	       *arg[];	/* pointers to arguments */
X{
X	char		opt = 0;/* selected action */
X	char	       *a;	/* option pointer */
X	char	       *makefnam();	/* filename fixup routine */
X	void		upper();/* case conversion routine */
X	char	       *index();/* string index utility */
X	char	       *envfind();	/* environment searcher */
X	int		n;	/* index */
X	char	       *arctemp2, *calloc(), *mktemp();
X#if	GEMDOS
X	void		exitpause();
X#endif
X#if	MTS
X	fortran void	guinfo();
X	char		gotinf[4];
X#endif
X
X	if (num < 3) {
X		printf("ARC - Archive utility, Version 5.21, created on 04/22/87 at 15:05:21\n");
X/*		printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
X		printf(" ALL RIGHTS RESERVED\n\n");
X		printf("Please refer all inquiries to:\n\n");
X		printf("       System Enhancement Associates\n");
X		printf("       21 New Street, Wayne NJ 07470\n\n");
X		printf("You may copy and distribute this program freely,");
X		printf(" provided that:\n");
X		printf("    1)	 No fee is charged for such copying and");
X		printf(" distribution, and\n");
X		printf("    2)	 It is distributed ONLY in its original,");
X		printf(" unmodified state.\n\n");
X		printf("If you like this program, and find it of use, then your");
X		printf(" contribution will\n");
X		printf("be appreciated.	 You may not use this product in a");
X		printf(" commercial environment\n");
X		printf("or a governmental organization without paying a license");
X		printf(" fee of $35.  Site\n");
X		printf("licenses and commercial distribution licenses are");
X		printf(" available.  A program\n");
X		printf("disk and printed documentation are available for $50.\n");
X		printf("\nIf you fail to abide by the terms of this license, ");
X		printf(" then your conscience\n");
X		printf("will haunt you for the rest of your life.\n\n"); */
X#if	MSDOS
X		printf("Usage: ARC {amufdxerplvtc}[bswnoq][g<password>]");
X#endif
X#if	GEMDOS
X		printf("Usage: ARC {amufdxerplvtc}[bhswnoq][g<password>]");
X#endif
X#if	UNIX
X		printf("Usage: arc {amufdxerplvtc}[biswnoq][g<password>]");
X#endif
X#if	MTS
X		printf("Parameters: {amufdxeplvtc}[biswnoq][g<password>]");
X#endif
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#if	!MTS
X		printf("	 r   = run files from archive\n");
X#endif
X		printf("	 p   = copy files from archive to");
X		printf(" 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");
X		printf("	 b   = retain backup copy of archive\n");
X#if	GEMDOS
X		printf("	 h   = hold screen after finishing\n");
X#endif
X#if	MTS
X		printf("	 i   = suppress ASCII/EBCDIC translation\n");
X#endif
X#if	UNIX
X		printf("	 i   = suppress image mode (translate EOL)\n");
X#endif
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("	 o   = overwrite existing files when");
X		printf(" extracting\n");
X		printf("	 q   = squash instead of crunching\n");
X		printf("	 g   = Encrypt/decrypt archive entry\n");
X		printf("\nAdapted from MSDOS by Howard Chu\n");
X		/*
X		 * printf("\nPlease refer to the program documentation for");
X		 * printf(" complete instructions.\n"); 
X		 */
X#if	GEMDOS
X		exitpause();
X#endif
X		return 1;
X	}
X	/* see where temp files go */
X#if	!MTS
X	arctemp = calloc(1, STRLEN);
X	if (!(arctemp2 = envfind("ARCTEMP")))
X		arctemp2 = envfind("TMPDIR");
X	if (arctemp2) {
X		strcpy(arctemp, arctemp2);
X		n = strlen(arctemp);
X		if (arctemp[n - 1] != CUTOFF)
X			arctemp[n] = CUTOFF;
X	}
X#if	!MSDOS
X	strcat(arctemp, mktemp("AXXXXXX"));
X#else
X	strcat(arctemp, "$ARCTEMP");
X#endif
X#else
X	guinfo("SHFSEP	", gotinf);
X	sepchr[0] = gotinf[0];
X	guinfo("SCRFCHAR", gotinf);
X	tmpchr[0] = gotinf[0];
X	arctemp = "-$$$";
X	arctemp[0] = tmpchr[0];
X#endif
X
X#if	!UNIX
X	/* avoid any case problems with arguments */
X
X	for (n = 1; n < num; n++)	/* for each argument */
X		upper(arg[n]);	/* convert it to uppercase */
X#else
X	/* avoid case problems with command options */
X	upper(arg[1]);		/* convert to uppercase */
X#endif
X
X	/* create archive names, supplying defaults */
X	makefnam(arg[2], ".arc", arcname);
X	/* makefnam(".$$$",arcname,newname); */
X	sprintf(newname, "%s.arc", arctemp);
X	makefnam(".BAK", arcname, bakname);
X
X	/* now scan the command and see what we are to do */
X
X	for (a = arg[1]; *a; a++) {	/* scan the option flags */
X#if	!MTS
X		if (index("AMUFDXEPLVTCR", *a)) {	/* if a known command */
X#else
X		if (index("AMUFDXEPLVTC", *a)) {
X#endif
X			if (opt)/* do we have one yet? */
X				abort("Cannot mix %c and %c", opt, *a);
X			opt = *a;	/* else remember it */
X		} else if (*a == 'B')	/* retain backup copy */
X			keepbak = 1;
X
X		else if (*a == 'W')	/* suppress warnings */
X			warn = 0;
X#if	!DOS
X		else if (*a == 'I')	/* image mode, no ASCII/EBCDIC x-late */
X			image = !image;
X#endif
X#if	GEMDOS
X		else if (*a == 'H')	/* pause before exit */
X			hold = 1;
X#endif
X
X		else if (*a == 'N')	/* suppress notes and comments */
X			note = 0;
X
X		else if (*a == 'O')	/* overwrite file on extract */
X			overlay = 1;
X
X		else if (*a == 'G') {	/* garble */
X			password = a + 1;
X			while (*a)
X				a++;
X			a--;
X#if	MTS
X			etoa(password, strlen(password));
X#endif
X		} else if (*a == 'S')	/* storage kludge */
X			nocomp = 1;
X
X		else if (*a == 'K')	/* special kludge */
X			kludge = 1;
X
X		else if (*a == 'Q')	/* use squashing */
X			dosquash = 1;
X
X		else if (*a == '-' || *a == '/')	/* UNIX and PC-DOS
X							 * option markers */
X			;
X
X		else
X			abort("%c is an unknown command", *a);
X	}
X
X	if (!opt)
X		abort("I have nothing to do!");
X
X	/* get the files list set up */
X
X	lnum = num - 3;		/* initial length of list */
X	lst = (char **) calloc((lnum==0) ? 1:lnum,
X				 sizeof(char *));	/* initial list */
X	for (n = 3; n < num; n++)
X		lst[n - 3] = arg[n];
X
X	for (n = 0; n < lnum;) {/* expand indirect references */
X		if (*lst[n] == '@')
X			expandlst(n);
X		else
X			n++;
X	}
X
X	/* act on whatever action command was given */
X
X	switch (opt) {		/* action depends on command */
X	case 'A':		/* Add */
X	case 'M':		/* Move */
X	case 'U':		/* Update */
X	case 'F':		/* Freshen */
X		addarc(lnum, lst, (opt == 'M'), (opt == 'U'), (opt == 'F'));
X		break;
X
X	case 'D':		/* Delete */
X		delarc(lnum, lst);
X		break;
X
X	case 'E':		/* Extract */
X	case 'X':		/* eXtract */
X	case 'P':		/* Print */
X		extarc(lnum, lst, (opt == 'P'));
X		break;
X
X	case 'V':		/* Verbose list */
X		bose = 1;
X	case 'L':		/* List */
X		lstarc(lnum, lst);
X		break;
X
X	case 'T':		/* Test */
X		tstarc();
X		break;
X
X	case 'C':		/* Convert */
X		cvtarc(lnum, lst);
X		break;
X#if	!MTS
X	case 'R':		/* Run */
X		runarc(lnum, lst);
X		break;
X#endif
X	default:
X		abort("I don't know how to do %c yet!", opt);
X	}
X#if	GEMDOS
X	if (hold)
X		exitpause();
X#endif
X	return nerrs;
X}
Xstatic
Xexpandlst(n)			/* expand an indirect reference */
X	int		n;	/* number of entry to expand */
X{
X	FILE	       *lf, *fopen();	/* list file, opener */
X	char	       *malloc(), *realloc();	/* memory managers */
X	char		buf[100];	/* input buffer */
X	int		x;	/* index */
X	char	       *p = lst[n] + 1; /* filename pointer */
X
X	if (*p) {		/* use name if one was given */
X		makefnam(p, ".CMD", buf);
X		if (!(lf = fopen(buf, "r")))
X			abort("Cannot read list of files in %s", buf);
X	} else
X		lf = stdin;	/* else use standard input */
X
X	for (x = n + 1; x < lnum; x++)	/* drop reference from the list */
X		lst[x - 1] = lst[x];
X	lnum--;
X
X	while (fscanf(lf, "%99s", buf) > 0) {	/* read in the list */
X		if (!(lst =(char **)realloc(lst, (lnum + 1) * sizeof(char *))))
X			abort("too many file references");
X
X		lst[lnum] = malloc(strlen(buf) + 1);
X		strcpy(lst[lnum], buf); /* save the name */
X		lnum++;
X	}
X
X	if (lf != stdin)	/* avoid closing standard input */
X		fclose(lf);
X}
________This_Is_The_END________
if test `wc -c < arc.c` -ne    11146; then
	echo 'shar: arc.c was damaged during transit (should have been    11146 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arc.h'
if test -f arc.h; then echo 'shar: not overwriting arc.h'; else
sed 's/^X//' << '________This_Is_The_END________' > arc.h
X/*
X * $Header: arc.h,v 1.7 88/06/01 17:51:06 hyc Locked $
X */
X
X#undef	MSDOS
X#undef	GEMDOS		/* This amusing garbage is to get all my */
X#undef	DOS		/* define's past some compilers, which */
X#undef	BSD		/* apparently define some of these themselves */
X#undef	SYSV
X#undef	UNIX
X#undef	MTS
X
X#define	MSDOS	0		/* MSDOS machine */
X#define	GEMDOS	0		/* Atari, GEMDOS */
X#define	BSD	1		/* BSD4.2 or 4.3 */
X#define	SYSV	0		/* Also uses BSD */
X#define	MTS	0		/* MTS or 370(?) */
X
X/*
X * Assumptions:
X * char = 8 bits
X * short = 16 bits
X * long = 32 bits
X * int >= 16 bits
X */
X
X#if	MSDOS || GEMDOS
X#define	DOS	1
X#define	CUTOFF	'\\'
X#endif
X
X#if	!MSDOS
X#define	envfind	getenv
X#define	setmem(a, b, c)	memset(a, c, b)
X#endif
X
X#if	BSD || SYSV
X#define	UNIX	1
X#define	CUTOFF	'/'
X#include <ctype.h>
X#endif
X
X#if	MTS
X#define rindex strrchr
X#define index strchr
X#undef  USEGFINFO		/* define this to use GFINFO for directory */
X#define USECATSCAN		/* scanning, else use CATSCAN/FILEINFO... */
X#define	CUTOFF	sepchr[0]
X#endif
X
X/*  ARC - Archive utility - ARC Header
X  
X    Version 2.17, created on 04/22/87 at 13:09:43
X  
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X  
X    By:	 Thom Henderson
X  
X    Description: 
X	 This is the header file for the ARC archive utility.  It defines
X	 global parameters and the references to the external data.
X  
X  
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X
X#define ARCMARK 26		/* special archive marker        */
X#define ARCVER 9		/* archive header version code   */
X#define STRLEN 100		/* system standard string length */
X#define FNLEN 13		/* file name length              */
X#define MAXARG 25		/* maximum number of arguments   */
X
X#ifndef DONT_DEFINE		/* Defined by arcdata.c */
X#include "arcs.h"
X
Xextern int      keepbak;	/* true if saving the old archive */
X#if	!DOS
Xextern int      image;		/* true to suppress CRLF/LF x-late */
X#endif
X#if	MTS
Xextern char     sepchr[2];	/* Shared file separator, default = ':' */
Xextern char     tmpchr[2];	/* Temporary file prefix, default = '-' */
X#endif
X#if	GEMDOS
Xextern int      hold;		/* hold screen before exiting */
X#endif
Xextern int      warn;		/* true to print warnings */
Xextern int      note;		/* true to print comments */
Xextern int      bose;		/* true to be verbose */
Xextern int      nocomp;		/* true to suppress compression */
Xextern int      overlay;	/* true to overlay on extract */
Xextern int      kludge;		/* kludge flag */
Xextern char    *arctemp;	/* arc temp file prefix */
Xextern char    *password;	/* encryption password pointer */
Xextern int      nerrs;		/* number of errors encountered */
Xextern int      changing;	/* true if archive being modified */
X
Xextern char     hdrver;		/* header version */
X
Xextern FILE    *arc;		/* the old archive */
Xextern FILE    *new;		/* the new archive */
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 short arcdate;	/* archive date stamp */
Xextern unsigned short arctime;	/* archive time stamp */
Xextern unsigned short olddate;	/* old archive date stamp */
Xextern unsigned short oldtime;	/* old archive time stamp */
Xextern int      dosquash;	/* squash instead of crunch */
X#endif				/* DONT_DEFINE */
________This_Is_The_END________
if test `wc -c < arc.h` -ne     3318; then
	echo 'shar: arc.h was damaged during transit (should have been     3318 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcadd.c'
if test -f arcadd.c; then echo 'shar: not overwriting arcadd.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcadd.c
X/*
X * $Header: arcadd.c,v 1.8 88/06/13 00:31:15 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCADD
X * 
X * Version 3.40, created on 06/18/86 at 13:10:18
X * 
X * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to add files to an archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X#if	MTS
X#include <mts.h>
X#endif
X
Xstatic	void	addfile();
Xchar	*strcpy();
Xint	strcmp(), strlen(), free(), readhdr(), unlink();
X#if	UNIX
Xint	izadir();
X#endif
Xvoid	writehdr(), filecopy(), getstamp();
Xvoid	pack(), closearc(), openarc(), abort();
X
Xvoid
Xaddarc(num, arg, move, update, fresh)		/* add files to archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
Xint             move;		/* true if moving file */
Xint             update;		/* true if updating */
Xint             fresh;		/* true if freshening */
X{
X	char           *d, *dir();	/* directory junk */
X	char            buf[STRLEN];	/* pathname buffer */
X	char          **path;	/* pointer to pointers to paths */
X	char          **name;	/* pointer to pointers to names */
X	int             nfiles = 0;	/* number of files in lists */
X	int             notemp;	/* true until a template works */
X	int             nowork = 1;	/* true until files are added */
X	char           *i, *rindex();	/* string indexing junk */
X	char           *malloc(), *realloc();	/* memory allocators */
X	int             n;	/* index */
X#if	MSDOS
X	unsigned int	coreleft();	/* remaining memory reporter */
X#endif
X	int		addbunch();
X
X	if (num < 1) {		/* if no files named */
X		num = 1;	/* then fake one */
X#if	DOS
X		arg[0] = "*.*";	/* add everything */
X#endif
X#if	UNIX
X		arg[0] = "*";
X#endif
X#if	MTS
X		arg[0] = "?";
X#endif
X	}
X	path = (char **) malloc(sizeof(char **));
X	name = (char **) malloc(sizeof(char **));
X
X
X	for (n = 0; n < num; n++) {	/* for each template supplied */
X		strcpy(buf, arg[n]);	/* get ready to fix path */
X#if	!MTS
X		if (!(i = rindex(buf, '\\')))
X			if (!(i = rindex(buf, '/')))
X				if (!(i = rindex(buf, ':')))
X					i = buf - 1;
X#else
X		if (!(i = rindex(buf, sepchr[0])))
X			if (buf[0] != tmpchr[0])
X				i = buf - 1;
X			else
X				i = buf;
X#endif
X		i++;		/* pointer to where name goes */
X
X		notemp = 1;	/* reset files flag */
X		for (d = dir(arg[n]); d; d = dir(NULL)) {
X			notemp = 0;	/* template is giving results */
X			nfiles++;	/* add each matching file */
X			path = (char **) realloc(path, nfiles * sizeof(char **));
X			name = (char **) realloc(name, nfiles * sizeof(char **));
X			strcpy(i, d);	/* put name in path */
X			path[nfiles - 1] = malloc(strlen(buf) + 1);
X			strcpy(path[nfiles - 1], buf);
X			name[nfiles - 1] = d;	/* save name */
X#if	MSDOS
X			if (coreleft() < 5120) {
X				nfiles = addbunch(nfiles, path, name, move, update, fresh);
X				nowork = nowork && !nfiles;
X				while (nfiles) {
X					free(path[--nfiles]);
X					free(name[nfiles]);
X				}
X				free(path);
X				free(name);
X				path = name = NULL;
X			}
X#endif
X		}
X		if (notemp && warn)
X			printf("No files match: %s\n", arg[n]);
X	}
X
X	if (nfiles) {
X		nfiles = addbunch(nfiles, path, name, move, update, fresh);
X		nowork = nowork && !nfiles;
X		while (nfiles) {
X			free(path[--nfiles]);
X			free(name[nfiles]);
X		}
X		free(path);
X		free(name);
X	}
X	if (nowork && warn)
X		printf("No files were added.\n");
X}
X
Xint
Xaddbunch(nfiles, path, name, move, update, fresh)	/* add a bunch of files */
X	int             nfiles;	/* number of files to add */
X	char          **path;	/* pointers to pathnames */
X	char          **name;	/* pointers to filenames */
X	int             move;	/* true if moving file */
X	int             update;	/* true if updating */
X	int             fresh;	/* true if freshening */
X{
X	int             m, n;	/* indices */
X	char           *d;	/* swap pointer */
X	struct heads    hdr;	/* file header data storage */
X
X	for (n = 0; n < nfiles - 1; n++) {	/* sort the list of names */
X		for (m = n + 1; m < nfiles; m++) {
X			if (strcmp(name[n], name[m]) > 0) {
X				d = path[n];
X				path[n] = path[m];
X				path[m] = d;
X				d = name[n];
X				name[n] = name[m];
X				name[m] = d;
X			}
X		}
X	}
X
X	for (n = 0; n < nfiles - 1;) {	/* consolidate the list of names */
X		if (!strcmp(path[n], path[n + 1])	/* if duplicate names */
X		    ||!strcmp(path[n], arcname)	/* or this archive */
X#if	UNIX
X		    ||izadir(path[n])	/* or a directory */
X#endif
X		    ||!strcmp(path[n], newname)	/* or the new version */
X		    ||!strcmp(path[n], bakname)) {	/* or its backup */
X			free(path[n]);	/* then forget the file */
X			free(name[n]);
X			for (m = n; m < nfiles - 1; m++) {
X				path[m] = path[m + 1];
X				name[m] = name[m + 1];
X			}
X			nfiles--;
X		} else
X			n++;	/* else test the next one */
X	}
X
X	if (!strcmp(path[n], arcname)	/* special check for last file */
X	    ||!strcmp(path[n], newname)	/* courtesy of Rick Moore */
X#if	UNIX
X	    ||izadir(path[n])
X#endif
X	    || !strcmp(path[n], bakname)) {
X		free(path[n]);
X		free(name[n]);
X		nfiles--;
X	}
X	if (!nfiles)		/* make sure we got some */
X		return 0;
X
X	for (n = 0; n < nfiles - 1; n++) {	/* watch out for duplicate
X						 * names */
X		if (!strcmp(name[n], name[n + 1]))
X			abort("Duplicate filenames:\n  %s\n  %s", path[n], path[n + 1]);
X	}
X	openarc(1);		/* open archive for changes */
X
X	for (n = 0; n < nfiles; n++)	/* add each file in the list */
X		addfile(path[n], name[n], update, fresh);
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		writehdr(&hdr, new);
X		filecopy(arc, new, hdr.size);
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) {		/* if this was a move */
X		for (n = 0; n < nfiles; n++) {	/* then delete each file
X						 * added */
X			if (unlink(path[n]) && warn) {
X				printf("Cannot unsave %s\n", path[n]);
X				nerrs++;
X			}
X		}
X	}
X	return nfiles;		/* say how many were added */
X}
X
Xstatic          void
Xaddfile(path, name, update, fresh)	/* add named file to archive */
X	char           *path;	/* path name of file to add */
X	char           *name;	/* name of file to add */
X	int             update;	/* true if updating */
X	int             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	!MTS
X	if (!(f = fopen(path, "rb")))
X#else
X	if (image)
X		f = fopen(path, "rb");
X	else
X		f = fopen(path, "r");
X	if (!f)
X#endif
X	{
X		if (warn) {
X			printf("Cannot read file: %s\n", path);
X			nerrs++;
X		}
X		return;
X	}
X	strcpy(nhdr.name, name);/* save name */
X	nhdr.size = 0;		/* clear out size storage */
X	nhdr.crc = 0;		/* clear out CRC check storage */
X#if	!MTS
X	getstamp(f, &nhdr.date, &nhdr.time);
X#else
X	{
X	char *buffer, *malloc();
X	int	inlen;
X	struct	GDDSECT	*region;
X
X	region=gdinfo(f->_fd);
X	inlen=region->GDINLEN;
X	buffer=malloc(inlen);   /* maximum line length */
X	setbuf(f,buffer);        
X	f->_bufsiz=inlen;        
X	f->_mods|=0x00040000;   /* Don't do "$continue with" */
X	f->_mods&=0xfff7ffff;   /* turn it off, if set... */
X	}
X	getstamp(path, &nhdr.date, &nhdr.time);
X#endif
X
X	/* position archive to spot for new file */
X
X	if (arc) {		/* if adding to existing archive */
X		starts = ftell(arc);	/* where are we? */
X		while (readhdr(&ohdr, arc)) {	/* while more files to check */
X			if (!strcmp(ohdr.name, nhdr.name)) {
X				upd = 1;	/* replace existing entry */
X				if (update || fresh) {	/* if updating or
X							 * freshening */
X					if (nhdr.date < ohdr.date
X					    || (nhdr.date == ohdr.date && nhdr.time <= ohdr.time)) {
X						fseek(arc, starts, 0);
X						fclose(f);
X						return;	/* skip if not newer */
X					}
X				}
X			}
X			if (strcmp(ohdr.name, nhdr.name) >= 0)
X				break;	/* found our spot */
X
X			writehdr(&ohdr, new);	/* entry preceeds update;
X						 * 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			if (note) {
X				printf("Updating file: %-12s  ", name);
X				fflush(stdout);
X			}
X			fseek(arc, ohdr.size, 1);
X		} else if (fresh) {	/* else if freshening */
X			fseek(arc, starts, 0);	/* then do not add files */
X			fclose(f);
X			return;
X		} else {	/* else adding a new file */
X			if (note) {
X				printf("Adding file:   %-12s  ", name);
X				fflush(stdout);
X			}
X			fseek(arc, starts, 0);	/* reset for next time */
X		}
X	} else {		/* no existing archive */
X		if (fresh) {	/* cannot freshen nothing */
X			fclose(f);
X			return;
X		} else if (note) {	/* else adding a file */
X			printf("Adding file:   %-12s  ", 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	strcpy(nhdr.name, name);
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}
________This_Is_The_END________
if test `wc -c < arcadd.c` -ne     9286; then
	echo 'shar: arcadd.c was damaged during transit (should have been     9286 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arccode.c'
if test -f arccode.c; then echo 'shar: not overwriting arccode.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arccode.c
X/*
X * $Header: arccode.c,v 1.1 88/06/01 15:15:58 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCCODE
X * 
X * Version 1.02, created on 01/20/86 at 13:33:35
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to encrypt and decrypt data
X * in an archive.  The encryption method is nothing fancy, being just a
X * routine XOR, but it is used on the packed data, and uses a variable length
X * key.  The end result is something that is in theory crackable, but I'd
X * hate to try it.  It should be more than sufficient for casual use.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
Xstatic char    *p;		/* password pointer */
X
Xvoid
Xsetcode()
X{				/* get set for encoding/decoding */
X	p = password;		/* reset password pointer */
X}
X
Xunsigned char
Xcode(c)				/* encode some character */
X	char            c;	/* character to encode */
X{
X	if (p) {		/* if password is in use */
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	} else
X		return c;	/* else no encryption */
X}
________This_Is_The_END________
if test `wc -c < arccode.c` -ne     1204; then
	echo 'shar: arccode.c was damaged during transit (should have been     1204 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arccvt.c'
if test -f arccvt.c; then echo 'shar: not overwriting arccvt.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arccvt.c
X/*
X * $Header: arccvt.c,v 1.5 88/06/01 19:17:40 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCCVT
X * 
X * Version 1.16, created on 02/03/86 at 22:53:02
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to convert archives to use
X * newer file storage methods.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
Xvoid	openarc(), rempath(), closearc(), abort(), pack(), writehdr(), filecopy();
Xint	match(), readhdr(), unpack(), unlink();
X
Xstatic char     tempname[STRLEN];	/* temp file name */
X
Xvoid
Xcvtarc(num, arg)		/* convert archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* file header */
X	int             cvt;	/* true to convert current file */
X	int             did[MAXARG];/* true when argument was used */
X	int             n;	/* index */
X	char           *makefnam();	/* filename fixer */
X	FILE           *fopen();/* file opener */
X	void            cvtfile();
X
X	if (arctemp)		/* use temp area if specified */
X		sprintf(tempname, "%s.CVT", arctemp);
X	else
X		makefnam("$ARCTEMP.CVT", arcname, tempname);
X#if	!DOS
X	image = 1;
X#endif
X
X	openarc(1);		/* open archive for changes */
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* while more files to check */
X			cvt = 0;/* reset convert flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, arg[n])) {
X					cvt = 1;	/* turn on convert flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (cvt)/* if converting this one */
X				cvtfile(&hdr);	/* then do it */
X			else {	/* else just copy it */
X				writehdr(&hdr, new);
X				filecopy(arc, new, hdr.size);
X			}
X		}
X	} else
X		while (readhdr(&hdr, arc))	/* else convert all files */
X			cvtfile(&hdr);
X
X	hdrver = 0;		/* archive EOF type */
X	writehdr(&hdr, new);	/* write out our end marker */
X	closearc(1);		/* close archive after changes */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
X
Xvoid
Xcvtfile(hdr)			/* convert a file */
X	struct heads   *hdr;	/* pointer to header data */
X{
X	long            starts, ftell();	/* where the file goes */
X	FILE           *tmp, *fopen();	/* temporary file */
X
X	if (!(tmp = fopen(tempname, "w+b")))
X		abort("Unable to create temporary file %s", tempname);
X
X	if (note) {
X		printf("Converting file: %-12s   reading, ", hdr->name);
X		fflush(stdout);
X	}
X	unpack(arc, tmp, hdr);	/* unpack the entry */
X	fseek(tmp, 0L, 0);	/* reset temp for reading */
X
X	starts = ftell(new);	/* note where header goes */
X	hdrver = ARCVER;		/* anything but end marker */
X	writehdr(hdr, new);	/* write out header skeleton */
X	pack(tmp, new, hdr);	/* pack file into archive */
X	fseek(new, starts, 0);	/* move back to header skeleton */
X	writehdr(hdr, new);	/* write out real header */
X	fseek(new, hdr->size, 1);	/* skip over data to next header */
X	fclose(tmp);		/* all done with the file */
X	if (unlink(tempname) && warn) {
X		printf("Cannot unsave %s\n", tempname);
X		nerrs++;
X	}
X}
________This_Is_The_END________
if test `wc -c < arccvt.c` -ne     3396; then
	echo 'shar: arccvt.c was damaged during transit (should have been     3396 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcdata.c'
if test -f arcdata.c; then echo 'shar: not overwriting arcdata.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcdata.c
X/*
X * $Header: arcdata.c,v 1.6 88/06/01 19:17:58 hyc Locked $
X */
X
X/*  ARC - Archive utility - ARCDATA
X
X    Version 2.17, created on 04/22/87 at 13:09:43
X
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description: 
X	 This file defines the external data storage used by the ARC
X	 archive utility.
X
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X
X#define DONT_DEFINE
X#include "arc.h"
X
Xint             keepbak = 0;	/* true if saving the old archive */
X#if	UNIX
Xint		image = 1;	/* true to suppress CRLF/LF x-late */
X#endif
X#if	MTS
Xint             image = 0;	/* true to suppress EBCDIC/ASCII x-late */
Xchar            sepchr[2] = ":";/* Shared file separator */
Xchar            tmpchr[2] = "-";/* Temporary file prefix */
X#endif
X#if	GEMDOS
Xint		hold = 0;	/* true to pause before exit */
X#endif
Xint             warn = 1;	/* true to print warnings */
Xint             note = 1;	/* true to print comments */
Xint             bose = 0;	/* true to be verbose */
Xint             nocomp = 0;	/* true to suppress compression */
Xint             overlay = 0;	/* true to overlay on extract */
Xint             kludge = 0;	/* kludge flag */
Xchar           *arctemp = NULL;	/* arc temp file prefix */
Xchar           *password = NULL;/* encryption password pointer */
Xint             nerrs = 0;	/* number of errors encountered */
Xint		changing = 0;	/* true if archive being modified */
X
Xchar            hdrver;		/* header version */
X
XFILE           *arc;		/* the old archive */
XFILE           *new;		/* the new archive */
Xchar            arcname[STRLEN];	/* storage for archive name */
Xchar            bakname[STRLEN];	/* storage for backup copy name */
Xchar            newname[STRLEN];	/* storage for new archive name */
Xunsigned short  arcdate = 0;	/* archive date stamp */
Xunsigned short  arctime = 0;	/* archive time stamp */
Xunsigned short  olddate = 0;	/* old archive date stamp */
Xunsigned short  oldtime = 0;	/* old archive time stamp */
Xint		dosquash = 0;	/* true to squash instead of crunch */
________This_Is_The_END________
if test `wc -c < arcdata.c` -ne     2070; then
	echo 'shar: arcdata.c was damaged during transit (should have been     2070 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcdel.c'
if test -f arcdel.c; then echo 'shar: not overwriting arcdel.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcdel.c
X/*
X * $Header: arcdel.c,v 1.3 88/04/19 01:39:32 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCDEL
X * 
X * Version 2.09, created on 02/03/86 at 22:53:27
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to delete entries in an
X * archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
Xvoid	abort(), rempath(), openarc(), closearc(), writehdr(), filecopy();
Xint	match(), readhdr();
X
Xvoid
Xdelarc(num, arg)		/* remove files from archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* header data */
X	int             del;	/* true to delete a file */
X	int             did[MAXARG];/* true when argument used */
X	int             n;	/* index */
X
X	if (!num)		/* she must specify which */
X		abort("You must tell me which files to delete!");
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	openarc(1);		/* open archive for changes */
X
X	while (readhdr(&hdr, arc)) {	/* while more entries in archive */
X		del = 0;	/* reset delete flag */
X		for (n = 0; n < num; n++) {	/* for each template given */
X			if (match(hdr.name, arg[n])) {
X				del = 1;	/* turn on delete flag */
X				did[n] = 1;	/* turn on usage flag */
X				break;	/* stop looking */
X			}
X		}
X
X		if (del) {	/* skip over unwanted files */
X			fseek(arc, hdr.size, 1);
X			if (note)
X				printf("Deleting file: %s\n", hdr.name);
X		} else {	/* else copy over file data */
X			writehdr(&hdr, new);	/* write out header and file */
X			filecopy(arc, new, hdr.size);
X		}
X	}
X
X	hdrver = 0;		/* special end of archive type */
X	writehdr(&hdr, new);	/* write out archive end marker */
X	closearc(1);		/* close archive after changes */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused arguments */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
________This_Is_The_END________
if test `wc -c < arcdel.c` -ne     2055; then
	echo 'shar: arcdel.c was damaged during transit (should have been     2055 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcdos.c'
if test -f arcdos.c; then echo 'shar: not overwriting arcdos.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcdos.c
X/*
X * $Header: arcdos.c,v 1.5 88/06/13 00:40:49 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCDOS
X * 
X * Version 1.44, created on 07/25/86 at 14:17:38
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains certain DOS level routines that assist in
X * doing fancy things with an archive, primarily reading and setting the date
X * and time last modified.
X * 
X * These are, by nature, system dependant functions.  But they are also, by
X * nature, very expendable.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
X#if	MSDOS
X#include "fileio2.h"		/* needed for filehand */
X#endif
X
X#if	UNIX
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/time.h>
X#include "tws.h"
X#endif
X
X#if	SYSV
Xstruct timeval {
X	long tv_sec;
X	long tv_usec;
X};
X#endif
X
X#if	GEMDOS
X#include <osbind.h>
X#endif
X
Xchar	*strcpy(), *strcat(), *malloc();
X
Xvoid
Xgetstamp(f, date, time)		/* get a file's date/time stamp */
X#if	!MTS
X	FILE           *f;	/* file to get stamp from */
X#else
X	char           *f;	/* filename "" "" */
X#endif
X	unsigned short   *date, *time;	/* storage for the stamp */
X{
X#if	MSDOS
X	struct {
X		int             ax, bx, cx, dx, si, di, ds, es;
X	}               reg;
X
X	reg.ax = 0x5700;	/* get date/time */
X	reg.bx = filehand(f);	/* file handle */
X	if (sysint21(&reg, &reg) & 1)	/* DOS call */
X		printf("Get timestamp fail (%d)\n", reg.ax);
X
X	*date = reg.dx;		/* save date/time */
X	*time = reg.cx;
X#endif
X#if	GEMDOS
X	int	fd, ret[2];
X
X	fd = fileno(f);
X	Fdatime(ret, fd, 0);
X	*date = ret[1];
X	*time = ret[0];
X#endif
X#if	UNIX
X	char	       *ctime();
X	struct stat    *buf;
X	int             day, hr, min, sec, yr, imon;
X	static char     mon[4], *mons[12] = {
X				   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X				    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X	};
X
X	buf = (struct stat *) malloc(sizeof(struct stat));
X	fstat(fileno(f), buf);
X
X	sscanf(ctime(&(buf->st_mtime)), "%*4s%3s%d%d:%d:%d%d", mon, &day, &hr, &min,
X	       &sec, &yr);
X	for (imon = 0; imon < 12 && strcmp(mon, mons[imon]); imon++);
X
X	*date = (unsigned short) (((yr - 1980) << 9) + ((imon + 1) << 5) + day);
X	*time = (unsigned short) ((hr << 11) + (min << 5) + sec / 2);
X#endif
X#if	MTS
X	fortran         timein(),
X#if	USEGFINFO
X	                gfinfo();
X#else
X	                fileinfo();
X#endif
X	int             stclk[2];
X	char            name[24];
X	struct bigtime {
X		int             greg;
X		int             year;
X		int             mon;
X		int             day;
X		int             hour;
X		int             min;
X		int             sec;
X		int             usec;
X		int             week;
X		int             toff;
X		int             tzn1;
X		int             tzn2;
X	}               tvec;
X#if	USEGFINFO
X	static int      gfflag = 0x0009, gfdummy[2] = {
X						       0, 0
X	};
X	int             gfcinfo[18];
X#else
X	static int      cattype = 2;
X#endif
X
X	strcpy(name, f);
X	strcat(name, " ");
X#if	USEGFINFO
X	gfcinfo[0] = 18;
X	gfinfo(name, name, &gfflag, gfcinfo, gfdummy, gfdummy);
X	timein("*IBM MICROSECONDS*", &gfcinfo[16], &tvec);
X#else
X	fileinfo(name, &cattype, "CILCCT  ", stclk);
X	timein("*IBM MICROSECONDS*", stclk, &tvec);
X#endif
X
X	*date = (unsigned short) (((tvec.year - 1980) << 9) + ((tvec.mon) << 5) + tvec.day);
X	*time = (unsigned short) ((tvec.hour << 11) + (tvec.min << 5) + tvec.sec / 2);
X#endif
X}
X
Xvoid
Xsetstamp(f, date, time)		/* set a file's date/time stamp */
X	char           *f;	/* filename to stamp */
X	unsigned short    date, time;	/* desired date, time */
X{
X#if	MSDOS
X	FILE	*ff;
X	struct {
X		int             ax, bx, cx, dx, si, di, ds, es;
X	}               reg;
X
X	ff = fopen(f, "w+");	/* How else can I get a handle? */
X
X	reg.ax = 0x5701;	/* set date/time */
X	reg.bx = filehand(f);	/* file handle */
X	reg.cx = time;		/* desired time */
X	reg.dx = date;		/* desired date */
X	if (sysint21(&reg, &reg) & 1)	/* DOS call */
X		printf("Set timestamp fail (%d)\n", reg.ax);
X	fclose(ff);
X#endif
X#if	GEMDOS
X	int	fd, set[2];
X
X	fd = Fopen(f, 0);
X	set[0] = time;
X	set[1] = date;
X	Fdatime(set, fd, 1);
X	Fclose(fd);
X#endif
X#if	UNIX
X	struct tws      tms;
X	struct timeval  tvp[2];
X	int	utimes();
X	twscopy(&tms, dtwstime());
X	tms.tw_sec = (time & 31) * 2;
X	tms.tw_min = (time >> 5) & 63;
X	tms.tw_hour = (time >> 11);
X	tms.tw_mday = date & 31;
X	tms.tw_mon = ((date >> 5) & 15) - 1;
X	tms.tw_year = (date >> 9) + 80;
X	tms.tw_clock = 0L;
X	tms.tw_flags = TW_NULL;
X	tvp[0].tv_sec = twclock(&tms);
X	tvp[1].tv_sec = tvp[0].tv_sec;
X	tvp[0].tv_usec = tvp[1].tv_usec = 0;
X	utimes(f, tvp);
X#endif
X}
X
X#if	MSDOS
Xint
Xfilehand(stream)		/* find handle on a file */
X	struct bufstr  *stream;	/* file to grab onto */
X{
X	return stream->bufhand;	/* return DOS 2.0 file handle */
X}
X#endif
X
X#if	UNIX
Xint
Xizadir(filename)		/* Is filename a directory? */
X	char           *filename;
X{
X	struct stat     buf;
X
X	if (stat(filename, &buf) != 0)
X		return (0);	/* Ignore if stat fails since */
X	else
X		return (buf.st_mode & S_IFDIR);	/* bad files trapped later */
X}
X#endif
________This_Is_The_END________
if test `wc -c < arcdos.c` -ne     5008; then
	echo 'shar: arcdos.c was damaged during transit (should have been     5008 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcext.c'
if test -f arcext.c; then echo 'shar: not overwriting arcext.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcext.c
X/*
X * $Header: arcext.c,v 1.5 88/06/01 19:26:31 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCEXT
X * 
X * Version 2.19, created on 10/24/86 at 14:53:32
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to extract files from an
X * archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X#if	!MSDOS
X#include <ctype.h>
X#endif
X
Xvoid	openarc(), closearc(), setstamp();
Xint	free(), match(), readhdr(), unpack();
Xchar	*strcpy(), *strcat();
X
Xvoid
Xextarc(num, arg, prt)		/* extract files from archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X	int             prt;		/* true if printing */
X{
X	struct heads    hdr;	/* file header */
X	int             save;	/* true to save current file */
X	int             did[MAXARG];/* true when argument was used */
X	char           *i, *rindex();	/* string index */
X	char          **name, *malloc();	/* name pointer list,
X						 * allocator */
X	int             n;	/* index */
X	void            extfile();
X
X	name = (char **) malloc(num * sizeof(char *));	/* get storage for name
X							 * pointers */
X
X	for (n = 0; n < num; n++) {	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X#if	!MTS
X		if (!(i = rindex(arg[n], '\\')))	/* find start of name */
X			if (!(i = rindex(arg[n], '/')))
X				if (!(i = rindex(arg[n], ':')))
X					i = arg[n] - 1;
X#else
X		if (!(i = rindex(arg[n], sepchr[0])))
X			if (arg[n][0] != tmpchr[0])
X				i = arg[n] - 1;
X			else
X				i = arg[n];
X#endif
X		name[n] = i + 1;
X	}
X
X
X	openarc(0);		/* open archive for reading */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* while more files to check */
X			save = 0;	/* reset save flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, name[n])) {
X					save = 1;	/* turn on save flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (save)	/* extract if desired, else skip */
X				extfile(&hdr, arg[n], prt);
X			else
X				fseek(arc, hdr.size, 1);
X		}
X	} else
X		while (readhdr(&hdr, arc))	/* else extract all files */
X			extfile(&hdr, "", prt);
X
X	closearc(0);		/* close archive after reading */
X
X	if (note) {
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X	free(name);
X}
X
Xvoid
Xextfile(hdr, path, prt)		/* extract a file */
X	struct heads   *hdr;	/* pointer to header data */
X	char           *path;	/* pointer to path name */
X	int             prt;	/* true if printing */
X{
X	FILE           *f, *fopen();	/* extracted file, opener */
X	char            buf[STRLEN];	/* input buffer */
X	char            fix[STRLEN];	/* fixed name buffer */
X	char           *i, *rindex();	/* string index */
X
X	if (prt) {		/* printing is much easier */
X		unpack(arc, stdout, hdr);	/* unpack file from archive */
X		printf("\f");	/* eject the form */
X		return;		/* see? I told you! */
X	}
X	strcpy(fix, path);	/* note path name template */
X#if	!MTS
X	if (*path) {
X	if (!(i = rindex(fix, '\\')))	/* find start of name */
X		if (!(i = rindex(fix, '/')))
X			if (!(i = rindex(fix, ':')))
X				i = fix - 1;
X	} else i = fix -1;
X#else
X	if (!(i = rindex(fix, sepchr[0])))
X		if (fix[0] != tmpchr[0])
X			i = fix - 1;
X		else
X			i = fix;
X#endif
X	strcpy(i + 1, hdr->name);	/* replace template with name */
X
X	if (note)
X		printf("Extracting file: %s\n", fix);
X
X	if (warn && !overlay) {
X		if (f = fopen(fix, "r")) {	/* see if it exists */
X				fclose(f);
X				printf("WARNING: File %s already exists!", fix);
X				fflush(stdout);
X				while (1) {
X					printf("  Overwrite it (y/n)? ");
X					fflush(stdout);
X					fgets(buf, STRLEN, stdin);
X					*buf = toupper(*buf);
X					if (*buf == 'Y' || *buf == 'N')
X						break;
X				}
X				if (*buf == 'N') {
X					printf("%s not extracted.\n", fix);
X					fseek(arc, hdr->size, 1);
X					return;
X				}
X		}
X	}
X#if	!MTS
X	if (!(f = fopen(fix, "wb")))
X#else
X	{
X		fortran         create();
X		void		memset();
X		char            c_name[256];
X		struct crsize {
X			short           maxsize, cursize;
X		}               c_size;
X		char            c_vol[6];
X		int             c_type;
X		strcpy(c_name, fix);
X		strcat(c_name, " ");
X		c_size.maxsize = 0;
X		c_size.cursize = hdr->length / 4096 + 1;
X		memset(c_vol, 0, sizeof(c_vol));
X		c_type = 0x100;
X		create(c_name, &c_size, c_vol, &c_type);
X	}
X	if (image) {
X		f = fopen(fix, "wb");
X	} else
X		f = fopen(fix, "w");
X	if (!f)
X#endif
X	{
X		if (warn) {
X			printf("Cannot create %s\n", fix);
X			nerrs++;
X		}
X		fseek(arc, hdr->size, 1);
X		return;
X	}
X	/* now unpack the file */
X
X	unpack(arc, f, hdr);	/* unpack file from archive */
X	fclose(f);		/* all done writing to file */
X#if	!MTS
X	setstamp(fix, hdr->date, hdr->time);	/* use filename for stamp */
X#endif
X}
________This_Is_The_END________
if test `wc -c < arcext.c` -ne     4898; then
	echo 'shar: arcext.c was damaged during transit (should have been     4898 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arcio.c'
if test -f arcio.c; then echo 'shar: not overwriting arcio.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arcio.c
X/*
X * $Header: arcio.c,v 1.7 88/06/02 16:27:32 hyc Locked $
X */
X
X/*  ARC - Archive utility - ARCIO
X
X    Version 2.50, created on 04/22/87 at 13:25:20
X
X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description:
X	 This file contains the file I/O routines used to manipulate
X	 an archive.
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if	MTS
X#include <ctype.h>
X#endif
X
Xvoid	abort();
Xint	strlen(), free();
X
Xint
Xreadhdr(hdr, f)			/* read a header from an archive */
X	struct heads   *hdr;	/* storage for header */
X	FILE           *f;	/* archive to read header from */
X{
X#if	!MSDOS
X	unsigned char   dummy[28];
X	int             i;
X#endif
X	char            name[FNLEN];	/* filename buffer */
X	int             try = 0;/* retry counter */
X	static int      first = 1;	/* true only on first read */
X
X	if (!f)			/* if archive didn't open */
X		return 0;	/* then pretend it's the end */
X	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		if (warn) {
X			printf("An entry in %s has a bad header.", arcname);
X			nerrs++;
X		}
X		while (!feof(f)) {
X			try++;
X			if (fgetc(f) == ARCMARK) {
X				ungetc(hdrver = fgetc(f), f);
X				if (!(hdrver & 0x80) && hdrver <= ARCVER)
X					break;
X			}
X		}
X
X		if (feof(f) && first)
X			abort("%s is not an archive", arcname);
X
X		if (changing && warn)
X			abort("%s is corrupted -- changes disallowed", arcname);
X
X		if (warn)
X			printf("  %d bytes skipped.\n", try);
X
X		if (feof(f))
X			return 0;
X	}
X	hdrver = fgetc(f);	/* get header version */
X	if (hdrver & 0x80)	/* sign bit? negative? */
X		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		fread(name, sizeof(char), FNLEN, f);
X#if	MTS
X		atoe(name, strlen(name));
X#endif
X		printf("I don't know how to handle file %s in archive %s\n",
X		       name, arcname);
X		printf("I think you need a newer version of ARC.\n");
X		exit(1);
X	}
X	/* amount to read depends on header type */
X
X	if (hdrver == 1) {	/* old style is shorter */
X		fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f);
X		hdrver = 2;	/* convert header to new format */
X		hdr->length = hdr->size;	/* size is same when not
X						 * packed */
X	} else
X#if	MSDOS
X		fread(hdr, sizeof(struct heads), 1, f);
X#else
X		fread(dummy, 27, 1, f);
X
X	for (i = 0; i < FNLEN; hdr->name[i] = dummy[i], i++);
X#if	MTS
X	(void) atoe(hdr->name, strlen(hdr->name));
X#endif
X	for (i = 0; i<4; hdr->size<<=8, hdr->size += dummy[16-i], i++);
X	hdr->date = (short) ((dummy[18] << 8) + dummy[17]);
X	hdr->time = (short) ((dummy[20] << 8) + dummy[19]);
X	hdr->crc = (short) ((dummy[22] << 8) + dummy[21]);
X	for (i = 0; i<4; hdr->length<<=8, hdr->length += dummy[26-i], i++);
X#endif
X
X	if (hdr->date > olddate
X	    || (hdr->date == olddate && hdr->time > oldtime)) {
X		olddate = hdr->date;
X		oldtime = hdr->time;
X	}
X	first = 0;
X	return 1;		/* we read something */
X}
X
Xvoid
Xput_int(number, f)		/* write a 2 byte integer */
X	short           number;
X	FILE           *f;
X{
X	fputc((char) (number & 255), f);
X	fputc((char) (number >> 8), f);
X}
X
Xvoid
Xput_long(number, f)		/* write a 4 byte integer */
X	long            number;
X	FILE           *f;
X{
X	put_int((short) (number & 0xFFFF), f);
X	put_int((short) (number >> 16), f);
X}
X
Xvoid
Xwritehdr(hdr, f)		/* write a header to an archive */
X	struct heads   *hdr;	/* header to write */
X	FILE           *f;	/* archive to write to */
X{
X	fputc(ARCMARK, f);		/* write out the mark of ARC */
X	fputc(hdrver, f);	/* write out the header version */
X	if (!hdrver)		/* if that's the end */
X		return;		/* then write no more */
X#if	MSDOS
X	fwrite(hdr, sizeof(struct heads), 1, f);
X#else
X	/* byte/word ordering hassles... */
X#if	MTS
X	etoa(hdr->name, strlen(hdr->name));
X#endif
X	fwrite(hdr->name, 1, FNLEN, f);
X	put_long(hdr->size, f);
X	put_int(hdr->date, f);
X	put_int(hdr->time, f);
X	put_int(hdr->crc, f);
X	put_long(hdr->length, f);
X#endif
X
X	/* note the newest file for updating the archive timestamp */
X
X	if (hdr->date > arcdate
X	    || (hdr->date == arcdate && hdr->time > arctime)) {
X		arcdate = hdr->date;
X		arctime = hdr->time;
X	}
X}
X
Xvoid
Xputc_tst(c, t)			/* put a character, with tests */
X	char            c;	/* character to output */
X	FILE           *t;	/* file to write to */
X{
X	c &= 0xff;
X	if (t)
X#if	UNIX
X		fputc(c, t);
X#else
X		if (fputc(c, t) == EOF)
X			abort("Write fail (disk full?)");
X#endif
X}
X
X/*
X * NOTE:  The filecopy() function is used to move large numbers of bytes from
X * one file to another.  This particular version has been modified to improve
X * performance in Computer Innovations C86 version 2.3 in the small memory
X * model.  It may not work as expected with other compilers or libraries, or
X * indeed with different versions of the CI-C86 compiler and library, or with
X * the same version in a different memory model.
X * 
X * The following is a functional equivalent to the filecopy() routine that
X * should work properly on any system using any compiler, albeit at the cost
X * of reduced performance:
X * 
X * filecopy(f,t,size) 
X *      FILE *f, *t; long size; 
X * { 
X *      while(size--)
X *              putc_tst(fgetc(f),t); 
X * }
X */
X#if	MSDOS
X#include <fileio2.h>
X
Xfilecopy(f, t, size)		/* bulk file copier */
X	FILE           *f, *t;	/* files from and to */
X	long            size;	/* bytes to copy */
X{
X	char           *buf;	/* buffer pointer */
X	char           *alloc();/* buffer allocator */
X	unsigned int    bufl;	/* buffer length */
X	unsigned int    coreleft();	/* space available reporter */
X	unsigned int    cpy;	/* bytes being copied */
X	long            floc, tloc, fseek();	/* file pointers, setter */
X	struct regval   reg;	/* registers for DOS calls */
X
X	if ((bufl = coreleft()) < 1000)	/* see how much space we have */
X		abort("Out of memory");
X	bufl -= 1000;		/* fudge factor for overhead */
X	if (bufl > 60000)
X		bufl = 60000;	/* avoid choking alloc() */
X	if (bufl > size)
X		bufl = size;	/* avoid wasting space */
X	buf = alloc(bufl);	/* allocate our buffer */
X
X	floc = fseek(f, 0L, 1);	/* reset I/O system */
X	tloc = fseek(t, 0L, 1);
X
X	segread(&reg.si);	/* set segment registers for DOS */
X
X	while (size > 0) {	/* while more to copy */
X		reg.ax = 0x3F00;/* read from handle */
X		reg.bx = filehand(f);
X		reg.cx = bufl < size ? bufl : size;	/* amount to read */
X		reg.dx = buf;
X		if (sysint21(&reg, &reg) & 1)
X			abort("Read fail");
X
X		cpy = reg.ax;	/* amount actually read */
X		reg.ax = 0x4000;/* write to handle */
X		reg.bx = filehand(t);
X		reg.cx = cpy;
X		reg.dx = buf;
X		sysint21(&reg, &reg);
X
X		if (reg.ax != cpy)
X			abort("Write fail (disk full?)");
X
X		size -= (long) cpy;
X	}
X
X	free(buf);		/* all done with buffer */
X}
X#else
X
Xvoid
Xfilecopy(f, t, size)		/* bulk file copier */
X	FILE           *f, *t;	/* files from and to */
X	long            size;	/* bytes to copy */
X{
X	char           *buf;	/* buffer pointer */
X	char           *malloc();	/* buffer allocator */
X	unsigned int    bufl;	/* buffer length */
X	unsigned int    cpy;	/* bytes being copied */
X
X	bufl = 32760;
X	if (bufl > size)
X		bufl = size;	/* don't waste space */
X
X	buf = malloc(bufl);
X
X	while (size > 0) {
X		cpy = fread(buf, sizeof(char),
X			bufl < size ? bufl : (unsigned short) size, f);
X		if (fwrite(buf, sizeof(char), cpy, t) != cpy)
X			abort("Write fail (no space?)");
X		size -= cpy;
X	}
X
X	free(buf);
X}
X#endif
________This_Is_The_END________
if test `wc -c < arcio.c` -ne     7418; then
	echo 'shar: arcio.c was damaged during transit (should have been     7418 bytes)'
fi
fi		; : end of overwriting check
echo 'x - arclst.c'
if test -f arclst.c; then echo 'shar: not overwriting arclst.c'; else
sed 's/^X//' << '________This_Is_The_END________' > arclst.c
X/*
X * $Header: arclst.c,v 1.5 88/06/01 18:05:57 hyc Locked $
X */
X
X/*  ARC - Archive utility - ARCLST
X  
X    Version 2.39, created on 04/22/87 at 13:48:29
X  
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X  
X    By:	 Thom Henderson
X  
X    Description:
X	 This file contains the routines used to list the contents
X	 of an archive.
X  
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xvoid            rempath(), openarc(), closearc();
Xint             readhdr(), match();
X
Xvoid
Xlstarc(num, arg)		/* list files in archive */
X	int             num;	/* number of arguments */
X	char           *arg[];	/* pointers to arguments */
X{
X	struct heads    hdr;	/* header data */
X	int             list;	/* true to list a file */
X	int             did[MAXARG];	/* true when argument was used */
X	long            tnum, tlen, tsize;	/* totals */
X	int             n;	/* index */
X	void            lstfile();
X
X	tnum = tlen = tsize = 0;/* reset totals */
X
X	for (n = 0; n < num; n++)	/* for each argument */
X		did[n] = 0;	/* reset usage flag */
X	rempath(num, arg);	/* strip off paths */
X
X	if (note && !kludge) {
X		printf("Name          Length  ");
X		if (bose)
X			printf("  Stowage    SF   Size now");
X		printf("  Date     ");
X		if (bose)
X			printf("  Time    CRC");
X		printf("\n");
X
X		printf("============  ========");
X		if (bose)
X			printf("  ========  ====  ========");
X		printf("  =========");
X		if (bose)
X			printf("  ======  ====");
X		printf("\n");
X	}
X	openarc(0);		/* open archive for reading */
X
X	if (num) {		/* if files were named */
X		while (readhdr(&hdr, arc)) {	/* process all archive files */
X			list = 0;	/* reset list flag */
X			for (n = 0; n < num; n++) {	/* for each template
X							 * given */
X				if (match(hdr.name, arg[n])) {
X					list = 1;	/* turn on list flag */
X					did[n] = 1;	/* turn on usage flag */
X					break;	/* stop looking */
X				}
X			}
X
X			if (list) {	/* if this file is wanted */
X				if (!kludge)
X					lstfile(&hdr);	/* then tell about it */
X				tnum++;	/* update totals */
X				tlen += hdr.length;
X				tsize += hdr.size;
X			}
X			fseek(arc, hdr.size, 1);	/* move to next header */
X		}
X	} else
X		while (readhdr(&hdr, arc)) {	/* else report on all files */
X			if (!kludge)
X				lstfile(&hdr);
X			tnum++;	/* update totals */
X			tlen += hdr.length;
X			tsize += hdr.size;
X			fseek(arc, hdr.size, 1);	/* skip to next header */
X		}
X
X	closearc(0);		/* close archive after reading */
X
X	if (note && !kludge) {
X		printf("        ====  ========");
X		if (bose)
X			printf("            ====  ========");
X		printf("\n");
X	}
X	if (note) {
X		printf("Total %6ld  %8ld", tnum, tlen);
X		if (bose) {
X			if (tlen)
X				printf("            %3ld%%", 100L - (100L * tsize) / tlen);
X			else
X				printf("            ---");
X			printf("  %8ld", tsize);
X		}
X		printf("\n");
X
X		for (n = 0; n < num; n++) {	/* report unused args */
X			if (!did[n]) {
X				printf("File not found: %s\n", arg[n]);
X				nerrs++;
X			}
X		}
X	}
X}
X
Xvoid
Xlstfile(hdr)			/* tell about a file */
X	struct heads   *hdr;	/* pointer to header data */
X{
X	int             yr, mo, dy;	/* parts of a date */
X	int             hh, mm;	/* parts of a time */
X
X	static char    *mon[] =	/* month abbreviations */
X	{
X	 "Jan", "Feb", "Mar", "Apr",
X	 "May", "Jun", "Jul", "Aug",
X	 "Sep", "Oct", "Nov", "Dec"
X	};
X
X	if (!note) {		/* no notes means short listing */
X		printf("%s\n", hdr->name);
X		return;
X	}
X
X	yr = (hdr->date >> 9) & 0x7f;	/* dissect the date */
X	mo = (hdr->date >> 5) & 0x0f;
X	dy = hdr->date & 0x1f;
X
X	hh = (hdr->time >> 11) & 0x1f;	/* dissect the time */
X	mm = (hdr->time >> 5) & 0x3f;
X/*	ss = (hdr->time & 0x1f) * 2;	seconds, not used. */
X
X	printf("%-12s  %8ld  ", hdr->name, hdr->length);
X
X	if (bose) {
X		switch (hdrver) {
X		case 1:
X		case 2:
X			printf("   --   ");
X			break;
X		case 3:
X			printf(" Packed ");
X			break;
X		case 4:
X			printf("Squeezed");
X			break;
X		case 5:
X		case 6:
X		case 7:
X			printf("crunched");
X			break;
X		case 8:
X			printf("Crunched");
X			break;
X		case 9:
X			printf("Squashed");
X			break;
X		default:
X			printf("Unknown!");
X		}
X
X		if (hdr->length)
X			printf("  %3ld%%", 100L - (100L * hdr->size) / hdr->length);
X		else
X			printf("  ---");
X		printf("  %8ld  ", hdr->size);
X	}
X	printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100);
X
X	if (bose)
X		printf("  %2d:%02d%c  %04x",
X		       (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'),
X		       hdr->crc & 0xffff);
X
X	printf("\n");
X}
________This_Is_The_END________
if test `wc -c < arclst.c` -ne     4418; then
	echo 'shar: arclst.c was damaged during transit (should have been     4418 bytes)'
fi
fi		; : end of overwriting check
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.