/* RunBack.c version 5 */
/* Author:  Rob Peck.  5/9/86 */
/* Re-written by Greg Searle 7/14/89 */
/* Modified by Doug Keller 8/12/89 */

/* Command format:  RUNBACK [[-]delay [priority]] command [argumentss...]
 *
 *    delay is an integer number of seconds to wait for the task to
 *    load.  This may be used to eliminate "disk thrashing" when 
 *    loading many tasks in sequence.  May be preceded with a dash.
 *
 *    priority sets the task's priority.  Recommended between -5 and
 *    5, but may theoretically be between -127 and 127.  Don't precede
 *    with a dash unless you wish the priority to be negative.
 *
 *  Modifed 8/14/89 by Doug Keller.  v6.0  Used Lattice C v5.02
 *  with registerized parameters, no stack checking, short ints,
 *  forced prototyping, and global optimizing.
 *
 *
 * Modified 7/3/89 by Greg Searle.  version 5.  Major Cleanup.
 * Removed crash situation when program tries to input
 * input or output to the CLI.
 *
 * Oh my!  What a little cleaning up a re-coding will do!  This had a whole lot
 * of wrong turns and tangled code.  Now it works like a dream.  Even runs
 * DPaint.
 *
 * Doesn't need to check if command exists anymore.
 * Doesn't need to search path.  AmigaDOS does this automatically.
 *
 * Added priority setting.
 *
 * Parameter checking improved.  Knows when it sees a number.
 * Treats everything after its own parameters as arguments.
 *
 * Removed obsolete comments.
 */

/* Modified 5/21/88 by Dan Barrett.  version 4.
 *
 * [path searching removed in version 5.]
 *
 * 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. */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dos.h>


/* protos */
void main (int , char **);
void Usage(void);
int IsInteger (char *);
/*        */

void main (int argc, char *argv[])
{   
   LONG   loaddelay = 0, fromparm = 1, priority = 0, oldpriority,
          priorityset = FALSE, SetTaskPri();
   UBYTE  commandstring[255], name[255];

   /*struct FileHandle *nilfh;*/   /* Don't free this.  It is passed on to the task. */
   BPTR nilfh;
   struct TaskCB     *task, *FindTask();

    if (argc < 2  ||  argv[1][0] == '?') Usage();

    /********* *  Check for Delay and Priority parameters.  * *********/

    if (IsInteger (argv[1])) 
	{               /* Load Delay. */
	fromparm  = 2;
	loaddelay = 50 * atol (argv[1]);
	if (loaddelay < 0) loaddelay = -loaddelay;
	if (argc < 3) Usage();           /* Only a delay, and no filename! */
	strcpy(name, argv[2]);
    	if (IsInteger (argv[2]))
		{        /* Task priority.  */
		fromparm    = 3;
		priority    = atol (argv[2]);
		priorityset = TRUE;
		if (argc < 4) Usage();    /* Still no filename! */
		strcpy(name, argv[3]);
    		}
	}
    else
	{
	strcpy(name, argv[1]);
	}

    nilfh = Open ("NIL:" ,MODE_NEWFILE); /* will always succeed */

   /********* *  Rebuild parameter string  * *********/

    strcpy (commandstring, "RUN ");

    while (fromparm < argc) {
       strcat (commandstring, " "); /* add a blank */

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


    } /* while */

   /********* *  Run the program * *********/

   /* Priority is set by temporarily setting the priority
    * of the current CLI.  The new task takes on this
    * priority.
    */

#ifdef DEBUG
    printf("%s\n", commandstring);
    printf("Delay %ld Priority %ld\n", loaddelay, priority);
#else
    task = FindTask (NULL);
    if (priorityset) oldpriority = SetTaskPri (task, priority);
    Execute (commandstring, nilfh, nilfh);
    if (priorityset) SetTaskPri (task, oldpriority);
    printf("Started [33;3m%s[m as a background task, with a priority of %ld\n", name, priority);
#endif

   /* The full command passed to Execute now looks like this:
    *
    *   "RUN FILENAME PARAMETER(s)"
    *
    * There is no need to put re-direction in here, as it defaults to the
    * file handle passed on to the Execute() call.  Redirection only
    * confuses things, and was one of the reason for past crashes.
    */

   /* RunBack won't check if the file exists, and won't say anything to the
    * user about its actions.
    */

   /* 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 (loaddelay);

}  /* main() */
   
int IsInteger (char *s)  /* Return TRUE if string is an integer. */
{
   if (*s == '-') ++s;
   while (*s)
      if (*s < '0'  ||  *(s++) > '9') return (FALSE);
   return (TRUE);
}


void Usage()  /* Called from many places. */
{
    printf("Runback V6.0\n");
    printf("Usage: RUNBACK [[-]delay [priority]] command [arguments...]\n\n");
    exit(0);
}
