[comp.sources.amiga] v91i030: CShell 5.00 - alternative command interface, Part04/06

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/04/91)

Submitted-by: <umueller@iiic.ethz.ch>
Posting-number: Volume 91, Issue 030
Archive-name: shells/cshell-5.00/part04

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 6)."
# Contents:  comm1.c execom.c
# Wrapped by tadguy@ab20 on Sun Mar  3 16:56:00 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'comm1.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'comm1.c'\"
else
echo shar: Extracting \"'comm1.c'\" \(30286 characters\)
sed "s/^X//" >'comm1.c' <<'END_OF_FILE'
X/*
X * COMM1.C
X *
X * Matthew Dillon, August 1986
X *
X * Version 2.07M by Steve Drew 10-Sep-87
X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
X * Version 5.00L by Urban Mueller 17-Feb-91
X *
X */
X
X#include "shell.h"
X
X/* comm1.c */
Xstatic void display_file(char *filestr);
Xstatic char *myfgets(char *buf, int buflen, struct __stdio *file);
Xstatic int search_file(char *s);
Xstatic int quicksearch(char *name, int nocasedep, char *pattern);
Xstatic int rm_file(char *file);
Xstatic void setsystemtime(struct DateStamp *ds);
Xstatic int found( char *lstart, int lnum, int loffs, char *name, char left );
Xstatic void recurse(char *name, int (*action)(char *));
Xstatic void recurse2( char *name, void (*action)(FIB *));
X
Xextern int has_wild;
X
Xint
Xdo_sleep( void )
X{
X	int i;
X
X	if (ac == 2) for (i=atoi(av[1]); i>0 && !CHECKBREAK(); i--) Delay(50);
X	return 0;
X}
X
Xint
Xdo_protect( void )
X{
X	static char flags[]="DEWRAPSH";
X	char *s, *p;
X	long setmask=0, clrmask=0xFF, mask;
X	int  i, mode=0, stat;
X	struct DPTR *dp;
X
X	for (s=strupr(av[--ac]); *s; s++) {
X		if (*s=='=') { mode=0; continue; }
X		if (*s=='+') { mode=1; clrmask=FIBF_ARCHIVE; continue; }
X		if (*s=='-') { mode=2; clrmask=FIBF_ARCHIVE; continue; }
X
X		if (p=index(flags, *s)) {
X			if( mode==0 ) setmask|= 1<<(p-flags), clrmask=0xFF;
X			if( mode==1 ) setmask|= 1<<(p-flags);
X			if( mode==2 ) clrmask|= 1<<(p-flags);
X		} else
X			ierror(av[ac],500);
X	}
X
X	for (i=1; i<ac; i++) {
X		if( (dp=dopen(av[i],&stat))) {
X			mask = dp->fib->fib_Protection ^ 0x0F;
X			mask&=~clrmask;
X			mask|= setmask;
X			dclose(dp);
X			if( !SetProtection( av[i], mask ^ 0x0F))
X				pError(av[i]);
X		} else
X			pError(av[i]);
X	}
X	return 0;
X}
X
Xint
Xdo_filenote( void )
X{
X	struct DPTR *dp;
X	char *note;
X	int i, stat;
X
X	if( options&1 ) {
X		for( i=1; i<ac && !dobreak(); i++ )
X			if( dp=dopen( av[i], &stat )) {
X				printf( "%-12s %s\n", av[i],dp->fib->fib_Comment );
X				dclose( dp );
X			}
X	} else {
X		note=av[--ac];
X		for (i=1; i<ac; i++) if (!SetComment(av[i], note)) pError(av[i]);
X	}
X	return 0;
X}
X
Xint
Xdo_cat( void )
X{
X	FILE *fi;
X	int lctr, i;
X	char buf[256];
X
X	prepscroll(0);
X	if (ac<=1) {
X		if (has_wild) { printf("No files matching\n"); return 20; }
X		lctr=0;
X		while (fgets(buf,256,stdin) &&
X		       !dobreak()) {
X			if (options) printf("%4d ",++lctr);
X			quickscroll();
X			fputs(buf,stdout);
X		}
X	} else {
X		for (i=1; i<ac; i++)
X			if (fi = fopen (av[i], "r")) {
X				lctr=0;
X				while (fgets(buf,256,fi) && !dobreak()) {
X					if (options&1) printf("%4d ",++lctr);
X					quickscroll();
X					printf("%s",buf);
X				}
X				fclose (fi);
X			} else
X				pError(av[i]);
X	}
X	return 0;
X}
X
X
Xvoid
Xget_drives(char *buf)
X{
X	struct DirectoryEntry *de_head=NULL, *de;
X
X	buf[0]=0;
X	AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
X	for(de=de_head; de; de=de->de_Next) {
X		if( buf[0] )
X			strcat( buf, "\240" );
X		strcat( buf, de->de_Name );
X	}
X	FreeDAList(de_head);
X}
X
Xstatic char infobuf[100];
Xstatic char namebuf[12];
X
Xchar *
Xdrive_name( char *name )
X{
X	struct DirectoryEntry *de_head=NULL, *de;
X	struct MsgPort *proc=DeviceProc( name );
X
X	strcpy( namebuf, name );
X	AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
X	for(de=de_head; de; de=de->de_Next)
X		if( DeviceProc( de->de_Name) == proc ) 
X			strcpy( namebuf, de->de_Name );
X	FreeDAList(de_head);
X
X	return namebuf;
X}
X
Xint
Xdo_info( void )
X{
X	struct DirectoryEntry *de_head=NULL, *de;
X	int i;
X
X	puts("Unit    Size  Bytes  Used Blk/Byt-Free Full Errs  Status    Name");
X	Myprocess->pr_WindowPtr = (APTR)(-1);
X
X	if( ac==1 ) {
X		AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
X		for(de=de_head; de; de=de->de_Next)
X			oneinfo( de->de_Name, 0);
X		FreeDAList(de_head);
X	} else {
X		for( i=1; i<ac; i++ )
X			oneinfo( drive_name( av[i] ), 0 );
X	}
X
X	Myprocess->pr_WindowPtr = (APTR) o_noreq;
X	return 0;
X}
X
Xchar *
Xoneinfo( char *name, int mode )
X{
X	BPTR lock;
X	struct InfoData *info;
X	long size, free, freebl, blocks;
X	char *p, buf[130], *state="          ";
X	char *fmt="%s\240%s\240%d\240%d\240%d\240%s\240%d%%\240%d\240%s\240%s";
X
X	infobuf[0]=0;
X	if( !name ) name="";
X	strcpy(infobuf,"0");
X	info=(struct InfoData *)AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC);
X	if (lock=Lock(name,ACCESS_READ)) {
X		if (Info(lock, info)) {
X			PathName(lock, buf, 128L);
X			if (p=index(buf,':')) *p = '\0';
X			size  = ((info->id_NumBlocks + 2)* info->id_BytesPerBlock);
X			freebl= (info->id_NumBlocks-info->id_NumBlocksUsed);
X			free  = freebl * info->id_BytesPerBlock;
X			switch(info->id_DiskState) {
X				case ID_WRITE_PROTECTED: state="Read Only "; break;
X				case ID_VALIDATED:       state="Read/Write"; break;
X				case ID_VALIDATING:      state="Validating"; break;
X			}
X			blocks=info->id_NumBlocks;
X			if( mode==0 ) fmt="%-7s%5s%6d%7d%7d %5s%4d%%%4d  %s %s\n";
X			sprintf(infobuf,fmt,
X				name,
X				itok( size ),
X				info->id_BytesPerBlock,
X				info->id_NumBlocksUsed,
X				freebl,
X				itok( free ),
X				(blocks) ? (info->id_NumBlocksUsed * 100)/blocks : 0,
X				info->id_NumSoftErrors,
X				state,
X				buf);
X			if( mode==2 ) sprintf( infobuf, "%d", free );
X			if( mode==3 ) sprintf( infobuf, "%d", freebl );
X			if( mode==4 ) sprintf( infobuf, "%s", itok( free ));
X			if( mode==5 ) sprintf( infobuf, "%s:", buf );
X		} else
X			pError (name);
X		UnLock(lock);
X	} else {
X		if     ( mode==1 ) sprintf( infobuf, "%s\240No disk present", name );
X		else if( mode==0 ) sprintf( infobuf, "%-7s No disk present\n",name);
X		else if( mode==5 ) sprintf( infobuf, ""  );
X		else               sprintf( infobuf, "0" );
X	}
X	if( mode==0 ) printf( "%s",infobuf);
X	FreeMem(info,sizeof(struct InfoData));
X	return infobuf;
X}
X
X
X/* things shared with display_file */
X
X#define DIR_SHORT 0x1
X#define DIR_FILES 0x2
X#define DIR_DIRS  0x4
X#define DIR_NOCOL 0x8
X#define DIR_NAMES 0x10
X#define DIR_HIDE  0x20
X#define DIR_LEN   0x40
X#define DIR_TIME  0x80
X#define DIR_BACK  0x100
X#define DIR_UNIQ  0x200
X#define DIR_IDENT 0x400
X#define DIR_CLASS 0x800
X#define DIR_QUIET 0x1000
X#define DIR_AGE   0x2000
X#define DIR_VIEW  0x4000
X#define DIR_NOTE  0x8000
X
Xstatic BPTR lastlock;
Xstatic int filecount, col, wwidth;
Xstatic long bytes, blocks;
X
X/* the args passed to do_dir will never be expanded */
X
Xextern expand_err;
Xextern int w_width;
X
X
Xstatic struct DateStamp Stamp;
X
Xint
Xdo_dir( void )
X{
X	int i=1, c, eac, reverse, nump=ac, retcode=0;
X	char **eav, **av1, **av2, inter=interactive();
X	int (*func)(), ac1, ac2;
X
X	if( options&DIR_CLASS ) options|=DIR_IDENT;
X	if( ac == i) ++nump, av[i]="";
X	if( !(options & (DIR_FILES | DIR_DIRS))) options|=(DIR_FILES | DIR_DIRS);
X	if( options&DIR_UNIQ) {
X		if( ac-i!=2 )  { show_usage(NULL); return 20; }
X		i=0, nump=3;
X	}
X
X	if( options&DIR_AGE )
X		DateStamp( &Stamp );
X
X	col = filecount = bytes = blocks = 0L;
X	lastlock=NULL;
X
X	wwidth=77;
X	if( inter ) printf( "\033[?7l" ), wwidth=w_width; /* end of line wrap off */
X
X	prepscroll(0);
X	for( ; i<nump && !CHECKBREAK(); ++i ) {
X		if( options&DIR_UNIQ ) {
X			switch( i ) {
X				case 0: av1=expand( av[ac-2], &ac1 );
X				        av2=expand( av[ac-1], &ac2 );
X				        eav=without( av1, ac1, av2, ac2, &eac, 1 );
X				        break;
X				case 1: printf("\nCommon files\n");
X				        eav=and( av1, ac1, av2, ac2, &eac, 1 );
X				        break;
X				case 2: printf("\n");
X				        eav=without( av2, ac2, av1, ac1, &eac, 1 );
X				        break;
X			}
X			col = filecount = bytes = blocks = 0L;
X			lastlock=NULL;
X		} else if (!(eav = expand(av[i], &eac)) && expand_err) {
X			pError(av[i]);
X			retcode=5;
X			continue;
X		}
X
X		reverse= ( options&DIR_BACK ) ? 1 : 0;
X		func=cmp;
X		if( options & DIR_TIME) func=datecmp;
X		if( options & DIR_LEN ) func=sizecmp;
X		if( options & DIR_CLASS)func=classcmp;
X		DirQuickSort(eav, eac, func, reverse);
X		for(c=0; c<eac && !CHECKBREAK(); ++c) {
X			if( options & DIR_HIDE ) {
X				char *b=BaseName(eav[c]);
X				int  l=strlen(b)-5;
X				struct file_info *info =
X				    (struct file_info *)(eav[c]-sizeof(struct file_info));
X				if(*b=='.'|| (l>=0 && !strcmp(b+l,".info"))||(info->flags&128))
X					continue;
X			}
X			if (options & DIR_NAMES)
X				puts(eav[c]);
X			else
X				display_file(eav[c]);
X		}
X
X		if (col) { quickscroll(); printf("\n"); col=0; }
X		if (options&DIR_UNIQ || (filecount>1 && i==nump-1)) {
X			blocks += filecount; /* account for dir blocks */
X			quickscroll();
X			printf(" %ld Blocks, %s Bytes used in %d files\n",
X			    blocks, itoa(bytes), filecount);
X		}
X		if( options&DIR_UNIQ )
X			free(eav);
X		else 
X			free_expand (eav);
X		if (lastlock) UnLock(lastlock), lastlock=0;
X	}
X	if (lastlock) UnLock(lastlock), lastlock=0;
X
X	if( options&DIR_UNIQ )
X		free_expand( av1 ), free_expand( av2 );
X
X	if( inter ) printf( "\033[?7h" );                /* end of line wrap off */
X
X	return retcode;
X}
X
X
Xstatic void
Xdisplay_file( char *filestr )
X{
X	int isadir,slen;
X	char sc, *base, buf[130];
X	struct file_info *info;
X	BPTR thislock;
X
X	base=BaseName(filestr);
X	sc = *base;
X	*base = '\0';
X	thislock=Lock(filestr,SHARED_LOCK);
X	/* if (thislock==NULL) return; */
X	if (lastlock==NULL || CompareLock(thislock,lastlock)) {
X		/* struct InfoData *id=AllocMem( sizeof(struct InfoData), 0); */
X		if (col) { quickscroll(); printf("\n"); col=0; }
X		quickscroll();
X		PathName(thislock, buf, 128L);
X		/* Info( thislock, id ); */
X		printf("Directory of %s\n", buf );
X		/*itok((id->id_NumBlocks-id->id_NumBlocksUsed)*id->id_BytesPerBlock));*/
X		/* FreeMem( id, sizeof(struct InfoData)); */
X		if (lastlock) UnLock(lastlock);
X		lastlock=thislock;
X	} else
X		UnLock(thislock);
X
X	*base    = sc;
X	if((slen = strlen(base)+1) & 1 ) ++slen;
X	info     = (struct file_info *)(filestr - sizeof(struct file_info));
X	isadir   = info->size<0;
X
X	if (!(((options & DIR_FILES) && !isadir) ||
X	                 ((options & DIR_DIRS) &&  isadir)))
X		return;
X	if (isadir && !(options & DIR_NOCOL)) printf (o_hilite);
X	if (options & DIR_SHORT) {
X		slen= (slen>18) ? 37 : 18;
X		if (col && col+slen>=wwidth )
X			{ quickscroll(); printf("\n"); col = 0; }
X		printf(" %-*s",slen,base);
X		col+= ++slen;
X	} else {
X		quickscroll();
X		printf("   %-24s %s \n",base,formatfile(info));
X	}
X	if (isadir && !(options & DIR_NOCOL))
X		printf(o_lolite);
X	if(info->size>0)
X		bytes  += info->size;
X	blocks += info->blocks;
X	filecount++;
X}
X
X/* will have either of these formats:
X *
X *    fullfilename'\0'hsparwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
X *    fullfilename'\0'hsparwed NNNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
X *                              1111111111222222222233333333334 4  4
X *                    01234567890123456789012345678901234567890 1  2
X */
X
Xstatic char linebuf[140];
Xstatic long dlen, dblocks;
X
Xstatic void
Xcount( FIB *fib )
X{
X	dlen+=fib->fib_Size;
X	dblocks+=fib->fib_NumBlocks+1;
X}
X
Xchar *
Xformatfile( struct file_info *info)
X{
X	char *str=linebuf, *class, *t;
X	int i, stat;
X
X	if( options & DIR_NOTE ) {
X		struct DPTR *dp;
X		if( dp=dopen( (char *)(info+1), &stat )) {
X			strcpy( str, dp->fib->fib_Comment );
X			dclose( dp );
X		}
X		return linebuf;
X	}
X
X	*str++= info->flags & 1<<30 ? 'c' : '-';
X	for (i=7; i>=0; i--)
X		*str++ = ((info->flags & (1L<<i)) ? "hspa----" : "----rwed")[7-i];
X	if (info->size >= 0)
X		sprintf(str,options&DIR_QUIET?" %7ld ":" %7ld %4ld  ",
X		            info->size, info->blocks);
X	else
X		strcpy(str,options&DIR_QUIET?"   <Dir> ":"   <Dir>       ");
X	str+=strlen(str);
X	if( options&DIR_VIEW && info->size<0 ) {
X		dlen=dblocks=0;
X		recurse2( (char *)(info+1),count);
X		sprintf( str, "%10s",itoa(dlen));
X		info->size=dlen; info->blocks=dblocks;
X	} else if( options&DIR_IDENT ) {
X		if( *info->class!=1 )
X			strcpy(str,info->class);
X		else if( class=getclass((char *)(info+1)))
X			if( t=index(strncpy(str,class,40),0xA0) )
X				*t=0;
X	} else if( options&DIR_AGE) {
X		long mins=0;
X		if( Stamp.ds_Days!=0 ) {
X			mins =Stamp.ds_Days*1440 + Stamp.ds_Minute;
X			mins-=info->date.ds_Days*1440 + info->date.ds_Minute;
X		}
X		if( mins>=0 )
X			sprintf(str,"%4d %02d:%02d",mins/1440,mins/60%60,mins%40);
X		else 
X			sprintf(str,"Future");
X	} else if( !(options&DIR_VIEW) )
X		strcat(str,dates(&info->date));
X	return linebuf;
X}
X
X
Xint
Xdo_quit( void )
X{
X	if (Src_stack) {
X		Quit = 1;
X		return(do_return());
X	}
X	main_exit(0);
X	return 0;
X}
X
Xint
Xdo_echo( void )
X{
X	char *args=compile_av(av,1,ac,' ',0);
X	fprintf( (options&2)?stderr:stdout, (options&1)?"%s":"%s\n",args );
X	free(args);
X	return 0;
X}
X
X
Xstatic int
Xbreakcheckd(void)
X{
X	int ret=!o_nobreak && SetSignal(0L,0L) & SIGBREAKF_CTRL_D;
X	SetSignal(0L, SIGBREAKF_CTRL_D);
X	if( ret )
X		fprintf(stderr,"^D\n");
X	return ret;
X}
X
X/* gets a line from file, joining two lines if the first ends in '\' */
X
Xstatic char *
Xmyfgets(char *buf, int buflen, FILE *file)
X{
X	char *bufptr=buf, *limit=buf+buflen;
X
X	do {
X		if (fgets(bufptr, limit-bufptr, file)==NULL) {
X			if (bufptr != buf)
X				fprintf(stderr,"Source: file ends in '\\'\n");
X			return NULL;
X		}
X		bufptr = bufptr+strlen(bufptr)-2;
X	} while (*bufptr=='\\');
X	return buf;
X}
X
Xint
Xdo_source( char *str )
X{
X	FILE *fi;
X	char *buf;
X	int len;
X
X	if (Src_stack == MAXSRC) {
X		ierror(NULL,217);
X		return -1;
X	}
X	if ((fi = fopen (av[1], "r")) == 0)
X		{ pError(av[1]); return -1;	}
X	buf=malloc(512);
X	set_var(LEVEL_SET, v_passed, next_word(next_word(str)));
X	++H_stack;
X	Src_pos[Src_stack] = 0;
X	Src_base[Src_stack] = fi;
X	Src_if[Src_stack]=If_stack;
X	++Src_stack;
X	while (myfgets (buf, 512, fi) && !dobreak() && !breakcheckd()) {
X		len = strlen(buf);
X		if(buf[len-1]=='\n')
X			buf[len-1] = '\0';
X		Src_pos[Src_stack - 1] += len;
X		if (Verbose && !forward_goto) fprintf(stderr,"%s\n",buf);
X		exec_command (buf);
X	}
X	--H_stack;
X	--Src_stack;
X	if( If_stack>Src_if[Src_stack] )
X		If_stack=Src_if[Src_stack], disable=If_stack && If_base[If_stack-1];
X
X	if (forward_goto) ierror(NULL,501);
X	forward_goto = 0;
X	unset_level(LEVEL_SOURCE + Src_stack);
X	unset_var(LEVEL_SET, v_gotofwd);
X	unset_var(LEVEL_SET, v_passed);
X	free(buf);
X	fclose (fi);
X	return 0;
X}
X
X/* set process cwd name and $_cwd, if str != NULL also print it. */
X
Xint
Xdo_pwd( char *str )
X{
X	char pwd[130];
X
X	PathName(Myprocess->pr_CurrentDir, pwd, 128L);
X	if (str) puts(pwd);
X	set_var(LEVEL_SET, v_cwd, pwd);
X	/* put the current dir name in our CLI task structure */
X	CtoBStr(pwd, Mycli->cli_SetName, 128L);
X	return 0;
X}
X
X/*
X * CD
X *
X * CD(str, 0)      -do CD operation.
X *
X */
X
Xextern int qcd_flag;
X
Xstatic char lastqcd[80];
Xstatic lastoffs;
X
Xint
Xdo_cd( char *str )
X{
X	BPTR oldlock, filelock;
X	FILE *file;
X	char buf[100], *old;
X	int  i=1, repeat;
X
X	if( options & 1 ) {
X		if( !(file=fopen( o_csh_qcd, "w" )))
X			{ fprintf(stderr,"Can't open output\n"); return 20; }
X		for( ; i<ac && !breakcheck(); i++ ) {
X			fprintf(file,"%s\n",av[i]);
X			strcpy(buf,av[i]);
X			appendslash( buf );
X			expand_all( buf, file );
X		}
X		fclose(file);
X		return 0;
X	}
X
X	str= ( has_wild && ac>=2 ) ? av[1] : next_word(str);
X	if (!strcmp("..",str)) str="/";
X
X	if( !*str ) {
X		printf("%s\n", get_var( LEVEL_SET, v_cwd ));
X		return 0;
X	}
X
X	if (filelock=Lock(str,ACCESS_READ)) {
X		lastqcd[0]=0;
X		if (!isdir(str)) { UnLock(filelock); ierror(str,212); return 20; }
X	} else {
X		repeat= !strncmp( lastqcd, str, 79 );
X		strncpy( lastqcd, str, 79);
X
X		if( !quick_cd( buf, av[i], repeat) )
X			{ fprintf(stderr,"Object not found %s\n",str); return 20; }
X		if (!(filelock=Lock(buf,ACCESS_READ))) 
X			{ pError(buf); return 20; }
X	}
X	if (oldlock=CurrentDir(filelock)) UnLock(oldlock);
X	if( !(old=get_var(LEVEL_SET, v_cwd)) )
X		old="";
X	set_var(LEVEL_SET, v_lcd, old);
X	do_pwd(NULL);
X
X	return 0;
X}
X
Xchar *
Xquick_cd( char *buf, char *name, int repeat )
X{
X	qcd_flag=repeat ? 2 : 1;
X	strcpy(buf,name);
X	if( quicksearch( o_csh_qcd, 1, buf)!=2 )
X		return NULL;
X	return buf;
X}
X
X
Xint
Xdo_mkdir( void )
X{
X	int i;
X	BPTR lock;
X	
X	for (i=1; i<ac; ++i) {
X		if (exists(av[i]))
X			ierror(av[i],203);
X		else if (lock=CreateDir(av[i]))
X			UnLock (lock);
X		else
X			pError(av[i]);
X	}
X	return 0;
X}
X
Xint
Xdo_mv( void )
X{
X	char *dest, buf[256];
X	int dirflag, i;
X
X	dirflag=isdir(dest=av[--ac]);
X	if (ac>3 && !dirflag) { ierror(dest, 507); return (-1); }
X	for (i=1; i<ac; ++i) {
X		strcpy(buf, dest);
X		if (dirflag) TackOn(buf, BaseName(av[i]));
X		if (Rename(av[i], buf)==0)
X			{ pError(av[i]); return -1; }
X		else 
X			clear_archive_bit( buf );
X	}
X	return 0;
X}
X
Xstatic int dirstoo;
X
Xint
Xall_args( int (*action)(char *str), int dirsflag )
X{
X	int i;
X
X	dirstoo=dirsflag;
X	for ( i=1; i<ac && !dobreak(); ++i)
X		if (isdir(av[i])) {
X			if (options & 1) recurse(av[i], action);
X			else if (dirstoo) (*action)(av[i]);
X		} else
X			(*action)(av[i]);
X	return 0;
X}
X
Xchar *searchstring;
Xchar docr;
X
X#define SEARCH_REC   1
X#define SEARCH_CASE  2
X#define SEARCH_WILD  4
X#define SEARCH_NUM   8
X#define SEARCH_EXCL  16
X#define SEARCH_QUIET 32
X#define SEARCH_VERB  64
X#define SEARCH_BIN   128
X#define SEARCH_FILE  256
X#define SEARCH_ABORT 512
X#define SEARCH_LEFT  1024
X#define SEARCH_ONLY  2048
X
Xstatic int abort_search;
Xstatic char lowbuf[256], file_name, file_cr;
X
Xstatic int
Xsearch_file( char *s )
X{
X	FILE *fopen(), *fi;
X	char *p, *q;
X	int nocasedep, lctr, len, excl=((options & 16) !=0 ), yesno;
X	char buf[256], searchit[120], first, left;
X
X	if( abort_search )
X		return 0;
X
X	nocasedep=!(options & SEARCH_CASE);
X	lctr= docr= file_name= file_cr= 0;
X	if (!(options & (SEARCH_QUIET|SEARCH_FILE)))
X		if( options & SEARCH_VERB )
X			printf("Examining %s...\n",s);
X		else 
X			printf("\015Examining %s...                  ",s), docr=1;
X
X	strcpy(searchit,searchstring);
X	if (options & SEARCH_WILD) strcat(searchit,"\n");
X	len=strlen(searchit);
X	if (nocasedep) strupr(searchit);
X	first=*searchit;
X
X	if( strcmp("STDIN",s) && !(options&SEARCH_WILD) && !excl ||
X	             options&SEARCH_BIN )
X		if( quicksearch(s,nocasedep,searchit) )
X			return 0;
X
X	if( options&SEARCH_BIN )
X		{ fprintf(stderr,"Out of memory\n"); return 20; }
X
X	fi = strcmp("STDIN",s) ?  fopen(s,"r") : stdin;
X	if (fi==NULL) { pError(s); return 20; }
X
X	prepscroll(0);
X
X	while (fgets(buf,256,fi) && !dobreak()) {
X		lctr++; left=1;
X		if (options & SEARCH_WILD)
X			yesno=compare_ok(searchit, buf, options&SEARCH_CASE);
X		else {
X			if (nocasedep) {
X				strcpy(lowbuf,buf);
X				strupr(lowbuf);
X				p=lowbuf;
X			} else
X				p=buf;
X			q=p;
X			while ((p=index(p,first)) && strncmp(p++,searchit,len)) ;
X			yesno= (p!=NULL);
X			left = --p - q;
X		}
X		if( yesno ^ excl )
X			if(!(options&SEARCH_ONLY)|| !isalphanum(p[-1])&&!isalphanum(p[len]))
X				if( found(buf, lctr, 0, s, left ) )
X					break;
X	}
X	if (fi!=stdin) fclose (fi);
X	if( file_cr ) printf("\n");
X	return 0;
X}
X
Xint qcd_flag, qcd_offs;
X
Xstatic int
Xquicksearch( char *name, int nocasedep, char *pattern )
X{
X	int i, ptrn=strlen(pattern);
X	char ut[256], *buffer, *lend;
X	char *uptab=ut, *get, c, *lpos, *lstart;
X	int len, lnum, qcd=qcd_flag, repeat=(qcd==2 && qcd_offs!=0);
X	int sofar, got;
X	BPTR fh;
X
X#ifdef AZTEC_C
X	while(0) while(0) c=c=0, uptab=uptab=ut, get=get=NULL;
X#endif
X
X	qcd_flag=0;
X	if( !(fh=Open(name,MODE_OLDFILE))) { 
X		i=(long)IoErr(), docr=0;
X		printf("\n");
X		ierror(name,i);
X		return 1;
X	}
X	len=filesize( name );
X	if( !(buffer=(void *)malloc(len+2))) { Close(fh); return 0; }
X	sofar=0;
X	do {
X		got=Read( fh, (char *)buffer+sofar, 60000);
X		sofar+=got;
X	} while( got==60000 );
X	Close( fh);
X	if( sofar != len ) { pError(pattern); return 1; }
X
X	if( nocasedep )
X		strupr( pattern );
X
X	if( !qcd )
X		prepscroll(0);
X
X	for( i=0; i<256; i++ ) uptab[i]=i;
X	if( nocasedep ) for( i='a'; i<='z'; i++ ) uptab[i]=i-'a'+'A';
Xretry:
X	c=*pattern, buffer[len]=c, buffer[len+1]=c;
X	get= (qcd==2) ? buffer+qcd_offs : buffer;
X	if( qcd==1 ) qcd_offs=0;
X
X	lpos=lstart=buffer, lnum=1;
X	for( ;; ) {
X		do ; while( uptab[*get++]!=c );
X		if( --get>=buffer + len )
X			break;
X		for( i=1; i<ptrn; i++ )
X			if( uptab[get[i]]!=pattern[i] )
X				break;
X		if( i==ptrn ) {
X			for( ;lpos<get; lpos++ )
X				if( *lpos=='\n' )
X					lstart=lpos+1, lnum++;
X			for( lend=lstart+1; *lend!='\n'; lend++ ) ;
X			if( qcd ) {
X				if( get[-1]==':' || get[-1]=='/' ||
X				      lpos==lstart && lend[-1]==':' ) {
X					char *tmp;
X					for( tmp=get+ptrn; *tmp&& *tmp!='\n'&& *tmp!='/'; tmp++ );
X					if( *tmp!='/' ) {
X						*lend=0;
X						strncpy(pattern,lstart,79);
X						qcd_offs=lend-buffer;
X						free( buffer );
X						return 2;
X					}
X				} else 
X					lend=lpos+1;
X			} else {
X				*lend=0;
X				if(!(options&SEARCH_ONLY) ||
X				     !isalphanum(lpos[-1])&&!isalphanum(lpos[ptrn]))
X					if(found(lstart, lnum, get-buffer, name, lpos==lstart ))
X						break;
X				*lend='\n';
X			}
X			get=lend+1;
X		} else
X			get++;
X	}
X	if( repeat )  { repeat=0; qcd_offs=0; goto retry; }
X	if( file_cr ) { printf("\n"); quickscroll(); }
X	free( buffer );
X	return 1;
X}
X
Xstatic int
Xfound( char *lstart, int lnum, int loffs, char *name, char left )
X{
X	int fileabort=0;
X
X	if ( docr )
X		{ quickscroll(); printf("\n"); docr=0; }
X
X	if( (options&SEARCH_LEFT) && !left)
X		return 0;
X
X	if( options&SEARCH_FILE ) {
X		file_cr=1;
X		if( !file_name )
X			printf("%s",name), file_name=1;
X		if( options&SEARCH_NUM )
X			fileabort=1;
X		else 
X			printf(" %d",lnum);
X	} else if( options & SEARCH_BIN ) {
X		if (!(options & SEARCH_NUM))
X			printf("Byte offset %d\n",loffs);
X		else 
X			printf("%d\n",loffs);
X		quickscroll();
X	} else {
X		if (!(options & SEARCH_NUM))
X			printf("%4d ",lnum);
X		printf((lstart[strlen(lstart)-1]=='\n')?"%s":"%s\n",lstart);
X		quickscroll();
X	}
X	abort_search= options&SEARCH_ABORT;
X	return dobreak() || fileabort || abort_search;
X}
X
X
Xint
Xdo_search( void )
X{
X	if( Cout_name ) options |= SEARCH_VERB;
X	abort_search=0;
X	searchstring=av[--ac];
X	all_args(search_file, 0);
X	if(docr) printf("\n"),docr=0;
X	return 0;
X}
X
Xstatic int
Xrm_file(char *file)
X{
X	if ( file[strlen(file)-1]=='/' ) file[strlen(file)-1]=0;
X	if (has_wild) printf(" %s...",file);
X	if (options & 2) SetProtection(file,0L);
X	if (!DeleteFile(file)) 
X		{ pError (file); return 20; }
X	else if (has_wild)
X		printf("Deleted\n");
X	return 0;
X}
X
Xint
Xdo_rm( void )
X{
X	all_args( rm_file, 1);
X	return 0;
X}
X
Xstatic void
Xrecurse(char *name, int (*action)(char *))
X{
X	BPTR lock, cwd;
X	FIB *fib=(FIB *)AllocMem((long)sizeof(FIB),MEMF_PUBLIC);
X	char *namecopy=malloc(256);
X
X	if (name[0] =='\0') return;
X	namecopy[0]=0;
X	if (lock=Lock(name,ACCESS_READ)) {
X		cwd =CurrentDir(lock);
X		if (Examine(lock, fib))
X			while (ExNext(lock, fib) && !CHECKBREAK()) {
X				if (*namecopy)
X					{ (*action)(namecopy); namecopy[0]=0; }
X				if (fib->fib_DirEntryType>=0) recurse(fib->fib_FileName,action);
X				else strcpy(namecopy,fib->fib_FileName);
X			}
X		if (*namecopy) (*action)(namecopy);
X		UnLock(CurrentDir(cwd));
X		if (dirstoo) (*action)(name);
X	} else
X		pError(name);
X	free(namecopy);
X	FreeMem(fib, (long)sizeof(FIB));
X}
X
Xstatic void
Xrecurse2( char *name, void (*action)(FIB *))
X{
X	BPTR lock, cwd;
X	FIB  *fib=(FIB *)AllocMem(sizeof(FIB),MEMF_PUBLIC);
X
X	if (lock=Lock(name,ACCESS_READ)) {
X		cwd =CurrentDir(lock);
X		if (Examine(lock, fib))
X			while (ExNext(lock, fib) && !CHECKBREAK()) {
X				(*action)(fib);
X				if (fib->fib_DirEntryType>=0)
X					recurse2(fib->fib_FileName,action);
X			}
X		UnLock(CurrentDir(cwd));
X	}
X
X	FreeMem(fib, sizeof(FIB));
X}
X
X
Xint
Xdo_history( void )
X{
X	struct HIST *hist;
X	int i = H_tail_base;
X	int len = (av[1]) ? strlen(av[1]) : 0;
X
X	for (hist = H_tail; hist && !dobreak(); hist = hist->prev, i++)
X		if (len == 0 || !strncmp(av[1], hist->line, len))
X			printf("%3d %s\n", i, hist->line);
X	return 0;
X}
X
Xint
Xdo_mem( void )
X{
X	static long clast, flast;
X	long cfree, ffree;
X	char *desc="Free";
X
X	Forbid();
X	cfree = AvailMem (MEMF_CHIP);
X	ffree = AvailMem (MEMF_FAST);
X	Permit();
X	if( options&8 ) {
X		clast=cfree, flast=ffree;
X		return 0;
X	}
X	if( options&16 )
X		cfree=clast-cfree, ffree=flast-ffree, desc="Used";
X	if( options&4 ) {
X		if     ( options & 1 ) printf("%ld\n",cfree);
X		else if( options & 2 ) printf("%ld\n",ffree);
X		else                   printf("%ld\n",cfree+ffree);
X	} else {
X		if     ( options & 1 ) printf("Free CHIP memory %s\n",itoa(cfree));
X		else if( options & 2 ) printf("Free FAST memory %s\n",itoa(ffree));
X		else {
X			if(ffree) {
X				printf("FAST memory: %s\n",itoa(ffree));
X				printf("CHIP memory: %s\n",itoa(cfree));
X			}
X			printf("Total  %s: %s\n",desc,itoa(cfree+ffree));
X		}
X	}
X	return 0;
X}
X
Xint
Xdo_forline( void )
X{
X	char vname[33], buf[256], *cstr;
X	int lctr;
X	FILE *f;
X
X	strcpy(vname,av[1]);
X	f=fopen(av[2],"r");
X	if (f==NULL) pError(av[2]);
X	lctr=0;
X	++H_stack;
X	cstr = compile_av (av, 3, ac, ' ', 0);
X	while (fgets(buf,256,f) && !dobreak()) {
X		buf[strlen(buf)-1]='\0';	/* remove CR */
X		lctr++;
X		set_var(LEVEL_SET, vname, buf);
X		sprintf(buf,"%d",lctr);
X		set_var(LEVEL_SET, v_linenum, buf);
X		exec_command(cstr);
X	}
X	fclose(f);
X	--H_stack;
X	free (cstr);
X	unset_var (LEVEL_SET, vname);
X	unset_var (LEVEL_SET, v_linenum);
X	return 0;
X}
X
Xint
Xdo_fornum( void )
X{
X	char vname[33], buf[16];
X	int n1, n2, step, i=1, verbose;
X	char *cstr;
X
X	verbose=(options & 1);
X	strcpy(vname,av[i++]);
X	n1=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
X	n2=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
X	if (options & 2) {
X		step=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
X	} else
X		step=1;
X	++H_stack;
X	cstr = compile_av (av, i, ac, ' ', 0);
X	for (i=n1; (step>=0 ? i<=n2 : i>=n2) && !CHECKBREAK(); i+=step) {
X		if (verbose) fprintf(stderr, "fornum: %d\n", i);
X		sprintf(buf,"%d",i);
X		set_var (LEVEL_SET, vname, buf);
X		exec_command(cstr);
X	}
X	--H_stack;
X	free (cstr);
X	unset_var (LEVEL_SET, vname);
X	return 0;
X}
X
X/*
X * foreach var_name  ( str str str str... str ) commands
X * spacing is important (unfortunately)
X *
X * ac=0    1 2 3 4 5 6 7
X * foreach i ( a b c ) echo $i
X * foreach i ( *.c ) "echo -n "file ->";echo $i"
X */
X
Xint
Xdo_foreach( void )
X{
X	int cstart, cend;
X	char *cstr, **fav, vname[33];
X	int i=1, verbose;
X
X	verbose=(options & 1);
X	strcpy(vname, av[i++]);
X	if (*av[i] == '(') i++;
X	cstart = i;
X	while (i<ac && *av[i] != ')') i++;
X	if (i > ac) { fprintf(stderr,"')' expected\n"); return 20; }
X	++H_stack;
X	cend = i;
X
X	fav = (char **)malloc(sizeof(char *) * (ac));
X	cstr = compile_av (av, cend + 1, ac, ' ', 0);
X
X	for (i = cstart; i < cend; ++i) fav[i] = av[i];
X
X	for (i = cstart; i<cend && !CHECKBREAK(); ++i) {
X		set_var (LEVEL_SET, vname, fav[i]);
X		if (verbose) fprintf(stderr, "foreach: %s\n", fav[i]);
X		exec_command(cstr);
X	}
X	--H_stack;
X	free (fav);
X	free (cstr);
X	unset_var (LEVEL_SET, vname);
X	return 0;
X}
X
Xint
Xdo_forever( char *str )
X{
X	int rcode = 0;
X	char *ptr = next_word( str );
X
X	++H_stack;
X	for (;;) {
X		if (CHECKBREAK()) { rcode = 20; break; }
X		if (exec_command (ptr) < 0) {
X			str = get_var(LEVEL_SET, v_lasterr);
X			rcode = (str) ? atoi(str) : 20;
X			break;
X		}
X	}
X	--H_stack;
X	return rcode;
X}
X
Xextern struct IntuitionBase *IntuitionBase;
X
Xint
Xdo_window( void )
X{
X	long x=-1, y=-1, w=-1, h=-1, maxwidth, maxheight, arg[5];
X	int i;
X
X	if(options & 32) {
X		struct Screen *scrn;
X		struct Window *window;
X		char buf[80];
X		buf[40]=0;
X		for (scrn=IntuitionBase->FirstScreen; scrn; scrn=scrn->NextScreen) {
X			buf[0]=0;
X			if( scrn->Title )
X				strncpy(buf,scrn->Title,40);
X			printf("\nScreen \"%s\" (%d,%d,%dx%d):\n",
X				buf,
X				scrn->LeftEdge,
X				scrn->TopEdge,
X				scrn->Width,
X				scrn->Height
X			);
X			for (window=scrn->FirstWindow; window; window=window->NextWindow) {
X				buf[0]=0;
X				if( window->Title )
X					strncpy(buf,window->Title,40);
X				printf("\tWindow\t\"%s\" (%d,%d,%dx%d)\n",
X					buf,
X					window->LeftEdge,
X					window->TopEdge,
X					window->Width,
X					window->Height
X				);
X			}
X		}
X		return 0;
X	}
X
X	if( o_nowindow || !Win )
X		return 20;
X
X	maxwidth = Win->WScreen->Width;
X	maxheight= Win->WScreen->Height;
X	if( options&1 )
X		x=Win->LeftEdge,y=Win->TopEdge,w=Win->MinWidth,h=Win->MinHeight;
X	if( options&2 ) x=y=0, w=maxwidth, h=maxheight;
X	if( options&4 ) WindowToFront(Win);
X	if( options&8 ) WindowToBack(Win);
X	if( options&16) ActivateWindow(Win);
X	if( ac >= 5) {
X		for(i=1; i<5; i++) {
X			arg[i] = myatoi(av[i],0,1023); if (atoierr) return 20;
X		}
X		x=arg[1]; y=arg[2]; w=arg[3]; h=arg[4];
X	}
X	if( w!=-1 ) {
X		int i;
X		if ( x+w>maxwidth || y+h>maxheight ) {
X			ierror(NULL, 500);
X			return 20;
X		}
X		if( w<Win->MinWidth  ) w=Win->MinWidth;
X		if( h<Win->MinHeight ) h=Win->MinHeight;
X		if( Win->LeftEdge!=0 || Win->TopEdge!=0 )
X			MoveWindow(Win, -Win->LeftEdge, -Win->TopEdge );
X		if( Win->Width!=w || Win->Height!=h )
X			SizeWindow(Win, w-Win->Width   , h-Win->Height  );
X		if( x || y )
X			MoveWindow(Win, x, y );
X		for( i=0; i<7; i++ ) {
X			if(  Win->LeftEdge==x && Win->TopEdge==y && 
X			     Win->Width   ==w && Win->Height ==h )
X				break;
X			Delay(5);
X		}
X	} else 
X		Delay(30); /* pause 1/2 sec. before trying to print */
X
X	printf("\014");
X	return 0;
X}
X
X
Xstatic void
Xsetsystemtime(struct DateStamp *ds)
X{
X	struct timerequest tr;
X	long secs= ds->ds_Days*86400+ds->ds_Minute*60+ds->ds_Tick/TICKS_PER_SECOND;
X
X	if (OpenDevice(TIMERNAME, UNIT_VBLANK,(struct IORequest *)&tr, 0L)) {
X		fprintf(stderr,"Clock error: can't open timer device\n");
X		return;
X	}
X
X	tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
X	tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
X	tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
X	tr.tr_node.io_Message.mn_ReplyPort = NULL;
X	tr.tr_node.io_Command = TR_SETSYSTIME;
X	tr.tr_time.tv_secs = secs;
X	tr.tr_time.tv_micro = 0L;
X	if (DoIO ((struct IORequest *)&tr))
X		fprintf(stderr,"Clock error: can't talk to timer device\n");
X	CloseDevice ((struct IORequest *)&tr);
X}
X
Xchar tday[10];
X
Xchar *
Xdates( struct DateStamp *dss )
X{
X	static char timestr[40];
X	char tdate[10], ttime[10];
X	struct DateTime dt;
X	struct DateStamp *myds=&(dt.dat_Stamp);
X
X	dt.dat_Format=FORMAT_DOS;
X	dt.dat_StrDay=tday;
X	dt.dat_StrDate=tdate;
X	dt.dat_StrTime=ttime;
X	dt.dat_Flags=NULL;
X	myds->ds_Days=dss->ds_Days;
X	myds->ds_Minute=dss->ds_Minute;
X	myds->ds_Tick=dss->ds_Tick;
X	StamptoStr(&dt);
X	sprintf(timestr,"%s %s\n",tdate,ttime);
X	timestr[18]=0;	/* protection against bad timestamped files */
X	return timestr;
X}
X
Xint
Xdo_date( void )
X{
X	static long stopwatch;
X	struct DateStamp dss;
X	struct DateTime dt;
X	long time;
X	int i=1;
X
X	dt.dat_Format=FORMAT_DOS;
X	if (ac==1) {
X		DateStamp(&dss);
X		time=dss.ds_Minute*6000+2*dss.ds_Tick;   /* 2 = 100/TickPerSec   */
X		if( options & 1 )
X			stopwatch=time;
X		else if( options&2 )
X			printf( "%d.%02d\n",(time-stopwatch)/100,(time-stopwatch)%100);
X		else 
X			printf("%s %s\n",tday,dates(&dss));
X	} else {
X		DateStamp(&dt.dat_Stamp);
X		for ( ; i<ac; i++) {
X			dt.dat_StrDate=NULL;
X			dt.dat_StrTime=NULL;
X			dt.dat_Flags=DTF_FUTURE;
X			if (index(av[i],':')) dt.dat_StrTime=av[i];
X				else dt.dat_StrDate=av[i];
X			if (StrtoStamp(&dt)) ierror(av[i],500);
X		}
X		setsystemtime( & (dt.dat_Stamp) );
X	}
X	return 0;
X}
END_OF_FILE
if test 30286 -ne `wc -c <'comm1.c'`; then
    echo shar: \"'comm1.c'\" unpacked with wrong size!
