[comp.binaries.ibm.pc] ARC for SYS V: PArt 4 of 5

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

Article 26 of comp.sources.misc:
Path: brl-smoke!brl-adm!umd5!mimsy!seismo!husc6!rutgers!clyde!cbatt!cwruecmp!hal!ncoast!allbery
From: allbery@ncoast.UUCP (Brandon S. Allbery)
Newsgroups: comp.sources.misc
Subject: System V ARC bug fixes (1 of 2)
Message-ID: <264@cpsc6b.cpsc6a.ATT.COM>
Date: 16 May 87 06:04:30 GMT
Distribution: usa
Organization: AT&T (CPSC), Oakland, CA
Lines: 913
Keywords: arc
Approved: allbery@ncoast.UUCP


[ Line eater, here line eater, nice linMUNCH MUNCH.... ]

This archive contains repostings of eight files, which have
been altered due to bug fixes, and are full replacements for the previously
posted files of the same names.  Sorry about the reposting, but I haven't
gotten around to getting patch yet.

BSD users should be able to compile by adding "-DBSD" to their makefile.

If anyone has any trouble with any of the files, let me know.  If I am
still overlooking something on BSD (except differnces in file name length)
send me some mail and I'll try to fix it.

I have had a large number of requests from XENIX users for a clean port,
but since I don't have access to a XENIX system, I have been of no help.
I have responded to a couple of people who have been successful, but don't
have any diffs as yet.  As soon as I get something, I'll post it.

Keep those cards and letters coming.
Chris Seaman
..!ihnp4!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:
#	arc.c
#	arc.h
#	arcadd.c
#	arcdos.c
#	arcio.c
# This archive created: Fri May 15 22:56:53 1987
# By:	C. R. Seaman ()
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'arc.c'" '(8172 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.2
	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.	5/15/87
	X *
	X */
	X
	X#ifndef	lint
	Xstatic char	sccsid[] = "@(#)arc.c	1.2";
	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 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.2, 5/15/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 8172 -ne "`wc -c < 'arc.c'`"
then
	echo shar: "error transmitting 'arc.c'" '(should have been 8172 characters)'
fi
fi
echo shar: "extracting 'arc.h'" '(2371 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.2
	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.	5/15/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 * redefine string functions if BSD
	X */
	X#ifdef BSD
	X#define strchr index            /* index function */
	X#define strrchr rindex          /* reverse index function */
	X#endif /* BSD */
	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 2371 -ne "`wc -c < 'arc.h'`"
then
	echo shar: "error transmitting 'arc.h'" '(should have been 2371 characters)'
fi
fi
echo shar: "extracting 'arcadd.c'" '(7023 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.2
	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.	5/15/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    register int i;
	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    /* zero out name array - necessary because of strncpy */
	X    for (i = 0; i < FNLEN1; i++) nhdr.name[i] = '\0';
	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 7023 -ne "`wc -c < 'arcadd.c'`"
then
	echo shar: "error transmitting 'arcadd.c'" '(should have been 7023 characters)'
fi
fi
echo shar: "extracting 'arcdos.c'" '(4172 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.2
	X *
	X *	Author: Thom Henderson
	X *	Original System V port: Mike Stump
	X *	Enhancements, Bug fixes, and cleanup: Chris Seaman
	X *	BSD specific code provided by: Jeff Chiu
	X *	Date: Fri Mar 20 09:57:02 1987
	X *	Last Mod.	5/15/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#ifdef BSD
	X    struct timeval tv;
	X    struct timezone tz;
	X
	X    gettimeofday(&tv, &tz);
	X
	X    if (tz.tz_dsttime != 0)
	X        m_time -= 3600;
	X
	X    m_time += tz.tz_minuteswest * 60;  /* account for timezone differences */
	X#else
	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#endif
	X
	X    times.actime = m_time;             /* set the stamp on the file */
	X    times.modtime = m_time;
	X    utime(file,&times);
	X}
SHAR_EOF
if test 4172 -ne "`wc -c < 'arcdos.c'`"
then
	echo shar: "error transmitting 'arcdos.c'" '(should have been 4172 characters)'
fi
fi
echo shar: "extracting 'arcio.c'" '(5577 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.2
	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.	5/15/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    {
	X        fputc(c,t);
	X        if (ferror(t))
	X        {
	X            perror("system error:");
	X            abort("Write failed");
	X        }
	X    }
	X}
SHAR_EOF
if test 5577 -ne "`wc -c < 'arcio.c'`"
then
	echo shar: "error transmitting 'arcio.c'" '(should have been 5577 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
Brandon S. Allbery	{decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries	{ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd.	necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060	+01 216 255 1080	(also eddie.MIT.EDU)