/* * which: routines to find a file and return its type. * * */ #include #include #include #include #include "glob.h" #include "tsh.h" struct extension { char type; char ext[5]; } extension[] = { { PGM_EXE, ".com" }, { PGM_EXE, ".exe" }, #if 0 { PGM_SH, ".t" }, { PGM_CMD, ".bat" } #endif } ; #define NUM_EXTENSIONS (sizeof extension / sizeof extension[0]) struct mind { char *name; /* name the program has to the shell */ char *path; /* full path to it */ int type; /* == 0 if unused */ } ; #define HASHSIZE 16 static struct mind *mind[HASHSIZE]; static int mindsize[HASHSIZE]; /* * remember() saves a pathname in the hashtable. */ void remember(name, path, type) char *name, *path; { register hash, size; register struct mind *p; hash = (name[0]+name[1]) % HASHSIZE; size = mindsize[hash]; for (p=mind[hash]; size-- > 0; ++p) if (p->type == 0) goto remind; mind[hash] = realloc(mind[hash], (1+mindsize[hash]) * sizeof p[0]); if (mind[hash] == (struct mind*)0) { mindsize[hash] = 0; fprintf(stderr, "out of memory\n"); } else { p = mind[hash]+(mindsize[hash]++); remind: p->name = strdup(name); p->path = strdup(path); p->type = type; } } /* remember */ /* * _memory() gets a pathname from the hashtable. */ static struct mind * _memory(name) char *name; { register struct mind *p; register siz; siz = (name[0]+name[1]) % HASHSIZE; for (p = mind[siz], siz = mindsize[siz]; siz-- > 0; ++p) if (strcmp(p->name, name) == 0) return p; return (struct mind*)0; } /* _memory */ /* * forget() forgets about a remembered path */ void forget(name) char *name; { struct mind *p; if (p=_memory(name)) { p->type = 0; free(p->name); free(p->path); } } /* forget */ /* * findmatch() matches a string on some path, returning the extension # * of the matching type and filling in result with the actual matching * filename. */ static findmatch(path, target) char *path, *target; { register char *pathname, *gdot; register j; if (strrchr(basename(path), '.') == (char*)0) /* no extension supplied - look for one */ strcat(path, ".*"); if (pathname=glob(path, (struct glob_t*)0)) { /* found a match - is it one of the extensions we know about? */ do { if (gdot = strrchr(pathname, '.')) for (j=0; jpath); return remind->type; } for (p=path; p; p=q) { q = strchr(p, ';'); if (q) { sep = (q[-1] == ':') ? "" : "/"; sprintf(bfr, "%.*s%s%s", (int)(q-p), p, sep, name); ++q; } else { sep = (p[strlen(p)-1] == ':') ? "" : "/"; sprintf(bfr, "%s%s%s", p, sep, name); } if ((j=findmatch(bfr, result)) >= 0) return j; } return 0; } /* findfile */