/* runbackground.c */
/* Author:  Rob Peck.  5/9/86 */

/* Modified 5/21/88 by Dan Barrett to include PATH searching; added
 * the functions FullPathOf() and FindIt(), largely taken from C.
 * Scheppner's "which.c" program.
 *
 * Also, a few "#ifdef AZTEC_C" lines had to be added.  It seems that
 * Aztec C parses the command line differently from the way Lattice
 * does with respect to arguments in quotes.  When I compiled this
 * program with Aztec, all the quotes in quoted arguments were 
 * disappearing.  I re-insert them around any argument that has a
 * space character (' ') in it.
*/

/*#define DEBUG*/ 	/* Uncomment this line for debugging. */

#define EQUAL(a,b)	!strcmp(a,b)
	
#include "exec/types.h"
#include "exec/memory.h"
#include "libraries/dosextens.h"

extern struct FileHandle *Open();
extern struct FileLock *Lock();
extern VOID *AllocMem();
	
main(argc, argv)
int argc;
char *argv[];
{	
    LONG success, delaywillbe;
    UBYTE commandstring[255];
    char *test, *filename;
    LONG fromparm;
    struct FileInfoBlock *fib;
    struct FileHandle *nilfh;	/* NOTE: will hang around until next reset */
    struct FileLock *lock, *FullPathOf();
#ifdef AZTEC_C
    int hasSpace=0;		/* Does an string have a space in it. */
#endif
    
    fib = NULL;			/* No file info block so far. */
    delaywillbe = 1;

    if(argc < 2 || EQUAL(argv[1],"?")) {
usage:
	printf("Usage: RUNBACKGROUND [ -<loaddelay>] <name> [<parm(s)>]\n");
	printf("          where optional loaddelay is 0-9,\n");
	printf("          specified in seconds for the CLI\n");
	printf("          to sleep, waiting for task to load\n");
	printf("          (minimizes inter-task disk-thrashing)\n");
	if(fib)
		FreeMem(fib, sizeof(struct FileInfoBlock));
	exit(0);
    }

    /* See if there is a delay parameter present */

    test = argv[1];

    if(*test++ == '-') {
	filename = argv[2];	/* argv[1] is delay so argv[2] is file  */
	fromparm = 3;		/* Copy parms from 3 to end  		*/

	if(*test >= '0' && *test <= '9')
	    delaywillbe = 1 + (50 * (*test - '0')); 

	if (argc < 3)
		goto usage; /* Only a delay, and no filename!! */

	argc--;		/* one less parm to copy */
    }
    else {
	filename = argv[1];
	fromparm = 2;		/* Copy parms from 2 to end 		*/
    }

    /* Now see if the file exists!  If not, it can crash the background
     * CLI and take the system along with it.
     */

    lock = FullPathOf(filename);
    if(!lock) {
	printf("%ls: Command not found\n",filename);
	goto usage;
    }
    else {
	/* If file exists, it better be a file and not a directory */

/*DJB*/	/* With my (Dan's) changes, a file that is not found at all
	 * is falsely identified as a directory.  Irritating, but not
	 * fatal.
	 */

	/* Unfortunately, it is difficult to tell if it is an executable
	 * file.  If not executable, we'll still get blown out of the
	 * water, but that is up to the user to do it right!
	 */

	fib =  (struct FileInfoBlock *)
        	AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
	if(!fib) {
	    UnLock(lock);
	    printf("Ran out of memory!\n");
	    exit(0);
	}
	else {
	    success = Examine(lock,fib);
	    if(fib->fib_DirEntryType > 0) {
/*		printf("%ls is a directory, not a file!\n",filename); */
/*DJB*/		printf("Cannot open %ls... maybe a directory?\n",filename);
		goto usage;
	    }
	}
   	FreeMem(fib, sizeof(struct FileInfoBlock));
	UnLock(lock);
    }
 
    nilfh = Open("NIL:",MODE_NEWFILE); /* will always succeed */

    strcpy( &commandstring[0], "RUN >NIL: <NIL: " );
    strcat( &commandstring[0], filename);  

    /* REMOVE THIS NEXT LINE IF YOU WANT TO INCLUDE REDIRECTION IN
     * THE COMMAND LINE FOR RUNBACKGROUND.   (The line was installed
     * to assure that something like "RUNBACKGROUND date ?" would
     * not crash the system.  "Date ?" is expecting to have an interactive
     * CLI, and unless it is specifically told to direct its output to nil:
     * it causes a crash.  If the next line is removed, and you are careful
     * about putting only NON-interactive commands in the command line,
     * everything should be ok.  Notice that if you do not specify a 
     * non-interactive file handle (named_disk_file or NIL:) for your
     * program, it may still prevent the originating CLI from going away
     * until your program ends.  Also note that specifying two instances 
     * of the same redirection (">somewhere" or "<somewhere") for a 
     * background task crashes.
     */

    strcat( &commandstring[0], " >NIL: <NIL: ");

    argc--;

    while(--argc > 0) {     /* Rebuild parameter string for passing it on */
	strcat( &commandstring[0], " ");	/* add a blank */

#ifdef AZTEC_C
	hasSpace = HasASpace(argv[fromparm]);	/* Quoted argument?     */
	if (hasSpace)				/* Then quote it again! */
		strcat( &commandstring[0], "\"");
#endif

	strcat( &commandstring[0], argv[fromparm++]);

#ifdef AZTEC_C
	if (hasSpace)
		strcat( &commandstring[0], "\"");
#endif

    }

#ifdef DEBUG
    printf("Execute %s\n", &commandstring[0]);
#else
    success = Execute( &commandstring[0] , nilfh, nilfh);
#endif

    /* The full command passed to Execute now looks like this:
     *
     *	"RUN >NIL: <NIL: FILENAME >NIL: <NIL: PARAMETER(s)"
     *
     */

    if(success) {
	printf("Started %ls as a background task\n",filename);

	/* Execute, in this case, returns IMMEDIATELY.  The process
	 * that is loading the code that is to be run as a background
	 * process is working to get everything in and started.  
	 */
    }
    /* Now, to minimize thrashing between tasks, lets put this task to 
     * sleep so that the each task actually gets a chance to load.
     */
    Delay(delaywillbe);
}

	
struct FileLock *FullPathOf(filename)
char *filename;
{
	struct FileLock *lock;
	char realname[256], *FindIt();

	strcpy(realname, FindIt(filename));
	lock = Lock(realname,ACCESS_READ);
	return(lock);
}
