;/* Find.c - Amiga Mail ExAll() example. sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Find.c slink from Find.o to Find lib lib:amiga.lib; if you don't have pragmas quit * * Pure code if pragmas are used. * Tuesday, 16-Jul-91 16:21:14, Ewout * * Compiled with SAS/C 6.56 */ /* Copyright (c) 1991-1999 Amiga, Inc. This example is provided in electronic form by Amiga, Inc. for use with the Amiga Mail Volume II technical publication. Amiga Mail Volume II contains additional information on the correct usage of the techniques and operating system functions presented in these examples. The source and executable code of these examples may only be distributed in free electronic form, via bulletin board or as part of a fully non-commercial and freely redistributable diskette. Both the source and executable code (including comments) must be included, without modification, in any copy. This example may not be published in printed form or distributed with any commercial product. However, the programming techniques and support routines set forth in these examples may be used in the development of original executable software products for Amiga computers. All other rights reserved. This example is provided "as-is" and is subject to change; no warranties are made. All use is at your own risk. No liability or responsibility is assumed. */ #include <exec/memory.h> #include <dos/dosextens.h> #include <dos/rdargs.h> #include <dos/exall.h> #include <clib/exec_protos.h> #include <clib/dos_protos.h> #include <clib/utility_protos.h> /* undef PRAGMAS if you don't have them */ /* #define PRAGMAS */ #undef PRAGMAS #ifdef PRAGMAS #include <pragmas/exec_pragmas.h> #include <pragmas/dos_pragmas.h> #include <pragmas/utility_pragmas.h> #else struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct Library *UtilityBase; #endif /* ExAll buffersize to receive data in */ #define BUFFERSIZE 512 /* Default buffersize for hold fully qualified filenames */ #define NAMEBUFFERSIZE 512 /* Used to pass data around to functions */ struct FindControl { struct DosLibrary *fc_DOSBase; UBYTE *fc_Parsebuffer; /* Buffer which contains the parsed pattern */ ULONG fc_Parselength; /* The length of this buffer */ UBYTE *fc_Namebuffer; /* Buffer to hold the filename */ ULONG fc_Namelength; /* The length of that buffer */ BOOL fc_Files; /* BOOLEAN which tells if we should only look for files */ BOOL fc_Dirs; /* BOOLEAN which tells if we should only look for dirs */ BOOL fc_All; /* ALL keyword? */ }; static UBYTE *VersTag = "\0$VER: Find 37.1 (16.07.91)"; LONG main(VOID); LONG ScanDirectory(struct FindControl *, UBYTE *); BOOL IsAssign(struct FindControl *, UBYTE *); LONG MultiScanDirectory(struct FindControl *, UBYTE *); UWORD StrLen(UBYTE *); LONG main(VOID) { #ifdef PRAGMAS struct DosLibrary *DOSBase; struct Library *UtilityBase; #endif struct RDArgs *readargs; LONG rargs[6]; struct FindControl *fc; UBYTE *pattern, **directories; struct Process *process; APTR windowptr; COUNT i; LONG rc = 0, error = 0, fatalerror = 0; #ifndef PRAGMAS /* set up SysBase */ SysBase = (*((struct Library **) 4)); #endif /* Fail silently if < 37 */ if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37)) { UtilityBase = DOSBase->dl_UtilityBase; rargs[0] = 0L; rargs[1] = 0L; rargs[2] = 0L; rargs[3] = 0L; rargs[4] = 0L; rargs[5] = 0L; if (readargs = ReadArgs("PATTERN/A,DIRECTORY/A/M,FILES/S,DIRS/S,ALL/S,BUFFER/K/N", rargs, NULL)) { if (fc = AllocMem(sizeof(struct FindControl), MEMF_CLEAR)) { #ifdef PRAGMAS fc->fc_DOSBase = DOSBase; #endif pattern = (UBYTE *) rargs[0]; fc->fc_Parselength = StrLen(pattern) * 3; if (fc->fc_Parsebuffer = AllocMem(fc->fc_Parselength, MEMF_CLEAR)) { /* Make pattern uppercase for possible character classes */ i = 0; while (pattern[i]) pattern[i] = ToUpper(pattern[i++]); if ((ParsePatternNoCase(pattern, fc->fc_Parsebuffer, fc->fc_Parselength)) != -1) { directories = (UBYTE **) rargs[1]; fc->fc_Files = (BOOL) rargs[2]; fc->fc_Dirs = (BOOL) rargs[3]; fc->fc_All = (BOOL) rargs[4]; /* * Both set or cleared, clear both anyway. Easier checking later on. */ if (fc->fc_Files == fc->fc_Dirs) fc->fc_Files = fc->fc_Dirs = FALSE; if (rargs[5]) fc->fc_Namelength = *((LONG *) rargs[5]); if (fc->fc_Namelength < NAMEBUFFERSIZE || fc->fc_Namelength > 4096) fc->fc_Namelength = NAMEBUFFERSIZE; if (fc->fc_Namebuffer = AllocMem(fc->fc_Namelength, MEMF_CLEAR)) { process = (struct Process *) FindTask(NULL); windowptr = process->pr_WindowPtr; process->pr_WindowPtr = (APTR) - 1L; while (*directories) { /* * Check if this is a standalone assign which appears in the assign * list? */ if (IsAssign(fc, *directories)) error = MultiScanDirectory(fc, *directories++); else error = ScanDirectory(fc, *directories++); if (error != 0) break; } process->pr_WindowPtr = windowptr; FreeMem(fc->fc_Namebuffer, fc->fc_Namelength); } else fatalerror = ERROR_NO_FREE_STORE; } else fatalerror = ERROR_BAD_TEMPLATE; FreeMem(fc->fc_Parsebuffer, fc->fc_Parselength); } else fatalerror = ERROR_NO_FREE_STORE; FreeMem(fc, sizeof(struct FindControl)); } else fatalerror = ERROR_NO_FREE_STORE; FreeArgs(readargs); } else fatalerror = IoErr(); /* * Error handling: To be informative, errors are shown while scanning, so the * file name which caused the error can be displayed. Other errors are shown * here. Errors which occured in the main loop are considered fatal, others * (except BREAK) just error. */ if (fatalerror) { error = fatalerror; PrintFault(fatalerror, NULL); } SetIoErr(error); if (error != 0) { if (fatalerror) rc = RETURN_FAIL; else if (error == ERROR_BREAK) rc = RETURN_WARN; else rc = RETURN_ERROR; } CloseLibrary((struct Library *) DOSBase); } else rc = RETURN_FAIL; return (rc); } LONG ScanDirectory(struct FindControl * fc, UBYTE * source) { #ifdef PRAGMAS struct DosLibrary *DOSBase = fc->fc_DOSBase; #endif LONG vargs[1]; struct ExAllControl *excontrol; struct ExAllData *ead, *buffer; BPTR sourcelock, namelock, olddirlock; BOOL exmore; LONG error; /* * Because this function may be recursively, get a fresh buffer per function call. */ if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR)) { /* Get a lock on the start directory and make it the current directory */ if (sourcelock = Lock(source, SHARED_LOCK)) { olddirlock = CurrentDir(sourcelock); if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL)) { do { /* Get both file name and type to support FILES/DIRS kewords */ exmore = ExAll(sourcelock, buffer, BUFFERSIZE, ED_TYPE, excontrol); error = IoErr(); if ((exmore == NULL && (error != ERROR_NO_MORE_ENTRIES))) { PrintFault(error, source); break; } if (excontrol->eac_Entries == 0) continue; ead = buffer; do { /* Check for CTRL-C */ if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { error = ERROR_BREAK; PrintFault(error, NULL); exmore = FALSE; break; } /* * Check if this one matches. If it does see if it is of the right type. */ if (MatchPatternNoCase(fc->fc_Parsebuffer, ead->ed_Name)) { if ((ead->ed_Type < 0 && fc->fc_Dirs == FALSE) || (ead->ed_Type > 0 && fc->fc_Files == FALSE)) { /* It is. Lock it and get the fully qualified file name */ if (namelock = Lock(ead->ed_Name, SHARED_LOCK)) { if ((NameFromLock(namelock, fc->fc_Namebuffer, fc->fc_Namelength)) == DOSTRUE) { vargs[0] = (LONG) fc->fc_Namebuffer; VFPrintf(Output(), "%s\n", vargs); } else { error = IoErr(); PrintFault(error, ead->ed_Name); } UnLock(namelock); } else { error = IoErr(); PrintFault(error, ead->ed_Name); } } } /* * If the ALL keyword is used and this is a directory, step in it by * calling this function recursively. */ if (ead->ed_Type > 0 && fc->fc_All) { error = ScanDirectory(fc, ead->ed_Name); if (error != 0) { exmore = FALSE; break; } } ead = ead->ed_Next; } while (ead); } while (exmore); FreeDosObject(DOS_EXALLCONTROL, excontrol); } else error = ERROR_NO_FREE_STORE; CurrentDir(olddirlock); UnLock(sourcelock); } else { error = IoErr(); PrintFault(error, source); } FreeMem(buffer, BUFFERSIZE); } else error = ERROR_NO_FREE_STORE; if (error == ERROR_NO_MORE_ENTRIES) error = 0; else if (error == ERROR_NO_FREE_STORE) PrintFault(error, NULL); return (error); } BOOL IsAssign(struct FindControl * fc, UBYTE * name) { #ifdef PRAGMAS struct DosLibrary *DOSBase = fc->fc_DOSBase; struct Library *UtilityBase = DOSBase->dl_UtilityBase; #endif struct DosList *doslist; UBYTE *assignname; UCOUNT assignlength; LONG position; BOOL result = FALSE; /* First lets check if this resembles a devicename. */ position = SplitName(name, ':', fc->fc_Namebuffer, 0, fc->fc_Namelength); if (position != -1) { /* Hmmm. */ if (name[position] == '\0') { /* * I guess it does. Lets see if we can find it in the assign list. Keep the * DoSList locked as briefly as possible. This shouldn't take long. */ if (doslist = AttemptLockDosList(LDF_ASSIGNS | LDF_READ)) { while (doslist = NextDosEntry(doslist, LDF_ASSIGNS)) { /* It's a BPTR */ assignname = (UBYTE *) BADDR(doslist->dol_Name); assignlength = assignname[0]; if ((Strnicmp(assignname + 1, fc->fc_Namebuffer, assignlength)) == 0) { /* Yup, it is. */ result = TRUE; break; } } UnLockDosList(LDF_ASSIGNS | LDF_READ); } /* Can't lock DosList, don't bother */ } } return (result); } LONG MultiScanDirectory(struct FindControl * fc, UBYTE * source) { #ifdef PRAGMAS struct DosLibrary *DOSBase = fc->fc_DOSBase; #endif struct DevProc *cproc = NULL; struct MsgPort *filesystemtask; LONG error; filesystemtask = GetFileSysTask(); do { /* Find handler */ if (cproc = GetDeviceProc(source, cproc)) { SetFileSysTask(cproc->dvp_Port); if ((NameFromLock(cproc->dvp_Lock, fc->fc_Namebuffer, fc->fc_Namelength)) == DOSTRUE) { error = ScanDirectory(fc, fc->fc_Namebuffer); } else { error = IoErr(); PrintFault(error, source); } if (error != 0) break; } else { error = IoErr(); PrintFault(error, source); } /* Handle multi-assign */ } while (cproc && (cproc->dvp_Flags & DVPF_ASSIGN)); SetFileSysTask(filesystemtask); if (cproc) FreeDeviceProc(cproc); return (error); } UWORD StrLen(UBYTE * string) { UBYTE *length = string + 1; while (*string++ != '\0'); return ((UWORD) (string - length)); }