
/*
 * 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"

char *rindex();
int MySyncRun( char *com, char *args, BPTR in, BPTR out );
int echofunc(void);
long IoError;

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

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

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

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

	IoError=0;
	if( ac==1 && (isdir(av[0]) || !strcmp( av[0],"..") || !strcmp(av[0],"~"))) {
		if( !strcmp(av[0],"~") && (dst=get_var(LEVEL_SET,v_lcd)) )
			sprintf(buf,"cd %s",dst);
		else 
			sprintf(buf,"cd %s",av[0]);
		execute( buf );
		return 0;
	}

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

	argline=compile_av(av, 1, ac, ' ', 1);
	trueargline= (*argline ? argline : "\n");

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

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

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

	strcpy(buf,"source ");
	if (path = dofind(av[0],"",buf+7,v_path)) {             /* shell path    */
		if((retcode = MySyncRun(path,trueargline,0L,0L))>=0)
			goto done2;
		else {
			struct DPTR *dp;
			int stat;
			if(dp=dopen(path,&stat)) {
				stat=dp->fib->fib_Protection & FIBF_SCRIPT;
				dclose(dp);
				if( stat ) {
					execute(buf);
					return 0;
				}
			}
		}
	}

	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 = malloc(strlen(str)+3);
		sprintf(copy,"x %s",str);
		retcode = do_source(copy);
		goto done;
	}

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

	ext=strcmp(end,".rexx") ? ".rexx" : "";           /* automatic rx-ing   */
	if( path = dofind(av[0], ext, buf, v_rxpath )) {
		if( (retcode=MySyncRun("rx",copy,0L,0L)) >=0 ) goto done;
		if (path = dofind("rx","",buf,v_path)) {
			retcode = MySyncRun(path,copy,0L,0L);
			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:
	free( argline );
	return retcode;
}

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

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

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

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

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

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

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

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

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

	return ret;
}

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;
}


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

	Myprocess->pr_WindowPtr = (APTR)(-1);
	sprintf(buf,"%s%s",cmd,ext);
	if (exists(buf)) return buf;
	if (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)) {
				Myprocess->pr_WindowPtr = (APTR)o_noreq;
				return buf;
			}
			if (*s) s++;
		}
	}
	Myprocess->pr_WindowPtr = (APTR)o_noreq;
	return NULL;
}
