george@osu-eddie.UUCP (George Jones) (01/20/86)
Rick Shaffner asked me to forward his LS program and wildcard routines here. The routines (used by LS) provide a means of looking up files using the familiar "?" and "*" wildcard characters. There is also a jacket routine that handles redirection of output to seperate files when there are multiple (possibly wildcarded) input files. I will forward any feedback, suggestions, etc. to Rick. ================================Cut Here================================ #! /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: # ls.c # wildexp.c # wildexp.h # utilskel.c # This archive created: Sun Jan 19 21:44:00 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'ls.c'" '(3071 characters)' if test -f 'ls.c' then echo shar: will not over-write existing file "'ls.c'" else sed 's/^ X//' << \SHAR_EOF > 'ls.c' X/* X** ls - List directory using unix style wildcards X** X** usage: ls [-l] filename X** X** -l is an optional flag which will cause the directory listing to X** be printed one-up with file size and date included. Otherwise X** directory listing is printed two-up. The listing is NOT X** sorted. X** X** examples: X** ls *.c print all files which end in ".c" X** ls -l a* print all files which begin with "a" X** ls -l a??b* print all files which begin with "a" followed by any X** two characters followed by "b" and then any other X** characters X** X** Written by: Rick Schaeffer 1/11/86 and placed in public domain. X** E. 13611 26th Ave. X** Spokane, Wa. 99216 X** Compuserve ID: 70120,174 X** Bytenet ID: ricks. X*/ X X#include "wildexp.h" X Xstruct find fwk; X Xint totfiles; Xlong totsize; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X char pattern[128]; X int retval,lflag; X char *fferror(); X X lflag = 0; X totfiles = 0; X totsize = 0; X if (argc <= 1) X strcpy(pattern,"*"); X else { X if (argc == 2) { X strncpy(pattern,argv[1],120); X if (strcmp(pattern,"-l") == 0) { X strcpy(pattern,"*"); X lflag = 1; X } X } X else { X strncpy(pattern,argv[2],120); X if (strcmp(argv[1],"-l") == 0) X lflag = 1; X } X } X if (pattern[strlen(pattern)-1] == ':') X strcat(pattern,"*"); X retval = findfirst(pattern,&fwk); X if (retval > 0) { X printf("ls: Error - %s\n",fferror(retval)); X find_cleanup(&fwk); X exit(1); X } X while (retval <= 0) { X if (retval < 0) X break; X if (lflag) X print_long(&fwk); X else X print_short(&fwk); X retval = findnext(&fwk); X } X printf("\n"); X if (lflag) X printf("%d Files containing %ld bytes.\n",totfiles,totsize); X find_cleanup(&fwk); X} X Xchar *dates(s,dss) Xchar *s; Xstruct DateStamp *dss; X{ X int year,month,day; X static char dpm[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; X X year = 1978; X day = dss->ds_Days; X while (day >= 366) { X if ((year-1976) % 4 == 0) { X day -= 366; X year++; X } X else X if ((year-1976) % 4 != 0 && day >= 365) { X day -= 365; X year++; X } X } X if ((year-1976) % 4 == 0) { X day = day % 366; X dpm[2] = 29; X } X else { X day = day % 365; X dpm[2] = 28; X } X for (month = 0; day > dpm[month]; month++) X day -= dpm[month]; X sprintf(s,"%02d/%02d/%04d",month+1,day,year); X return(s); X} X Xchar *times(s,dss) Xchar *s; Xstruct DateStamp *dss; X{ X int hours,minutes,seconds; X X seconds = dss->ds_Tick / 50; X seconds %= 60; X minutes = dss->ds_Minute; X hours = minutes / 60; X minutes %= 60; X sprintf(s,"%02d:%02d:%02d",hours,minutes,seconds); X return(s); X} X Xprint_long(fwk) Xstruct find *fwk; X{ X struct FileInfoBlock *f; X char s[12],t[12]; X X f = fwk->fp; X if (f->fib_DirEntryType < 0) { X printf("%-30s %7d %s %s\n",f->fib_FileName,f->fib_Size, X dates(s,&f->fib_Date),times(t,&f->fib_Date)); X totsize += f->fib_Size; X } X else X printf("%-30s <DIR> %s\n",f->fib_FileName,dates(s,&f->fib_Date)); X totfiles++; X} X Xprint_short(fwk) Xstruct find *fwk; X{ X static int f=0; X X printf("%-30s ",fwk->fname); X if (f == 0) X f = 1; X else { X printf("\n"); X f = 0; X } X} SHAR_EOF if test 3071 -ne "`wc -c < 'ls.c'`" then echo shar: error transmitting "'ls.c'" '(should have been 3071 characters)' fi fi # end of overwriting check echo shar: extracting "'wildexp.c'" '(8739 characters)' if test -f 'wildexp.c' then echo shar: will not over-write existing file "'wildexp.c'" else sed 's/^ X//' << \SHAR_EOF > 'wildexp.c' X/* X** The following module contains functions which permit wildcard X** filename expansion using Unix type wildcard characters. This X** module can be compiled separately and included in the link for X** any programs which desire it's support. The following functions X** are present: X** X** findfirst - find the first occurance of a file matching X** the given name which may contain Unix style X** wildcards. X** findnext - find the next occurance of a file. Returns X** 0 if no more matches remain. X** find_cleanup - release all storage and locks reserved by findfirst X** and/or findnext. MUST be called before exit! X** fferror - given an error code returned by findnext, this X** function returns a pointer to a descriptive X** error message string. X** iswild - given a string, this function returns X** TRUE if the string contains a wildcard character X** and FALSE if not. X** wildexp - given a file name and a pointer to a table of X** pointers, this function will fill the table X** with a list of file names in the indicated X** directory which match the given name. X** X** X** Written by: Rick Schaeffer X** E. 13611 26th Ave. X** Spokane, Wa. 99216 X** Compuserve ID: 70120,174 X** Bytenet ID: ricks. X*/ X X#include "wexp.h" X X/* X** Return values for findfirst and findnext are: X** 0 = retval ok, find struct "fname" contains name of file found X** 1 = file name too long X** 2 = error in parsing X** 3 = invalid path name X** 4 = first Examine failed X** 5 = not a directory X*/ X X/* fferror -- return a meaningful error message for findxxx errors */ X** Parameter: X** errcd - An integer containing the error code returned by findfirst X** or findnext. X** X** Returns: X** msgptr - A pointer to a meaningful error message X*/ Xchar *fferror(errcd) Xint errcd; X{ X static char *errmsg[] = { X "Filename too long", X "Filename invalid", X "Pathname invalid", X "Examine failed", X "Pathname invalid", X "Error code invalid" X }; X X if (--errcd > 4) X errcd = 5; X return(errmsg[errcd]); X} X X/* findfirst -- find the first occurance of a given file name in either X** the given or the current directory. X** Parameters: X** name - A pointer to a filename string. May contain wildcard X** characters ('?' and/or '*'). May optionally contain X** a directory path. Example: "df0:c/d*" matches all X** files in directory "df0:c" which begin with the letter X** "d". X** fwk - A pointer to a structure which will be filled in by X** findfirst and used by findnext. Must NOT be disturbed X** between calls! X** X** Returns: X** 0 = successful completion. fwk filled in with first matching X** file. X** >0 = error code. use fferror to obtain a meaningful description. X** X** Example: X** findfirst("*.c",fwk) X** The first matching file is in fwk->fname. X*/ Xfindfirst(name,fwk) Xchar *name; Xstruct find *fwk; X{ X struct Process *tp,*FindTask(); X int pt[16]; X int last; X char *p1,*strchr(); X X fwk->fp = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),0); X /* caller must free this space! */ X fwk->flock = 0; X X if (strlen(name) > 128) X return(1); /* file name too long */ X if ((p1 = strchr(name,':')) != NULL) X if (strchr(name,'/') == NULL) { X *p1 = 0; X strcpy(fwk->path,name); X strcat(fwk->path,":/"); X strcat(fwk->path,p1+1); X strcpy(name,fwk->path); X } X strcpy(fwk->path,name); X if (stspfp(name,pt) == -1) X return(2); /* error in parsing */ X for (last=0; last < 16; last++) X if (pt[last] == -1) X break; X last--; /* now points at file name portion */ X if ((last == 0) && (pt[0] == 0)) { /* no path */ X if (strlen(name) > 32) X return(1); /* file name too long */ X strcpy(fwk->name,name); X fwk->path[0] = 0; X tp = FindTask(NULL); X fwk->flock = DupLock(tp->pr_CurrentDir); X bldfull(fwk); /* build full path name */ X } X else { X if (strlen(&name[pt[last]]) > 32) X return(1); /* file name too long */ X strcpy(fwk->name,&name[pt[last]]); X fwk->path[pt[last] - 1] = 0; X if ((fwk->flock = Lock(fwk->path,ACCESS_READ)) == 0) X return(3); /* invalid path name */ X bldfull(fwk); X } X if (Examine(fwk->flock,fwk->fp)) { /* get directory name */ X if (fwk->fp->fib_DirEntryType > 0) X return(findnext(fwk)); X else X return(5); /* not a directory */ X } X else X return(4); /* first examine failed */ X} X X/* X** findnext -- find next occurance of a matching file. X** Parameter: X** fwk - pointer to a "find" structure which has been filled in X** by a call to findfirst. X** X** Returns: X** 0 = Match found. fwk->fname contains the name. X** -1 = No more matches. X*/ Xint findnext(fwk) Xstruct find *fwk; X{ X while (ExNext(fwk->flock,fwk->fp)) { X strcpy(fwk->fname,fwk->fp->fib_FileName); X if (fnmatch(fwk->fname,fwk->name)) X return(0); X } X return(-1); X} X Xbldfull() X{ X} X X/* find_cleanup -- release any structures and locks used by findfirst. X** Parameters: X** fwk - pointer to a "find" structure which has been previously X** filled in by findfirst. X** Returns: X** nothing X*/ Xfind_cleanup(fwk) Xstruct find *fwk; X{ X if (fwk->flock) X UnLock(fwk->flock); X if (fwk->fp) X FreeMem(fwk->fp,sizeof(struct FileInfoBlock)); X} X X/* fnmatch -- perform unix style pattern match on a file name X** usage: result = fnmatch(name,pattern) X** returns 1 if "name" matches "pattern", 0 otherwise X*/ X Xint fnmatch(name,pattern) Xregister char *name,*pattern; X{ X X while (*pattern) { X if (*pattern == '*') { X while (*pattern == '*') X pattern++; X while ((*name) && (tolower(*name) != tolower(*pattern))) X name++; X if (*name == 0) X if (*pattern == 0) X return(1); /* matched */ X else X return(0); X } X if (*pattern == '?') { X pattern++; X name++; X continue; X } X if (tolower(*pattern) != tolower(*name)) X return(0); /* not matched */ X pattern++; X name++; X } X if ((*name == 0) && (*pattern == 0)) X return(1); /* matched */ X else X return(0); /* not matched */ X} X X/* X** wildexp -- expand a wildcard file name X** Parameters: X** name - Pointer to the file name to be expanded. X** adtbl - Pointer to an array of pointers. X** maxargs - The maximum number of pointers contained in adtbl. X** X** Returns: X** 1 = Successful completion. The adtbl array will contain pointers X** to all file names found and will be terminated with a NULL X** pointer. It's use is exactly like use of the standard C X** argv array except that the first filename argument is in X** adtbl[0] whereas argv[0] contains a pointer to the name of X** the function which was invoked. X** 0 = An error occured. X*/ Xint wildexp(name,adtbl,maxargs) Xchar *name; Xregister char **adtbl; Xint maxargs; X{ X struct find f; X register int i=0; X char *malloc(); X int retval; X X if ((retval = findfirst(name,&f)) > 0) { X *adtbl = NULL; X find_cleanup(&f); X return(0); X } X while (retval == 0) { X if (f.fp->fib_DirEntryType > 0) { X retval=findnext(&f); X continue; /* it's a directory */ X } X *adtbl = malloc(strlen(f.path)+strlen(f.fname)+1); X if (*adtbl == NULL) { X find_cleanup(&f); X return(0); /* arena is full */ X } X strcpy(*adtbl,f.path); X if ((f.path[0] != 0) && (f.path[strlen(f.path)-1] != ':')) X strcat(*adtbl,"/"); X strcat(*adtbl++,f.fname); X if ((++i) >= maxargs) X return(0); X retval=findnext(&f); X } X *adtbl = NULL; X find_cleanup(&f); X return(1); X} X Xint iswild(s) Xchar *s; X{ X while (*s) { X if ((*s == '*') || (*s == '?')) X return(1); X s++; X } X return(0); X} X SHAR_EOF if test 8739 -ne "`wc -c < 'wildexp.c'`" then echo shar: error transmitting "'wildexp.c'" '(should have been 8739 characters)' fi fi # end of overwriting check echo shar: extracting "'wildexp.h'" '(1885 characters)' if test -f 'wildexp.h' then echo shar: will not over-write existing file "'wildexp.h'" else sed 's/^ X//' << \SHAR_EOF > 'wildexp.h' X/* X** The following is an include file for wildexp.c and also X** for any programs which desire to use findfirst and/or findnext. X** This file is not needed for programs that are only using X** iswild and wildexp. X** X** Written by: Rick Schaeffer X** E. 13611 26th Ave X** Spokane, Wa. 99216 X** Compuserve ID: 70120,174 X** Bytenet ID: ricks. X*/ X X#ifndef LIBRARIES_DOS_H X#include <libraries/dos.h> X#endif X X#ifndef LIBRARIES_DOSEXTENS_H Xstruct Msg { int dummy; }; /* make Lattice shut-up about this */ X#include <libraries/dosextens.h> X#endif X X/* X** The following is the structure used by findfirst and findnext. X** A pointer to this structure MUST be passed to findfirst, which X** fills it in. Subsequent calls to findnext must pass a pointer X** to the structure which was filled in by findfirst. The actual X** file name found is in the "fname" element of the structure after X** each call. NOTE: The last two elements of the structure refer X** to AmigaDos specific items. Users of findfirst and findnext may, X** if they choose, define the "find" structure such that the last X** two elements (flock and fp) are defined as "long". In that fashion, X** you can eliminate the need to #include the "dos" information. Of X** course, if access to the FileInfoBlock is desired, you must use X** the structure as defined below. X*/ Xstruct find { X char path[128]; /* path portion of the argument */ X char name[32]; /* name portion of the argument */ X char fpath[128]; /* FULL path to actual file found */ X /* NOTE: fpath is currently not filled in. To X be added later */ X char fname[32]; /* actual name of file found */ X BPTR flock; /* lock for the directory containing the file */ X struct FileInfoBlock *fp; /* pointer to fib of file */ X }; X SHAR_EOF if test 1885 -ne "`wc -c < 'wildexp.h'`" then echo shar: error transmitting "'wildexp.h'" '(should have been 1885 characters)' fi fi # end of overwriting check echo shar: extracting "'utilskel.c'" '(4588 characters)' if test -f 'utilskel.c' then echo shar: will not over-write existing file "'utilskel.c'" else sed 's/^ X//' << \SHAR_EOF > 'utilskel.c' X/* X** The following is a suggested skeleton for utilities which expect X** to handle a variable number of files with wildcards handled in X** input files and redirection of output files. This type of application X** is very common and is difficult to handle...thus this example. X** X** The command line syntax for the resulting program is: X** **name** [-o outputpath] file file file... X** where the -o parameter is optional and indicates the path to X** the directory where output files are to be placed. X** X** The skeleton handles wild card file names in the following fashion: X** First, if a "-o" option is detected, the skeleton builds an output X** file name mask consisting of the path given by the user after the X** option. Then it reads file names from the command line and uses X** the "wildexp" function to expand them into a table of existing X** filenames which match. For each filename in the table, the skeleton X** opens a file. If a "-o" option was given by the user, it concatenates X** the input filename to the path obtained above, otherwise it X** concatenates ".f" to the end of the input filename. These actions X** are necessary to ensure that the input file and the output file X** have different names. The skeleton then opens the output file X** and calls "dowork". If there are errors in opening either the X** input file or the output file, "dowork" is not called and an X** appropriate message is printed to stderr. X** X** Basically, to use this skeleton, first replace occurances of "**name**" X** with the name of the utility you are creating. Then, write the X** "dowork" function. The "dowork" function gets two arguments..."fin" X** and "fout". For each file the user wants to process, the "main" X** function opens an input file (fin) and an output file (fout) and X** then calls "dowork"...which performs whatever processing there is X** to be done and then returns. X** X** Written by: Rick Schaeffer X** E. 13611 26th Ave. X** Spokane, Wa. 99216 X** Compuserve ID: 70120,174 X** Bytenet ID: ricks. X*/ X X#include <stdio.h> Xextern int Enable_Abort; X Xchar *largv[128]; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X char outpath[80]; X char outname[80]; X char *nameonly,*strrchr(); X char *malloc(); X int i,j,begarg; X FILE *fin,*fout; X X Enable_Abort = 1; X outpath[0] = 0; X if ((argc < 2) || (strcmp(argv[1],"?") == 0)) { X printf("**name** -- Usage:\n"); X printf(" **name** [-o outpath] file file\n\n"); X printf("if -o option present, will write files to that path\n"); X printf("Otherwise concatenates '.f' to input file names\n\n"); X exit(1); X } X if (strcmp(argv[1],"-o") == 0) { X strncpy(outpath,argv[2],78); X begarg = 3; X } X else X begarg = 1; X for (i=begarg; i<argc; i++) { X if (iswild(argv[i])) { X wildexp(argv[i],largv,127); X if (largv[0] == NULL) X fprintf(stderr,"No matching files for ==> %s!\n",argv[i]); X } X else { X largv[0] = malloc(strlen(argv[i])+1); X strcpy(largv[0],argv[i]); X largv[1] = NULL; X } X j=0; X while (largv[j] != NULL) { X if (outpath[0] == 0) { X strncpy(outname,largv[j],77); X strcat(outname,".f"); X } X else { X strcpy(outname,outpath); X nameonly = strrchr(largv[j],'/'); X if (nameonly == NULL) X nameonly = strrchr(largv[j],':'); X if (nameonly == NULL) X nameonly = largv[j]; X else X nameonly++; X if ((strlen(outname) + strlen(nameonly)) > 79) { X fprintf(stderr,"Pathname+Filename too long\n"); X break; X } X strcat(outname,nameonly); X } X if ((fin = fopen(largv[j],"r")) == NULL) { X fprintf(stderr,"Couldn't open input file ==> %s\n",largv[j]); X break; X } X if ((fout = fopen(outname,"w")) == NULL) { X fprintf(stderr,"Couldn't open output file ==> %s\n",outname); X fclose(fin); X break; X } X fprintf(stderr,"%s ==> %s\n",largv[j],outname); X dowork(fin,fout); X fclose(fin); X fclose(fout); X j++; X } X } X} X Xdowork(*fin,*fout) XFILE *fin,*fout; X{ X} SHAR_EOF if test 4588 -ne "`wc -c < 'utilskel.c'`" then echo shar: error transmitting "'utilskel.c'" '(should have been 4588 characters)' fi fi # end of overwriting check # End of shell archive exit 0 -- ----------- George M. Jones cbosgd!osu-eddie!george (uucp) (614) 885-5102 (home) george@ohio-state.csnet (csnet) (614) 457-8600 (work) 70003,2443 (CompusServe)
star@fluke.UUCP (David Whitlock) (01/24/86)
> Rick Shaffner asked me to forward his LS program and wildcard routines > here. The routines (used by LS) provide a means of looking up > files using the familiar "?" and "*" wildcard characters. There is also > a jacket routine that handles redirection of output to seperate > files when there are multiple (possibly wildcarded) input files. > > I will forward any feedback, suggestions, etc. to Rick. > > ================================Cut Here================================ In the source files is mentioned another #include file named 'wexp.h'. This file was not included in this batch. Can someone repost this file. Without it, nothing will compile! -- -- Dave Whitlock {decvax!microsof,uw-beaver,ssc-vax,allegra,lbl-csam}!fluke!star John Fluke Mfg. Co., 33031 Schoolcraft Road, Livonia, MI 48150
george@osu-eddie.UUCP (George Jones) (01/30/86)
> > Rick Shaffner asked me to forward his LS program and wildcard routines > > here. The routines (used by LS) provide a means of looking up > > files using the familiar "?" and "*" wildcard characters. There is also > > a jacket routine that handles redirection of output to seperate > > files when there are multiple (possibly wildcarded) input files. > > > > I will forward any feedback, suggestions, etc. to Rick. > > > > ================================Cut Here================================ > > > In the source files is mentioned another #include file named 'wexp.h'. > > This file was not included in this batch. Can someone repost this file. > Without it, nothing will compile! Ooops ! ==============================Cut Here============================== /* ** The following is an include file for wildexp.c and also ** for any programs which desire to use findfirst and/or findnext. ** This file is not needed for programs that are only using ** iswild and wildexp. ** ** Written by: Rick Schaeffer ** E. 13611 26th Ave ** Spokane, Wa. 99216 ** Compuserve ID: 70120,174 ** Bytenet ID: ricks. */ #ifndef LIBRARIES_DOS_H #include <libraries/dos.h> #endif #ifndef LIBRARIES_DOSEXTENS_H struct Msg { int dummy; }; /* make Lattice shut-up about this */ #include <libraries/dosextens.h> #endif /* ** The following is the structure used by findfirst and findnext. ** A pointer to this structure MUST be passed to findfirst, which ** fills it in. Subsequent calls to findnext must pass a pointer ** to the structure which was filled in by findfirst. The actual ** file name found is in the "fname" element of the structure after ** each call. NOTE: The last two elements of the structure refer ** to AmigaDos specific items. Users of findfirst and findnext may, ** if they choose, define the "find" structure such that the last ** two elements (flock and fp) are defined as "long". In that fashion, ** you can eliminate the need to #include the "dos" information. Of ** course, if access to the FileInfoBlock is desired, you must use ** the structure as defined below. */ struct find { char path[128]; /* path portion of the argument */ char name[32]; /* name portion of the argument */ char fpath[128]; /* FULL path to actual file found */ /* NOTE: fpath is currently not filled in. To be added later */ char fname[32]; /* actual name of file found */ BPTR flock; /* lock for the directory containing the file */ struct FileInfoBlock *fp; /* pointer to fib of file */ }; -- ----------- George M. Jones cbosgd!osu-eddie!george (uucp) (614) 885-5102 (home) george@ohio-state.csnet (csnet) (614) 457-8600 (work) 70003,2443 (CompusServe)