From:	CSBVAX::MRGATE!RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP  2-SEP-1988 12:14
To:	ARISIA::EVERHART
Subj:	ARC mods 3/7


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu,  1 SEP 88 06:28:33 PDT
Received: from CUNYVM.CUNY.EDU by KL.SRI.COM with TCP; Thu, 1 Sep 88 06:05:57 PDT
Received: from UKACRL.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 7796; Thu, 01 Sep 88 09:02:29 EDT
Received: from RL.IB by UKACRL.BITNET (Mailer X1.25) with BSMTP id 3358; Thu,
 01 Sep 88 14:00:22 BST
Received: from RL.IB by UK.AC.RL.IB (Mailer X1.25) with BSMTP id 3348; Thu, 01
          Sep 88 14:00:19 BS
Via:      UK.AC.KCL.CC.OAK;  1 SEP 88 14:00:03 BST
Date:     1-SEP-1988 14:00:46 GMT
From:     UDAA055%OAK.CC.KCL.AC.UK@CUNYVM.CUNY.EDU
To:       info-vax@KL.SRI.COM
Subject:  ARC mods 3/7
Sender:   Andy Harper, Kings College London <A.Harper%OAK.CC.KCL.AC.UK@CUNYVM.CUNY.EDU>

+-+-+-+ Beginning of part 3 +-+-+-+
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 added */
X         $    if(unlink(path[n]) && warn)
X              $    printf("Cannot unsave %s\n",path[n]);
X                   nerrs++;
X              
X         
X    
X
X    return nfiles;                     /* say how many were added */
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 c;                             /* one char of file */
X INT upd = 0;                       /* true if replacing an entry */
X
X    if(!(f=fopen(path,"r")))
X    $    if(warn)
X         $    printf("Cannot read file: %s\n",path);
X              nerrs++;
X         
X         return;
X    
X
X    /* Truncate filenames longer than FNLEN, else the following 'strcpy'
X     * will overflow the spae available in the destination.    AH  1/sep/88
X     */
X
X    if (strlen(name) >= FNLEN)
X         $ int i;
X           for (i=0; i>=FNLEN; i++)
X               nhdr.name[i] = name[i];
X         
X    else
X
X    /* End of kludgy fix to the problem!!! */
X
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    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    $    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 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
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         $    if(note)
X                 $ printf("Updating file: %-12s  ",name); fflush(stdout);
X              fseek(arc,ohdr.size,1);
X         
X         else if(fresh)                /* else if freshening */
X         $    fseek(arc,starts,0);     /* then do not add files */
X              fclose(f);
X              return;
X         
X         else                          /* else adding a new file */
X         $    if(note)
X                 $ printf("Adding file:   %-12s  ",name); fflush(stdout);
X              fseek(arc,starts,0);     /* reset for next time */
X         
X    
X
X    else                               /* no existing archive */
X    $    if(fresh)                     /* cannot freshen nothing */
X         $    fclose(f);
X              return;
X         
X         else if(note)                 /* else adding a file */
X            $ printf("Adding file:   %-12s  ",name); fflush(stdout);
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
X
$ GOSUB UNPACK_FILE
$ FILE_IS = "ARCDOS.C"
$ CHECKSUM_IS = 1802292698
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcdos.c,v 1.2 86/07/15 07:53:02 turner Exp $";
X
X/*
X * $Log:`009arcdos.c,v $
X * VAXC modifications       31-AUG-1988`009`009Andy Harper, KCL
X * Separated VAXC and BSD dependencies
X *
X * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
X * `009Bludgeoned into submission for VAX 11/780 BSD4.2
X *`009(ugly code, but fewer core dumps)
X *
X * Revision 1.2  86/07/15  07:53:02  turner
X *
X *
X * Revision 1.1  86/06/26  15:00:15  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCDOS
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =1.43), created on $tag(
XTED_DATE DB =11/09/85) at $tag(
XTED_TIME DB =22:24:44))#
X$undefine(tag)#
X    $version
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:  Thom Henderson
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    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if MSDOS
X#include "fileio2.h"                   /* needed for filehand */
X#endif
X#if BSD
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#ifdef VAXC
X#include <types.h>
X#include <stat.h>
X#endif
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#if MSDOS
X    struct $INT ax,bx,cx,dx,si,di,ds,es; 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 VAXC | BSD
X    struct stat *buf;
X    int day,hr,min,sec,yr,imon;
X    static char mon[4],*mons[12] = $"Jan","Feb","Mar","Apr","May","Jun","Jul",
X`009`009`009`009`009"Aug","Sep","Oct","Nov","Dec";
X
X    buf = (struct stat *)malloc(sizeof(struct stat));
X/*    fstat(f->_file,buf);  */
X    fstat(fileno(f),buf);
X/*
X * assume the UGLY ibm format for date and time
X */
X    sscanf(ctime(&(buf->st_mtime)),"%*4s%3s%d%d:%d:%d%d"
X`009,mon,&day,&hr,&min,&sec,&yr);
X    for(imon = 0; imon < 12 && strcmp(mon,mons[imon]); imon++);
X
X    *date = (unsigned INT)(((yr-1980)<<9)+((imon+1)<<5)+day);
X    *time = (unsigned INT)((hr<<11)+(min<<5)+sec/2);
X#endif
X
X
XINT setstamp(f,date,time)                  /* set a file's date/time stamp */
XFILE *f;                               /* file to set stamp on */
Xunsigned INT date, time;               /* desired date, time */
X$
X#if MSDOS
X    struct $INT ax,bx,cx,dx,si,di,ds,es; reg;
X
X    fflush(f);                         /* force any pending output */
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#endif
X
X
Xstatic INT filehand(stream)            /* find handle on a file */
Xstruct bufstr *stream;                 /* file to grab onto */
X$
X#if MSDOS
X    return stream->bufhand;            /* return DOS 2.0 file handle */
X#endif
X
X
XINT izadir(filename)`009`009`009/* Is filename a directory? */
Xchar *filename;
X$
X#if MSDOS
X    return 0;
X#else
Xstruct stat buf;
X
X    if (stat(filename,&buf)!=0) return 0;   /* Ignore if stat fails since we */
X    else return (buf.st_mode & S_IFDIR);    /* trap for bad file elsewhere.  */
X
X#endif
X
X
$ GOSUB UNPACK_FILE
$ FILE_IS = "ARCEXT.C"
$ CHECKSUM_IS = 561633054
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*
X * VAXC modifications       31-AUG-1988`009`009Andy Harper, KCL
X * Separated VAXC and BSD dependencies
X *
X/*
X
X
X/*
X$define(arc,$ifdef(xarc,off,on))#      macro switch for ARC only code
X$define(xarc,$ifdef(xarc,on,off))#     macro switch for XARC only code
X */
X/*  ARC - Archive utility - ARCEXT
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =2.18), created on $tag(
XTED_DATE DB =02/03/86) at $tag(
XTED_TIME DB =22:55:19))#
X$undefine(tag)#
X    $version
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:  Thom Henderson
X
X    Description:
X         This file contains the routines used to extract files from
X         an archive.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if ARC`009`009`009`009`009/* $emit($arc)# */
XINT extarc(num,arg,prt)                    /* extract files from archive */
XINT num;                               /* number of arguments */
Xchar *arg[];                           /* pointers to arguments */
XINT prt;                               /* true if printing */
X#endif`009`009`009`009`009/* $emit($xarc)# */
X#if XARC
XINT extarc()                               /* extract files from archive */
X#endif`009`009`009`009`009/* $emit(on)# */
X$
X    struct heads hdr;                  /* file header */
X#if ARC`009`009`009`009`009/* $emit($arc)# */
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, allocator */
X INT n;                             /* index */
X    INT extfile();
X
X#if MSDOS
X    name = malloc(num*sizeof(char *));  /* get storage for name pointers */
X#endif
X#if VAXC | BSD
V    name = (char **)malloc(num*sizeof(char *));  /* get storage for name pointe
Xrs */
X#endif
X
X    for(n=0; n<num; n++)               /* for each argument */
X    $    did[n] = 0;                   /* reset usage flag */
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         name[n] = i+1;
X    
X
X#endif`009`009`009`009`009/* $emit(on)# */
X
X    openarc(0);                        /* open archive for reading */
X
X#if ARC`009`009`009`009`009/* $emit($arc)# */
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 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 fseek(arc,hdr.size,1);
X         
X    
X
X    else while(readhdr(&hdr,arc))      /* else extract all files */
X         extfile(&hdr,"",prt);
X#endif`009`009`009`009`009/* $emit($xarc)# */
X#if XARC
X    while(readhdr(&hdr,arc))           /* extract all files */
X         extfile(&hdr);
X#endif`009`009`009`009`009/* $emit(on)# */
X
X    closearc(0);                       /* close archive after reading */
X#if ARC`009`009`009`009`009/* $emit($arc)# */
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    free(name);
X#endif`009`009`009`009`009/* $emit(on)# */
X
X
X#if ARC`009`009`009`009`009/* $emit($arc)# */
Xstatic INT extfile(hdr,path,prt)           /* extract a file */
Xstruct heads *hdr;                     /* pointer to header data */
Xchar *path;                            /* pointer to path name */
XINT prt;                               /* true if printing */
X#endif`009`009`009`009`009/* $emit($xarc)# */
X#if XARC
Xstatic INT extfile(hdr)                    /* extract a file */
X#endif`009`009`009`009`009/* $emit(on)# */
X`009`009`009/* $define(use,$ife($arc,on,fix,hdr->name))# */
X#if ARC
X#define USE fix
X#else
X#define USE hdr->name
X#endif
X
X$
X    FILE *f, *fopen();                 /* extracted file, opener */
X    char buf[STRLEN];                 /* input buffer */
X#if ARC`009`009`009`009`009/* $emit($arc)# */
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
X    strcpy(fix,path);                  /* note path name template */
X    if(!(i=rindex(fix,'\\')))          /* find start of name */
X         if(!(i=rindex(fix,'/')))
X              if(!(i=rindex(fix,':')))
X                   i = fix-1;
X    strcpy(i+1,hdr->name);             /* replace template with name */
X#endif`009`009`009`009`009/* $emit(on)# */
X
X    if(note)
X         printf("Extracting file: %s\n",USE);
X
X    if(warn)
X    $    if(f=fopen(USE,"r"))        /* see if it exists */
X         $    fclose(f);
X              printf("WARNING: File %s already exists!",USE);
X              while(1)
X              $    printf("  Overwrite it (y/n)? ");
X                   fgets(buf,STRLEN,stdin);
X                   *buf = toupper(*buf);
-+-+-+-+-+ End of part 3 +-+-+-+-+-

