
/*
 * 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 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
 * Version 5.00L by Urban Mueller 17-Feb-91
 *
 */

#include "shell.h"

int MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync );
int echofunc(void);

int
do_run( char *str, int nosync )
{
	int retcode;
	char buf[200];        /* enough space for 100 char cmd name + path stuff */
	char *path, *path2, *argline, *copy, *ext, *end;

	if( !*av[0] )
		return 0;

	if( (retcode=echofunc())>=0 )
		return retcode;

	a0tospace( av[0] );                                 /* allow "com mand" */

	argline=compile_av(av, 1, ac, ' ', 1);

	if (strlen(av[0]) > 100) { ierror(NULL,509); return -1; }

	if( ac==1 && isdir(av[0])) {
		sprintf(buf,"cd \"%s\"",av[0]);
		return execute( buf );
	}

	IoError=IoErr();
	if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
		ierror( av[0], IoError );
		return 20;
	}

	sprintf(buf,"res_%s",BaseName(av[0]));               /* delayed residents */
	if (o_resident && Getenv(buf, buf+100, 90L)) {
		Setenv(buf,NULL);
		loadres(buf+100);
	}

	if( (retcode=MySyncRun(av[0],argline,0,0,nosync))>=0 )   /* AmigaDOS path */
		goto done2;

	if( retcode==PR_NOMEM ) {
		ierror( av[0], 103 );
		return 20;
	}

	IoError=IoErr();
	if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
		ierror( av[0], IoError );
		return 20;
	}

	if (path = dofind(av[0],"",buf+80,v_path)) {             /* shell path    */
		DPTR *dp;
		BPTR fh;
		int stat, script;
		if((retcode = MySyncRun(path,argline,0,0,nosync))>=0)
			goto done2;
		if(dp=dopen(path,&stat)) {
			script= dp->fib->fib_Protection&FIBF_SCRIPT;
			dclose(dp);
			if( !stat && script ) {
				char *t;
				buf[0]=0;
				if( fh=Open(path,MODE_OLDFILE )) {
					Read(fh,buf,79);
					Close(fh);
					if(t=index(buf,'\n')) *t=0;
				}
				if( buf[0]=='/' && buf[1]=='*' ) {
					sprintf(buf, "Rx %s", str );
				} else if( (buf[0]!=';' || buf[0]!='#') && buf[1]=='!' ) {
					memmove(buf,buf+2,strlen(buf+2)+1);
					strcat( buf," ");
					strcat( buf,str);
				} else {
					sprintf(buf,"Execute %s", str );
				}
				return execute( a0tospace(buf));
			}
		}
	}

	if(!(end=rindex(av[0],'.'))) end="";               /* automatic sourcing */
	ext=strcmp(end,".sh") ? ".sh" : "";
	if (path = dofind(av[0],ext,buf,v_path)) {
		av[1] = buf;
		copy = salloc(strlen(str)+3);
		sprintf(copy,"x %s",str);
		retcode = do_source(copy);
		goto done;
	}

	copy=salloc(strlen(av[0])+strlen(argline)+5);
	sprintf(copy,"%s %s",av[0],argline);

	ext=strcmp(end,".rexx") ? ".rexx" : "";           /* automatic rx-ing   */
	if( path = dofind(av[0], ext, buf, v_rxpath )) {
		strcat (path," ");
		if( strlen(argline)>140 ) argline[140]=0;
		strcat (path,argline);

/*		strncpy(path+strlen(path),argline,190); */
		if( (retcode=MySyncRun("rx",path,0,0,0)) >=0 ) goto done;
		if (path2 = dofind("rx","",buf+160,v_path)) {
			retcode = MySyncRun(path2,path,0,0,0);
			goto done;
		}

	}

	if( !doaction(av[0],"exec",argline)) {
		retcode=0;
		goto done;
	}

	retcode=-1;
	fprintf(stderr,"Command not found %s\n",av[0]);

done:
	free( copy );
done2:
	setioerror( IoErr() );
	free( argline );
	return retcode;
}

struct Segment {
	BPTR NextEntry;
	LONG UseCount;
	BPTR SegPtr;
	BSTR SegName;
};

int
MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync )
{
	struct Segment *seg;
	int ret, len=strlen(args);
	char buf2[200], *buf=buf2;
	long oldname;

#ifdef KICK20
	if( o_kick20 ) {
		oldname = (long)Mycli->cli_CommandName;

		args[len]='\n'; args[len+1]=0;

		while( (long)buf & 3 ) buf++;
		buf[0] = strlen( com );
		strncpy(buf+1,com,80);

		Forbid();
		if(seg=FindSegment( (UBYTE *)com, NULL, 0 ))
			seg->UseCount++;
		Permit();
		if( seg ) {
			Mycli->cli_CommandName = (long)buf/4;

			ret=RunCommand(seg->SegPtr, Mycli->cli_DefaultStack,
			                           (UBYTE *)args, strlen(args));
			seg->UseCount--;
			Mycli->cli_CommandName = (long)oldname;
			return ret;
		}

		if( o_internal ) {
			Forbid();
			seg=FindSegment( (UBYTE *)com, NULL, 1 );
			Permit();
			if( seg && seg->UseCount==-2 ) {
				Mycli->cli_CommandName = (long)buf/4;

				ret=RunCommand(seg->SegPtr, Mycli->cli_DefaultStack,
				                           (UBYTE *)args, strlen(args));
				Mycli->cli_CommandName = (long)oldname;
				return ret;
			}
		}

		args[len]=0;

	}
#endif

	if( nosync ) {
		sprintf(buf2,"%s %s",com,args);
		Execute(buf2,0,Myprocess->pr_COS);
		return 0;
	}

	if( (ret= SyncRun( com, args, in, out ))>=0 )
		return ret;

	if( ret==PR_NOMEM ) {
		ierror(NULL,103);
		return 20;
	}

	return -1;
}

#if 0
int
do_which( char *str )
{
	char *got, *com=av[1];

	if( get_var(LEVEL_ALIAS,com) ) {
		printf("Shell Alias '%s'\n",com);
		return 0;
	}

	if( *(got=find_internal( com ))>1 ) {
		printf("Shell Internal '%s'\n",got);
		return 0;
	}



	printf( "Not found\n" );
	return 20;
}
#endif


char *
dofind( char *cmd, char *ext, char *buf, char *path)
{
	char *ptr, *s=path, *ret=NULL;

	Myprocess->pr_WindowPtr = (APTR)(-1);
	sprintf(buf,"%s%s",cmd,ext);
	if (exists(buf)) {
		ret=buf;
		goto terminate;
	}
	if ((char*)BaseName(buf)==buf) {
		if( *path=='_' )
			s = get_var(LEVEL_SET, path);
		while (*s) {
			for (ptr=buf; *s && *s!=','; ) *ptr++ = *s++;
			if( ptr[-1]!=':' && ptr[-1]!='/')
				*ptr++='/';
			sprintf(ptr, "%s%s", cmd, ext);
			if (exists(buf)) {
				ret=buf;
				goto terminate;
			}
			if (*s) s++;
		}
	}
terminate:
	Myprocess->pr_WindowPtr = (APTR)o_noreq;
	return ret;
}
