From:	CSBVAX::MRGATE!info-vax-RELAY@KL.SRI.COM@SMTP  8-JUL-1988 23:19
To:	ARISIA::EVERHART
Subj:	ARC_C.SHAR05_OF_19


Received: from CORNELLC.CCS.CORNELL.EDU by KL.SRI.COM with TCP; Fri, 24 Jun 88 18:21:21 PDT
Received: from UNCAEDU.BITnet by CORNELLC.CCS.CORNELL.EDU ; Fri, 24 Jun 88 21:21:03 EDT
Received: from Stasis.MRC.AdhocNet.CA by UcEdu.UNCA.AdhocNet.CA with DECNET ;
          Fri, 24 Jun 88 09:30:18 MDT
Date:    Fri, 24 Jun 88 09:24:05 MDT
From:     ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU
         BITnet (Ed Wilts)
Message-Id: <880624092407.025@Ins.MRC.AdhocNet.CA>
Subject: ARC_C.SHAR05_OF_19
To:       info-vax@kl.sri.com
X-ST-Vmsmail-To: INFOVAX

$Part05:
$ File_is="ARCEXT.C"
$ Check_Sum_is=890573280
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
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 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);
X                   if(*buf=='Y' || *buf=='N')
X                        break;
X              }
X              if(*buf=='N')
X              {    printf("%s not extracted.\n",USE);
X                   fseek(arc,hdr->size,1);
X                   return;
X              }
X         }
X    }
X
X    if(!(f=fopen(USE,"w")))
X    {    if(warn)
X         {    printf("Cannot create %s\n",USE);
X              nerrs++;
X         }
X         fseek(arc,hdr->size,1);
X         return;
X    }
X
X    /* now unpack the file */
X
X    unpack(arc,f,hdr);                 /* unpack file from archive */
X    setstamp(f,hdr->date,hdr->time);   /* set the proper date/time stamp */
X    fclose(f);                         /* all done writing to file */
X}
X
$ GoSub Convert_File
$ File_is="ARCIO.C"
$ Check_Sum_is=322898887
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcio.c,v 1.2 86/07/15 07:53:11 turner Exp $";
X
X/*
X * $Log:`009arcio.c,v $
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:11  turner
X *
X *
X * Revision 1.1  86/06/26  15:00:21  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCIO
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =2.30), created on $tag(
XTED_DATE DB =02/03/86) at $tag(
XTED_TIME DB =22:56:00))#
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 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
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#if BSD | ST
X        unsigned char dummy[28];
X`009INT i,j,k;
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.\n",arcname);
X              nerrs++;
X         }
X
X         while(!feof(f))
X         {    try++;
X              if(fgetc(f)==ARCMARK)
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    {    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         exit(1);
X    }
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),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#if MSDOS
X`009fread(hdr,sizeof(struct heads),1,f);
X#endif
X#if BSD | ST
X`009fread(dummy,27,1,f);
X
X`009for(i=0;i<13;hdr->name[i]=dummy[i],i++);
X`009hdr->size = (long)((dummy[16]<<24) + (dummy[15]<<16) + (dummy[14]<<8)
X`009    + dummy[13]);
X`009hdr->date = (short)((dummy[18]<<8) + dummy[17]);
X`009hdr->time = (short)((dummy[20]<<8) + dummy[19]);
X`009hdr->crc  = (short)((dummy[22]<<8) + dummy[21]);
X`009hdr->length = (long)((dummy[26]<<24) + (dummy[25]<<16)
X`009    + (dummy[24]<<8) + dummy[23]);
X#endif
X    }
X
X    first = 0; 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    unsigned char dummy[28];
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#endif
X#if BSD | ST
X/*
X * put out the hdr in the brain damaged unaligned half back *sswards
X * way HAL does it
X */
X    fwrite(hdr->name,1,13,f);
X    fwrite(&hdr->size,sizeof(long),1,f);
X    fwrite(&hdr->date,sizeof(INT),1,f);
X    fwrite(&hdr->time,sizeof(INT),1,f);
X    fwrite(&hdr->crc ,sizeof(INT),1,f);
X    fwrite(&hdr->length,sizeof(long),1,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
XINT filecopy(f,t,size)                     /* bulk file copier */
XFILE *f, *t;                           /* from, to */
Xlong size;                             /* number of bytes */
X{
X INT len;                           /* length of a given copy */
X INT putc_tst();
X
X    while(size--)                      /* while more bytes to move */
X         putc_tst(fgetc(f),t);
X}
X
XINT putc_tst(c,t)                          /* put a character, with tests */
Xchar c;                                /* character to output */
XFILE *t;                               /* file to write to */
X{
X    if(t)
X#if MSDOS | ST
X         if(fputc(c,t)==EOF)
X              abort("Write fail (disk full?)");
X#endif
X#if BSD
X/*
X * for reasons beyond me BSD unix returns EOF
X */
X`009fputc(c,t);
X#endif
X}
X
$ GoSub Convert_File
$ Goto Part06
