home *** CD-ROM | disk | FTP | other *** search
- /* findfile: given a base filename, a list of directories, and a list
- of possible extensions to the filename, attempts to find a file.
- Useful for doing, e.g. spawnvp. Note that the current directory
- is always searched first! If the filename already contains a
- path specification (or extension) then the given path list
- (or extension list) is ignored.
- Returns the name by which the file was found, or NULL.
-
- Written by Eric R. Smith and placed in the public domain.
- */
-
- #include <limits.h> /* needed for PATH_MAX */
- #include <stddef.h>
- #include <types.h>
- #include <stat.h>
- #include <string.h>
-
- /* characters used to separate components in a path list */
- #define PATHSEP1 ':'
- #define PATHSEP2 ','
-
- /* characters used to separate directory names in a file */
- #define DIRSEP1 '\\' /* native OS directory separator */
- #define DIRSEP2 '/' /* for emulating another OS */
-
- static char *nullext[] = { NULL };
-
- static int
- EXISTS(name)
- char *name;
- {
- struct stat dummy;
-
- if (stat(name, &dummy) != 0)
- return 0;
- if ( (dummy.st_mode & S_IFMT) != S_IFREG )
- return 0;
- return 1;
- }
-
- char *
- findfile(fname, fpath, fext)
- char *fname, *fpath, **fext;
- {
- static char try[PATH_MAX];
- char *s, *t, *extplace, **nextext, c;
- int hasext = 0, haspath = 0;
-
- if (!fname || !*fname)
- return NULL;
-
- s = try; t = fname;
-
- /* copy the file in, checking to see if a path and/or extension are already
- given */
-
- while ( c = *t++ ) {
- if (c == DIRSEP1 || c == DIRSEP2) {
- haspath = 1; hasext = 0;
- }
- else if (c == '.')
- hasext = 1;
- *s++ = c;
- }
- extplace = s;
- *s++ = 0;
-
- if (haspath || !fpath)
- fpath = "";
- if (hasext || !fext)
- fext = nullext;
-
- for(;;) { /* loop on path elements */
- nextext = fext;
- if (!hasext) {
- extplace[0] = 0;
- extplace[1] = 0;
- }
-
- if (EXISTS(try))
- return try;
- extplace[0] = '.';
- while(*nextext) { /* loop on extensions */
- (void)strcpy(&extplace[1], *nextext++);
- if (EXISTS(try))
- return try;
- }
- if (!*fpath) break; /* no more places to look */
-
- /* copy in next element of path list */
- s = try;
- while ((c = *fpath) && c != PATHSEP1 && c != PATHSEP2) {
- *s++ = c;
- fpath++;
- }
- if (c) fpath++;
- *s++ = DIRSEP1;
- t = fname;
- while (*s++ = *t++) ;
- extplace = --s ; /* where the extension gets written */
- }
- return NULL;
- }
-