/*
**	RunBackground.c
**	Executes a command in a background shell (like Run <>NIL:), but allows
**	priority, stacksize, etc. to be specified on the command line.
**	Requires V36 or higher.
**
**	Written on 30/08/1994 by Etienne Vogt (Public domain)
*/

#include <exec/alerts.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/dostags.h>
#include <workbench/startup.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <stdlib.h>

struct ExecBase *SysBase;
static struct RDArgs *myrda;
static struct WBStartup *wbmsg;

ULONG __saveds main(void);
static void clearall(void);

static UBYTE template[] = "STACK=STACKSIZE/K/N,PRI=PRIORITY/K/N,DELAY/K/N,NOREQ/S,COMMAND/F/A";
static UBYTE version[] = "$VER: RunBackground 0.3 (19.11.95)";

#define OPT_STACKSIZE	0
#define OPT_PRIORITY	1
#define OPT_DELAY	2
#define OPT_NOREQ	3
#define OPT_COMMAND	4
#define OPTMAX		5


ULONG __saveds main(void)	/* No startup code */
{
  struct Process *myproc;
  struct CommandLineInterface *myCLI;
  LONG opts[OPTMAX];
  ULONG rc = 0;
  ULONG stacksize;
  LONG priority, noreq = 0;
  BPTR fhin, fhout;

  SysBase = *(struct ExecBase **)4;
  DOSBase = NULL;
  wbmsg = NULL;
  myrda = NULL;

  myproc = (struct Process *)FindTask(NULL);
  if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
  { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
    clearall();
    return 100;
  }

  if (!(myCLI = (struct CommandLineInterface *)BADDR(myproc->pr_CLI)))
  { WaitPort(&myproc->pr_MsgPort);	/* If started from WB, exit cleanly */
    wbmsg = (struct WBStartup *)GetMsg(&myproc->pr_MsgPort);
    clearall();
    return 20;
  }
  else
  { memset((char *)opts, 0, sizeof(opts));
    if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
    { PrintFault(IoErr(),NULL);
      clearall();
      return 20;
    }

    if (opts[OPT_STACKSIZE]) stacksize = *(ULONG *)opts[OPT_STACKSIZE];
    else stacksize = myCLI->cli_DefaultStack << 2;

    if (opts[OPT_PRIORITY]) priority = *(LONG *)opts[OPT_PRIORITY];
    else priority = myproc->pr_Task.tc_Node.ln_Pri;
    if (priority < -128 || priority > 127)
    { Printf("Invalid priority value %ld.\n", priority);
      clearall();
      return 20;
    }

    if (opts[OPT_NOREQ]) noreq = -1;

    if (!(fhin = Open("NIL:", MODE_OLDFILE)))
    { PrintFault(IoErr(), "Error opening input stream");
      clearall();
      return 20;
    }
    if (!(fhout = Open("NIL:", MODE_OLDFILE)))
    { PrintFault(IoErr(), "Error opening output stream");
      clearall();
      return 20;
    }

    if (SystemTags((STRPTR)opts[OPT_COMMAND],
		SYS_Input,	fhin,
		SYS_Output,	fhout,
		SYS_Asynch,	TRUE,
		SYS_UserShell,	TRUE,
		NP_StackSize,	stacksize,
		NP_Priority,	priority,
		NP_WindowPtr,	noreq,
		TAG_DONE ))
    { PrintFault(IoErr(), "Error starting command");
      rc = 10;
    }

    if (opts[OPT_DELAY]) Delay(*(ULONG *)opts[OPT_DELAY]);
  }
  clearall();
  return rc;
}

static void clearall(void)
{
  if (myrda) FreeArgs(myrda);
  if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  if (wbmsg)
  { Forbid();
    ReplyMsg((struct Message *)wbmsg);
  }
}