fi
# end of 'comm1.c'
fi
if test -f 'execom.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'execom.c'\"
else
echo shar: Extracting \"'execom.c'\" \(30651 characters\)
sed "s/^X//" >'execom.c' <<'END_OF_FILE'
X/*
X * EXECOM.C
X *
X * Matthew Dillon, 10 August 1986
X *    Finally re-written.
X *
X * Version 2.07M by Steve Drew 10-Sep-87
X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
X * Version 5.00L by Urban Mueller 17-Feb-91
X *
X */
X
X#include "shell.h"
X
X/* execom.c */
Xstatic void preformat(char *s, char *d);
Xstatic void backtrans(char *str);
Xstatic int fcomm(char *str);
Xstatic char *exarg(char **ptr);
Xstatic void mpush_base(void);
Xstatic char *mpush(int bytes);
Xstatic void mpop_tobase(void);
Xstatic char *format_insert_string(char *str, char *from);
Xstatic int cmd_stat(char *str);
Xstatic int find_command(char *str);
Xstatic char *push_cpy(char *s);
Xstatic void exec_every(void);
Xstatic void show_usage(char *str);
Xstatic void get_opt(char **av, int *ac, int ccno);
Xstatic int checkav( int n );
X
X
Xint has_wild = 0;                 /* set if any arg has wild card */
Xchar *LastCommand;
X
Xstruct COMMAND {
X	int (*func)();
X	short minargs;
X	short stat;
X	int val;
X	char *name;
X	char *options;
X	char *usage;
X};
X
Xextern int do_basename(), do_tackon();
Xextern int do_fltupper(), do_fltlower(), do_linecnt();
Xextern int do_strleft(), do_strright(), do_strmid(), do_strlen();
Xextern int do_fornum(), do_forline(), do_exec();
Xextern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
Xextern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
Xextern int do_open(), do_close(), do_fileslist(), do_htype(), do_aget();
Xextern int do_run(), do_number(), do_assign(), do_join();
Xextern int do_quit(), do_set_var(), do_unset_var();
Xextern int do_echo(), do_source(), do_mv(), do_addbuffers();
Xextern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
Xextern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
Xextern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
Xextern int do_input(), do_ver(), do_sleep(), do_help();
Xextern int do_strhead(), do_strtail(), do_relabel();
Xextern int do_copy(), do_date(), do_protect(), do_ps();
Xextern int do_forever(), do_abortline(), do_strings(), do_touch();
Xextern int do_window(), do_search(), do_filenote(), do_rxrec(), do_rxsend();
Xextern int do_ascii(), do_whereis(), do_sort(), do_qcd(), do_usage();
Xextern int do_uniq(), do_man(), do_head(), do_tee(), do_menu(), do_readfile();
Xextern int do_rxreturn(), do_split(), do_which(), do_class();
Xextern int do_action(), do_keymap();
X
X#define ST_COND   0x01
X#define ST_NORED  0x02
X#define ST_NOEXP  0x04
X#define ST_AV     0x08 /* delimit args within a variable */
X#define ST_FUNC   0x10
X
X#define COND  ST_COND
X#define NORED ST_NORED
X#define NOEXP ST_NOEXP
X#define AV    ST_AV
X#define FUNC  ST_FUNC
X
X#define ALIAS LEVEL_ALIAS
X#define SET   LEVEL_SET
X
XBPTR   OldCin;
X
Xstruct COMMAND Command[] = {
X do_run,       0,   AV,     0, "\001",       NULL, NULL, /* may call do_source, do_cd */
X do_abortline, 0,    0,     0, "abortline",  NULL, "",
X do_action,    2,    0,     9, "action",     "av", "action file [args]",
X do_addbuffers,2,    0,     0, "addbuffers", NULL, "{drive bufs}",
X do_set_var,   0,    0, ALIAS, "alias",      NULL, "[name [string] ]",/* uses avline */
X do_ascii,     0,    0,     0, "ascii",      "oh", "-oh [string]",
X do_aset,      1,    0,     0, "aset",       NULL, "name value",
X do_assign,    0,    0,     0, "assign",     "ln", ",logical,-ln {logical physical}",
X do_basename,  2, FUNC,     0, "basename",   NULL, "var path",
X do_cat,       0,    0,     0, "cat",        "n",  "-n [file file...]",
X do_cd,        0,    0,     0, "cd",         "g",  "[path],-g path...path",
X do_class,     0,   AV,     0, "class",      "n",  "-n name {type=param} \"actions\" {action=command}",
X do_close,     0,    0,     0, "close",      NULL, "filenumber",
X do_copy,      1,    0,     0, "copy",       "rudpf","-rudpf file file,-ud file...file dir,-ud dir...dir dir",
X do_copy,      1,    0,     0, "cp",         "rudpf","-rudpf file file,-ud file...file dir,-ud dir...dir dir",
X do_date,      0,    0,     0, "date",       "sr", "-sr [date/time]",
X do_inc,       1,    0,    -1, "dec",        NULL, "varname [step]",
X do_rm,        0,    0,     0, "delete",     "rp", "-pr file...file",
X do_dir,       0,NOEXP,     0, "dir",        "sfdcnhltbuikqavo","-abcdfhiklnoqstuv [path...path]",
X do_diskchange,1,    0,     0, "diskchange", NULL, "drive",
X do_echo,      0,   AV,     0, "echo",       "ne", "-ne string",
X do_if,        0, COND,     1, "else",       NULL, "",
X do_if,        0, COND,     2, "endif",      NULL, "",
X do_exec,      1,    0,     0, "exec",       NULL, "command",
X do_fault,     1,    0,     0, "fault",      NULL, "error",
X do_filenote,  1,    0,     0, "filenote",   "s",  "file...file note,-s file...file",
X do_fileslist, 0,    0,     0, "flist",      NULL, "",
X do_fltlower,  0,    0,     0, "fltlower",   NULL, "<in >out",
X do_fltupper,  0,    0,     0, "fltupper",   NULL, "<in >out",
X do_foreach,   3,NORED,     0, "foreach",    "v",  "-v varname ( string ) command",
X do_forever,   1,NORED,     0, "forever",    NULL, "command",
X do_forline,   3,NORED,     0, "forline",    NULL, "var filename command",
X do_fornum,    4,NORED,     0, "fornum",     "vs", "-vs var n1 n2 command",
X do_getenv,    1, FUNC,     0, "getenv",     NULL, "shellvar envvar",
X do_goto,      1,    0,     0, "goto",       NULL, "label",
X do_head,      1,    0,     0, "head",       NULL, "filename [num]",
X do_help,      0,    0,     0, "help",       NULL, "",
X do_history,   0,    0,     0, "history",    NULL, "[partial_string]",
X do_howmany,   0,    0,     0, "howmany",    NULL, "",
X do_htype,     1,    0,     0, "htype",      "r",  "-r file...file",
X do_if,        1,COND|NORED,0, "if",         "rftmdvn","-n arg cond arg,-n arg,-nf file,-nd dir -nm,-nt file...file,-nr rpn_expr,-v varname",
X do_inc,       1,    0,     1, "inc",        NULL, "varname [step]",
X do_info,      0,    0,     0, "info",       NULL, "[drive...drive]",
X do_input,     1,    0,     0, "input",      "sr", "-rs var...var",
X do_join,      2,    0,     1, "join",       "r",  "-r file...file",
X do_keymap,    1,    0,     0, "keymap",     "n",  "-n number {key=function}",
X do_label,     1, COND,     0, "label",      NULL, "name",
X do_linecnt,   0,    0,     0, "linecnt",    NULL, "<in >out",
X do_dir,       0,NOEXP,     0, "ls",         "sfdcnhltbuikqav","-abcdfhiklnqstuv [path...path]",
X do_man,       0,    0,     0, "man",        NULL, "command...command",
X do_mkdir,     0,    0,     0, "md",         NULL, "name...name",
X do_mem,       0,    0,     0, "mem",        "cfqsr","-cfqsr",
X do_menu,      0,    0,     0, "menu",       "n",  "-n [title item...item]",
X do_mkdir,     0,    0,     0, "mkdir",      NULL, "name...name",
X do_mv,        2,    0,     0, "mv",         NULL, "from to,from...from todir",
X do_open,      3,    0,     0, "open",       NULL, "file mode number",
X do_path,      0,    0,     0, "path",       "r",  "-r [dir...dir]",
X do_pri,       2,    0,     0, "pri",        NULL, "clinumber pri,0 pri",
X do_protect,   2,    0,     0, "protect",    NULL, "file...file flags",
X do_ps,        0,    0,     0, "ps",         "le", "-el [commandname...commandname]",
X do_pwd,       0,    0,     0, "pwd",        NULL, "",
X do_qsort,     0,    0,     0, "qsort",      NULL, "<in >out",
X do_quit,      0,NORED,     0, "quit",       NULL, "",
X do_truerun,   1,NORED,     1, "rback",      NULL, "command",
X do_mv,        2,    0,     0, "rename",     NULL, "from to,from...from todir",
X do_readfile,  1,    0,     0, "readfile",   NULL, "varname [filename]",
X do_relabel,   2,    0,     0, "relabel",    NULL, "drive name",
X do_resident,  0,    0,     0, "resident",   "ard",",-ard file...file",
X do_return,    0,    0,     0, "return",     NULL, "[n]",
X do_rm,        0,    0,     0, "rm",         "rp", "-rp file...file",
X do_rpn,       0,NOEXP,     0, "rpn",        NULL, "expression",
X do_rxrec,     0,    0,     0, "rxrec",      NULL, "[portname]",
X do_rxsend,    2,    0,     0, "rxsend",     "rl", "-lc portname string",
X do_truerun,   1,NORED,     0, "run",        NULL, "command",
X do_search,    2,    0,     0, "search",     "rcwneqvbfalo","-abceflnoqrvw file...file string",
X do_set_var,   0,   AV,   SET, "set",        NULL, "[name [string] ]",
X do_setenv,    2,    0,     0, "setenv",     NULL, "var value",
X do_sleep,     0,    0,     0, "sleep",      NULL, "timeout",
X do_split,     1,    0,     0, "split",      NULL, "srcvar dstvar...dstvar",
X do_source,    1,NORED|AV,  0, "source",     NULL, "file", /* uses avline */
X do_stack,     0,    0,     0, "stack",      NULL, "[bytes]",
X do_strhead,   3, FUNC,     0, "strhead",    NULL, "varname breakchar string",
X do_strings,   1,    0,     0, "strings",    "r",  "-r file...file minlength",
X do_strleft,   3, FUNC,     0, "strleft",    NULL, "varname string n",
X do_strlen,    2, FUNC,     0, "strlen",     NULL, "varname string",
X do_strmid,    3, FUNC,     0, "strmid",     NULL, "varname string n1 [n2]",
X do_strright,  3, FUNC,     0, "strright",   NULL, "varname string n",
X do_strtail,   3, FUNC,     0, "strtail",    NULL, "varname breakchar string",
X do_tackon,    3, FUNC,     0, "tackon",     NULL, "var pathname filename",
X do_head,      1,    0,     1, "tail",       NULL, "filename [num]",
X do_tee,       0,    0,     0, "tee",        NULL, "<in >out",
X do_touch,     0,    0,     0, "touch",      NULL, "file...file",
X do_truncate,  0,    0,     0, "truncate",   NULL, "<in >out",
X do_cat,       0,    0,     0, "type",       NULL, "-n [file...file]",
X do_unset_var, 0,    0, ALIAS, "unalias",    NULL, "name...name",
X do_uniq,      0,    0,     0, "uniq",       NULL, "<in >out",
X do_unset_var, 0,    0,   SET, "unset",      NULL, "name...name",
X do_usage,     0,    0,     0, "usage",      NULL, "[command...command]",
X do_ver,       0,    0,     0, "version",    NULL, "",
X do_waitport,  1,    0,     0, "waitforport",NULL, "portname [seconds]",
X do_whereis,   1,NOEXP,     0, "whereis",    "r",  "-r file [path...path]",
X do_window,    0,NOEXP,     0, "window",     "slfbaq","-slfbaq",
X NULL,         0,    0,     0, NULL,         NULL, NULL,
X};
X
X
X/* do_which,     1,    0,     0, "which",      NULL, "command", */
X
Xstatic char elast;		/* last end delimeter */
Xchar Cin_ispipe, Cout_ispipe;
X
X#ifdef isalphanum
Xchar isalph[256];
X#endif
X
Xint
Xexec_command( char *base )
X{
X	char *scr;
X	char buf[32];
X
X	if (!H_stack && S_histlen>1) {
X		add_history(base);
X		sprintf(buf, "%d", H_tail_base + H_len);
X		set_var(LEVEL_SET, v_histnum, buf);
X	}
X	scr = malloc((strlen(base) << 2) + 2);
X	preformat(base, scr);
X	return (fcomm(scr) ? -1 : 1);
X}
X
X#ifndef isalphanum
Xisalphanum( char c )
X{
X	return (
X		(c >= 'a' && c <= 'z') ||
X		(c >= 'A' && c <= 'Z') ||
X		(c >= '0' && c <= '9') ||
X		(c == '_')
X	);
X}
X#endif
X
X#define HOT_GAP    0x80
X#define HOT_BLANK  0x81
X#define HOT_STAR   0x82
X#define HOT_QUES   0x83
X#define HOT_EXCL   0x84
X#define HOT_SEMI   0x85
X#define HOT_PIPE   0x86
X#define HOT_DOLLAR 0x87
X#define HOT_IN     0x88
X#define HOT_OUT    0x89
X#define HOT_BSLASH 0x8a
X#define HOT_APOSTR 0x8b
X#define HOT_USAGE  0x8c
X#define HOT_SBLANK 0xA0
X
X
Xstatic void
Xpreformat( char *s, char *d )
X{
X	int qm, i;
X
X	qm = 0;
X	while (*s == ' ' || *s == 9) ++s;
X	if      (*s == '\\' ) { *d++=HOT_BSLASH; if( *d++=*++s ) ++s; }
X	else if (*s == '~'  ) { *d++=HOT_APOSTR; s++; }
X
X	while (*s) {
X		if (qm ) {
X			while( *s && *s != '\"' && *s != '\\')
X				*d++ = *s++;
X			if( !*s ) break;
X		}
X		switch (*s) {
X		case ' ':
X		case 9:
X			*d++ = HOT_BLANK;
X			while (*s == ' ' || *s == 9) ++s;
X			if      (*s == '~'  ) { *d++=HOT_APOSTR; s++; }
X			else if (*s == 0 || *s == '|' || *s == ';') --d;
X			break;
X		case '*':
X			*d++ = HOT_GAP;
X			*d++ = HOT_STAR;
X			++s;
X			break;
X		case '?':
X			*d++ = HOT_GAP;
X			*d++ = HOT_QUES;
X			++s;
X			break;
X		case '!':
X			*d++ = HOT_EXCL;
X			++s;
X			break;
X		case '#':
X			*d++ = '\0';
X			while (*s) ++s;
X			break;
X		case ';':
X		case '|':
X			*d++= (*s++==';') ? HOT_SEMI : HOT_PIPE;
X			while (*s == ' ' || *s == 9) ++s;
X			if    (*s == '\\' ) { *d++=HOT_BSLASH; if( *d++=*++s ) ++s; }
X			break;
X		case '\\':
X			if( (i=*++s-'0')>=0 && i<=7 ) {
X				if( *++s>='0' && *s<='7' ) {
X					i= 8*i + *s++-'0';
X					if( *s>='0' && *s<='7' )
X						i= 8*i + *s++-'0';
X				}
X				*d++ = i;
X			} else {
X				*d++ = *s;
X				if (*s) ++s;
X			}
X			break;
X		case '\"':
X			qm = 1 - qm;
X			++s;
X			break;
X		case '^':
X			*d++ = *++s & 0x1F;
X			if (*s) ++s;
X			break;
X		case '<':
X			*d++ = HOT_IN;
X			++s;
X			break;
X		case '>':
X			*d++ = HOT_OUT;
X			++s;
X			break;
X		case '$': /* search end of var name and place false space */
X			*d++ = HOT_GAP;
X			*d++ = HOT_DOLLAR;
X			++s;
X			while (isalphanum(*s)) *d++ = *s++;
X			*d++ = HOT_GAP;
X			break;
X		default:
X			*d++ = *s++;
X			break;
X		}
X	}
X	*d++=0;
X	*d=0;
X	if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
X}
X
Xstatic void
Xbacktrans( char *str )
X{
X	while( *str ) {
X		while( *(signed char *)str>0 ) str++;
X		if( !*str ) break;
X		switch( *str) {
X			case HOT_GAP   : *str++=0;    break;
X			case HOT_BLANK : *str++=' ';  break;
X			case HOT_STAR  : *str++='*';  break;
X			case HOT_QUES  : *str++='?';  break;
X			case HOT_EXCL  : *str++='!';  break;
X			case HOT_SEMI  : *str++=';';  break;
X			case HOT_PIPE  : *str++='|';  break;
X			case HOT_DOLLAR: *str++='$';  break;
X			case HOT_IN    : *str++='<';  break;
X			case HOT_OUT   : *str++='>';  break;
X			case HOT_BSLASH: *str++='\\'; break;
X			case HOT_APOSTR: *str++='~';  break;
X			default        : str++;       break;
X		}
X	}
X}
X
X
Xvoid *
Xmymalloc( int len )
X{
X	return malloc(len);
X}
X
Xextern BPTR extOpen();
X
X/*
X * process formatted string.  ' ' is the delimeter.
X *
X *    0: check '\0': no more, stop, done.
X *    1: check $.     if so, extract, format, insert
X *    2: check alias. if so, extract, format, insert. goto 1
X *    3: check history or substitution, extract, format, insert. goto 1
X *
X *    4: assume first element now internal or disk based command.
X *
X *    5: extract each ' ' or 0x80 delimited argument and process, placing
X *       in av[] list (except 0x80 args appended).  check in order:
X *
X *             '$'         insert string straight
X *             '>'         setup stdout
X *             '>>'        setup stdout flag for append
X *             '<'         setup stdin
X *             '*' or '?'  do directory search and insert as separate args.
X *
X *             ';' 0 '|'   end of command.  if '|' setup stdout
X *                          -execute command, fix stdin and out (|) sets
X *                           up stdin for next guy.
X */
X
X
Xint
Xfcomm( char *str )
X{
X	static int alias_count;
X	int p_alias_count;
X	char *istr, *nextstr, *command;
X	char *pend_alias;
X	int err;
X
X	++alias_count;
X
Xentry:
X	p_alias_count = 0;
X	pend_alias = NULL;
X	err=0;
X	has_wild = 0;
X
X	mpush_base();
X	if (*str == 0)
X		goto done1;
Xstep1:
X	if (alias_count >= MAXALIAS || p_alias_count >= MAXALIAS) {
X		fprintf(stderr,"Alias Loop\n");
X		err = 20;
X		goto done1;
X	}
X
X	istr = NULL;
X	if ( *str == HOT_BSLASH )
X		memmove( str, str+1, strlen(str));
X	else 
X		istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
X
X	if (istr) {
X		p_alias_count++;
X		if (*istr == '%' || *istr=='*') {
X			pend_alias = istr;
X		} else {
X			str = format_insert_string(str, istr );
X			goto step1;
X		}
X	}
X
X	if (*str == HOT_EXCL) {
X		char *p, c;                     /* fix to allow !cmd1;!cmd2 */
X		for(p = str; *p && *p != HOT_SEMI ; ++p);
X		c = *p;
X		*p = '\0';
X		istr = get_history(str,1);
X		*p = c;
X		replace_head(istr);
X		str = format_insert_string(str, istr );
X		goto step1;
X	}
X
X	nextstr = str;
X	command = exarg(&nextstr);
X	if (*command == 0)
X		goto done0;
X	if (pend_alias == 0) {
X		if (cmd_stat(command) & ST_COND)
X			goto skipgood;
X	}
X
X	if (disable || forward_goto) {
X		while (elast && elast != HOT_SEMI && elast != HOT_PIPE)
X			exarg(&nextstr);
X		goto done0;
X	}
Xskipgood:
X	{
X		char *arg, *ptr;
X		short redir;
X		short doexpand;
X		short cont;
X		short inc;
X
X		ac = 1;
X		av[0] = command;
X		backtrans( av[0] );
Xstep5:                                          /* ac = nextac */
X		if (!elast || elast == HOT_SEMI || elast == HOT_PIPE)
X			goto stepdone;
X
X		av[ac] = NULL;
X		cont = 1;
X		doexpand = redir = inc = 0;
X
X		while (cont && elast) {
X			int cstat = cmd_stat(command);
X
X			ptr = exarg(&nextstr);
X			inc = 1;
X			arg = "";
X			cont = (elast == 0x80);
X			switch (*ptr) {
X			case HOT_IN:
X				redir = -2;
X			case HOT_OUT:
X				if (cstat & (ST_NORED | ST_COND)) {     /* don't extract   */
X					redir = 0;                          /* <> stuff if its */
X					arg = ptr;                          /* external cmd.   */
X					break;
X				}
X				++redir;
X				arg = ptr + 1;
X				if (*arg == HOT_OUT) {
X					redir = 2;        /* append >> */
X					++arg;
X				}
X				cont = 1;
X				break;
X			case HOT_DOLLAR:
X				/* restore args if from set command or pend_alias */
X				if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
X					char *pe, sv;
X					while (pe = index(arg,0xA0)) {
X						sv = *pe;
X						*pe = '\0';
X						checkav(1);
X						av[ac++] = push_cpy(arg);
X						*pe = sv;
X						av[ac] = NULL;
X						arg = pe+1;
X					}
X				} else
X					arg = ptr;
X				break;
X			case HOT_APOSTR:
X				if ((arg = get_var(LEVEL_SET, v_lcd)) != NULL) {
X					if( ptr[1] ) {
X						strcpy(Buf,arg);
X						appendslash(Buf);
X						strcat(Buf,ptr+1);
X						arg=Buf;
X					}
X				} else
X					arg = ptr;
X				break;
X
X			case HOT_STAR:
X			case HOT_QUES:
X				if((cstat & ST_NOEXP) == 0 && !(pend_alias && *istr=='*'))
X					if(ac==1&&(av[1]==NULL||!*av[1])&& *ptr==HOT_QUES&& !ptr[1])
X						;
X					else 
X						doexpand = 1;
X				arg = ptr;
X				break;
X			default:
X				arg = ptr;
X				break;
X			}
X
X			/* Append arg to av[ac] */
X
X			if (av[ac]) {
X				char *old = av[ac];
X				av[ac] = mpush(strlen(arg)+strlen(av[ac]));
X				strcpy(av[ac], old);
X				strcat(av[ac], arg);
X			} else
X				av[ac] = push_cpy(arg);
X
X			if (elast != 0x80)
X				break;
X		}
X
X		/* process expansion */
X
X		backtrans( av[ac] );
X		if (doexpand) {
X			char **eav, **ebase;
X			int eac;
X			has_wild = 1;
X			eav = ebase = expand(av[ac], &eac);
X			inc = 0;
X			if (eav) {
X				if( checkav( eac ) ) {
X					ierror (NULL, 506);
X					err = 1;
X				} else {
X					QuickSort(eav, eac);
X					for (; eac; --eac, ++eav)
X					av[ac++] = push_cpy(*eav);
X				}
X				free_expand (ebase);
X			}
X		} else if( av[ac][0]==')' ) {
X			int i;
X			char *pe, sv;
X			for( i=ac-1; i>0; i-- )
X				if( *av[i]=='@' )
X					break;
X			if( i>0 && av[i][strlen(av[i])-1]=='(' ) {
X				extern int exec_fn_err;
X				char *exec_function();
X				char *avi=av[i], *last=av[ac];
X				av[i]=v_value; av[ac]=NULL;
X				arg=exec_function( avi+1, av+i, ac-i );
X				av[i]=avi;     av[ac]=last;
X				inc=0;
X				if( exec_fn_err<0 )
X					ac++;
X				else if( exec_fn_err>0 || !arg )
X					ac=i, av[ac++]="";
X				else {
X					ac=i;
X					while (pe = index(arg,0xA0)) {
X						sv = *pe;
X						*pe = '\0';
X						checkav( 2 );
X						av[ac++] = push_cpy(arg);
X						*pe = sv;
X						arg= pe+1;
X					}
X					av[ac] = mpush(strlen(arg)+strlen(last+1)+4);
X					strcpy(av[ac],arg);
X					strcat(av[ac++], last+1 );
X				}
X			}
X		}
X
X
X		/* process redirection  */
X
X		if (redir && !err) {
X			char *file = (doexpand) ? av[--ac] : av[ac];
X
X			if (redir < 0)
X				Cin_name = file;
X			else {
X				Cout_name = file;
X				Cout_append = (redir == 2);
X			}
X			inc = 0;
X		}
X
X		/* check elast for space */
X
X		if (inc) {
X			++ac;
X			if (ac + 2 > MAXAV) {
X				ierror (NULL, 506);
X				err = 1;                /* error condition */
X				elast = 0;              /* don't process any more arguemnts */
X			}
X		}
X		if (elast == HOT_BLANK)
X			goto step5;
X	}
Xstepdone:
X	av[ac] = NULL;
X
X	/* process pipes via files */
X
X	if (elast == HOT_PIPE && !err) {
X		static int which;             /* 0 or 1 in case of multiple pipes */
X		which = 1 - which;
X		Cout_name = (which) ? Pipe1 : Pipe2;
X		Cout_ispipe = 1;
X	}
X
X
X	if (err)
X		goto done0;
X
X	{
X		int i;
X		char save_elast;
X		char *avline;
X		char delim = ' ';
X		char *larg=av[ac-1];
X
X		if( *larg && larg[strlen(larg)-1]=='&' ) {
X			memmove( av+1, av, (ac-1)*sizeof(*av));
X			command=av[0]="rback";
X			if( strlen(larg)>1 )
X				larg[strlen(larg)-1]=0, ac++;
X		}
X		save_elast = elast;
X		if (pend_alias || (cmd_stat(command) & ST_AV))
X			delim = 0xA0;
X		avline = compile_av(av,((pend_alias) ? 1 : 0), ac, delim, 0);
X
X		if (pend_alias) {                               /* special % alias */
X			char *ptr, *scr, *varname, *val=avline, *gap;
X			ptr=pend_alias;
X			do {                                        /* set all args    */
X				for ( varname= ++ptr; *ptr && *ptr!=' ' && *ptr!='%'; ++ptr);
X				if( *ptr=='%' && (gap=index(val,0xA0 )) ) *gap=0;
X				set_var( LEVEL_SET, varname, val );
X				val= gap ? gap+1 : "";
X			} while( *ptr=='%' );
X			free (avline);
X
X			scr = malloc((strlen(ptr) << 2) + 2);
X			preformat (ptr, scr);
X			fcomm (scr);
X			ptr=pend_alias;
X			do {                                        /* unset all args  */
X				for ( varname=++ptr; *ptr && *ptr!=' ' && *ptr!='%'; ++ptr);
X				unset_var( LEVEL_SET, varname );
X			} while( *ptr=='%' );
X			unset_var (LEVEL_SET, pend_alias + 1);
X		} else {                                        /* normal command  */
X			int ccno;
X			BPTR  oldcin  = Myprocess->pr_CIS;
X			BPTR  oldcout = Myprocess->pr_COS;
X			char *Cin_buf;
X			struct FileHandle *ci;
X			long oldbuf;
X
X			OldCin=oldcin;
X			fflush(stdout);
X			LastCommand=command;
X			ccno = find_command ( command);
X			if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
X				if (Cin_name) {
X					if ((Cin = (long)extOpen(Cin_name,1005L)) == 0) {
X						ierror (NULL, 504);
X						err = 1;
X						Cin_name = NULL;
X					} else {
X						Myprocess->pr_CIS = DEVTAB(stdin) = Cin;
X						ci = (struct FileHandle *)(((long)Cin)<<2);
X						Cin_buf = AllocMem(202L, MEMF_PUBLIC);
X						oldbuf = ci->fh_Buf;
X						if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
X							ci->fh_Buf = (long)Cin_buf>>2;
X					}
X				}
X				if (Cout_name) {
X					if (Cout_append && (Cout =(long)extOpen(Cout_name,1005L))) {
X						Seek(Cout, 0L, 1L);
X					} else {
X						Cout = (long)extOpen(Cout_name,1006L);
X					}
X					if (Cout == NULL) {
X						err = 1;
X						ierror (NULL, 504);
X						Cout_name = NULL;
X						Cout_append = 0;
X					} else {
X						Myprocess->pr_COS = DEVTAB(stdout) = Cout;
X					}
X				}
X			}
X			if (ac < Command[ccno].minargs + 1) {
X				show_usage( NULL );
X				err = -1;
X			} else if (!err) {
X				int (*func)(char*,int)=Command[ccno].func;
X				get_opt( av, &ac, ccno );
X				i=0;
X				if( ccno>0 && ac>1 && !strcmp(av[1],"?") )
X					show_usage(avline);
X				else 
X					i = (*func)(avline, Command[ccno].val);
X				fflush(stderr);
X				if (i < 0)
X					i = 20;
X				err = i;
X			}
X			free (avline);
X			if (E_stack == 0 && Lastresult != err) {
X				Lastresult = err;
X				seterr();
X			}
X			if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
X				if (Cin_name) {
X					ci->fh_Buf = oldbuf;
X					fflush(stdin);
X					clearerr(stdin);
X#ifdef AZTEC_C
X					stdin->_bp=stdin->_bend;
X#else
X					stdin->_rcnt=stdin->_wcnt;
X#endif
X					extClose(Cin);
X					FreeMem(Cin_buf, 202L);
X				}
X				if (Cout_name) {
X					fflush(stdout);
X					clearerr(stdout);
X#ifdef AZTEC_C
X					stdout->_flags &= ~_IODIRTY;    /* because of nil: device */
X#endif
X					extClose(Cout);
X					Cout_append = 0;
X				}
X			}
X			Myprocess->pr_CIS = DEVTAB(stdin)  = oldcin;
X			Myprocess->pr_COS = DEVTAB(stdout) = oldcout;
X		}
X
X		if (Cin_ispipe && Cin_name)
X			DeleteFile(Cin_name);
X		if (Cout_ispipe) {
X			Cin_name = Cout_name;         /* ok to assign.. static name */
X			Cin_ispipe = 1;
X		} else {
X			Cin_name = NULL;
X		}
X		Cout_name = NULL;
X		Cout_ispipe = 0;
X		elast = save_elast;
X	}
X	mpop_tobase();                      /* free arguments   */
X	mpush_base();                       /* push dummy base  */
X
Xdone0:
X	{
X		char *exc;
X		if (err && E_stack == 0) {
X			exc = get_var(LEVEL_SET, v_except);
X			if (err >= ((exc)?atoi(exc):1)) {
X				if (exc) {
X					++H_stack, ++E_stack;
X					a0tospace(exc);
X					exec_command(exc);
X					--E_stack, --H_stack;
X				} else {
X					Exec_abortline = 1;
X				}
X			}
X		}
X		if (elast != 0 && Exec_abortline == 0) {
X			memmove( str, nextstr, strlen(nextstr)+1 );
X			goto entry;
X		}
X		Exec_abortline = 0;
X		if (Cin_name)
X			DeleteFile(Cin_name);
X		Cin_name = NULL;
X		Cin_ispipe = 0;
X	}
Xdone1:
X	mpop_tobase();
X	free(str);
X	--alias_count;
X	return err;                      /* TRUE = error occured    */
X}
X
X
Xstatic char *
Xexarg(ptr)
Xchar **ptr;
X{
X	char *end, *start;
X
X	start = end = *ptr;
X	while ( *(signed char *)end>0 || *end && *end != 0x80 &&
X	         *end != HOT_SEMI &&  *end != HOT_PIPE && *end != HOT_BLANK)
X		++end;
X	elast = *end;
X	*end = '\0';
X	*ptr = end + 1;
X	return start;
X}
X
Xstatic char **Mlist;
X
Xstatic void
Xmpush_base()
X{
X	char *str;
X
X	str = malloc(5);
X	*(char ***)str = Mlist;
X	str[4] = 0;
X	Mlist = (char **)str;
X}
X
Xstatic char *
Xmpush(bytes)
X{
X	char *str;
X
X	str = malloc(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
X	*(char ***)str = Mlist;
X	str[4] = 1;
X	Mlist = (char **)str;
X	return (str + 5);
X}
X
Xstatic void
Xmpop_tobase()
X{
X	char *next;
X	while (Mlist) {
X		next = *Mlist;
X		if (((char *)Mlist)[4] == 0) {
X			free (Mlist);
X			Mlist = (char **)next;
X			break;
X		}
X		free (Mlist);
X		Mlist = (char **)next;
X	}
X}
X
X
X/*
X * Insert 'from' string in front of 'str' while deleting the
X * first entry in 'str'.  if freeok is set, then 'str' will be
X * free'd
X */
X
Xstatic char *
Xformat_insert_string(char *str, char *from)
X{
X	char *new1, *new2;
X	char *strskip;
X	int len;
X
X	for (strskip = str; *(signed char *)strskip>0 ||
X		*strskip && *strskip != HOT_BLANK 
X		&& *strskip != HOT_SEMI && *strskip != HOT_PIPE
X		&& *strskip != 0x80; ++strskip);
X	len = strlen(from);
X	new1 = malloc((len << 2) + 2);
X	preformat(from, new1);
X	len = strlen(new1) + strlen(strskip);
X	new2 = malloc(len+2);
X	strcpy(new2, new1);
X	strcat(new2, strskip);
X	new2[len+1] = 0;
X	free (new1);
X	free (str);
X	return new2;
X}
X
Xstatic int
Xcmd_stat( char *str )
X{
X	return (int)Command[find_command(str)].stat;
X}
X
Xchar *
Xfind_internal( char *str )
X{
X	return(Command[find_command(str)].name);
X}
X
Xstatic int
Xfind_command( char *str )
X{
X	int i, len = strlen(str);
X	struct COMMAND *com;
X	char c=*str;
X
X	for( com=Command, i=0; com->func; com++, i++ )
X		if ( c==*com->name && !strncmp(str, com->name, len))
X			return i;
X	return 0;
X}
X
Xint exec_fn_err;
X
Xextern struct FUNCTION {
X	short id, minargs, maxargs;
X	char *name;
X} Function[];
X
X
Xchar *gotfunc( int i, char **fav, int fac );
X
Xchar *
Xexec_function( char *str, char **fav, int fac)
X{
X	int len=strlen(str)-1, i;
X
X	exec_fn_err=0;
X	for (i = 0; Command[i].func; ++i)
X		if ( Command[i].stat&ST_FUNC && !strncmp(str,Command[i].name,len)) {
X			if( fac<Command[i].minargs ) {
X				exec_fn_err=20;
X				return NULL;
X			} else {
X				int (*func)( void )=Command[i].func;
X				char **oldav=av;
X				int  oldac=ac;
X				av=fav-1, ac=fac+1;
X				exec_fn_err=(*func)();
X				av=oldav, ac=oldac;
X				return get_var( LEVEL_SET, fav[0] );
X			}
X		}
X	for (i = 0; Function[i].id; ++i)
X		if ( len==strlen(Function[i].name)&&!strncmp(str,Function[i].name,len))
X			return gotfunc( i,fav,fac );
X
X	exec_fn_err=-1;
X	return NULL;
X}
X
Xint
Xechofunc(void)
X{
X	int  i;
X	char *str;
X
X	if( !strlen(av[0]) ) return -1;
X	exec_fn_err=0;
X	for (i = 0; Function[i].id; ++i)
X		if ( !strcmp(av[0],Function[i].name)) {
X			if(str=gotfunc( i,av,ac ))
X				printf("%s\n",str);
X			return exec_fn_err;
X		}
X	return -1;
X}
X
X
Xchar *
Xgotfunc( int i, char **fav, int fac )
X{
X	fac--; fav++;
X	if( fac<Function[i].minargs ) {
X		fprintf( stderr, "Not enough arguments for @%s\n",
X		                  Function[i].name );
X		exec_fn_err=20;
X		return NULL;
X	} else if( fac>Function[i].maxargs ) {
X		if( ac > Function[i].maxargs )
X			fprintf( stderr, "Too many arguments for @%s\n",
X			                  Function[i].name );
X		exec_fn_err=20;
X		return NULL;
X	} else {
X		exec_fn_err=dofunc( Function[i].id, fav, fac);
X		return get_var( LEVEL_SET, v_value );
X	}
X	return NULL;
X}
X
X
X
Xdo_help()
X{
X	struct COMMAND *com;
X	int i=0;
X
X	for (com = &Command[1]; com->func; ++com) {
X		printf ("%-12s", com->name);
X		if (++i % 6 == 0) printf("\n");
X	}
X	printf("\n\nUse   man <command>   for more information\n");
X	return 0;
X}
X
Xstatic char *
Xpush_cpy(s)
Xchar *s;
X{
X	return strcpy(mpush(strlen(s)), s);
X}
X
Xvoid
Xexec_every(void)
X{
X	char *str = get_var(LEVEL_SET, v_every);
X
X	if (str) {
X		++H_stack, ++E_stack;
X		a0tospace( str );
X		exec_command(str);
X		--E_stack, --H_stack;
X	}
X}
X
Xchar *
Xa0tospace( str )
X	char *str;
X{
X	char *get=str, *put=str;
X
X	while( *get )
X		if( *get==0xA0 )
X			*put++=' ', get++;
X		else 
X			*put++=*get++;
X	return str;
X}
X
Xvoid
Xshow_usage( str )
X	char *str;
X{
X	int ccno, first=0, err=0;
X	char *get, *put, buf[300];
X
X	if( !str )
X		str=LastCommand, err=1;
X	for( put=str; *put && (*put&127)!=32; put++ ) ;
X	*put=0;
X
X	put=buf;
X	ccno = find_command (str);
X	if( get= Command[ccno].usage ) {
X		do {
X			put+=sprintf(put, first++?"       %s ":"Usage: %s ",
X			             Command[ccno].name );
X			if( *get=='-' ) {
X				*put++='['; *put++='-';
X				get++;
X				while( *get && *get!=' ' && *get!=',' )
X					*put++=*get++;
X				*put++=']';
X			}
X			while( *get && *get!=','  )
X				*put++=*get++;
X			*put++='\n';
X		} while( *get++ );
X		*put=0;
X		fprintf( err ? stderr : stdout, "%s", buf );
X	}
X}
X
Xint
Xexecute( char *str )
X{
X	char  **tav=av, telast=elast;
X	int   tac=ac;
X	ULONG toptions=options;
X	int   thas_wild=has_wild;
X
X	if( !str ) return -1;
X
X	++H_stack;
X	exec_command(str);
X	--H_stack;
X
X	av=tav; ac=tac; elast=telast; options=toptions; has_wild=thas_wild;
X
X	return 0;
X}
X
Xdo_exec( char *str )
X{
X	return execute( next_word( str ) );
X}
X
Xint
Xinteractive( void )
X{
X	return IsInteractive(Output());
X}
X
Xstatic int
Xcheckav( int n )
X{
X	char **tmp;
X	int newac;
X
X	if( ac+n+10>=max_ac ) {
X		newac=max_ac+n+40;
X		if( tmp=(char **)malloc(newac*sizeof(char *))) {
X			memcpy(tmp,av,max_ac*sizeof(char *));
X			free(av);
X			av=tmp; max_ac=newac;
X		} else 
X			return 1;
X	}
X	return 0;
X}
X
X/*	Parse the options specified in sw[]
X	Setting a bit in global variable options
X	for each one found
X*/
X
Xstatic void
Xget_opt( char **av, int *ac, int ccno )
X{
X	char **get=av+1,**put=av+1, *c, *s;
X	int i=1, l, usage=0, nac;
X	long oldopts;
X
X	options=0;
X	if( !ccno )
X		return;
X
X	for( ; i<*ac && *av[i]=='-'; i++, get++ ) {
X		if( !*(c=*get+1) )
X			goto stop;
X		oldopts=options;
X		for ( ; *c ; c++) {
X			if( *c<'a' || *c>'z' ) 
X				{ options=oldopts; goto stop; }
X			for( l=0, s=Command[ccno].options; *s && *s != *c; ++s )
X				++l;
X			if ( *s )
X				options |= (1 << l);
X			else if( !usage ) {
X				usage=1;
X				show_usage(NULL);
X			}
X		}
X	}
Xstop:
X	for( nac=1; i<*ac; i++ )
X		*put++=*get++, nac++;
X	*put=NULL;
X	*ac=nac;
X}
X
X#if 0
XUSHORT Options[160];
X
Xint
Xdo_options()
X{
X	for( i=1; i<ac; i+=2 ) {
X		if( ac-i<=1 )
X			{ ierror( av[i], 500 ); return 20; }
X		if( *av[i+1]!='-' )
X			{ ierror( av[i+1], 500 ); return 20; }
X		options=0;
X		parseopts( av[i+1]+1 );
X	}
X}
X#endif
END_OF_FILE
if test 30651 -ne `wc -c <'execom.c'`; then
    echo shar: \"'execom.c'\" unpacked with wrong size!
fi
# end of 'execom.c'
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.