home *** CD-ROM | disk | FTP | other *** search
- /*->c.wild */
-
- /* wildcard code added by David Pilling for the Archimedes */
- /* bits taken from C Kermit */
-
- /* Section modified by Justin Fletcher to work with kernel.h and swis.h
- rather than arthur.h */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include "kernel.h"
- #include "swis.h"
-
- #define MAXWLD 512 /* Maximum wildcard filenames */
- #define MAXNAMLEN 255
-
-
- static int fcount; /* Number of files in wild group */
- static char nambuf[MAXNAMLEN+2]; /* Buffer for a filename */
-
- static char *mtchs[MAXWLD], /* Matches found for filename */
- **mtchptr; /* Pointer to current match */
-
-
- /*
- * osgbpb with r0==9 is used to read directory names;
- * the data returned is copied into a struct dirent.
- */
-
- struct dirent {
- unsigned int d_reclen; /* length of this record */
- unsigned int d_namlen; /* length of string in d_name */
- char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
- };
-
- /*
- * This macro calculates the amount of storage required for
- * the directory entry.
- */
- #undef DIRSIZ
- #define DIRSIZ(dp) \
- ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &3))
-
- /*
- * Definitions for library routines operating on directories.
- */
- typedef struct _dirdesc
- {
- long dd_pos; /* current position in directory. */
- struct dirent *dd_dirent;
- char dd_name[MAXNAMLEN+1]; /* osgbpb needs a name */
- char dd_buf[MAXNAMLEN+1]; /* osgbpb needs a buffer */
- } DIR;
-
- extern DIR *opendir( char * );
- extern void closedir( DIR *);
-
- struct FileData {int loadaddr, execaddr, length, attrib;};
-
- struct BTim {int low, high;};
-
- int
- GetFileInformation(
- struct FileData *info,
- struct BTim *tstamp,
- char * name,
- int len )
- {
- static _kernel_osfile_block o_b;
- static _kernel_swi_regs rs;
- _kernel_oserror *ret;
- int objtype;
-
- #define osfind(regs) _kernel_swi(OS_Find,regs,regs)
- #define osfile(regs) _kernel_swi(OS_Find,regs,regs)
-
- /* printf("Info on %s\n",name); */
- /* Open file for reading */
- rs.r[0] = 0x40;
- rs.r[1] = (int)name;
- if( (ret=osfind( &rs )) != NULL )
- {
- fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
- return -1;
- }
-
- if( rs.r[0] == 0 )
- /* File does not exist */
- return -1;
-
- /* close the file just opened */
- rs.r[1] = rs.r[0];
- rs.r[0] = 0;
-
- if( (ret=osfind( &rs )) != NULL )
- {
- fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
- return -1;
- }
-
- /* o_b.action = 5; */
- /* o_b.name = name; */
-
- if( (objtype=_kernel_osfile( 5,name,&o_b )) <0 )
- {
- ret=_kernel_last_oserror();
- fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
- return -1;
- }
- /* printf("Objtype=%i\n",objtype); */
-
- info->loadaddr = o_b.load;
- info->execaddr = o_b.exec;
- info->length = o_b.start;
- info->attrib = o_b.end;
-
- len=0; /* filename len */
- tstamp->low=0;
-
- /* Return file type */
- return objtype;
- }
-
- DIR *
- opendir( filename )
- char *filename;
- {
- DIR * dirp;
-
- if( (dirp = (DIR*)malloc(sizeof(DIR))) == NULL )
- return NULL;
-
- if( (dirp->dd_dirent =
- (struct dirent*)malloc(sizeof(struct dirent))) == NULL )
- return NULL;
-
- dirp->dd_pos = 0;
- strcpy( dirp->dd_name, filename );
-
- return dirp;
-
- }
-
- struct dirent *
- readdir( dirp )
- DIR *dirp;
- {
- static _kernel_osgbpb_block par;
- struct dirent *dp;
- char *name;
-
- /* par.action = 9; */
- /* par.file_handle = (int)dirp->dd_name; */
- par.dataptr = dirp->dd_buf;
- par.nbytes = 1;
- par.fileptr = (int)dirp->dd_pos;
- par.buf_len = sizeof( dirp->dd_buf );
- par.wild_fld = "*";
-
- /* printf("Doing GBPB on %s\n",dirp->dd_name); */
- if( _kernel_osgbpb( 9, (int)dirp->dd_name, &par ) ==-2 )
- return NULL;
-
- if( (par.nbytes != 1) || (par.fileptr == -1) )
- return NULL;
-
- name = dirp->dd_buf;
- /* printf("Read %s\n",name); */
-
- dp = dirp->dd_dirent;
-
- dp->d_namlen = strlen( name );
- dp->d_reclen = sizeof(struct dirent) - (MAXNAMLEN+1) +
- dp->d_namlen + 1;
- strcpy( dp->d_name, name );
-
- dirp->dd_pos++;
-
- return dp;
-
- }
-
- long
- telldir( dirp )
- DIR *dirp;
- {
- return dirp->dd_pos;
- }
-
- void
- seekdir( dirp, loc )
- DIR *dirp;
- long loc;
- {
- dirp->dd_pos = loc;
- return;
- }
-
- void
- closedir( dirp )
- DIR *dirp;
- {
- free( dirp->dd_dirent );
- free( dirp );
- return;
- }
-
-
- /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
-
- /*
- * The path structure is used to represent the name to match.
- * Each slash-separated segment of the name is kept in one
- * such structure, and they are linked together, to make
- * traversing the name easier.
- */
-
- struct path {
- char npart[MAXNAMLEN]; /* name part of path segment */
- struct path *fwd; /* forward ptr */
- };
-
-
- #define SSPACE 2000 /* size of string-generating buffer */
- static char sspace[SSPACE]; /* buffer to generate names in */
- static char *freeptr,**resptr; /* copies of caller's arguments */
- static int remlen; /* remaining length in caller's array*/
- static int numfnd; /* number of matches found */
-
- void traverse(struct path *,char *,char *);
- int match(char *,char *);
- void addresult(char *);
- int iswild(char *);
-
- /*
- * splitpath:
- * takes a string and splits the slash-separated portions into
- * a list of path structures. Returns the head of the list. The
- * structures are allocated by malloc, so they must be freed.
- * Splitpath is used internally by the filename generator.
- *
- * Input: A string.
- * Returns: A linked list of the slash-separated segments of the input.
- */
-
- struct path * splitpath(p) char *p;
- {
- struct path *head,*cur,*prv;
- int i;
- head = prv = NULL;
-
- if (*p == ':') p+=2;
- if (*p== '.') p++;
-
- while (*p != '\0')
- {
- cur = (struct path *) malloc(sizeof (struct path));
- if (cur == NULL) {fprintf(stderr,"malloc fails in splitpath()\n");exit(1);}
- cur -> fwd = NULL;
- if (head == NULL) head = cur;
- else prv -> fwd = cur; /* link into chain */
- prv = cur;
-
- for (i=0; i < MAXNAMLEN && *p != '.' && *p != '\0'; i++)
- cur -> npart[i] = *p++;
- cur -> npart[i] = '\0'; /* end this segment */
- if (i >= MAXNAMLEN) while (*p != '.' && *p != '\0') p++;
- if (*p == '.') p++;
- }
-
- return(head);
- }
-
-
- /*
- * fgen:
- * This is the actual name generator. It is passed a string,
- * possibly containing wildcards, and an array of character pointers.
- * It finds all the matching filenames and stores them into the array.
- * The returned strings are allocated from a static buffer local to
- * this module (so the caller doesn't have to worry about deallocating
- * them); this means that successive calls to fgen will wipe out
- * the results of previous calls. This isn't a problem here
- * because we process one wildcard string at a time.
- *
- * Input: a wildcard string, an array to write names to, the
- * length of the array.
- * Returns: the number of matches. The array is filled with filenames
- * that matched the pattern. If there wasn't enough room in the
- * array, -1 is returned.
- * By: Jeff Damens, CUCCA, 1984.
- */
-
- int fgen(pat,resarry,len)
- char *pat,*resarry[];
- int len;
- {
- struct path *head;
- char scratch[100],*sptr;
-
- head = splitpath(pat);
- if (*pat != ':')
- {
- scratch[0] = '\0';
- sptr = scratch;
- }
- else
- {
- strcpy(scratch,pat);
- scratch[3]=0;
- sptr = scratch+3;
- }
- /* init buffer correctly */
- numfnd = 0; /* none found yet */
- freeptr = sspace; /* this is where matches are copied */
- resptr = resarry; /* static copies of these so*/
- remlen = len; /* recursive calls can alter them */
- traverse(head,scratch,sptr); /* go walk the directory tree */
- for (; head != NULL; head = head -> fwd)
- free(head); /* return the path segments */
- return(numfnd); /* and return the number of matches */
- }
-
- /* traverse:
- * Walks the directory tree looking for matches to its arguments.
- * The algorithm is, briefly:
- * If the current pattern segment contains no wildcards, that
- * segment is added to what we already have. If the name so far
- * exists, we call ourselves recursively with the next segment
- * in the pattern string; otherwise, we just return.
- *
- * If the current pattern segment contains wildcards, we open the name
- * we've accumulated so far (assuming it is really a directory), then read
- * each filename in it, and, if it matches the wildcard pattern segment, add
- * that filename to what we have so far and call ourselves recursively on the
- * next segment.
- *
- * Finally, when no more pattern segments remain, we add what's accumulated
- * so far to the result array and increment the number of matches.
- *
- * Input: a pattern path list (as generated by splitpath), a string
- * pointer that points to what we've traversed so far (this
- * can be initialized to "/" to start the search at the root
- * directory, or to "./" to start the search at the current
- * directory), and a string pointer to the end of the string
- * in the previous argument.
- * Returns: nothing.
- */
-
-
- void
- traverse(pl,sofar,endcur)
- struct path *pl;
- char *sofar,*endcur;
- {
- DIR *fd;
- struct dirent dir_entry;
- struct dirent *dirbuf = &dir_entry;
-
- struct FileData fileinfo;
- struct BTim timeinfo;
- int rc;
- int stamped;
-
- if (pl == NULL)
- {
- *--endcur = '\0'; /* end string, overwrite trailing / */
- addresult(sofar);
- return;
- }
-
- if (!iswild(pl -> npart))
- {
- strcpy(endcur,pl -> npart);
- endcur += strlen(pl -> npart);
- *endcur = '\0'; /* end current string */
- /* if (stat(sofar,&statbuf) == 0) */ /* if current piece exists */
- rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
- if( rc >= 0 ) /* if current piece exists */
- {
- *endcur++ = '.'; /* add slash to end */
- *endcur = '\0'; /* and end the string */
- traverse(pl -> fwd,sofar,endcur);
- }
- return;
- }
-
- /* segment contains wildcards, have to search directory */
-
- *endcur = '\0'; /* end current string */
- if( *(endcur-1) == '.' )
- {
- /* Stamp on trailing . */
- *--endcur = '\0';
- stamped = 1;
- }
- else
- stamped = 0;
- /* if (stat(sofar,&statbuf) == -1) return;*/ /* doesn't exist, forget it */
- /* if ((statbuf.st_mode & S_IFDIR) == 0) return;*/ /* not a directory, skip */
-
- if( sofar[0] != '\0' )
- {
- /* cwd is represented as a NULL string!! */
- rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
- if( rc == -1 ) return; /* doesn't exist, forget it */
- if( rc != 2 ) return; /* not a directory, skip */
- }
-
- if ((fd = opendir(sofar)) == NULL) return; /* can't open, forget it */
-
- if( stamped != 0 )
- {
- *endcur++ = '.';
- *endcur = '\0';
- }
-
- while ( (dirbuf = readdir(fd)) != NULL )
- {
- strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); /* Get a null terminated copy!!! */
- nambuf[MAXNAMLEN] = '\0';
- /* if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) {*/
- if ( match(pl -> npart,nambuf)) {
- char *eos;
- strcpy(endcur,nambuf);
- eos = endcur + strlen(nambuf);
- *eos = '.'; /* end this segment */
- traverse(pl -> fwd,sofar,eos+1);
- }
- }
-
- closedir(fd);
- }
- /*
- * addresult:
- * Adds a result string to the result array. Increments the number
- * of matches found, copies the found string into our string
- * buffer, and puts a pointer to the buffer into the caller's result
- * array. Our free buffer pointer is updated. If there is no
- * more room in the caller's array, the number of matches is set to -1.
- * Input: a result string.
- * Returns: nothing.
- */
-
- void addresult(str)
- char *str;
- {
- int l;
- if (strncmp(str,"./",2) == 0) str += 2;
- if (--remlen < 0) {
- numfnd = -1;
- return;
- }
- l = strlen(str) + 1; /* size this will take up */
- if ((freeptr + l) > &sspace[SSPACE-1]) {
- numfnd = -1; /* do not record if not enough space */
- return;
- }
- strcpy(freeptr,str);
- *resptr++ = freeptr;
- freeptr += l;
- numfnd++;
- }
-
-
- int iswild(str)
- char *str;
- {
- char c;
- while ((c = *str++) != '\0')
- if (c == '*' || c == '?') return(1);
- return(0);
- }
-
- /*
- * match:
- * pattern matcher. Takes a string and a pattern possibly containing
- * the wildcard characters '*' and '?'. Returns true if the pattern
- * matches the string, false otherwise.
- * by: Jeff Damens, CUCCA
- *
- * Input: a string and a wildcard pattern.
- * Returns: 1 if match, 0 if no match.
- */
-
- int match(pattern,string) char *pattern,*string; {
- char *psave,*ssave; /* back up pointers for failure */
- psave = ssave = NULL;
- while (1) {
- for (; toupper(*pattern)==toupper(*string); pattern++,string++)
- /* skip first */
- if (*string == '\0') return(1); /* end of strings, succeed */
- if (*string != '\0' && *pattern == '?') {
- pattern++; /* '?', let it match */
- string++;
- } else if (*pattern == '*') { /* '*' ... */
- psave = ++pattern; /* remember where we saw it */
- ssave = string; /* let it match 0 chars */
- } else if (ssave != NULL && *ssave != '\0') { /* if not at end */
- /* ...have seen a star */
- string = ++ssave; /* skip 1 char from string */
- pattern = psave; /* and back up pattern */
- } else return(0); /* otherwise just fail */
- }
- }
-
-
-
- /* Z X P A N D -- Expand a wildcard string into an array of strings */
- /*
- Returns the number of files that match fn1, with data structures set up
- so that first file (if any) will be returned by the next znext() call.
- */
- int zxpand(fn) char *fn;
- {
- fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */
- if (fcount > 0)
- {
- mtchptr = mtchs; /* Save pointer for next. */
- }
- return(fcount);
- }
-
-
- /* Z N E X T -- Get name of next file from list created by zxpand(). */
- /*
- Returns >0 if there's another file, with its name copied into the arg string,
- or 0 if no more files in list.
- */
- int znext(fn) char *fn; {
- if (fcount-- > 0) strcpy(fn,*mtchptr++);
- else *fn = '\0';
- return(fcount+1);
- }
-
-