/* Sf - Search files in volumes or directories. Strictly based on the SF program by Andrea Suatoni published in MC-Microcomputer 86, June 1989. Little enhancements by Fabio Rossetti: resident support, NOCOL option. (c) 1989 by Fabio Rossetti To compile under Lattice C v5.0x use: lc -O -v -cus sf blink lib:cres.o sf.o to sf lib lib:a.lib lib:lc.lib lib:amiga.lib sc sd nd */ #include #include #include #include #include #include #include #include #include #define NO_ERROR 0 #define ERROR_NO_MEM -101 typedef struct { struct MinNode dir_Node; LONG PathLen; STRPTR PathName; } DIR_ENTRY; GLOBAL VOID (*_ONBREAK)(); UBYTE DateFormat = FORMAT_DOS; struct Process *Pr; struct ArpBase *ArpBase; struct MinList DirList; VOID Cleanup(r1,r2,msg) LONG r1,r2; STRPTR msg; { if (msg) Puts(msg); if (ArpBase) CloseLibrary((struct Library *)ArpBase); Pr->pr_Result2 = r2; exit(r1); } STRPTR StrUpper(Str) REGISTER STRPTR Str; { REGISTER STRPTR r = Str; do { *Str = Toupper(*Str); } while (*(++Str)); return(r); } LONG AddDirEntry(PathNode,Dir) REGISTER STRPTR PathNode, Dir; { REGISTER DIR_ENTRY *Entry; if ((Entry = (DIR_ENTRY*) AllocMem(sizeof(DIR_ENTRY), MEMF_CLEAR)) == NULL) return(ERROR_NO_MEM); Entry->PathLen = strlen(PathNode) + strlen(Dir) + 2; if((Entry->PathName = (STRPTR) AllocMem(Entry->PathLen, MEMF_CLEAR)) == NULL) { FreeMem(Entry, sizeof(DIR_ENTRY)); return(ERROR_NO_MEM); } strcpy(Entry->PathName, PathNode); TackOn(Entry->PathName, Dir); AddTail((struct List *) &DirList, (struct Node *) Entry); return(0); } VOID RemDirEntry() { REGISTER DIR_ENTRY *Entry; Entry = (DIR_ENTRY *) RemHead((struct List *) &DirList); FreeMem(Entry->PathName, Entry->PathLen); FreeMem((STRPTR) Entry, sizeof(DIR_ENTRY)); } VOID FreeDirList() { while (DirList.mlh_Head->mln_Succ) RemDirEntry(); } VOID FindFile(ArgV) STRPTR ArgV[]; #define PATTERN ArgV[0] #define FILES ArgV[1] #define DIRS ArgV[2] #define QUICK ArgV[3] #define NOROOT ArgV[4] #define NOCOL ArgV[5] { REGISTER struct FileLock *DirLock; REGISTER struct FileInfoBlock *FileInfo; REGISTER STRPTR CurrentPath; REGISTER LONG Error; REGISTER BOOL Found = FALSE, First, Dir; TEXT Day [12], Time [10], Date [10], StrToken[120], Path [120]; WORD Tabs = 0; struct DateTime DateTime; if ((FileInfo = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL) { DateTime.dat_Format = DateFormat; DateTime.dat_Flags = DTF_FUTURE; DateTime.dat_StrDay = Day; DateTime.dat_StrDate = Date; DateTime.dat_StrTime = Time; NewList((struct List *) &DirList); *Path = '\0'; if (NOROOT == NULL) if (strchr(PATTERN, ':') == NULL) strcpy(Path, ":"); strcat(Path, PATTERN); PreParse((CurrentPath = StrUpper(BaseName(Path))), StrToken); *CurrentPath = '\0'; if ((DirLock = (struct FileLock *) Lock(Path, ACCESS_READ)) == NULL) Error = ERROR_INVALID_LOCK; else { PathName((BPTR) DirLock, Path, 10); UnLock((BPTR) DirLock); Error = AddDirEntry(Path,""); } while (DirList.mlh_Head->mln_Succ) { CurrentPath = ((DIR_ENTRY *) DirList.mlh_Head)->PathName; if ((DirLock = (struct FileLock *) Lock(CurrentPath, ACCESS_READ)) == (struct FileLock *) 0) { Error = ERROR_INVALID_LOCK; break; } First = TRUE; if (Examine((BPTR) DirLock, FileInfo)) { while (ExNext((BPTR) DirLock, FileInfo)) { if (Dir = (FileInfo->fib_DirEntryType >= 0)) if ((Error = AddDirEntry(CurrentPath, FileInfo->fib_FileName)) != NO_ERROR) break; if (PatternMatch(StrToken, StrUpper(strcpy(Path, FileInfo->fib_FileName))) == TRUE) if (!(DIRS || FILES) || (DIRS && Dir) || (FILES && !Dir)) { Found = TRUE; if (First) { if(Tabs) { Puts(""); Tabs = 0; } if(NOCOL) Printf("\n\"%s\"\n",CurrentPath); else Printf("\n\033[33m\"%s\"\033[31m\n", CurrentPath); First = FALSE; } if (QUICK) { if (Dir) if (NOCOL) Printf("%s%-18s",(Tabs) ? "": " ", FileInfo->fib_FileName); else Printf("\033[33m%s%-18s\033[31m",(Tabs) ? "": " ", FileInfo->fib_FileName); else Printf("%s%-18s",(Tabs) ? "": " ", FileInfo->fib_FileName); if (++Tabs == 4) { Tabs = 0; Puts(""); } } else { DateTime.dat_Stamp.ds_Days = FileInfo->fib_Date.ds_Days; DateTime.dat_Stamp.ds_Minute= FileInfo->fib_Date.ds_Minute; DateTime.dat_Stamp.ds_Tick = FileInfo->fib_Date.ds_Tick; StamptoStr(&DateTime); Printf(" %-30s ", FileInfo->fib_FileName); if (Dir) Printf(" (dir)"); else Printf("%7ld", FileInfo->fib_Size); Printf(" %-9s %9s %8s\n", Day, Date, Time); } } if (CheckBreak(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D,NULL)) { Error = ERROR_BREAK; break; } } if (Error == NO_ERROR) Error = IoErr(); } RemDirEntry(); UnLock((BPTR) DirLock); if (Error != ERROR_NO_MORE_ENTRIES) break; } if (Tabs) Puts(""); if (Error == ERROR_NO_MORE_ENTRIES && Found == TRUE) Error = NO_ERROR; FreeDirList(); FreeMem((STRPTR) FileInfo, sizeof(struct FileInfoBlock)); } else Error = ERROR_NO_MEM; switch(Error) { case NO_ERROR: break; case ERROR_INVALID_LOCK: Puts("Invalid pattern or path name"); break; case ERROR_NO_MEM: Puts("No memory"); break; case ERROR_NO_MORE_ENTRIES: Puts("Search failed"); break; case ERROR_OBJECT_NOT_FOUND: Puts("Object not found"); break; case ERROR_BREAK: Puts("***Break"); break; default: Printf("Error %ld\n", Error); } } VOID MemCleanup() { } VOID Break() { Cleanup(RETURN_WARN,NULL,"***Break"); } VOID _main(Line) REGISTER STRPTR Line; #define MAX_ARG 6 { REGISTER LONG ArgC; STRPTR Arg[MAX_ARG]; TEXT EnvBuf[2]; _ONBREAK = Break; Pr = (struct Process*)FindTask(NULL); if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion))) Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY,NULL); for (ArgC = 0; ArgC < MAX_ARG; ++ArgC) Arg[ArgC] = (STRPTR)NULL; while (*Line > ' ') ++Line; if ((ArgC = GADS(++Line, strlen(Line), "Usage: Sf PAT [FILES=F] [DIRS=D] [QUICK=Q] [NOROOT=NR] [NOCOL=NC]", Arg, "PAT/A,FILES=F/S,DIRS=D/S,QUICK=Q/S,NOROOT=NR/S,NOCOL=NC/S"))<= 0) Cleanup(RETURN_FAIL,ERROR_LINE_TOO_LONG,Arg[0]); if(Getenv("dateformat",EnvBuf,2)) switch (EnvBuf[0]) { case '1': DateFormat = FORMAT_INT; break; case '2': DateFormat = FORMAT_USA; break; case '3': DateFormat = FORMAT_CDN; break; }; if (ArgC > 0) FindFile(Arg); Cleanup(NULL,NULL,NULL); }