home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / examples / nostartup / example_3 / cat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  9.4 KB  |  256 lines

  1. /*
  2.  * Copyright (c) 1992-1993 SAS Institute, Inc, Cary, NC, USA 
  3.  * All Rights Reserved
  4.  * Command: cat.c
  5.  * Author: James E. Cooper Jr.
  6.  * Change History:
  7.  *  Date    Person      Action
  8.  * -------  ------------- -----------------
  9.  * 20AUG92  Jim Cooper      Initial Creation
  10.  *
  11.  * Notes:
  12.  *   2.0 specific program similar to the UNIX 'cat' command, with full
  13.  *   command-line parsing, wildcard support, and recursive subdirectory
  14.  *   scanning.    The AmigaDOS ROM code makes this whole thing almost trivial!
  15.  */
  16. #define __USE_SYSBASE
  17.  
  18. #include <exec/types.h>
  19. #include <exec/execbase.h>
  20. #include <exec/memory.h>
  21. #include <dos/dosextens.h>
  22. #include <dos/rdargs.h>
  23.  
  24. #include <string.h>
  25.  
  26. #include <proto/dos.h>
  27. #include <proto/exec.h>
  28.  
  29. #define DOSLIB    "dos.library"
  30. #define DOSVER    36L            /* We require AT LEAST V36 of OS */
  31.  
  32. #define THISPROC   ((struct Process *)(SysBase->ThisTask))
  33. #define Result2(x) THISPROC->pr_Result2 = x
  34.  
  35. #define BUFLEN 256            /* Size of buffer to read into */
  36.  
  37. #define MSG_CAT_FAILED "Cat failed"
  38.  
  39. #define TEMPLATE  "FILE/A/M,ALL/S"
  40. #define OPT_FILE  0
  41. #define OPT_ALL   1
  42. #define OPT_COUNT 2
  43.  
  44. int cmd_cat(void)
  45. {
  46.    struct ExecBase *SysBase = (*((struct ExecBase **) 4));
  47.    struct DosLibrary *DOSBase;
  48.    long temprc, rc;
  49.    long opts[OPT_COUNT];
  50.    struct RDArgs *rdargs;
  51.    struct AnchorPath __aligned ua;
  52.    BPTR oldlock, curlock, fh;
  53.    char fname[32];
  54.    char *curarg, **argptr, *buf;
  55.  
  56.    /*------------------------------------------------------------------------*/
  57.    /* Set up the default return code.                         */
  58.    /*------------------------------------------------------------------------*/
  59.    rc = RETURN_FAIL;
  60.  
  61.    /*------------------------------------------------------------------------*/
  62.    /* And open the dos library for our use.                     */
  63.    /*------------------------------------------------------------------------*/
  64.    if ((DOSBase = (struct DosLibrary *)OpenLibrary(DOSLIB, DOSVER)))
  65.    {
  66.       /*---------------------------------------------------------------------*/
  67.       /* O.K., now we know we're running under the correct version of DOS.   */
  68.       /* We need to get a buffer to read data into, in order for out program */
  69.       /* to work.  If we can't get one, we'll just fall out with a failure.  */
  70.       /*---------------------------------------------------------------------*/
  71.       if ((buf = AllocVec(BUFLEN, 0L)) == NULL)
  72.       {
  73.      PrintFault(IoErr(), MSG_CAT_FAILED);
  74.       }
  75.       else
  76.       {
  77.      /*------------------------------------------------------------------*/
  78.      /* Clear the options array, just to be on the safe side...         */
  79.      /*------------------------------------------------------------------*/
  80.      memset((char *)opts, 0, sizeof(opts));
  81.  
  82.      /*------------------------------------------------------------------*/
  83.      /* Parse the command line.                         */
  84.      /*------------------------------------------------------------------*/
  85.      rdargs = ReadArgs(TEMPLATE, opts, NULL);
  86.  
  87.      /*------------------------------------------------------------------*/
  88.      /* If there was an error parsing, print an error message and exit!  */
  89.      /*------------------------------------------------------------------*/
  90.      if (rdargs == NULL)
  91.      {
  92.         PrintFault(IoErr(), NULL);
  93.      }
  94.      else
  95.      {
  96.         /*---------------------------------------------------------------*/
  97.         /* Initialize for MultiArgs handling...                 */
  98.         /*---------------------------------------------------------------*/
  99.         argptr = (char **)opts[OPT_FILE];
  100.  
  101.         /*---------------------------------------------------------------*/
  102.         /* The following while loop handles the MultiArgs spec.         */
  103.         /*---------------------------------------------------------------*/
  104.         while (curarg = *argptr++)
  105.         {
  106.            /*------------------------------------------------------------*/
  107.            /* Clear our UserAnchor structure to all zeros before going   */
  108.            /* to the next step.                         */
  109.            /*------------------------------------------------------------*/
  110.            memset(&ua, 0, sizeof(struct AnchorPath));
  111.  
  112.            /*------------------------------------------------------------*/
  113.            /* Set up a default message leader.                 */
  114.            /*------------------------------------------------------------*/
  115.            strcpy(fname, MSG_CAT_FAILED);
  116.  
  117.            /*------------------------------------------------------------*/
  118.            /* Finally, call the matcher.                     */
  119.            /*------------------------------------------------------------*/
  120.            MatchFirst(curarg, &ua);
  121.            temprc = IoErr();
  122.  
  123.            /*------------------------------------------------------------*/
  124.            /* Process all matches returned.  If 'MatchFirst()' returned  */
  125.            /* an error, the 'while()' let's us skip all this and fall    */
  126.            /* through the exit code.                     */
  127.            /*------------------------------------------------------------*/
  128.            while (temprc == 0)
  129.            {
  130.           strcpy(fname, ua.ap_Info.fib_FileName);
  131.  
  132.           if (ua.ap_Info.fib_DirEntryType > 0 && opts[OPT_ALL])
  133.           {
  134.              /*------------------------------------------------------*/
  135.              /* The flag APF_DIDDIR tells us that we are 'backing    */
  136.              /* out' of a subdirectory... in other words, we have    */
  137.              /* processed all sub-files of that directory and we are */
  138.              /* moving back to its parent.  If this flag is set, we  */
  139.              /* need to clear it.                     */
  140.              /*------------------------------------------------------*/
  141.              if (!(ua.ap_Flags & APF_DIDDIR))
  142.              {
  143.             /*---------------------------------------------------*/
  144.             /* If we are printing ALL files, tell the matcher to */
  145.             /* enter this directory.                 */
  146.             /*---------------------------------------------------*/
  147.             ua.ap_Flags |= APF_DODIR;
  148.              }
  149.              ua.ap_Flags &= ~APF_DIDDIR;
  150.           }
  151.  
  152.           /*---------------------------------------------------------*/
  153.           /* If we have an error OTHER than that we are out of         */
  154.           /* files, we need to exit IMMEDIATELY!             */
  155.           /*---------------------------------------------------------*/
  156.           if (temprc && (temprc != ERROR_NO_MORE_ENTRIES))
  157.           {
  158.              break;
  159.           }
  160.  
  161.           /*---------------------------------------------------------*/
  162.           /* Set us to the directory this file lives in.         */
  163.           /*---------------------------------------------------------*/
  164.           curlock = DupLock(ua.ap_Current->an_Lock);
  165.           oldlock = CurrentDir(curlock);
  166.  
  167.           /*---------------------------------------------------------*/
  168.           /* We must open the file to read.                 */
  169.           /*---------------------------------------------------------*/
  170.           if ((fh = Open(fname, MODE_OLDFILE)) == NULL)
  171.           {
  172.              temprc = IoErr();
  173.              CurrentDir(oldlock);
  174.              UnLock(curlock);
  175.              break;
  176.           }
  177.  
  178.           /*---------------------------------------------------------*/
  179.           /* O.K., the file is open.  Now we simply read lines from  */
  180.           /* the file and write them out.  Simple two-function         */
  181.           /* operation.                          */
  182.           /*---------------------------------------------------------*/
  183.           while (FGets(fh, buf, BUFLEN))
  184.           {
  185.              PutStr(buf);
  186.           }
  187.  
  188.           /*---------------------------------------------------------*/
  189.           /* Close the file, now that we're finished with it.        */
  190.           /*---------------------------------------------------------*/
  191.           Close(fh);
  192.  
  193.           /*---------------------------------------------------------*/
  194.           /* Now change the directory back to where it was when we   */
  195.           /* got started.                         */
  196.           /*---------------------------------------------------------*/
  197.           CurrentDir(oldlock);
  198.           UnLock(curlock);
  199.  
  200.           /*---------------------------------------------------------*/
  201.           /* Now get the next file which matches the given pattern.  */
  202.           /*---------------------------------------------------------*/
  203.           MatchNext(&ua);
  204.           temprc = IoErr();
  205.            }
  206.  
  207.            /*------------------------------------------------------------*/
  208.            /* If the only error we had was that we ran out of files to   */
  209.            /* type, we are doing fine!  Set the return code so the user  */
  210.            /* knows everything went well.                     */
  211.            /*------------------------------------------------------------*/
  212.            if (temprc == ERROR_NO_MORE_ENTRIES)
  213.            {
  214.           rc = RETURN_OK;
  215.            }
  216.            else
  217.            {
  218.           PrintFault(temprc,fname);
  219.  
  220.           /*---------------------------------------------------------*/
  221.           /* If the user hit Ctrl-C, we have to warn him that he is  */
  222.           /* being rude!                         */
  223.           /*---------------------------------------------------------*/
  224.           if (temprc == ERROR_BREAK)
  225.           {
  226.              rc = RETURN_WARN;
  227.           }
  228.           else
  229.           {
  230.              /*------------------------------------------------------*/
  231.              /* If there was any other error, FAIL!!!             */
  232.              /*------------------------------------------------------*/
  233.              rc = RETURN_FAIL;
  234.           }
  235.            }
  236.            /*------------------------------------------------------------*/
  237.            /* We have to clean up after ourselves.                 */
  238.            /*------------------------------------------------------------*/
  239.            MatchEnd(&ua);
  240.         }
  241.         FreeArgs(rdargs);
  242.      }
  243.       }
  244.       CloseLibrary((struct Library *)DOSBase);
  245.    }
  246.    else
  247.    {
  248.       /*---------------------------------------------------------------------*/
  249.       /* They tried to run us under the wrong version of the OS.  We need to */
  250.       /* exit gracefully, yet still let them know what went wrong...         */
  251.       /*---------------------------------------------------------------------*/
  252.       Result2(ERROR_INVALID_RESIDENT_LIBRARY);
  253.    }
  254.    return(rc);
  255. }
  256.