ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU.BITNET (Ed Wilts) (06/24/88)
$Part04: $ File_is="ARCDIR.C" $ Check_Sum_is=611663484 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY Xstatic char *RCSid = "$Header: arcdir.c,v 1.2 86/07/15 07:52:56 turner Exp $"; X X/* X * $Log:`009arcdir.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:56 turner X * X * X * Revision 1.1 86/06/26 15:00:12 turner X * initial version X * X * X */ X X/* ARC - Archive utility - ARCDIR X*/ X#include <stdio.h> X#include "arc.h" X X#if MSDOS X#include <dir.h> X#endif X X#ifndef VAXC X#if BSD X#include <sys/types.h> X#include <sys/dir.h> X#endif X#else X#include "dir.h" X#endif X Xchar *pattern;`009`009`009 /* global so that fmatch can use them */ XINT filemode; X Vextern char *dir(filename,mode,NameList) /* get files, one by one X */ Xchar *filename; /* template, or NULL */ XINT mode; /* search mode bits */ Xchar *(*NameList[]); X{ X/* struct direct *(*namelist[]);`009*/ X static struct direct *(**namelist), *np; X#ifdef BSD X`009INT alphasort(); X`009INT scandir(); X#endif BSD X INT fmatch(); X`009static INT Nnum = 0,ii; X`009char *result; X X`009pattern = filename; X`009filemode = mode;`009`009/* set up globals for fmatch */ X`009if(Nnum == 0) { /* first call */ X/* cmb */ X`009 namelist = (char **)malloc(sizeof(char **)); X Nnum = scandir(".", namelist, fmatch, alphasort); X *NameList = (char **)malloc(Nnum*sizeof(char *)); X for (ii=0; ii<Nnum; ii++) { V/* (*NameList)[ii] = (char *)malloc((*namelist)[ii]->d_namlen+1) X; X * strcpy((*NameList)[ii],(*namelist)[ii]->d_name); X */ X (*NameList)[ii] = (char *)malloc((*namelist)[ii]->d_namlen+1); X strcpy((*NameList)[ii],(*namelist)[ii]->d_name); X } X ii = 0; X`009} X`009if(ii >= Nnum) { /* all out of files */ X`009`009if(Nnum) { /* there were some files found */ X`009`009 freedir(namelist); X`009`009 } X`009`009Nnum = 0; X`009`009return(NULL); X`009} X`009else { X`009`009return((*NameList)[ii++]); X`009} X} X X X#define ASTERISK '*'`009`009/* The '*' metacharacter */ X#define QUESTION '?'`009`009/* The '?' metacharacter */ X#define LEFT_BRACKET '['`009/* The '[' metacharacter */ X#define RIGHT_BRACKET ']'`009/* The ']' metacharacter */ X X#define IS_OCTAL(ch) (ch >= '0' && ch <= '7') X Xtypedef INT BOOLEAN; X#define VOID short X#define TRUE 1 X#define FALSE 0 X#define EOS '\000' X Xstatic BOOLEAN do_list (); Xstatic char nextch (); Xstatic VOID list_parse (); X X`012 X/* X * FUNCTION X * X *`009match test string for wildcard match X * X * SYNOPSIS X * X *`009BOOLEAN match (string, pattern) X *`009register char *string; X *`009register char *pattern; X * X * DESCRIPTION X * X *`009Test string for match using pattern. The pattern may X *`009contain the normal shell metacharacters for pattern X *`009matching. The '*' character matches any string, X *`009including the null string. The '?' character matches X *`009any single character. A list of characters enclosed X *`009in '[' and ']' matches any character in the list. X *`009If the first character following the beginning '[' X *`009is a '!' then any character not in the list is matched. X * X */ X X`012 X/* X * PSEUDO CODE X * X *`009Begin match X *`009 Switch on type of pattern character X *`009`009Case ASTERISK: X *`009`009 Attempt to match asterisk X *`009`009 Break X *`009`009Case QUESTION MARK: X *`009`009 Attempt to match question mark X *`009`009 Break X *`009`009Case EOS: X *`009`009 Match is result of EOS on string test X *`009`009 Break X *`009`009Case default: X *`009`009 If explicit match then X *`009`009`009Match is result of submatch X *`009`009 Else X *`009`009`009Match is FALSE X *`009`009 End if X *`009`009 Break X *`009 End switch X *`009 Return result of match test X *`009End match X * X */ X Xstatic BOOLEAN match (string, pattern) Xregister char *string; Xregister char *pattern; X{ X register BOOLEAN ismatch; X X ismatch = FALSE; X switch (*pattern) { X`009case ASTERISK: X`009 pattern++; X`009 do { X`009`009ismatch = match (string, pattern); X`009 } while (!ismatch && *string++ != EOS); X`009 break; X`009case QUESTION: X`009 if (*string != EOS) { X`009`009ismatch = match (++string, ++pattern); X`009 } X`009 break; X`009case EOS: X`009 if (*string == EOS) { X`009`009ismatch = TRUE; X`009 } X`009 break; X`009case LEFT_BRACKET: X`009 if (*string != EOS) { X`009`009ismatch = do_list (string, pattern); X`009 } X`009 break; X`009default: X`009 if (tolower(*string) == tolower(*pattern)) X`009 { X`009 `009string++; X`009 `009pattern++; X`009`009ismatch = match (string, pattern); X`009 } else { X`009`009ismatch = FALSE; X`009 } X`009 break; X } X return (ismatch); X} X X`012 X/* X * FUNCTION X * X *`009do_list process a list and following substring X * X * SYNOPSIS X * X *`009static BOOLEAN do_list (string, pattern) X *`009register char *string; X *`009register char *pattern; X * X * DESCRIPTION X * X *`009Called when a list is found in the pattern. Returns X *`009TRUE if the current character matches the list and X *`009the remaining substring matches the remaining pattern. X * X *`009Returns FALSE if either the current character fails to X *`009match the list or the list matches but the remaining X *`009substring and subpattern's don't. X * X * RESTRICTIONS X * X *`009The mechanism used to match characters in an inclusive X *`009pair (I.E. [a-d]) may not be portable to machines X *`009in which the native character set is not ASCII. X * X *`009The rules implemented here are: X * X *`009`009(1)`009The backslash character may be X *`009`009`009used to quote any special character. X *`009`009`009I.E. "\]" and "\-" anywhere in list, X *`009`009`009or "\!" at start of list. X * X *`009`009(2)`009The sequence \nnn becomes the character X *`009`009`009given by nnn (in octal). X * X *`009`009(3)`009Any non-escaped ']' marks the end of list. X * X *`009`009(4)`009A list beginning with the special character X *`009`009`009'!' matches any character NOT in list. X *`009`009`009The '!' character is only special if it X *`009`009`009is the first character in the list. X * X */ X X`012 X/* X * PSEUDO CODE X * X *`009Begin do_list X *`009 Default result is no match X *`009 Skip over the opening left bracket X *`009 If the next pattern character is a '!' then X *`009`009List match gives FALSE X *`009`009Skip over the '!' character X *`009 Else X *`009`009List match gives TRUE X *`009 End if X *`009 While not at closing bracket or EOS X *`009`009Get lower and upper bounds X *`009`009If character in bounds then X *`009`009 Result is same as sense flag. X *`009`009 Skip over rest of list X *`009`009End if X *`009 End while X *`009 If match found then X *`009`009If not at end of pattern then X *`009`009 Call match with rest of pattern X *`009`009End if X *`009 End if X *`009 Return match result X *`009End do_list X * X */ X Xstatic BOOLEAN do_list (string, pattern) Xregister char *string; Xchar *pattern; X{ X register BOOLEAN ismatch; X register BOOLEAN if_found; X register BOOLEAN if_not_found; X auto char lower; X auto char upper; X X pattern++; X if (*pattern == '!') { X`009if_found = FALSE; X`009if_not_found = TRUE; X`009pattern++; X } else { X`009if_found = TRUE; X`009if_not_found = FALSE; X } X ismatch = if_not_found; X while (*pattern != ']' && *pattern != EOS) { X`009list_parse (&pattern, &lower, &upper); X`009if (*string >= lower && *string <= upper) { X`009 ismatch = if_found; X`009 while (*pattern != ']' && *pattern != EOS) {pattern++;} X`009} X } X if (*pattern++ != ']') { X`009fprintf (stderr, "warning - character class error\n"); X } else { X`009if (ismatch) { X`009 ismatch = match (++string, pattern); X`009} X } X return (ismatch); X} X X`012 X/* X * FUNCTION X * X *`009list_parse parse part of list into lower and upper bounds X * X * SYNOPSIS X * X *`009static VOID list_parse (patp, lowp, highp) X *`009char **patp; X *`009char *lowp; X *`009char *highp; X * X * DESCRIPTION X * X *`009Given pointer to a pattern pointer (patp), pointer to X *`009a place to store lower bound (lowp), and pointer to a X *`009place to store upper bound (highp), parses part of X *`009the list, updating the pattern pointer in the process. X * X *`009For list characters which are not part of a range, X *`009the lower and upper bounds are set to that character. X * X */ X Xstatic VOID list_parse (patp, lowp, highp) Xchar **patp; Xchar *lowp; Xchar *highp; X{ X *lowp = nextch (patp); X if (**patp == '-') { X`009(*patp)++; X`009*highp = nextch (patp); X } else { X`009*highp = *lowp; X } X} X X`012 X/* X * FUNCTION X * X *`009nextch determine next character in a pattern X * X * SYNOPSIS X * X *`009static char nextch (patp) X *`009char **patp; X * X * DESCRIPTION X * X *`009Given pointer to a pointer to a pattern, uses the pattern X *`009pointer to determine the next character in the pattern, X *`009subject to translation of backslash-char and backslash-octal X *`009sequences. X * X *`009The character pointer is updated to point at the next pattern X *`009character to be processed. X * X */ X Xstatic char nextch (patp) Xchar **patp; X{ X register char ch; X register char chsum; X register INT count; X X ch = *(*patp)++; X if (ch == '\\') { X`009ch = *(*patp)++; X`009if (IS_OCTAL (ch)) { X`009 chsum = 0; X`009 for (count = 0; count < 3 && IS_OCTAL (ch); count++) { X`009`009chsum *= 8; X`009`009chsum += ch - '0'; X`009`009ch = *(*patp)++; X`009 } X`009 (*patp)--; X`009 ch = chsum; X`009} X } X return (ch); X} X X/* X *`009Filename match - here, *.* matches everything X */ X XBOOLEAN fmatch (direntry) Xstruct direct *direntry; X{ X char *ptr,*string; X X string = direntry->d_name; X X if(!strcmp(pattern, "") || !strcmp(pattern, "*.*")) X `009return(1); X return(match(string, pattern)); X} X $ GoSub Convert_File $ File_is="ARCDOS.C" $ Check_Sum_is=1651676921 $ Copy SYS$Input VMS_SHAR_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 * 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 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(®,®)&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 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(®,®)&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 Convert_File $ Goto Part05