From:	CSBVAX::MRGATE!info-vax-RELAY@KL.SRI.COM@SMTP  9-JUL-1988 17:23
To:	ARISIA::EVERHART
Subj:	ARC_C.SHAR02_OF_19


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

$Part02:
$ File_is="ARCADD.C"
$ Check_Sum_is=775976552
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcadd.c,v 1.2 86/07/15 07:52:37 turner Exp $";
X
X/*
X * $Log:`009arcadd.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:52:37  turner
X *
X *
X * Revision 1.1  86/06/26  14:59:37  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCADD
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =3.39), created on $tag(
XTED_DATE DB =02/05/86) at $tag(
XTED_TIME DB =22:21:53))#
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 add files to an archive.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#ifdef VAXC
X#include "dir.h"
X#endif VAXC
X
XINT addarc(num,arg,move,update,fresh)      /* add files to archive */
XINT num;                               /* number of arguments */
Xchar *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 *NameList;`009/* Any pointer.  Used to pass file names around */
X    char buf[STRLEN];                 /* pathname buffer */
X    char **path = NULL;                /* pointer to pointers to paths */
X    char **name = NULL;                /* 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 m, n;                          /* indices */
X    unsigned INT coreleft();           /* remaining memory reporter */
X    INT addbunch();
X
X    if(num<1)                          /* if no files named */
X    {    num = 1;                      /* then fake one */
X         arg[0] = "*.*";               /* add everything */
X`009 printf("%%ARC-I-NOSPEC, File not specfied.  Defaulting to *.*\n");
X    }
X
X    for(n=0; n<num; n++)               /* for each template supplied */
X    {
X#ifdef VAXC
X/* We do not plan on using this... Take a look at the code where we talk
X * about the VMS file spec for more info... (down a page or so)
X */
X         strcpy(buf,arg[n]);           /* get ready to fix path */
X`009 (void) parsedir(buf, 0, PARSE_NODE|PARSE_DEVICE|PARSE_DIRECTORY);
X`009 i = buf + strlen(buf);`009`009/* Point to null byte */
X#else
X         strcpy(buf,arg[n]);           /* get ready to fix path */
X         if(!(i=rindex(buf,'\\')))
X              if(!(i=rindex(buf,'/')))
X                   if(!(i=rindex(buf,':')))
X                        i = buf-1;
X         i++;                          /* pointer to where name goes */
X#endif VAXC
X         notemp = 1;                   /* reset files flag */
X         NameList = (char *) malloc(sizeof(char *));
X         for(d=dir(arg[n],0,NameList); d; d=dir(NULL,0,NameList))
X         {    notemp = 0;              /* template is giving results */
X              nfiles++;                /* add each matching file */
X#ifdef VAXC
X/* For VMS */
X`009      if (!path)
X`009      {
X`009`009path = (char **)malloc(sizeof(char **));
X`009`009name = (char **)malloc(sizeof(char **));
X`009      }
X#endif VAXC
X              path = (char **)realloc(path,nfiles*sizeof(char **));
X              name = (char **)realloc(name,nfiles*sizeof(char **));
X#ifdef VAXC
X/*
X * For VMS, we are passing the whole filespec back from the directory
X * routines.  We do this as a person might specify [...]*.h which we
X * would need to have the directory of the filespec to do the open!
X * (node::device:[directory]filename.extension;version)
X */
X              strcpy(i,d);             /* put name in path */
X              path[nfiles-1] = malloc(strlen(buf)+1);
X              strcpy(path[nfiles-1],buf);
X/*
X * name[] is pointing at the WHOLE filespec, not the file name.
X * file parsing will have to be done later on to get the filename
X * and extension that are needed.
X */
X
X`009      (void) parsedir(d, 0, PARSE_NAME|PARSE_TYPE);
X`009      name[nfiles-1] = d;
X#else
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#endif VAXC
X
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); 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); free(name);
X    }
X
X    if(nowork && warn)
X         printf("No files were added.\n");
X}
X
XINT addbunch(nfiles,path,name,move,update,fresh) /* add a bunch of files */
XINT nfiles;                            /* number of files to add */
Xchar **path;                           /* pointers to pathnames */
Xchar **name;                           /* pointers to filenames */
XINT move;                              /* true if moving file */
XINT update;                            /* true if updating */
XINT fresh;                             /* true if freshening */
X{
X    char buf[STRLEN];                 /* pathname buffer */
X INT m, n;                          /* indices */
X    char *d;                           /* swap pointer */
X    struct heads hdr;                  /* file header data storage */
X    INT addfile();
X    INT izadir();`009`009   /* used to weed-out directories */
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         || izadir(path[n])            /* or directory */
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         }
X         else 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    || izadir(path[n])
X    || !strcmp(path[n],bakname))
X    {    free(path[n]);
X         free(name[n]);
X         nfiles--;
X    }
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 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 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    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 Convert_File
$ File_is="ARCCODE.C"
$ Check_Sum_is=1750696541
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arccode.c,v 1.1 86/06/26 14:59:53 turner Exp $";
X
X/*
X * $Log:`009arccode.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.1  86/06/26  14:59:53  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCCODE
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =1.02), created on $tag(
XTED_DATE DB =01/20/86) at $tag(
XTED_TIME DB =13:33:35))#
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 encrypt and decrypt
X         data in an archive.  The encryption method is nothing fancy,
X         being just a routine XOR, but it is used on the packed data,
X         and uses a variable length key.  The end result is something
X         that is in theory crackable, but I'd hate to try it.  It should
X         be more than sufficient for casual use.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xstatic char *p;                        /* password pointer */
X
XINT setcode()                              /* get set for encoding/decoding */
X{
X    p = password;                      /* reset password pointer */
X}
X
XINT code(c)                            /* encode some character */
XINT c;                                 /* character to encode */
X{
X    if(p)                              /* if password is in use */
X    {    if(!*p)                       /* if we reached the end */
X              p = password;            /* then wrap back to the start */
X         return c^*p++;                /* very simple here */
X    }
X    else return c;                     /* else no encryption */
X}
X
$ GoSub Convert_File
$ Goto Part03
