#include <stdio.h>
#include <exec/memory.h>
#include <functions.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#define MAXCMDLEN  1024L

int   cmdTooLong;
char  cmdstr[MAXCMDLEN+1]; /* This is where we put the command string.      */
char  firstchar;           /* '-' Do a pre-order tree traversal.            */
                           /* '+' Do a post-order tree traversal. (default) */
                           /* '?' Show command usage.                       */
                           /* Otherwise, it is part of the command string.  */

/* NOTE: dos.library is openned by the compiler startup code.
 * _cli_parse() is called during program startup to parse the command line.
 * We don't really want the command line parsed, so we replace it with our own
 * parser.  This works with Manx C.  I don't know what you would do to
 * make it work with Lattice.
 */

void _cli_parse( pp, alen, aptr )
  struct Process *pp;               /* Program's process structure */
  long            alen;             /* Length of the command string */
  char           *aptr;             /* The command string itself */
  {
    long   i, j;
    char *p;

    p         = aptr;
    firstchar = *p;
    j         = alen;

    switch (*p) {
       case '-' :
       case '+' :
       case '?' : p += 1; j -= 1; break;
       default  : ;
       }

    if ( alen < MAXCMDLEN ) {
         cmdTooLong = 0;
         for( i=0; i<j; i++)    /* Copy the pertinent parts of the command   */
             cmdstr[i] = p[i];  /* string to our buffer.  Make sure it fits. */
         cmdstr[i] = '\0';      /* Tack on a null char, just to be safe.     */
         }
       else
         cmdTooLong = 1;

    }

/*
 * _wb_parse() is called by Manx startup. Since we are only running from
 * the CLI, we can stub this out and reduce our program size.
 */

void _wb_parse() { }


void Syntax()
{
   printf("Sweep: Execute CLI command(s) in current directory and all\n"
          "       subdirectories.                           tml 11/89\n\n");
   printf("USAGE: SWEEP [+|-|?] cmd [ + \n cmd... ]\n\n"
          " '+'  Do a post-order (bottom up) tree traversal.  (default)\n"
          " '-'  Do a pre-order  (top  down) tree traversal.\n");
   printf(" '?'  Show command usage.  (this display)\n"
          " cmd  Command(s) you want executed in each directory.\n"
          "      Multiple commands can be issued as with the RUN command.\n");
   }

main()
{

    if (firstchar == '?') {
        Syntax();
        exit();
        }

    doDir( "\0" );
    }

doDir( topDirName )
  char *topDirName;
  {
    struct FileLock *topLock, *tmpLock;
    struct FileInfoBlock *fib;


    /* Get a lock on the Current Directory */
    topLock = Lock( topDirName, ACCESS_READ );

    if (topLock == NULL) {
        return();
        }

    tmpLock = CurrentDir( topLock );

    if (firstchar == '-')                /* Do a pre-order traversal. */
       Execute( cmdstr , 0L, Output() );

    /* The FileInfoBlock structure has to be long-word alligned, so */
    /* we should use AllocMem to insure this condition is met.      */

    fib = AllocMem( (long) sizeof( struct FileInfoBlock ), MEMF_PUBLIC );

    if ( Examine( topLock, fib ) )  /* We know this is our mother dir, so */
                                    /* don't recurse on this one.         */
       while ( ExNext( topLock, fib) ) {
            if ( fib->fib_DirEntryType > 0 ) {      /* It's a directory */
                    doDir( fib->fib_FileName);
                    }
            };

    if (firstchar != '-')                /* Do a Post-order traversal. */
       Execute( cmdstr , 0L, Output() );

    FreeMem( fib, ( long ) sizeof ( struct FileInfoBlock ) );

    topLock = CurrentDir( tmpLock );

    UnLock( topLock );
    }

