/************************************************************* * vt100 terminal emulator - Wild card and Directory support * * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 * v2.5 870214 DBW - more additions (see readme file) * v2.4 861214 DBW - lots of fixes/additions (see readme file) * v2.3 861101 DBW - minor bug fixes * v2.2 861012 DBW - more of the same * v2.1 860915 DBW - new features (see README) * 860830 Steve Drew Added Wild card support, * features(expand.c) * v2.0 860809 DBW - Major rewrite * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes * v1.0 860712 DBW - First version released * * Much of the code from this module extracted from * Matt Dillons Shell program. (Thanxs Matt.) *************************************************************/ #include "vt100.h" struct DPTR { /* Format of directory fetch ptr */ struct FileLock *lock; /* lock on directory */ struct FileInfoBlock *fib; /* mod'd fib for entry */ }; /* * Disk directory routines * * * diropen() returns a struct DPTR, or NULL if the given file does not * exist. stat will be set to 1 if the file is a directory. If the * name is "", then the current directory is openned. * * dirnext() returns 1 until there are no more entries. The **name and * *stat are set. *stat = 1 if the file is a directory. * * dirclose() closes a directory channel. * */ struct DPTR * diropen(name, stat) char *name; int *stat; { struct DPTR *dp; int namelen, endslash = 0; struct FileLock *MyLock; MyLock = (struct FileLock *)( (ULONG) ((struct Process *) (FindTask(NULL)))->pr_CurrentDir); namelen = strlen(name); if (namelen && name[namelen - 1] == '/') { name[namelen - 1] = '\0'; endslash = 1; } *stat = 0; dp = (struct DPTR *)malloc(sizeof(struct DPTR)); if (*name == '\0') dp->lock = (struct FileLock *)DupLock (MyLock); else dp->lock = (struct FileLock *)Lock (name, ACCESS_READ); if (endslash) name[namelen - 1] = '/'; if (dp->lock == NULL) { free (dp); return (NULL); } dp->fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (!Examine (dp->lock, dp->fib)) { dirclose (dp); return (NULL); } if (dp->fib->fib_DirEntryType >= 0) *stat = 1; return (dp); } dirnext(dp, pname, stat) struct DPTR *dp; char **pname; int *stat; { if (dp == NULL) return (0); if (ExNext (dp->lock, dp->fib)) { *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1; *pname = dp->fib->fib_FileName; return (1); } return (0); } dirclose(dp) struct DPTR *dp; { if (dp == NULL) return (1); if (dp->fib) FreeMem (dp->fib, (long)sizeof(*dp->fib)); if (dp->lock) UnLock (dp->lock); free (dp); return (1); } free_expand(av) char **av; { char **base = av; if (av) { while (*av) { free (*av); ++av; } free (base); } } /* * EXPAND(wild_name, pac) * wild_name - char * (example: "df0:*.c") * pac - int * will be set to # of arguments. * */ char ** expand(base, pac) char *base; int *pac; { char **eav = (char **)malloc (sizeof(char *)); int eleft, eac; char *ptr, *name; char *bname, *ename, *tail; int stat, scr; struct DPTR *dp; *pac = eleft = eac = 0; base = strcpy(malloc(strlen(base)+1), base); for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr); for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr); if (ptr < base) { bname = strcpy (malloc(1), ""); } else { scr = ptr[1]; ptr[1] = '\0'; bname = strcpy (malloc(strlen(base)+1), base); ptr[1] = scr; } ename = ptr + 1; for (ptr = ename; *ptr && *ptr != '/'; ++ptr); scr = *ptr; *ptr = '\0'; tail = (scr) ? ptr + 1 : NULL; if ((dp = diropen (bname, &stat)) == NULL || stat == 0) { free (bname); free (base); free (eav); req ("Could not open directory","",0); return (NULL); } while (dirnext (dp, &name, &stat)) { if (compare_ok(ename, name)) { if (tail) { int alt_ac; char *search, **alt_av, **scrav; struct FileLock *lock; if (!stat) /* expect more dirs, but this not a dir */ continue; lock = (struct FileLock *)CurrentDir (dp->lock); search = malloc(strlen(name)+strlen(tail)+2); strcpy (search, name); strcat (search, "/"); strcat (search, tail); scrav = alt_av = expand (search, &alt_ac); CurrentDir (lock); if (scrav) { while (*scrav) { if (eleft < 2) { char **scrav = (char **) malloc(sizeof(char *) * (eac + 10)); movmem (eav, scrav, sizeof(char *) * (eac + 1)); free (eav); eav = scrav; eleft = 10; } eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1); strcpy(eav[eac], bname); strcat(eav[eac], *scrav); free (*scrav); ++scrav; --eleft, ++eac; } free (alt_av); } } else { if (eleft < 2) { char **scrav = (char **) malloc(sizeof(char *) * (eac + 10)); movmem (eav, scrav, sizeof(char *) * (eac + 1)); free (eav); eav = scrav; eleft = 10; } eav[eac] = malloc (strlen(bname)+strlen(name)+1); eav[eac] = strcpy(eav[eac], bname); strcat(eav[eac], name); --eleft, ++eac; } } } dirclose (dp); *pac = eac; eav[eac] = NULL; free (bname); free (base); if (eac) return (eav); free (eav); return (NULL); } /* * Compare a wild card name with a normal name */ #define MAXB 8 compare_ok(wild, name) char *wild, *name; { char *w = wild; char *n = name; char *back[MAXB][2]; int bi = 0; while (*n || *w) { switch (*w) { case '*': if (bi == MAXB) { req ("Too many levels of '*'","",0); return (0); } back[bi][0] = w; back[bi][1] = n; ++bi; ++w; continue; goback: --bi; while (bi >= 0 && *back[bi][1] == '\0') --bi; if (bi < 0) return (0); w = back[bi][0] + 1; n = ++back[bi][1]; ++bi; continue; case '?': if (!*n) { if (bi) goto goback; return (0); } break; default: if (toupper(*n) != toupper(*w)) { if (bi) goto goback; return (0); } break; } if (*n) ++n; if (*w) ++w; } return (1); } set_dir(new) char *new; { register char *s; int i; struct FileLock *lock; char temp[60]; struct FileInfoBlock *fib; if (*new != '\000') { strcpy(temp, MyDir); s = new; if (*s == '/') { s++; for (i=strlen(MyDir); MyDir[i] != '/' && MyDir[i] != ':'; i--); MyDir[i+1] = '\0'; strcat(MyDir, s); } else if (exists(s, ':') == 0) { if (MyDir[strlen(MyDir)-1] != ':') strcat(MyDir, "/"); strcat(MyDir, s); } else strcpy(MyDir, s); if ((lock = (struct FileLock *)Lock(MyDir, (long)ACCESS_READ)) == 0) { req("Directory not found:",MyDir,0); strcpy(MyDir, temp); } else { fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (fib) { if (Examine(lock, fib)) { if (fib->fib_DirEntryType > 0) { CurrentDir(lock); if (MyDirLock != NULL) UnLock(MyDirLock); MyDirLock = lock; if (MyDir[strlen(MyDir)-1] == '/') MyDir[strlen(MyDir)-1] = '\000'; } else { req("Not a Directory:",MyDir,0); strcpy(MyDir,temp); } } FreeMem(fib, (long)sizeof(struct FileInfoBlock)); } else { req("Can't change directory... ","No free memory!",0); strcpy(MyDir,temp); } } } } exists(s,c) char *s,c; { while (*s != '\000') if (*s++ == c) return(1); return(0); }