home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol2 / ii-49 / find.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  13KB  |  484 lines

  1. ;/* Find.c - Amiga Mail ExAll() example.
  2. sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Find.c
  3. slink from Find.o to Find lib lib:amiga.lib; if you don't have pragmas
  4. quit
  5.  *
  6.  * Pure code if pragmas are used.
  7.  * Tuesday, 16-Jul-91 16:21:14, Ewout
  8.  *
  9.  * Compiled with SAS/C 6.56
  10.  */
  11. /*
  12. Copyright (c) 1991 Commodore-Amiga, Inc.
  13.  
  14. This example is provided in electronic form by Commodore-Amiga,
  15. Inc. for use with the Amiga Mail Volume II technical publication.
  16. Amiga Mail Volume II contains additional information on the correct
  17. usage of the techniques and operating system functions presented in
  18. these examples.  The source and executable code of these examples may
  19. only be distributed in free electronic form, via bulletin board or
  20. as part of a fully non-commercial and freely redistributable
  21. diskette.  Both the source and executable code (including comments)
  22. must be included, without modification, in any copy.  This example
  23. may not be published in printed form or distributed with any
  24. commercial product. However, the programming techniques and support
  25. routines set forth in these examples may be used in the development
  26. of original executable software products for Commodore Amiga
  27. computers.
  28.  
  29. All other rights reserved.
  30.  
  31. This example is provided "as-is" and is subject to change; no
  32. warranties are made.  All use is at your own risk. No liability or
  33. responsibility is assumed.
  34. */
  35.  
  36. #include <exec/memory.h>
  37. #include <dos/dosextens.h>
  38. #include <dos/rdargs.h>
  39. #include <dos/exall.h>
  40.  
  41. #include <clib/exec_protos.h>
  42. #include <clib/dos_protos.h>
  43. #include <clib/utility_protos.h>
  44.  
  45. /* undef PRAGMAS if you don't have them */
  46. /* #define PRAGMAS */
  47. #undef PRAGMAS
  48. #ifdef PRAGMAS
  49. #include <pragmas/exec_pragmas.h>
  50. #include <pragmas/dos_pragmas.h>
  51. #include <pragmas/utility_pragmas.h>
  52. #else
  53. struct ExecBase *SysBase;
  54. struct DosLibrary *DOSBase;
  55. struct Library *UtilityBase;
  56.  
  57. #endif
  58.  
  59. /* ExAll buffersize to receive data in */
  60. #define BUFFERSIZE 512
  61. /* Default buffersize for hold fully qualified filenames */
  62. #define NAMEBUFFERSIZE 512
  63.  
  64. /* Used to pass data around to functions */
  65. struct FindControl
  66. {
  67.   struct DosLibrary *fc_DOSBase;
  68.   UBYTE          *fc_Parsebuffer;       /* Buffer which contains the parsed pattern */
  69.   ULONG           fc_Parselength;       /* The length of this buffer */
  70.   UBYTE          *fc_Namebuffer;        /* Buffer to hold the filename */
  71.   ULONG           fc_Namelength;        /* The length of that buffer */
  72.   BOOL            fc_Files;  /* BOOLEAN which tells if we should only look for files */
  73.   BOOL            fc_Dirs;   /* BOOLEAN which tells if we should only look for dirs */
  74.   BOOL            fc_All;    /* ALL keyword? */
  75. };
  76.  
  77. static UBYTE   *VersTag = "\0$VER: Find 37.1 (16.07.91)";
  78.  
  79. LONG            main(VOID);
  80. LONG            ScanDirectory(struct FindControl *, UBYTE *);
  81. BOOL            IsAssign(struct FindControl *, UBYTE *);
  82. LONG            MultiScanDirectory(struct FindControl *, UBYTE *);
  83. UWORD           StrLen(UBYTE *);
  84.  
  85. LONG
  86. main(VOID)
  87. {
  88. #ifdef PRAGMAS
  89.   struct DosLibrary *DOSBase;
  90.   struct Library *UtilityBase;
  91.  
  92. #endif
  93.   struct RDArgs  *readargs;
  94.   LONG            rargs[6];
  95.   struct FindControl *fc;
  96.   UBYTE          *pattern, **directories;
  97.   struct Process *process;
  98.   APTR            windowptr;
  99.   COUNT           i;
  100.   LONG            rc = 0, error = 0, fatalerror = 0;
  101.  
  102. #ifndef PRAGMAS
  103.   /* set up SysBase */
  104.   SysBase = (*((struct Library **) 4));
  105. #endif
  106.  
  107.   /* Fail silently if < 37 */
  108.   if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  109.   {
  110.     UtilityBase = DOSBase->dl_UtilityBase;
  111.  
  112.     rargs[0] = 0L;
  113.     rargs[1] = 0L;
  114.     rargs[2] = 0L;
  115.     rargs[3] = 0L;
  116.     rargs[4] = 0L;
  117.     rargs[5] = 0L;
  118.  
  119.     if (readargs =
  120.         ReadArgs("PATTERN/A,DIRECTORY/A/M,FILES/S,DIRS/S,ALL/S,BUFFER/K/N",
  121.                  rargs,
  122.                  NULL))
  123.     {
  124.  
  125.       if (fc = AllocMem(sizeof(struct FindControl), MEMF_CLEAR))
  126.       {
  127.  
  128. #ifdef PRAGMAS
  129.         fc->fc_DOSBase = DOSBase;
  130. #endif
  131.  
  132.         pattern = (UBYTE *) rargs[0];
  133.  
  134.         fc->fc_Parselength = StrLen(pattern) * 3;
  135.         if (fc->fc_Parsebuffer = AllocMem(fc->fc_Parselength, MEMF_CLEAR))
  136.         {
  137.  
  138.           /* Make pattern uppercase for possible character classes */
  139.           i = 0;
  140.           while (pattern[i])
  141.             pattern[i] = ToUpper(pattern[i++]);
  142.  
  143.           if ((ParsePatternNoCase(pattern,
  144.                                   fc->fc_Parsebuffer,
  145.                                   fc->fc_Parselength)) != -1)
  146.           {
  147.  
  148.             directories = (UBYTE **) rargs[1];
  149.  
  150.             fc->fc_Files = (BOOL) rargs[2];
  151.             fc->fc_Dirs = (BOOL) rargs[3];
  152.             fc->fc_All = (BOOL) rargs[4];
  153.  
  154.             /*
  155.              * Both set or cleared, clear both anyway. Easier checking later on.
  156.              */
  157.             if (fc->fc_Files == fc->fc_Dirs)
  158.               fc->fc_Files = fc->fc_Dirs = FALSE;
  159.  
  160.             if (rargs[5])
  161.               fc->fc_Namelength = *((LONG *) rargs[5]);
  162.  
  163.             if (fc->fc_Namelength < NAMEBUFFERSIZE || fc->fc_Namelength > 4096)
  164.               fc->fc_Namelength = NAMEBUFFERSIZE;
  165.  
  166.             if (fc->fc_Namebuffer = AllocMem(fc->fc_Namelength, MEMF_CLEAR))
  167.             {
  168.               process = (struct Process *) FindTask(NULL);
  169.               windowptr = process->pr_WindowPtr;
  170.               process->pr_WindowPtr = (APTR) - 1L;
  171.  
  172.               while (*directories)
  173.               {
  174.  
  175.                 /*
  176.                  * Check if this is a standalone assign which appears in the assign
  177.                  * list?
  178.                  */
  179.                 if (IsAssign(fc, *directories))
  180.                   error = MultiScanDirectory(fc, *directories++);
  181.                 else
  182.                   error = ScanDirectory(fc, *directories++);
  183.  
  184.                 if (error != 0)
  185.                   break;
  186.               }
  187.  
  188.               process->pr_WindowPtr = windowptr;
  189.  
  190.               FreeMem(fc->fc_Namebuffer, fc->fc_Namelength);
  191.             }
  192.             else
  193.               fatalerror = ERROR_NO_FREE_STORE;
  194.           }
  195.           else
  196.             fatalerror = ERROR_BAD_TEMPLATE;
  197.  
  198.           FreeMem(fc->fc_Parsebuffer, fc->fc_Parselength);
  199.         }
  200.         else
  201.           fatalerror = ERROR_NO_FREE_STORE;
  202.         FreeMem(fc, sizeof(struct FindControl));
  203.       }
  204.       else
  205.         fatalerror = ERROR_NO_FREE_STORE;
  206.  
  207.       FreeArgs(readargs);
  208.  
  209.     }
  210.     else
  211.       fatalerror = IoErr();
  212.  
  213.     /*
  214.      * Error handling: To be informative, errors are shown while scanning, so the
  215.      * file name which caused the error can be displayed. Other errors are shown
  216.      * here. Errors which occured in the main loop are considered fatal, others
  217.      * (except BREAK) just error.
  218.      */
  219.  
  220.     if (fatalerror)
  221.     {
  222.       error = fatalerror;
  223.       PrintFault(fatalerror, NULL);
  224.     }
  225.  
  226.     SetIoErr(error);
  227.     if (error != 0)
  228.     {
  229.       if (fatalerror)
  230.         rc = RETURN_FAIL;
  231.       else if (error == ERROR_BREAK)
  232.         rc = RETURN_WARN;
  233.       else
  234.         rc = RETURN_ERROR;
  235.     }
  236.  
  237.     CloseLibrary((struct Library *) DOSBase);
  238.   }
  239.   else
  240.     rc = RETURN_FAIL;
  241.   return (rc);
  242. }
  243.  
  244.  
  245. LONG
  246. ScanDirectory(struct FindControl * fc, UBYTE * source)
  247. {
  248. #ifdef PRAGMAS
  249.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  250.  
  251. #endif
  252.   LONG            vargs[1];
  253.   struct ExAllControl *excontrol;
  254.   struct ExAllData *ead, *buffer;
  255.   BPTR            sourcelock, namelock, olddirlock;
  256.   BOOL            exmore;
  257.   LONG            error;
  258.  
  259.   /*
  260.    * Because this function may be recursively, get a fresh buffer per function call.
  261.    */
  262.   if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR))
  263.   {
  264.  
  265.     /* Get a lock on the start directory and make it the current directory */
  266.     if (sourcelock = Lock(source, SHARED_LOCK))
  267.     {
  268.       olddirlock = CurrentDir(sourcelock);
  269.  
  270.       if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL))
  271.       {
  272.  
  273.         do
  274.         {
  275.           /* Get both file name and type to support FILES/DIRS kewords */
  276.           exmore = ExAll(sourcelock, buffer, BUFFERSIZE, ED_TYPE, excontrol);
  277.           error = IoErr();
  278.           if ((exmore == NULL && (error != ERROR_NO_MORE_ENTRIES)))
  279.           {
  280.             PrintFault(error, source);
  281.             break;
  282.           }
  283.           if (excontrol->eac_Entries == 0)
  284.             continue;
  285.  
  286.           ead = buffer;
  287.           do
  288.           {
  289.  
  290.             /* Check for CTRL-C */
  291.             if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  292.             {
  293.               error = ERROR_BREAK;
  294.               PrintFault(error, NULL);
  295.               exmore = FALSE;
  296.               break;
  297.             }
  298.  
  299.             /*
  300.              * Check if this one matches. If it does see if it is of the right type.
  301.              */
  302.             if (MatchPatternNoCase(fc->fc_Parsebuffer, ead->ed_Name))
  303.             {
  304.               if ((ead->ed_Type < 0 && fc->fc_Dirs == FALSE)
  305.                   || (ead->ed_Type > 0 && fc->fc_Files == FALSE))
  306.               {
  307.                 /* It is. Lock it and get the fully qualified file name */
  308.                 if (namelock = Lock(ead->ed_Name, SHARED_LOCK))
  309.                 {
  310.                   if ((NameFromLock(namelock,
  311.                                     fc->fc_Namebuffer,
  312.                                     fc->fc_Namelength)) == DOSTRUE)
  313.                   {
  314.                     vargs[0] = (LONG) fc->fc_Namebuffer;
  315.                     VFPrintf(Output(), "%s\n", vargs);
  316.                   }
  317.                   else
  318.                   {
  319.                     error = IoErr();
  320.                     PrintFault(error, ead->ed_Name);
  321.                   }
  322.                   UnLock(namelock);
  323.                 }
  324.                 else
  325.                 {
  326.                   error = IoErr();
  327.                   PrintFault(error, ead->ed_Name);
  328.                 }
  329.               }
  330.             }
  331.  
  332.             /*
  333.              * If the ALL keyword is used and this is a directory, step in it by
  334.              * calling this function recursively.
  335.              */
  336.             if (ead->ed_Type > 0 && fc->fc_All)
  337.             {
  338.               error = ScanDirectory(fc, ead->ed_Name);
  339.               if (error != 0)
  340.               {
  341.                 exmore = FALSE;
  342.                 break;
  343.               }
  344.             }
  345.             ead = ead->ed_Next;
  346.           } while (ead);
  347.         } while (exmore);
  348.  
  349.         FreeDosObject(DOS_EXALLCONTROL, excontrol);
  350.  
  351.       }
  352.       else
  353.         error = ERROR_NO_FREE_STORE;
  354.  
  355.       CurrentDir(olddirlock);
  356.       UnLock(sourcelock);
  357.     }
  358.     else
  359.     {
  360.       error = IoErr();
  361.       PrintFault(error, source);
  362.     }
  363.     FreeMem(buffer, BUFFERSIZE);
  364.   }
  365.   else
  366.     error = ERROR_NO_FREE_STORE;
  367.  
  368.   if (error == ERROR_NO_MORE_ENTRIES)
  369.     error = 0;
  370.   else if (error == ERROR_NO_FREE_STORE)
  371.     PrintFault(error, NULL);
  372.  
  373.   return (error);
  374. }
  375.  
  376. BOOL
  377. IsAssign(struct FindControl * fc, UBYTE * name)
  378. {
  379. #ifdef PRAGMAS
  380.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  381.   struct Library *UtilityBase = DOSBase->dl_UtilityBase;
  382.  
  383. #endif
  384.   struct DosList *doslist;
  385.   UBYTE          *assignname;
  386.   UCOUNT          assignlength;
  387.   LONG            position;
  388.   BOOL            result = FALSE;
  389.  
  390.   /* First lets check if this resembles a devicename. */
  391.   position = SplitName(name, ':', fc->fc_Namebuffer, 0, fc->fc_Namelength);
  392.  
  393.   if (position != -1)
  394.   {
  395.     /* Hmmm. */
  396.     if (name[position] == '\0')
  397.     {
  398.  
  399.       /*
  400.        * I guess it does. Lets see if we can find it in the assign list. Keep the
  401.        * DoSList locked as briefly as possible. This shouldn't take long.
  402.        */
  403.       if (doslist = AttemptLockDosList(LDF_ASSIGNS | LDF_READ))
  404.       {
  405.         while (doslist = NextDosEntry(doslist, LDF_ASSIGNS))
  406.         {
  407.  
  408.           /* It's a BPTR */
  409.           assignname = (UBYTE *) BADDR(doslist->dol_Name);
  410.           assignlength = assignname[0];
  411.  
  412.           if ((Strnicmp(assignname + 1, fc->fc_Namebuffer, assignlength)) == 0)
  413.           {
  414.             /* Yup, it is. */
  415.             result = TRUE;
  416.             break;
  417.           }
  418.         }
  419.         UnLockDosList(LDF_ASSIGNS | LDF_READ);
  420.       }    /* Can't lock DosList, don't bother */
  421.     }
  422.   }
  423.   return (result);
  424. }
  425.  
  426. LONG
  427. MultiScanDirectory(struct FindControl * fc, UBYTE * source)
  428. {
  429. #ifdef PRAGMAS
  430.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  431.  
  432. #endif
  433.   struct DevProc *cproc = NULL;
  434.   struct MsgPort *filesystemtask;
  435.   LONG            error;
  436.  
  437.   filesystemtask = GetFileSysTask();
  438.  
  439.   do
  440.   {
  441.     /* Find handler */
  442.     if (cproc = GetDeviceProc(source, cproc))
  443.     {
  444.       SetFileSysTask(cproc->dvp_Port);
  445.       if ((NameFromLock(cproc->dvp_Lock,
  446.            fc->fc_Namebuffer,
  447.            fc->fc_Namelength)) == DOSTRUE)
  448.       {
  449.         error = ScanDirectory(fc, fc->fc_Namebuffer);
  450.       }
  451.       else
  452.       {
  453.         error = IoErr();
  454.         PrintFault(error, source);
  455.       }
  456.  
  457.       if (error != 0)
  458.         break;
  459.     }
  460.     else
  461.     {
  462.       error = IoErr();
  463.       PrintFault(error, source);
  464.     }
  465.  
  466.     /* Handle multi-assign */
  467.   } while (cproc && (cproc->dvp_Flags & DVPF_ASSIGN));
  468.  
  469.   SetFileSysTask(filesystemtask);
  470.   if (cproc)
  471.     FreeDeviceProc(cproc);
  472.  
  473.   return (error);
  474. }
  475.  
  476. UWORD
  477. StrLen(UBYTE * string)
  478. {
  479.   UBYTE          *length = string + 1;
  480.  
  481.   while (*string++ != '\0');
  482.   return ((UWORD) (string - length));
  483. }
  484.