/*
**	$VER: Execute.c 1.6 (20.05.97)
**
**	Execute enhancement
**
**	© Copyright 1996-1997 by Norbert Püschel
**	All Rights Reserved
*/

#include <proto/exec.h>
#include <proto/dos.h>

#include <string.h>

int ExecCommand(STRPTR command,ULONG stack,STRPTR argstr,
                struct ExecBase *SysBase,struct DosLibrary *DOSBase);

BPTR OpenScript(STRPTR script,struct DosLibrary *DOSBase);

#define BUFFLEN 384

int __saveds Start(void)

{
  struct ExecBase *SysBase;
  struct DosLibrary *DOSBase;

  struct RDArgs *args;
  LONG argvals[2];
  STRPTR filename;
  BPTR file;

  UBYTE buff[BUFFLEN+1];
  STRPTR command,argstr,s;
  int cvslash;

  ULONG stack;
  int retval = 20;

  SysBase = *(struct ExecBase **)4;

  if((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))) {
    retval = 10;

    args = ReadArgs("FILE/A,ARGUMENTS/F",argvals,0);
    if(!args) {
      PrintFault(IoErr(),"EXECUTE");
    }
    else {
      filename = (STRPTR)(argvals[0]);

      if(file = OpenScript(filename,DOSBase)) {
        if(!FGets(file,buff,BUFFLEN)) *buff = '\0';
        Close(file);

        if(buff[0] == '#' && buff[1] == '!') {   /* #! style shell select */
          for(argstr = buff+2;
              *argstr == ' ' || *argstr == '\t';
              argstr++);

          if(*argstr == '/') { /* UNIX style path name */
            cvslash = 1;
            argstr++;
          }
          else cvslash = 0;

          for(command = argstr;
              *argstr && *argstr != ' ' && *argstr != '\t' && *argstr != '\n';
              argstr++) {
            if(cvslash && *argstr == '/') {
              *argstr = ':';
              cvslash = 0;
            }
          }
          *(argstr++) = '\0';
          while(*argstr == ' ' || *argstr == '\t') argstr++;
          if(*argstr == '-') {
            for(s = argstr;*s && *s != ' ' && *s != '\t' && *s != '\n';s++);
            *(s++) = ' ';
            strcpy(s,GetArgStr());
          }
          else {
            argstr = GetArgStr();
          }
          stack = Cli()->cli_DefaultStack * sizeof(LONG);
        }
        else {
          stack = 4096;

          if(buff[0] == '/' && buff[1] == '*') { /* AREXX */
            command = "rx";
          }
          else {                                 /* normal script */
            command = "Execute.orig";
          }
          argstr = GetArgStr();
        }
        retval = ExecCommand(command,stack,argstr,SysBase,DOSBase);
      }
      FreeArgs(args);
    }
    CloseLibrary((struct Library *)DOSBase);
  }

  return(retval);
}

const UBYTE version[] = "$VER: Execute 43.7 " __AMIGADATE__;

struct PathInfo {
  BPTR nextPath;
  BPTR pathLock;
};

BPTR OpenScript(STRPTR script,struct DosLibrary *DOSBase)

{
  BPTR fh,dir;
  struct PathInfo *pi;

  fh = Open(script,MODE_OLDFILE);
  if(fh == 0) {
    for(pi = (struct PathInfo *)BADDR(Cli()->cli_CommandDir);
        fh == 0 && pi;
        pi = (struct PathInfo *)BADDR(pi->nextPath)) {
      dir = CurrentDir(pi->pathLock);
      fh = Open(script,MODE_OLDFILE);
      CurrentDir(dir);
    }
    if(fh == 0) {
      dir = Lock("C:",SHARED_LOCK);
      if(dir) {
        dir = CurrentDir(dir);
        fh = Open(script,MODE_OLDFILE);
        UnLock(CurrentDir(dir));
      }
    }
  }
  return(fh);
}

#define NAMELEN 80

int ExecCommand(STRPTR command,ULONG stack,STRPTR argstr,
                struct ExecBase *SysBase,struct DosLibrary *DOSBase)

{
  struct Segment *segment;
  BPTR seglist = 0;
  UBYTE name[NAMELEN+1];
  int i;
  BPTR dir;
  struct PathInfo *pi;

  int retval = 10;

  Forbid();
  segment = FindSegment(FilePart(command),0,0); /* check resident list */
  if(segment) {
    if(segment->seg_UC >= 0) {
      segment->seg_UC++;
      seglist = segment->seg_Seg;
    }
    else {
      if(segment->seg_UC == -2) {
        seglist = segment->seg_Seg;
      }
      else {
        segment = 0;
        seglist = 0;
      }
    }
  }
  Permit();

  if(seglist == 0) { /* load prog */
    seglist = LoadSeg(FilePart(command));
    if(seglist == 0) {
      for(pi = (struct PathInfo *)BADDR(Cli()->cli_CommandDir);
          seglist == 0 && pi;
          pi = (struct PathInfo *)BADDR(pi->nextPath)) {
        dir = CurrentDir(pi->pathLock);
        seglist = LoadSeg(command);
        CurrentDir(dir);
      }
      if(seglist == 0) {
        dir = Lock("C:",SHARED_LOCK);
        if(dir) {
          dir = CurrentDir(dir);
          seglist = LoadSeg(FilePart(command));
          UnLock(CurrentDir(dir));
        }
      }
    }
  }

  if(seglist) {
    for(i = 0;*command && i < NAMELEN;i++) {
      name[i] = *(command++);
    }
    if(i < NAMELEN) name[i++] = ' ' ;
    for(command = argstr;*command && *command != '\n' && i < NAMELEN;i++) {
      name[i] = *(command++);
    }
    name[i] = '\0';
    SetProgramName(name);
    retval = RunCommand(seglist,stack,argstr,strlen(argstr));
  }
  else {
    PrintFault(IoErr(),command);
  }

  if(segment) {
    Forbid();
    if(segment->seg_UC > 0) segment->seg_UC--;
    Permit();
  }
  else {
    if(seglist) UnLoadSeg(seglist);
  }

  return(retval);
}
