/* spawn.c	1 May 1990 David G. Grubbs (-dgg-)

   These functions are called from "eval" to perform the "system" and
   "exec" functions.
*/
#include <exec/types.h>
#include <exec/tasks.h>
#include <libraries/dosextens.h>
#include <functions.h>
#include <string.h>

#include "EXTERN.h"
#include "perl.h"

int ExecASpawn(STR *really, int *arglast, int spawn)
{
    STR **st = stack->ary_array;
    int sp = arglast[1];
    int items = arglast[2] - sp;
    char **a, **argv, *cmd = NULL;
    int status;

    if (!items)
	return(0xff00);

    New(1201,argv, items+1, char*);
    a = argv;
    for (st += ++sp; items > 0; items--,st++) {
	if (*st)
	    *a++ = str_get(*st);
	else
	    *a++ = "";
    }
    *a = Nullch;
    if (really) cmd = str_get(really);
    if (!cmd || !*cmd) cmd = argv[0];
    if (!cmdexists(cmd)) {
	Safefree(argv);
	return(0xff00);
    }

    for (a = argv; *a; a++)
	amigaizepath(*a = savestr(*a));

#ifdef DEBUGGING
    if (debug) {
	printf ("ExecASpawn Command = [%s] Args:", cmd);
	for (a = argv; *a; a++)
	    printf (" [%s]\n", *a);

	puts("");
    }
#endif
    fflush(stdout);
    fflush(stderr);
    if (!spawn)			/* exec, no return */
	execvp(cmd,argv);
    else if (!fexecv(cmd,argv))
	status = wait();
    else
	status = 0xff;

    for (a = argv; *a; a++)
	Safefree(*a);
    Safefree(argv);
    return(status << 8);	/* Unix wait has return code in bits 8-15 */
}


bool do_aexec(STR *really, int *arglast)
{
    return(ExecASpawn(really, arglast, 0));
}

int do_aspawn(STR *really, int *arglast)
{
    return(ExecASpawn(really, arglast, 1));
}

int ExecSpawn(char *ocmd, int spawn)
{
    char **a, **argv, *s, *cmd;
    int exists, status = 0xff;

    if (!ocmd) return(0xff00);
#ifdef DEBUGGING
    if (debug)
	printf ("Execspawn Command = [%s]\n", ocmd);
#endif
    cmd = savestr(ocmd);
    amigaizepath(cmd);
    for (s = cmd; *s; s++) {
	/* look for Amiga shell metacharacters */
	if (*s != ' ' && !isalpha(*s) && strchr("<>",*s)) {
	    if (*s == '\n' && !s[1]) {
		*s = '\0';
		break;
	    }
	    
	    if (s = strchr(cmd, ' ')) *s = '\0';
	    exists = cmdexists(cmd);
	    if (s) *s = ' ';
	    if (exists) {
		fflush(stdout);
		fflush(stderr);
		if (Execute(cmd, 0, 0)) status = 0;
	    }
	    if (status || spawn) {
		Safefree(cmd);
		return (status << 8);
	    }
	    exit(0);	/* Only in "exec"(not "system") if Execute worked */
	}
    }
    New(1202,argv, (s - cmd) / 2 + 2, char*);
    a = argv;
    for (s = cmd; *s;) {
	while (*s && isspace(*s)) s++;
	if (*s)
	    *(a++) = s;
	while (*s && !isspace(*s)) s++;
	if (*s)
	    *s++ = '\0';
    }

    *a = Nullch;
    if (argv[0]) {
	fflush(stdout);
	fflush(stderr);
	if (!spawn)	/* exec, no return */
	    execvp(argv[0],argv);
	else if (!fexecv(argv[0],argv))
	    status = wait();
#ifdef DEBUGGING
	if (debug)
	    printf ("Execspawn status: [%d]\n", status);
#endif
    }
    Safefree(cmd);
    Safefree(argv);
    return (status << 8);	/* Unix wait has return code in bits 8-15 */
}

bool do_exec(char *cmd)
{
    return(ExecSpawn(cmd, 0));
}

int do_spawn(char *cmd)
{
    return(ExecSpawn(cmd, 1));
}
