/* ** The following module contains functions which permit wildcard ** filename expansion using Unix type wildcard characters. This ** module can be compiled separately and included in the link for ** any programs which desire it's support. The following functions ** are present: ** ** findfirst - find the first occurance of a file matching ** the given name which may contain Unix style ** wildcards. ** findnext - find the next occurance of a file. Returns ** 0 if no more matches remain. ** find_cleanup - release all storage and locks reserved by findfirst ** and/or findnext. MUST be called before exit! ** fferror - given an error code returned by findnext, this ** function returns a pointer to a descriptive ** error message string. ** iswild - given a string, this function returns ** TRUE if the string contains a wildcard character ** and FALSE if not. ** wildexp - given a file name and a pointer to a table of ** pointers, this function will fill the table ** with a list of file names in the indicated ** directory which match the given name. ** ** ** Written by: Rick Schaeffer ** E. 13611 26th Ave. ** Spokane, Wa. 99216 ** Compuserve ID: 70120,174 ** Bytenet ID: ricks. */ #include "wildexp.h" /* ** Return values for findfirst and findnext are: ** 0 = retval ok, find struct "fname" contains name of file found ** 1 = file name too long ** 2 = error in parsing ** 3 = invalid path name ** 4 = first Examine failed ** 5 = not a directory */ /* fferror -- return a meaningful error message for findxxx errors ** Parameter: ** errcd - An integer containing the error code returned by findfirst ** or findnext. ** ** Returns: ** msgptr - A pointer to a meaningful error message */ char *fferror(errcd) int errcd; { static char *errmsg[] = { "Filename too long", "Filename invalid", "Pathname invalid", "Examine failed", "Pathname invalid", "Error code invalid" }; if (--errcd > 4) errcd = 5; return(errmsg[errcd]); } /* findfirst -- find the first occurance of a given file name in either ** the given or the current directory. ** Parameters: ** name - A pointer to a filename string. May contain wildcard ** characters ('?' and/or '*'). May optionally contain ** a directory path. Example: "df0:c/d*" matches all ** files in directory "df0:c" which begin with the letter ** "d". ** fwk - A pointer to a structure which will be filled in by ** findfirst and used by findnext. Must NOT be disturbed ** between calls! ** ** Returns: ** 0 = successful completion. fwk filled in with first matching ** file. ** >0 = error code. use fferror to obtain a meaningful description. ** ** Example: ** findfirst("*.c",fwk) ** The first matching file is in fwk->fname. */ findfirst(name,fwk) char *name; struct find *fwk; { struct Process *tp,*FindTask(); int pt[16]; int last; char *p1,*strchr(); fwk->fp = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),0); /* caller must free this space! */ fwk->flock = 0; if (strlen(name) > 128) return(1); /* file name too long */ if ((p1 = strchr(name,':')) != NULL) if (strchr(name,'/') == NULL) { *p1 = 0; strcpy(fwk->path,name); strcat(fwk->path,":/"); strcat(fwk->path,p1+1); strcpy(name,fwk->path); } strcpy(fwk->path,name); if (stspfp(name,pt) == -1) return(2); /* error in parsing */ for (last=0; last < 16; last++) if (pt[last] == -1) break; last--; /* now points at file name portion */ if ((last == 0) && (pt[0] == 0)) { /* no path */ if (strlen(name) > 32) return(1); /* file name too long */ strcpy(fwk->name,name); fwk->path[0] = 0; tp = FindTask(NULL); fwk->flock = DupLock(tp->pr_CurrentDir); bldfull(fwk); /* build full path name */ } else { if (strlen(&name[pt[last]]) > 32) return(1); /* file name too long */ strcpy(fwk->name,&name[pt[last]]); fwk->path[pt[last] - 1] = 0; if ((fwk->flock = Lock(fwk->path,ACCESS_READ)) == 0) return(3); /* invalid path name */ bldfull(fwk); } if (Examine(fwk->flock,fwk->fp)) { /* get directory name */ if (fwk->fp->fib_DirEntryType > 0) return(findnext(fwk)); else return(5); /* not a directory */ } else return(4); /* first examine failed */ } /* ** findnext -- find next occurance of a matching file. ** Parameter: ** fwk - pointer to a "find" structure which has been filled in ** by a call to findfirst. ** ** Returns: ** 0 = Match found. fwk->fname contains the name. ** -1 = No more matches. */ int findnext(fwk) struct find *fwk; { while (ExNext(fwk->flock,fwk->fp)) { strcpy(fwk->fname,fwk->fp->fib_FileName); if (fnmatch(fwk->fname,fwk->name)) return(0); } return(-1); } bldfull() { } /* find_cleanup -- release any structures and locks used by findfirst. ** Parameters: ** fwk - pointer to a "find" structure which has been previously ** filled in by findfirst. ** Returns: ** nothing */ find_cleanup(fwk) struct find *fwk; { if (fwk->flock) UnLock(fwk->flock); if (fwk->fp) FreeMem(fwk->fp,sizeof(struct FileInfoBlock)); } /* fnmatch -- perform unix style pattern match on a file name ** usage: result = fnmatch(name,pattern) ** returns 1 if "name" matches "pattern", 0 otherwise */ int fnmatch(name,pattern) register char *name,*pattern; { while (*pattern) { if (*pattern == '*') { while (*pattern == '*') pattern++; while ((*name) && (tolower(*name) != tolower(*pattern))) name++; if (*name == 0) if (*pattern == 0) return(1); /* matched */ else return(0); } if (*pattern == '?') { pattern++; name++; continue; } if (tolower(*pattern) != tolower(*name)) return(0); /* not matched */ pattern++; name++; } if ((*name == 0) && (*pattern == 0)) return(1); /* matched */ else return(0); /* not matched */ } /* ** wildexp -- expand a wildcard file name ** Parameters: ** name - Pointer to the file name to be expanded. ** adtbl - Pointer to an array of pointers. ** maxargs - The maximum number of pointers contained in adtbl. ** ** Returns: ** 1 = Successful completion. The adtbl array will contain pointers ** to all file names found and will be terminated with a NULL ** pointer. It's use is exactly like use of the standard C ** argv array except that the first filename argument is in ** adtbl[0] whereas argv[0] contains a pointer to the name of ** the function which was invoked. ** 0 = An error occured. */ int wildexp(name,adtbl,maxargs) char *name; register char **adtbl; int maxargs; { struct find f; register int i=0; char *malloc(); int retval; if ((retval = findfirst(name,&f)) > 0) { *adtbl = NULL; find_cleanup(&f); return(0); } while (retval == 0) { if (f.fp->fib_DirEntryType > 0) { retval=findnext(&f); continue; /* it's a directory */ } *adtbl = malloc(strlen(f.path)+strlen(f.fname)+1); if (*adtbl == NULL) { find_cleanup(&f); return(0); /* arena is full */ } strcpy(*adtbl,f.path); if ((f.path[0] != 0) && (f.path[strlen(f.path)-1] != ':')) strcat(*adtbl,"/"); strcat(*adtbl++,f.fname); if ((++i) >= maxargs) return(0); retval=findnext(&f); } *adtbl = NULL; find_cleanup(&f); return(1); } int iswild(s) char *s; { while (*s) { if ((*s == '*') || (*s == '?')) return(1); s++; } return(0); }