
/*
 * RUN.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    RUN   handles running of external commands.
 *
 * Version 2.07M by Steve Drew 10-Sep-87
 *
 * Version 3.02A by Carlo Borreo & Cesare Dieni 20-Dec-88
 *
 */

extern char *v_path;
char *FindIt();

do_run(str)
char *str;
{
int i, len, retcode;
char buf[200]; /* enough space for 100 char cmd name + path stuff */
char *path;

char *p = av[0];
char **args = av+1;

while(*p++) *p &= 0x7F;      /* allow "com mand" */

while(*args) {				/* if any arg contains a space then */
    if (index(*args,' ')) {		/* surround with quotes, since must */
	i = strlen(*args);		/* of specified via "arg u ment" on */
	movmem(*args,(*args)+1,i);	/* original command line.	    */
	args[0][0] = args[0][i+1] = '\"';	/* mpush in execom.c has    */
	args[0][i+2] = '\0';		/* allowed for these 2 extra bytes. */
	}
    ++args;
    }
if ((len = strlen(av[0])) > 100) { ierror(NULL,509); return -1; }
if (path = FindIt(av[0],"",buf)) retcode = myfexecv(path, av);
else {
	Myprocess->pr_WindowPtr = (APTR)(-1);
	/*
	 * manx's fexecv code only allows us 38
	 * chars for command name.
	 */
	if (len > 37) av[0][37] = '\0';
	retcode = myfexecv(av[0], av);
	Myprocess->pr_WindowPtr = NULL;
	}
if (retcode < 0) {
	char *copy;
	if ((path = FindIt(av[0],".sh",buf)) == NULL) {
		fprintf(stderr,"Command Not Found %s\n",av[0]);
		return -1;
		}
	av[1] = buf;               /* particular to do_source() */
	copy = malloc(strlen(str)+3);
	sprintf(copy,"x %s",str);
	retcode = do_source(copy);
	free(copy);
	}
return retcode;
}

char *dofind(cmd, ext, buf)
char *cmd, *ext, *buf;
{
char *ptr, *s;

sprintf(buf,"%s%s",cmd,ext);
if (exists(buf)) return buf;
if (BaseName(buf)==buf) {
	s = get_var(LEVEL_SET, v_path);
	while (*s) {
		for (ptr=buf; *s && *s!=','; ) *ptr++ = *s++;
		sprintf(ptr, "%s%s", cmd, ext);
		if (exists(buf)) return buf;
		if (*s) s++;
		}
	}
return NULL;
}

char *FindIt(cmd,ext,buf)
char *cmd, *ext, *buf;
{
char *response;

Myprocess->pr_WindowPtr = (APTR)(-1);
response=dofind(cmd,ext,buf);
Myprocess->pr_WindowPtr = NULL;
return response;
}

myfexecv(cmd, argv)
char *cmd, **argv;
{
long ret_val;
struct FileHandle *fhp;
APTR sav_ret;
register char **ap, *cp, *arg;
int i;
long len, seg, sav, stksiz;
char buf[40];
union {
	long *lp;
	long ll;
	} l, stk;
long oldcin, oldcout;
long doexec();
extern long _savsp;

if (seg = LoadPrg(cmd)) goto found;
l.lp = (long *) Mycli->cli_CommandDir;
while (l.ll) {
	l.ll <<= 2;
	sav = CurrentDir(l.lp[1]);
	seg = LoadPrg(cmd);
	CurrentDir(sav);
	if (seg) goto found;
	l.ll = *l.lp;
	}
sprintf(buf, "c:%s", cmd);
if (seg = LoadPrg(buf)) goto found;
return -1;

found:

stksiz = 4 * Mycli->cli_DefaultStack;
if ((stk.lp = AllocMem(stksiz+8, 0L)) == 0) {
	UnLoadPrg(seg);
	return -1;
	}
for (len=0,ap=argv+1;*ap;ap++)
	len += strlen(*ap) + 1;
if (len==0) len++;
if ((cp = arg = AllocMem(len, 0L)) == 0) {
	UnLoadPrg(seg);
	FreeMem(stk.lp, stksiz+8);
	return -1;
	}
*stk.lp = stksiz + 8;
stk.ll += stksiz;
stk.lp[0] = stksiz;
stk.lp[1] = ((long *)_savsp)[2];
sav_ret = Myprocess->pr_ReturnAddr;
Myprocess->pr_ReturnAddr = (APTR) stk.lp;

sav = Mycli->cli_Module;
Mycli->cli_Module = seg;

for (ap=argv+1;*ap;ap++) {
	strcpy(cp, *ap);
	if (ap[1]) strcat(cp, " ");
	cp += strlen(cp);
	}
if (len==1) arg[1]='\0';
arg[len-1] = '\n';

cp = (char *)((long)Mycli->cli_CommandName << 2);
movmem(cp, buf, 40);
strcpy(cp+1, cmd);
cp[0] = strlen(cmd);

fhp = (struct FileHandle *) (Myprocess->pr_CIS << 2);
strncpy(fhp->fh_Buf<<2, arg, (int)(len < 200?len:199));
fhp->fh_Pos = 0;
fhp->fh_End = len < 200?len:199;
oldcin  = Myprocess->pr_CIS;
oldcout = Myprocess->pr_COS;

ret_val = doexec(len, stksiz, stksiz+8, len, arg, (seg+1)<<2, stk.ll);

Myprocess->pr_CIS = oldcin;
Myprocess->pr_COS = oldcout;
fhp->fh_Pos = fhp->fh_End;
UnLoadPrg(Mycli->cli_Module);
Myprocess->pr_ReturnAddr = sav_ret;
Mycli->cli_Module = sav;
FreeMem(arg, len);
movmem(buf, cp, 40);
return ret_val;
}

static long doexec()
{
#asm
	movem.l	d3-d7/a2-a5,-(sp)		;save registers
	lea		savsp(pc),a0
	move.l	sp,(a0)					;save our sp
	movem.l	8(a5),d0/d2/d3/d4/a0/a4/a7	;load params
	move.l	4(sp),a3				;get old sp from CLI
	movem.l	4(a3),a1/a2/a5/a6		;get BCPL environment
	move.l	d0,12(a1)				;set length
	move.l	a0,d1					;copy to dreg
	lsr.l	#2,d1					;convert to BPTR
	move.l	d1,8(a1)				;set ptr
	move.l	a0,d1					;copy to d1 as well
	jsr		(a4)					;call new program
	movem.l	(sp)+,d2/d3				;get stk siz and old sp
	move.l	sp,a1					;save current sp
	move.l	savsp(pc),sp			;get back our sp
	movem.l	(sp)+,d3-d7/a2-a5		;get back registers
	move.l	d0,-(sp)				;save return code
	sub.l	d2,a1					;back up a bit
	sub.l	#8,a1					;back up over header
	move.l	(a1),d0					;get size to free
	move.l	4,a6					;get ExecBase
	jsr		-210(a6)				;free the memory
	move.l	(sp)+,d0				;get the return code
#endasm
}

#asm
savsp:
	dc.l	0
#endasm
