Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!hoptoad!mejac!decwrl!labrea!husc6!ddl
From: ddl@husc6.UUCP
Newsgroups: alt.sources
Subject: arc repost (sort of) 1/4
Message-ID: <2591@husc6.UUCP>
Date: Thu, 23-Jul-87 23:51:39 EDT
Article-I.D.: husc6.2591
Posted: Thu Jul 23 23:51:39 1987
Date-Received: Sat, 25-Jul-87 12:03:30 EDT
Organization: Harvard University Computer Services
Lines: 1497
Keywords: arc UnSquash
Since my first posting was apparently truncated in many places,
here is a "re"post cut into smaller pieces. This time, each is a separate
shar archive for more intuitive unpacking. Now, this isn't really a
repost since there are some changes. Various popular bug fixes were
applied, the non-repeat unpacking for squashed archives was removed as
it was indicated that this was wrong, and a 'q' flag to force squashing
instead of crunching was added. Now the bad news. Squashing big files
or more than one file per 'a' operation causes problems. Something is
probably being overwritten on the stack and I don't know when I will
be able to work on it much more. It is undoubtedly a stupid error on
my part and I hope someone will fix it. In any case, the important thing
remains the ability to unpack squashed archives.
Dan Lanciani
ddl@harvard.*
#! /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 the files:
# Makefile
# arc.c
# arc.h
# arcadd.c
# arccode.c
# arccvt.c
# arcdel.c
# arcdir.c
# This archive created: Thu Jul 23 23:39:48 1987
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# Makefile for Hack-attack 1.3
# VAX 11/780 BSD4.2 "ARC" utility
#
CFLAGS = -O
OBJS = arc.o arcadd.o arccode.o arccvt.o arcdel.o arcdir.o \
arcdos.o arcext.o arcio.o arclst.o arclzw.o arcmatch.o arcpack.o arcrun.o \
arcsq.o arcsvc.o arctst.o arcunp.o arcusq.o arcvax.o arcmisc.o squash.o
SRCS = arc.c arcadd.c arccode.c arccvt.c arcdel.c arcdir.c \
arcdos.c arcext.c arcio.c arclst.c arclzw.c arcmatch.c arcpack.c arcrun.c \
arcs.c arcsq.c arcsvc.c arctst.c arcunp.c arcusq.c arcvax.c arcmisc.c squash.c
arc: ${OBJS}
cc -O -o arc ${OBJS}
arc.o: arc.h
cc -O -c arc.c
arcadd.o: arc.h
cc -O -c arcadd.c
arccode.o: arc.h
cc -O -c arccode.c
arccvt.o: arc.h
cc -O -c arccvt.c
arcdel.o: arc.h
cc -O -c arcdel.c
arcdir.o: arc.h
cc -O -c arcdir.c
arcdos.o: arc.h
cc -O -c arcdos.c
arcext.o: arc.h
cc -O -c arcext.c
arcio.o: arc.h
cc -O -c arcio.c
arclst.o: arc.h
cc -O -c arclst.c
arclzw.o: arc.h
cc -O -c arclzw.c
arcmatch.o: arc.h
cc -O -c arcmatch.c
arcmisc.o: arc.h
cc -O -c arcmisc.c
arcpack.o: arc.h
cc -O -c arcpack.c
arcrun.o: arc.h
cc -O -c arcrun.c
arcs.o: arcm.h
cc -O -c arcs.c
arcsq.o: arc.h
cc -O -c arcsq.c
arcsvc.o: arc.h
cc -O -c arcsvc.c
arctst.o: arc.h
cc -O -c arctst.c
arcunp.o: arc.h
cc -O -c arcunp.c
arcusq.o: arc.h
cc -O -c arcusq.c
arcvax.o: arc.h
cc -O -c arcvax.c
squash.o: arc.h
cc -O -c squash.c
arc.h: arcm.h arcs.h
touch arc.h
SHAR_EOF
chmod +x 'Makefile'
fi # end of overwriting check
if test -f 'arc.c'
then
echo shar: will not over-write existing file "'arc.c'"
else
cat << \SHAR_EOF > 'arc.c'
static char *RCSid = "$Header: arc.c,v 1.2 86/07/15 07:52:04 turner Exp $";
/*
* $Log: arc.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:04 turner
* first working version for the vax
*
* Revision 1.1 86/06/26 14:59:15 turner
* initial version
*
*
*/
/* ARC - Archive utility
$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =5.12), created on $tag(
TED_DATE DB =02/05/86) at $tag(
TED_TIME DB =22:22:01))#
$undefine(tag)#
$version
(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This program is a general archive utility, and is used to maintain
an archive of files. An "archive" is a single file that combines
many files, reducing storage space and allowing multiple files to
be handled as one.
Instructions:
Run this program with no arguments for complete instructions.
Programming notes:
ARC Version 2 differs from version 1 in that archive entries
are automatically compressed when they are added to the archive,
making a separate compression step unecessary. The nature of the
compression is indicated by the header version number placed in
each archive entry, as follows:
1 = Old style, no compression
2 = New style, no compression
3 = Compression of repeated characters only
4 = Compression of repeated characters plus Huffman SQueezing
5 = Lempel-Zev packing of repeated strings (old style)
6 = Lempel-Zev packing of repeated strings (new style)
7 = Lempel-Zev Williams packing with improved has function
8 = Dynamic Lempel-Zev packing with adaptive reset
9 = Squashing
Type 5, Lempel-Zev packing, was added as of version 4.0
Type 6 is Lempel-Zev packing where runs of repeated characters
have been collapsed, and was added as of version 4.1
Type 7 is a variation of Lempel-Zev using a different hash
function which yields speed improvements of 20-25%, and was
added as of version 4.6
Type 8 is a different implementation of Lempel-Zev, using a
variable code size and an adaptive block reset, and was added
as of version 5.0
Verion 4.3 introduced a temporary file for holding the result
of the first crunch pass, thus speeding up crunching.
Version 4.4 introduced the ARCTEMP environment string, so that
the temporary crunch file may be placed on a ramdisk. Also
added was the distinction bewteen Adding a file in all cases,
and Updating a file only if the disk file is newer than the
corresponding archive entry.
The compression method to use is determined when the file is
added, based on whichever method yields the smallest result.
Language:
Computer Innovations Optimizing C86
*/
#include
#include "arc.h"
main(num,arg) /* system entry point */
INT num; /* number of arguments */
char *arg[]; /* pointers to arguments */
{
char opt = 0; /* selected action */
char *a; /* option pointer */
char *makefnam(); /* filename fixup routine */
char *upper(); /* case conversion routine */
char *index(); /* string index utility */
char *envfind(); /* environment searcher */
INT n; /* argument index */
char *arctemp2;
long getpid();
warn = 1;
note = 1;
if(num<3)
{ /* printf("ARC - Archive utility, $version\n");
printf("(C) COPYRIGHT 1985,86 by System Enhancement Associates;");
printf(" ALL RIGHTS RESERVED\n\n");
printf("Please refer all inquiries to:\n\n");
printf(" System Enhancement Associates\n");
printf(" 21 New Street, Wayne NJ 07470\n\n");
printf("You may copy and distribute this program freely,");
printf(" provided that:\n");
printf(" 1) No fee is charged for such copying and");
printf(" distribution, and\n");
printf(" 2) It is distributed ONLY in its original,");
printf(" unmodified state.\n\n");
printf("If you like this program, and find it of use, then your");
printf(" contribution will\n");
printf("be appreciated. You may not use this product in a");
printf(" commercial environment\n");
printf("or a governmental organization without paying a license");
printf(" fee of $35. Site\n");
printf("licenses and commercial distribution licenses are");
printf(" available. A program\n");
printf("disk and printed documentation are available for $50.\n");
printf("\nIf you fail to abide by the terms of this license, ");
printf(" then your conscience\n");
printf("will haunt you for the rest of your life.\n\n"); */
printf("Usage: ARC {amufdxerplvtc}[bswn][g]");
printf(" [ . . .]\n");
printf("Where: a = add files to archive\n");
printf(" m = move files to archive\n");
printf(" u = update files in archive\n");
printf(" f = freshen files in archive\n");
printf(" d = delete files from archive\n");
printf(" x,e = extract files from archive\n");
printf(" r = run files from archive\n");
printf(" p = copy files from archive to");
printf(" standard output\n");
printf(" l = list files in archive\n");
printf(" v = verbose listing of files in archive\n");
printf(" t = test archive integrity\n");
printf(" c = convert entry to new packing method\n");
printf(" b = retain backup copy of archive\n");
printf(" s = suppress compression (store only)\n");
printf(" w = suppress warning messages\n");
printf(" n = suppress notes and comments\n");
printf(" g = Encrypt/decrypt archive entry\n");
printf(" q = squash instead of crunching\n\n");
/* printf("\nPlease refer to the program documentation for"); */
/* printf(" complete instructions.\n"); */
return 1;
}
/* see where temp files go */
/* use process id to "enhance uniquity" of temp filenames */
/* (avoids multi-user or background foolishness) */
if(!(arctemp2 = envfind("ARCTEMP")))
arctemp2 = envfind("TEMP");
if (arctemp2) sprintf(arctemp,"%s.Arc%ld",arctemp2,getpid());
else sprintf(arctemp,".Arc%ld",getpid());
#if MSDOS
/* avoid any case problems with arguments */
for(n=1; n 'arc.h'
/*
* $Header: arc.h,v 1.2 86/07/15 07:52:34 turner Exp $
*/
/*
* $Log: arc.h,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:34 turner
*
*
* Revision 1.1 86/06/26 15:01:23 turner
* initial version
*
*
*/
#define ST 0 /* Atari 520ST or 1040 */
#define BSD 1 /* BSD4.2 on a vax */
#define MSDOS 0 /* MSDOS on an IBM PC or Wannabe */
#if ST
#define EXTERN
#define INT short
#endif
#if BSD
#include /* for isupper etc. */
#define EXTERN
#define INT short
#define envfind getenv
#endif
#if MSDOS
#define EXTERN extern
#define INT int
#endif
/*
* added macro def's in C format 6/26/86 jmt
*/
#include "arcm.h"
/* ARC - Archive utility - ARC Header
Version 2.14, created on 02/03/86 at 22:48:29
(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This is the header file for the ARC archive utility. It defines
global parameters and the references to the external data.
Language:
Computer Innovations Optimizing C86
*/
#include "arcs.h"
EXTERN INT keepbak; /* true if saving the old archive */
EXTERN INT warn; /* true to print warnings */
EXTERN INT note; /* true to print comments */
EXTERN INT bose; /* true to be verbose */
EXTERN INT nocomp; /* true to suppress compression */
EXTERN INT kludge; /* kludge flag */
EXTERN char arctemp[STRLEN]; /* arc temp file prefix */
EXTERN char *password; /* encryption password pointer */
EXTERN INT nerrs; /* number of errors encountered */
EXTERN char hdrver; /* header version */
EXTERN FILE *arc; /* the old archive */
EXTERN FILE *new; /* the new archive */
EXTERN char arcname[STRLEN]; /* storage for archive name */
EXTERN char bakname[STRLEN]; /* storage for backup copy name */
EXTERN char newname[STRLEN]; /* storage for new archive name */
EXTERN unsigned INT arcdate; /* archive date stamp */
EXTERN unsigned INT arctime; /* archive time stamp */
EXTERN int dosquash;
SHAR_EOF
chmod +x 'arc.h'
fi # end of overwriting check
if test -f 'arcadd.c'
then
echo shar: will not over-write existing file "'arcadd.c'"
else
cat << \SHAR_EOF > 'arcadd.c'
static char *RCSid = "$Header: arcadd.c,v 1.2 86/07/15 07:52:37 turner Exp $";
/*
* $Log: arcadd.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:37 turner
*
*
* Revision 1.1 86/06/26 14:59:37 turner
* initial version
*
*
*/
/* ARC - Archive utility - ARCADD
$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =3.39), created on $tag(
TED_DATE DB =02/05/86) at $tag(
TED_TIME DB =22:21:53))#
$undefine(tag)#
$version
(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This file contains the routines used to add files to an archive.
Language:
Computer Innovations Optimizing C86
*/
#include
#include "arc.h"
INT addarc(num,arg,move,update,fresh) /* add files to archive */
INT num; /* number of arguments */
char *arg[]; /* pointers to arguments */
INT move; /* true if moving file */
INT update; /* true if updating */
INT fresh; /* true if freshening */
{
char *d, *dir(); /* directory junk */
char *NameList; /* Any pointer. Used to pass file names around */
char buf[STRLEN]; /* pathname buffer */
char **path = NULL; /* pointer to pointers to paths */
char **name = NULL; /* pointer to pointers to names */
INT nfiles = 0; /* number of files in lists */
INT notemp; /* true until a template works */
INT nowork = 1; /* true until files are added */
char *i, *rindex(); /* string indexing junk */
char *malloc(), *realloc(); /* memory allocators */
INT m, n; /* indices */
unsigned INT coreleft(); /* remaining memory reporter */
INT addbunch();
if(num<1) /* if no files named */
{ num = 1; /* then fake one */
arg[0] = "*.*"; /* add everything */
}
for(n=0; n0)
{ d = path[n];
path[n] = path[m];
path[m] = d;
d = name[n];
name[n] = name[m];
name[m] = d;
}
}
}
for(n=0; n=0)
break; /* found our spot */
writehdr(&ohdr,new); /* entry preceeds update; keep it */
filecopy(arc,new,ohdr.size);
starts = ftell(arc); /* now where are we? */
}
if(upd) /* if an update */
{ if(note)
{ printf("Updating file: %-12s ",name); fflush(stdout);}
fseek(arc,ohdr.size,1);
}
else if(fresh) /* else if freshening */
{ fseek(arc,starts,0); /* then do not add files */
fclose(f);
return;
}
else /* else adding a new file */
{ if(note)
{ printf("Adding file: %-12s ",name); fflush(stdout);}
fseek(arc,starts,0); /* reset for next time */
}
}
else /* no existing archive */
{ if(fresh) /* cannot freshen nothing */
{ fclose(f);
return;
}
else if(note) /* else adding a file */
{ printf("Adding file: %-12s ",name); fflush(stdout);}
}
starts = ftell(new); /* note where header goes */
hdrver = ARCVER; /* anything but end marker */
writehdr(&nhdr,new); /* write out header skeleton */
pack(f,new,&nhdr); /* pack file into archive */
fseek(new,starts,0); /* move back to header skeleton */
writehdr(&nhdr,new); /* write out real header */
fseek(new,nhdr.size,1); /* skip over data to next header */
fclose(f); /* all done with the file */
}
SHAR_EOF
chmod +x 'arcadd.c'
fi # end of overwriting check
if test -f 'arccode.c'
then
echo shar: will not over-write existing file "'arccode.c'"
else
cat << \SHAR_EOF > 'arccode.c'
static char *RCSid = "$Header: arccode.c,v 1.1 86/06/26 14:59:53 turner Exp $";
/*
* $Log: arccode.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.1 86/06/26 14:59:53 turner
* initial version
*
*
*/
/* ARC - Archive utility - ARCCODE
$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =1.02), created on $tag(
TED_DATE DB =01/20/86) at $tag(
TED_TIME DB =13:33:35))#
$undefine(tag)#
$version
(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This file contains the routines used to encrypt and decrypt
data in an archive. The encryption method is nothing fancy,
being just a routine XOR, but it is used on the packed data,
and uses a variable length key. The end result is something
that is in theory crackable, but I'd hate to try it. It should
be more than sufficient for casual use.
Language:
Computer Innovations Optimizing C86
*/
#include
#include "arc.h"
static char *p; /* password pointer */
INT setcode() /* get set for encoding/decoding */
{
p = password; /* reset password pointer */
}
INT code(c) /* encode some character */
INT c; /* character to encode */
{
if(p) /* if password is in use */
{ if(!*p) /* if we reached the end */
p = password; /* then wrap back to the start */
return c^*p++; /* very simple here */
}
else return c; /* else no encryption */
}
SHAR_EOF
chmod +x 'arccode.c'
fi # end of overwriting check
if test -f 'arccvt.c'
then
echo shar: will not over-write existing file "'arccvt.c'"
else
cat << \SHAR_EOF > 'arccvt.c'
static char *RCSid = "$Header: arccvt.c,v 1.2 86/07/15 07:52:46 turner Exp $";
/*
* $Log: arccvt.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:46 turner
*
*
* Revision 1.1 86/06/26 14:59:56 turner
* initial version
*
*
*/
/* ARC - Archive utility - ARCCVT
$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =1.16), created on $tag(
TED_DATE DB =02/03/86) at $tag(
TED_TIME DB =22:53:02))#
$undefine(tag)#
$version
(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This file contains the routines used to convert archives to use
newer file storage methods.
Language:
Computer Innovations Optimizing C86
*/
#include
#include "arc.h"
static char tempname[STRLEN]; /* temp file name */
INT cvtarc(num,arg) /* convert archive */
INT num; /* number of arguments */
char *arg[]; /* pointers to arguments */
{
struct heads hdr; /* file header */
INT cvt; /* true to convert current file */
INT did[MAXARG]; /* true when argument was used */
INT n; /* index */
char *makefnam(); /* filename fixer */
FILE *fopen(); /* file opener */
INT cvtfile();
if(arctemp) /* use temp area if specified */
sprintf(tempname,"%s.CVT",arctemp);
else makefnam("$ARCTEMP.CVT",arcname,tempname);
openarc(1); /* open archive for changes */
for(n=0; nname); fflush(stdout);}
unpack(arc,tmp,hdr); /* unpack the entry */
fseek(tmp,0L,0); /* reset temp for reading */
starts = ftell(new); /* note where header goes */
hdrver = ARCVER; /* anything but end marker */
writehdr(hdr,new); /* write out header skeleton */
pack(tmp,new,hdr); /* pack file into archive */
fseek(new,starts,0); /* move back to header skeleton */
writehdr(hdr,new); /* write out real header */
fseek(new,hdr->size,1); /* skip over data to next header */
fclose(tmp); /* all done with the file */
if(unlink(tempname) && warn)
{ printf("Cannot unsave %s\n",tempname);
nerrs++;
}
}
SHAR_EOF
chmod +x 'arccvt.c'
fi # end of overwriting check
if test -f 'arcdel.c'
then
echo shar: will not over-write existing file "'arcdel.c'"
else
cat << \SHAR_EOF > 'arcdel.c'
static char *RCSid = "$Header: arcdel.c,v 1.2 86/07/15 07:52:53 turner Exp $";
/*
* $Log: arcdel.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:53 turner
*
*
* Revision 1.1 86/06/26 15:00:04 turner
* initial version
*
*
*/
/* ARC - Archive utility - ARCDEL
$define(tag,$$segment(@1,$$index(@1,=)+1))#
$define(version,Version $tag(
TED_VERSION DB =2.09), created on $tag(
TED_DATE DB =02/03/86) at $tag(
TED_TIME DB =22:53:27))#
$undefine(tag)#
$version
(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This file contains the routines used to delete entries
in an archive.
Language:
Computer Innovations Optimizing C86
*/
#include
#include "arc.h"
INT delarc(num,arg) /* remove files from archive */
INT num; /* number of arguments */
char *arg[]; /* pointers to arguments */
{
struct heads hdr; /* header data */
INT del; /* true to delete a file */
INT did[MAXARG]; /* true when argument used */
INT n; /* index */
if(!num) /* she must specify which */
abort("You must tell me which files to delete!");
for(n=0; n 'arcdir.c'
static char *RCSid = "$Header: arcdir.c,v 1.2 86/07/15 07:52:56 turner Exp $";
/*
* $Log: arcdir.c,v $
* Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
* Bludgeoned into submission for VAX 11/780 BSD4.2
* (ugly code, but fewer core dumps)
*
* Revision 1.2 86/07/15 07:52:56 turner
*
*
* Revision 1.1 86/06/26 15:00:12 turner
* initial version
*
*
*/
/* ARC - Archive utility - ARCDIR
*/
#include
#include "arc.h"
#if MSDOS
#include
#endif
#if BSD
#include
#include
#endif
char *pattern; /* global so that fmatch can use them */
INT filemode;
char *dir(filename,mode,NameList) /* get files, one by one */
char *filename; /* template, or NULL */
INT mode; /* search mode bits */
char *(*NameList[]);
{
struct direct *(*namelist[]);
#ifdef BSD
INT alphasort();
INT scandir();
#endif BSD
INT fmatch();
static INT Nnum = 0,ii;
char *result;
pattern = filename;
filemode = mode; /* set up globals for fmatch */
if(Nnum == 0) { /* first call */
Nnum = scandir(".", namelist, fmatch, alphasort);
*NameList = (char **)malloc(Nnum*sizeof(char *));
for (ii=0; iid_namlen+1);
strcpy((*NameList)[ii],(*namelist)[ii]->d_name);
}
ii = 0;
}
if(ii >= Nnum) { /* all out of files */
if(Nnum) { /* there were some files found */
freedir(namelist);
}
Nnum = 0;
return(NULL);
}
else {
return((*NameList)[ii++]);
}
}
#define ASTERISK '*' /* The '*' metacharacter */
#define QUESTION '?' /* The '?' metacharacter */
#define LEFT_BRACKET '[' /* The '[' metacharacter */
#define RIGHT_BRACKET ']' /* The ']' metacharacter */
#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
typedef INT BOOLEAN;
#define VOID short
#define TRUE 1
#define FALSE 0
#define EOS '\000'
static BOOLEAN do_list ();
static char nextch ();
static VOID list_parse ();
/*
* FUNCTION
*
* match test string for wildcard match
*
* SYNOPSIS
*
* BOOLEAN match (string, pattern)
* register char *string;
* register char *pattern;
*
* DESCRIPTION
*
* Test string for match using pattern. The pattern may
* contain the normal shell metacharacters for pattern
* matching. The '*' character matches any string,
* including the null string. The '?' character matches
* any single character. A list of characters enclosed
* in '[' and ']' matches any character in the list.
* If the first character following the beginning '['
* is a '!' then any character not in the list is matched.
*
*/
/*
* PSEUDO CODE
*
* Begin match
* Switch on type of pattern character
* Case ASTERISK:
* Attempt to match asterisk
* Break
* Case QUESTION MARK:
* Attempt to match question mark
* Break
* Case EOS:
* Match is result of EOS on string test
* Break
* Case default:
* If explicit match then
* Match is result of submatch
* Else
* Match is FALSE
* End if
* Break
* End switch
* Return result of match test
* End match
*
*/
static BOOLEAN match (string, pattern)
register char *string;
register char *pattern;
{
register BOOLEAN ismatch;
ismatch = FALSE;
switch (*pattern) {
case ASTERISK:
pattern++;
do {
ismatch = match (string, pattern);
} while (!ismatch && *string++ != EOS);
break;
case QUESTION:
if (*string != EOS) {
ismatch = match (++string, ++pattern);
}
break;
case EOS:
if (*string == EOS) {
ismatch = TRUE;
}
break;
case LEFT_BRACKET:
if (*string != EOS) {
ismatch = do_list (string, pattern);
}
break;
default:
if (tolower(*string) == tolower(*pattern))
{
string++;
pattern++;
ismatch = match (string, pattern);
} else {
ismatch = FALSE;
}
break;
}
return (ismatch);
}
/*
* FUNCTION
*
* do_list process a list and following substring
*
* SYNOPSIS
*
* static BOOLEAN do_list (string, pattern)
* register char *string;
* register char *pattern;
*
* DESCRIPTION
*
* Called when a list is found in the pattern. Returns
* TRUE if the current character matches the list and
* the remaining substring matches the remaining pattern.
*
* Returns FALSE if either the current character fails to
* match the list or the list matches but the remaining
* substring and subpattern's don't.
*
* RESTRICTIONS
*
* The mechanism used to match characters in an inclusive
* pair (I.E. [a-d]) may not be portable to machines
* in which the native character set is not ASCII.
*
* The rules implemented here are:
*
* (1) The backslash character may be
* used to quote any special character.
* I.E. "\]" and "\-" anywhere in list,
* or "\!" at start of list.
*
* (2) The sequence \nnn becomes the character
* given by nnn (in octal).
*
* (3) Any non-escaped ']' marks the end of list.
*
* (4) A list beginning with the special character
* '!' matches any character NOT in list.
* The '!' character is only special if it
* is the first character in the list.
*
*/
/*
* PSEUDO CODE
*
* Begin do_list
* Default result is no match
* Skip over the opening left bracket
* If the next pattern character is a '!' then
* List match gives FALSE
* Skip over the '!' character
* Else
* List match gives TRUE
* End if
* While not at closing bracket or EOS
* Get lower and upper bounds
* If character in bounds then
* Result is same as sense flag.
* Skip over rest of list
* End if
* End while
* If match found then
* If not at end of pattern then
* Call match with rest of pattern
* End if
* End if
* Return match result
* End do_list
*
*/
static BOOLEAN do_list (string, pattern)
register char *string;
char *pattern;
{
register BOOLEAN ismatch;
register BOOLEAN if_found;
register BOOLEAN if_not_found;
auto char lower;
auto char upper;
pattern++;
if (*pattern == '!') {
if_found = FALSE;
if_not_found = TRUE;
pattern++;
} else {
if_found = TRUE;
if_not_found = FALSE;
}
ismatch = if_not_found;
while (*pattern != ']' && *pattern != EOS) {
list_parse (&pattern, &lower, &upper);
if (*string >= lower && *string <= upper) {
ismatch = if_found;
while (*pattern != ']' && *pattern != EOS) {pattern++;}
}
}
if (*pattern++ != ']') {
fprintf (stderr, "warning - character class error\n");
} else {
if (ismatch) {
ismatch = match (++string, pattern);
}
}
return (ismatch);
}
/*
* FUNCTION
*
* list_parse parse part of list into lower and upper bounds
*
* SYNOPSIS
*
* static VOID list_parse (patp, lowp, highp)
* char **patp;
* char *lowp;
* char *highp;
*
* DESCRIPTION
*
* Given pointer to a pattern pointer (patp), pointer to
* a place to store lower bound (lowp), and pointer to a
* place to store upper bound (highp), parses part of
* the list, updating the pattern pointer in the process.
*
* For list characters which are not part of a range,
* the lower and upper bounds are set to that character.
*
*/
static VOID list_parse (patp, lowp, highp)
char **patp;
char *lowp;
char *highp;
{
*lowp = nextch (patp);
if (**patp == '-') {
(*patp)++;
*highp = nextch (patp);
} else {
*highp = *lowp;
}
}
/*
* FUNCTION
*
* nextch determine next character in a pattern
*
* SYNOPSIS
*
* static char nextch (patp)
* char **patp;
*
* DESCRIPTION
*
* Given pointer to a pointer to a pattern, uses the pattern
* pointer to determine the next character in the pattern,
* subject to translation of backslash-char and backslash-octal
* sequences.
*
* The character pointer is updated to point at the next pattern
* character to be processed.
*
*/
static char nextch (patp)
char **patp;
{
register char ch;
register char chsum;
register INT count;
ch = *(*patp)++;
if (ch == '\\') {
ch = *(*patp)++;
if (IS_OCTAL (ch)) {
chsum = 0;
for (count = 0; count < 3 && IS_OCTAL (ch); count++) {
chsum *= 8;
chsum += ch - '0';
ch = *(*patp)++;
}
(*patp)--;
ch = chsum;
}
}
return (ch);
}
/*
* Filename match - here, *.* matches everything
*/
BOOLEAN fmatch (direntry)
struct direct *direntry;
{
char *ptr,*string;
string = direntry->d_name;
if(!strcmp(pattern, "") || !strcmp(pattern, "*.*"))
return(1);
return(match(string, pattern));
}
SHAR_EOF
chmod +x 'arcdir.c'
fi # end of overwriting check
# End of shell archive
exit 0