home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 487.lha / whereis / whereis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-11  |  19.2 KB  |  723 lines

  1. /***************************************************************************
  2.  * Program: Whereis (searches for a filename on your [hard]-disk)          *
  3.  * Version: 1.21 for AMIGA-Computers. Last-Update:  Monday  07-Jan-1991    *
  4.  * Whereis.c by R. Bless 1989/90. All Rights reserved! Program (exe) is    *
  5.  * free distributable. Compilable under Aztec 3.6a.                        *
  6.  * ------------------------------ NOTE :---------------------------------- *
  7.  * No redistribution of a changed source and/or executable without         *
  8.  * permission of the author!!! Please ask me first. See address below.     *
  9.  * ----------------------------------------------------------------------- *
  10.  * I'm fed up with all 'whereis' or 'wo' utilities that I had, because the *
  11.  * one is always case sensitive and can't be aborted, the other is         *
  12.  * horribly slow and can't handle wildcards >:-(! So here is my product    *
  13.  * which uses no recursive procedures.                                     *
  14.  * Written from 17-10-89 to 24-10-89 (first version then addups)           *
  15.  * (C)opyright by Roland Bless (Byteable Software Products)                *
  16.  ***************************************************************************/
  17. /*
  18. Any comments or bug-reports to:
  19.  
  20. R o l a n d   B l e s s |UUCP: rob@spirits.ka.sub.org
  21. Kriegsstrasse 129       |FAX: +49211623818               BTX:0211623818-0001
  22. 7500 Karlsruhe - FRG    |---------spirits--in--the--material--world---------
  23. voice +49 721 857328    |"They built machines that they can't control" STING
  24.  
  25.    Please don't think that I'm not familiar with gotos or breaks and
  26.    such things of not structured languages, but I won't go back to
  27.    BASIC-Level with a jump here or there and you don't know where you are...
  28.    In a mood I just decided to leave these things out... Maybe I should
  29.    write in Pascal or Modula? :-)                                            */
  30. /*
  31.    future adds
  32.        -s|u|D date search
  33.        -l list format  */
  34.  
  35. #include <stdio.h>
  36. #include <ctype.h>
  37. #include <exec/memory.h>
  38. #include <libraries/dos.h>
  39. #include <libraries/dosextens.h>
  40.  
  41. #include "date.h"                  /* my own date function */
  42.  
  43. #define MAXPATH 256                /* Maximum pathname length  */
  44. #define MEMTYPE 0L                 /* Memtype: Fast or Chipmem */
  45. #define true 1                     /* Right boolean values, because */
  46. #define false 0                    /* typedef short BOOL, but TRUE= 1L! */
  47. #define ON true
  48. #define OFF false
  49.  
  50. struct ListType
  51. {
  52.   struct FileInfoBlock FIBlock;
  53.   struct FileLock      *FLock;
  54.   struct ListType  *prev;
  55. };
  56.  
  57.             /**** external functions & variables ****/
  58.  
  59. extern int Enable_Abort;
  60.  
  61. void *Lock();
  62. void *AllocMem();
  63. void *ParentDir();
  64. extern void date();
  65. struct Process *FindTask();
  66. struct MsgPort *CreatePort();
  67. long IsInteractive(), SetSignal();
  68. struct FileHandle *Input(), *Output();
  69. struct FileLock *CurrentDir();
  70.  
  71.                      /***** globals *****/
  72.  
  73. char MPath [256], c, casedep;            /* Global PathName (MainPath) */
  74. WORD  options= 0; /* options switches */
  75. WORD MPathPos= 0;
  76. struct StandardPacket *packet;
  77. struct MsgPort *replyport, *conid;
  78. struct Process *myprocess;
  79.  
  80. char *prgname;
  81. enum { CASESENSITIVE=1, DIRSONLY=2, FILESONLY=4, LONGPATH=8 , SIZE=16,
  82.        TIME=32, NOSUBDIRS=64, JUMPDIR=128 };
  83.       /* switches go here */
  84.  
  85. enum { NOMEM, NODIR, DESTROYEDENTRY, TOOMANYARGS, WRONGNAME, ILLEGALOPTION,
  86.        NOPATTERN, NOINPUT, STRANGE, INFO, USAGE };
  87.      /*** ErrorNumbers for ErrorHandle ***/
  88.  
  89. char *Msg[]=
  90. { "FATAL ERROR: Not enough memory available!\n",
  91.   "ERROR: Can't find that directory or device:",
  92.   "ERROR: Destroyed entry! Couldn't examine this '",
  93.   "ERROR: Can't handle so many arguments. See usage!\n",
  94.   "ERROR: Please no path in the filename/pattern! See usage!\n",
  95.   "ERROR: Illegal Option '",
  96.   "ERROR: I've no filepattern to search for!\n",
  97.   "ERROR: Input must be interactive! \n",
  98.   "STRANGE ERROR: Something strange happend...!\n",
  99.   "INFO: whereis V1.21 07-Jan-1991 by R. Bless.\n"
  100. };  /* Messages for ErrorHandle/Numbers */
  101.  
  102.                      /******************/
  103.  
  104. long
  105. Chk_Abort()
  106. {
  107.   return 0L;
  108. }
  109.  
  110. void ErrorHandle(ErrMsgNr)
  111. short ErrMsgNr;
  112. {
  113.   if (ErrMsgNr != USAGE)
  114.      fprintf(stderr, "%s- %s", prgname, Msg[ErrMsgNr]);
  115.   else
  116.   {
  117.      fprintf(stderr, "usage: %s [-acdfijnpst] [dev:path] filename.", prgname);
  118.      fprintf(stderr, " Wildcards *,? allowed.\n");
  119.   }
  120. }
  121.  
  122.  
  123. int SwitchRaw(RawMode)
  124. BOOL RawMode;
  125.  
  126. {
  127.   replyport= (struct MsgPort *) CreatePort(NULL, NULL);
  128.   if (!replyport)
  129.      return 1;
  130.  
  131.   packet= (struct StandardPacket *)
  132.           AllocMem((long)sizeof(*packet),MEMF_PUBLIC | MEMF_CLEAR);
  133.   if (!packet)
  134.   {
  135.     DeletePort(replyport);
  136.     return 1;
  137.   }
  138.  
  139.   /* init DOS-Packet */
  140.   packet->sp_Msg.mn_Node.ln_Name= (char *) &(packet->sp_Pkt); /* link packet- */
  141.   packet->sp_Pkt.dp_Link= &(packet->sp_Msg);                 /* to message    */
  142.   packet->sp_Pkt.dp_Port= replyport;                      /* set-up reply port*/
  143.   packet->sp_Pkt.dp_Type= ACTION_SCREEN_MODE;        /* function */
  144.  
  145.   if (RawMode==ON)
  146.   {
  147.     packet->sp_Pkt.dp_Arg1= DOSTRUE;
  148.     fflush(stdout);
  149.   }
  150.   else
  151.   {
  152.     packet->sp_Pkt.dp_Arg1= DOSFALSE;
  153.   }
  154.   PutMsg(conid,packet);  /* send packet */
  155.   WaitPort(replyport); /* wait for packet to come back */
  156.   GetMsg(replyport);   /* pull message */
  157.   FreeMem(packet, (long) sizeof(*packet));
  158.   DeletePort(replyport);
  159.   return 0;
  160. }
  161.  
  162.  
  163. void printdate(ds)
  164. struct DateStamp *ds;
  165. {
  166.   struct date mydate;
  167.  
  168.   date(&mydate, ds->ds_Days);
  169.   fprintf(stdout," %02d-%02d-%02ld %02ld:%02ld:%02ld",
  170.           mydate.day, mydate.month, mydate.year-1900,
  171.           ds->ds_Minute/60L, ds->ds_Minute%60L, ds->ds_Tick/50L);
  172. }
  173.  
  174.  
  175. void Append(s, root)   /* Appends the dirname to MPath (MainPath) */
  176. char *s;
  177. BOOL root;
  178.  
  179. {
  180.   int p;
  181.  
  182.   for (p= 0; s[p]!= '\0'; p++)
  183.       MPath[MPathPos+p]= s[p];
  184.   MPath[MPathPos+p++]= root==true ? ':' : '/';
  185.   MPath[MPathPos+p]= '\0';
  186.   MPathPos+=p;
  187. }
  188.  
  189.  
  190. void InsertPath(s, root)   /* Inserts a dirname into MPath */
  191. char *s;
  192. struct FileLock *root;
  193.  
  194. {
  195.   int p,len;
  196.  
  197.   len= strlen(s)+1;
  198.   for (p= MPathPos; p >= 0; p--)
  199.       MPath[p+len]= MPath[p];
  200.   MPathPos+=len;
  201.   for (p= 0; s[p] != '\0'; p++)
  202.       MPath[p]= s[p];
  203.  
  204.   MPath[p]= root==NULL ? ':' : '/';
  205. }
  206.  
  207.  
  208. void Cut()           /* Removes the last dirname from MPath */
  209. {
  210.   if (MPathPos) --MPathPos;
  211.   while (--MPathPos>=0 && MPath[MPathPos] != '/' && MPath[MPathPos] != ':');
  212.   MPath[++MPathPos]= '\0';
  213. }
  214.  
  215.  
  216. struct FileLock *FindRoot(FL)   /* Climbs up to root-directory */
  217. struct FileLock *FL;
  218.  
  219. {
  220.   struct FileLock *PL;
  221.  
  222.   PL= FL;
  223.   while (FL= ParentDir(FL))
  224.   {
  225.     UnLock(PL);
  226.     PL=FL;
  227.   }
  228.   return PL;
  229. }
  230.  
  231.  
  232. long GetFullPath(path)    /* Get the full pathname */
  233. char *path;
  234.  
  235. {
  236.   struct FileLock *FL, *PL;
  237.   struct FileInfoBlock *FIB;
  238.   BOOL Error= false;
  239.  
  240.   FIB= (struct FileInfoBlock *)
  241.        AllocMem ((long) sizeof(struct FileInfoBlock), MEMTYPE);
  242.  
  243.   if (!FIB)
  244.   {
  245.     ErrorHandle(NOMEM);
  246.     Error= true;
  247.   }
  248.   else
  249.   if (!(FL= (struct FileLock *) Lock(path, (ULONG) ACCESS_READ)))
  250.   {
  251.     ErrorHandle(NODIR);
  252.     fprintf(stderr," %s\n", path);
  253.     Error= true;
  254.   }
  255.  
  256.   while (FL && !Error)
  257.   {
  258.     if (!Examine(FL, FIB))
  259.     {
  260.       ErrorHandle(DESTROYEDENTRY);
  261.       fprintf(stderr,"%s'. Very strange!\n", path);
  262.       Error= true;
  263.     }
  264.     else
  265.     {
  266.       InsertPath(FIB->fib_FileName, PL= ParentDir(FL));
  267.       UnLock (FL);
  268.       FL= PL;
  269.     }
  270.   }
  271.   if (FIB) FreeMem (FIB,(long) sizeof(struct FileInfoBlock));
  272.   if (FL) UnLock (FL);
  273.   return Error;
  274. }
  275.  
  276.  
  277. /* Wildcard handling, new routine since V1.19 */
  278.  
  279. BOOL
  280. Match(s, fpat)
  281. register char *s,*fpat;
  282. {
  283.   while (*fpat!='\0')
  284.   {
  285.     if (*fpat == '*')
  286.     {
  287.       while (*fpat=='*' || *fpat=='?')
  288.       {
  289.         fpat++;         /* skip following wildcards, until letter or \0 */
  290.       }
  291.       if (*fpat!='\0')        /* letter/pattern detected! */
  292.          while (*s!='\0' && (*s&casedep) != (*fpat&casedep))
  293.                s++;
  294.       else
  295.          while (*s!='\0')    /* ingore all chars till end */
  296.                s++;
  297.     }
  298.     else
  299.     if (*fpat == '?')
  300.     {
  301.       fpat++;                    /* Just ignore that char */
  302.       if (*s!='\0') s++;
  303.     }
  304.     else
  305.     if ((*s&casedep) == (*fpat&casedep))
  306.     {
  307.       register char *stmp=s,*ptmp=fpat;
  308.  
  309.       /* test whether sub-string matches or not */
  310.       while (*stmp!='\0' && ((*stmp&casedep) == (*ptmp&casedep)))
  311.       {
  312.          stmp++;ptmp++;
  313.       }
  314.       if (*stmp=='\0' || *ptmp=='*' || *ptmp=='?' || *ptmp=='\0')
  315.       {
  316.         fpat=ptmp;s=stmp;     /* it does! next wildcard or so... */
  317.       }
  318.       else
  319.       {
  320.         s++;
  321.         while (*s!='\0' && (*s&casedep) != (*fpat&casedep)) s++;
  322.       }
  323.     }
  324.     else
  325.         return false;
  326.   }
  327.   return (*s=='\0' ? true : false);
  328. }
  329.  
  330.  
  331. /* Now comes the main-stuff!!! */
  332.  
  333. BOOL Search (path, fpat)       /* not recursive! */
  334. char *path, *fpat;
  335.  
  336. {
  337.   struct FileLock      *FL= NULL;
  338.   struct FileInfoBlock *FIB= NULL;
  339.   struct ListType  *LChainP= NULL, *OldLChainP= NULL;
  340.  
  341.   BOOL Error= false;
  342.   char cbuf;
  343.   int p;
  344.  
  345.   casedep= (options & CASESENSITIVE) ? 0xFF : 0x5F; /* Mask for match() */
  346.  
  347.   if (!fpat)
  348.   {
  349.     ErrorHandle(WRONGNAME);
  350.     Error= true;
  351.   }
  352.   else
  353.   if (path)
  354.   {
  355.      if (options & LONGPATH)
  356.         Error= GetFullPath(path); /* Full-Pathname */
  357.      else
  358.      {                            /* "short pathname" */
  359.        int p;
  360.  
  361.        for (p= 0; path[p]!= '\0'; p++)
  362.             MPath[MPathPos+p]= path[p];
  363.  
  364.        if (p>0)
  365.        {
  366.          p--;
  367.          if (MPath[MPathPos+p]!='/' && MPath[MPathPos+p]!=':')
  368.          {
  369.            p++; MPath[MPathPos+p]= '/';
  370.          }
  371.          p++;
  372.        }
  373.        else
  374.          MPathPos= 0;
  375.  
  376.        MPath[MPathPos+p]= '\0';
  377.        MPathPos+= p;
  378.      }
  379.   }
  380.  
  381.   if (!Error)
  382.   {
  383.     LChainP= (struct ListType *)
  384.              AllocMem ((long) sizeof(struct ListType), MEMTYPE);
  385.  
  386.     if (!LChainP)
  387.     {
  388.       ErrorHandle(NOMEM);
  389.       Error= true;
  390.     }
  391.     else
  392.     {
  393.       FIB= &LChainP->FIBlock;
  394.  
  395.       if (!(FL= (struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ)))
  396.       {
  397.         ErrorHandle(NODIR);
  398.         fprintf(stderr," %s\n", MPath);
  399.         Error= true;
  400.       }
  401.       else
  402.       {
  403.         if (!path)
  404.            FL= FindRoot(FL);
  405.  
  406.         if (!Examine(FL, FIB))
  407.         {
  408.           ErrorHandle(DESTROYEDENTRY);
  409.           fprintf(stderr,"%s'. Very strange!\n", path);
  410.           Error= true;
  411.         }
  412.         else
  413.           if (!path) Append(FIB->fib_FileName, true);
  414.  
  415.         if (!Error)
  416.          while (FL)
  417.          {
  418.            while (FL && ExNext(FL, FIB) && !Error)
  419.            {
  420.              if (Match(FIB->fib_FileName, fpat))  /*Compare filename&pattern*/
  421.              {
  422.                BOOL found= false;
  423.  
  424.                if (FIB->fib_DirEntryType >= 0L)      /** => it is a dirname **/
  425.                {
  426.                  if (!(options & FILESONLY))
  427.                  {
  428.                    fprintf(stdout, "%s%s", MPath, FIB->fib_FileName);
  429.  
  430.                    if (options & SIZE)
  431.                       fprintf(stdout, " (dir) ");
  432.  
  433.                    if (options & TIME)
  434.                       printdate(&(FIB->fib_Date));
  435.                    fprintf(stdout, "\n");
  436.                    if (options & JUMPDIR)
  437.                       found= true;
  438.                  }
  439.                }
  440.                else                                 /** => it is a filename **/
  441.                if (!(options & DIRSONLY))
  442.                {
  443.                  fprintf(stdout, "%s%s", MPath, FIB->fib_FileName);
  444.  
  445.                  if (options & SIZE)
  446.                      fprintf(stdout, " %ld",FIB->fib_Size);
  447.                  if (options & TIME)
  448.                     printdate(&(FIB->fib_Date));
  449.                  fprintf(stdout, "\n");
  450.                  if (options & JUMPDIR)
  451.                     found= true;
  452.                }
  453.                if (found)
  454.                {
  455.                  if (SwitchRaw(ON))
  456.                     Error= true;
  457.                  else
  458.                  {
  459.                    int c;
  460.  
  461.                    fprintf(stderr,"Change to that dir? [yNq]:");
  462.                    c= getchar();
  463.                    fprintf(stderr,"%c\n", c);
  464.                    SwitchRaw(OFF);
  465.  
  466.                    if (toupper(c)=='Y')
  467.                    {
  468.                      struct FileLock *CDL;
  469.                      struct CommandLineInterface *CLI;
  470.                      char *i;
  471.                      int p;
  472.  
  473.                      if (FIB->fib_DirEntryType >= 0L)
  474.                         Append(FIB->fib_FileName, false);
  475.                      /* if Directory found append it to mpath, cause we'll: */
  476.  
  477.                      /* change the current dir */
  478.  
  479.                      CDL=(struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ);
  480.                      if (!CDL)
  481.                      {
  482.                        ErrorHandle(STRANGE);
  483.                        Error= true;
  484.                      }
  485.                      CDL= CurrentDir(CDL);
  486.                      UnLock(CDL);
  487.                      /* The new-lock must be retained and can't be unlocked,
  488.                         the old one must be unlocked */
  489.  
  490.                      CLI=(struct CommandLineInterface *)
  491.                           BADDR(myprocess->pr_CLI);
  492.                      i= (char *) ((CLI->cli_SetName) << 2);
  493.  
  494.                      /* Copy the new name to CLI */
  495.                      for (p=0; MPath[p]!='\0'; p++)
  496.                          *(i+p+1)= MPath[p];
  497.                      if (MPath[p-1]=='/')
  498.                      {
  499.                        *i= (char) (p-1);
  500.                      }
  501.                      else
  502.                        *i= (char) p;
  503.  
  504.                      if (FIB->fib_DirEntryType >= 0L)
  505.                         Cut();
  506.  
  507.                      Error= true;
  508.                    }
  509.                    if (toupper(c)=='Q')
  510.                    {
  511.                      Error= true;
  512.                      fprintf(stdout,"Quit!\n");
  513.                    }
  514.                  }
  515.                }
  516.              }
  517.  
  518.              if (FIB->fib_DirEntryType >= 0L) /* Dirname? Climb down the tree */
  519.              {
  520.                if (!(options & NOSUBDIRS))
  521.                {
  522.                  Append(FIB->fib_FileName, false);
  523.                  LChainP->FLock= FL;
  524.                  LChainP->prev = OldLChainP;
  525.                  OldLChainP= LChainP;
  526.                  cbuf= MPath[MPathPos-1]; MPath[MPathPos-1]= '\0';
  527.                  FL=(struct FileLock *) Lock(MPath, (ULONG) ACCESS_READ);
  528.                  MPath[MPathPos-1]= cbuf;
  529.                  if (!FL)
  530.                  {
  531.                    ErrorHandle(STRANGE);
  532.                    Error= true;
  533.                  }
  534.                  else
  535.                  {
  536.                    LChainP= (struct ListType *) AllocMem
  537.                          ((long) sizeof(struct ListType), MEMTYPE);
  538.  
  539.                    if (!LChainP)
  540.                    {
  541.                      ErrorHandle(NOMEM);
  542.                      Error= true;
  543.                      UnLock(FL);           /* Free last Lock */
  544.                      LChainP= OldLChainP;  /* To free the whole list */
  545.                      FL= OldLChainP->FLock; /* Get actual Lock */
  546.                      OldLChainP= OldLChainP->prev;
  547.                    }
  548.                    else
  549.                    {
  550.                      FIB= &LChainP->FIBlock;
  551.                      Examine(FL, FIB);
  552.                    }
  553.                  }
  554.                }
  555.              }
  556.            }            /* Climb-up-the-tree section*/
  557.            if (SetSignal(NULL, NULL) & (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D))
  558.            {
  559.              SetSignal(NULL, (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D));
  560.              if (!Error)
  561.              {
  562.                 fprintf(stderr, "** BREAK **\n"); /* Just print one break */
  563.                 Error= true;
  564.              }
  565.            }
  566.            if (LChainP)    /* Is there still an entry? */
  567.            {
  568.              UnLock(FL);   /* Free actual Lock */
  569.              Cut();
  570.              FreeMem (LChainP, (long) sizeof(struct ListType));
  571.              if (OldLChainP)        /* Get next entry to free,climb up list */
  572.              {
  573.                FL = OldLChainP->FLock;
  574.                FIB= &OldLChainP->FIBlock;
  575.                LChainP= OldLChainP;
  576.                OldLChainP= OldLChainP->prev;
  577.              }
  578.              else                  /* Last entry reached */
  579.              {
  580.                FL= NULL;
  581.                LChainP= NULL;
  582.              }
  583.            }
  584.            else
  585.              FL= NULL;  /* No more entries? -> leave while loop */
  586.          }
  587.       }
  588.     }
  589.   }
  590.   if (LChainP) FreeMem (LChainP,(long) sizeof(struct ListType));
  591.   if (OldLChainP) FreeMem (OldLChainP,(long) sizeof(struct ListType));
  592.   if (FL) UnLock (FL);
  593.  
  594.   return Error;
  595. }
  596.  
  597.                  /******* main(), what else? *******/
  598.  
  599. main(argc, argv)
  600. int argc;
  601. char **argv;
  602.  
  603. {
  604.   int i1, i2, findx= 0;
  605.   char *args[2], *patharg=NULL, *filepattern=NULL;
  606.  
  607.  
  608.   Enable_Abort= 0;                     /*** No Ctrl-C please!!! ***/
  609.   args[0]= args[1]= NULL;
  610.   prgname= *argv;
  611.  
  612.   SetSignal(NULL, (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D));   /*** Clear Ctrl-D signal ***/
  613.  
  614.   if (argc == 1)
  615.   {
  616.     ErrorHandle(USAGE);
  617.     exit(RETURN_OK);
  618.   }
  619.  
  620.   for (i1= 1; i1 != argc; i1++)
  621.   {
  622.       if (*argv[i1] == '-')
  623.          for (i2= 1; argv[i1][i2] != '\0'; i2++)
  624.          {
  625.            switch (argv[i1][i2])
  626.            {
  627.              case 'a': options|= SIZE | TIME;
  628.                        break;
  629.  
  630.              case 'c': options|= CASESENSITIVE;
  631.                        break;
  632.  
  633.              case 'd': options|= DIRSONLY;
  634.                        break;
  635.  
  636.              case 'f': options|= FILESONLY;
  637.                        break;
  638.  
  639.              case 'i': ErrorHandle(USAGE);
  640.                        ErrorHandle(INFO);
  641.                        exit(RETURN_OK);
  642.                        break;
  643.  
  644.              case 'j': if (IsInteractive(Input()))
  645.                        {
  646.                          myprocess= (struct Process *) FindTask(NULL);
  647.                          conid = (struct MsgPort *) myprocess->pr_ConsoleTask;
  648.                                  /* get con-handler */
  649.                          options|= (JUMPDIR | LONGPATH);
  650.                        }
  651.                        else
  652.                        {
  653.                          ErrorHandle(NOINPUT);
  654.                          exit(RETURN_FAIL);
  655.                        }
  656.  
  657.                        break;
  658.  
  659.              case 'n': options|= NOSUBDIRS;
  660.                        break;
  661.  
  662.              case 'p': options|= LONGPATH;
  663.                        break;
  664.  
  665.              case 's': options|= SIZE;
  666.                        break;
  667.  
  668.              case 't': options|= TIME;
  669.                        break;
  670.  
  671.  
  672.              default : ErrorHandle(ILLEGALOPTION);
  673.                        fprintf(stderr,"%c' !\n", argv[i1][i2]);
  674.                        ErrorHandle(USAGE);
  675.                        exit (RETURN_ERROR);
  676.                        break;
  677.            }
  678.          }
  679.       else
  680.       {
  681.         if (findx > 1)
  682.         {
  683.           ErrorHandle(TOOMANYARGS);
  684.           exit (RETURN_ERROR);
  685.         }
  686.         else
  687.         {
  688.           args[findx]= argv[i1]; findx++;
  689.         }
  690.       }
  691.   }
  692.  
  693.   if (findx==0)
  694.   {
  695.     ErrorHandle(NOPATTERN);
  696.     ErrorHandle(USAGE);
  697.     exit(RETURN_ERROR);
  698.   }
  699.   for (i1= 0; i1 < 2; i1++)
  700.   {
  701.     if (args[i1] != NULL)
  702.     {
  703.       for (i2= 0; (c= args[i1][i2]) != '\0' && c != ':' && c != '/';i2++);
  704.  
  705.       if (c != '\0')
  706.          patharg= args[i1];
  707.       else
  708.          filepattern= args[i1];
  709.     }
  710.   }
  711.   if (findx == 2 && !patharg)
  712.   {
  713.      patharg= args[0];
  714.      filepattern= args[1];
  715.   }
  716.  
  717.   if (Search(patharg, filepattern) == true)
  718.   {
  719.     fprintf(stderr, "%s-- Aborted!\n", prgname);
  720.     exit(RETURN_ERROR);
  721.   }
  722. }
  723.