[comp.sources.amiga] v91i092: CShell 5.10 - alternative command interface, Part05/06

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

Submitted-by: umueller@iiic.ethz.ch
Posting-number: Volume 91, Issue 092
Archive-name: shells/cshell-5.10/part05

#!/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 5 (of 6)."
# Contents:  comm1.c comm2.c
# Wrapped by tadguy@ab20 on Tue Apr 16 15:34:35 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'\" \(34186 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 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 *));
Xstatic void lformat( char *s, char *d, struct file_info *info );
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, docr=0;
X	char buf[256], *l;
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) && !dobreak()) {
X			if (options) printf("%4d ",++lctr);
X			quickscroll();
X			l=buf+strlen( buf )-1; docr=1;
X			if( l>=buf && *l=='\n' ) docr=0;
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					l=buf+strlen( buf )-1; docr=1;
X					if( l>=buf && *l=='\n' ) docr=0;
X					fputs(buf,stdout); fflush(stdout);
X				}
X				fclose (fi);
X			} else
X				pError(av[i]);
X	}
X	if( docr && IsInteractive(Output()))
X		putchar('\n');
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
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	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	Myprocess->pr_WindowPtr = (APTR)(-1);
X
X	infobuf[0]=0;
X	if( !name ) name="";
X	strcpy(infobuf,"0");
X	info=(struct InfoData *)SAllocMem(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
X	Myprocess->pr_WindowPtr = (APTR) o_noreq;
X
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#define DIR_PATH  0x10000
X#define DIR_LFORM 0x20000
X#define DIR_BOT   0x40000
X#define DIR_TOP   0x80000
X
Xstatic BPTR lastlock;
Xstatic int filecount, col, colw, 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
Xstatic struct DateStamp Stamp;
Xstatic char *LineBuf, *LinePos, LastWasDir, *LFormat, _LFormat[80], NoTitles;
X
Xint
Xdo_dir( void )
X{
X	int i=1, c, eac, reverse, nump=ac, retcode=0;
X	char **eav=NULL, **av1=NULL, **av2=NULL, inter=interactive();
X	char linebuf[200];
X	int (*func)(), ac1, ac2, factor=0;
X
X	LineBuf=LinePos=linebuf;
X	LastWasDir=NoTitles=0;
X	colw=-1;
X
X	LFormat=_LFormat;
X
X	if( options&DIR_CLASS ) options|=DIR_IDENT;
X	if( !(options & (DIR_FILES | DIR_DIRS))) options|=(DIR_FILES | DIR_DIRS);
X
X	DateStamp( &Stamp );
X
X	col = filecount = bytes = blocks = 0L;
X	lastlock=0;
X
X	wwidth=77;
X	if( inter ) printf( "\033[?7l" ), wwidth=w_width; /* end of line wrap off */
X
X	if( options&DIR_SHORT )
X		strcpy(LFormat," %-18n%19m");
X	else if( options&DIR_PATH )
X		strcpy(LFormat," %-50p %7s %d"), NoTitles=1;
X	else {
X		if( options&DIR_NOTE )
X			strcpy(LFormat,"   %-24n %o");
X		else {
X			strcpy(LFormat,"   %-24n %c%f ");
X			if( options&DIR_VIEW )
X				strcat(LFormat,"%10v ");
X			else 
X				strcat(LFormat,"%7s ");
X			if( !(options&DIR_QUIET) )
X				strcat(LFormat,options&DIR_VIEW?"%5b ":"%4b ");
X			if( options&DIR_IDENT )
X				strcat(LFormat,"%k");
X			else if( options&DIR_AGE )
X				strcat(LFormat,"%a");
X			else 
X				strcat(LFormat,"%d %t");
X		}
X	}
X
X	if( options&DIR_LFORM )
X		if( ac>1 )
X			LFormat=av[i++];
X		else { 
X			show_usage(NULL);
X			return 20;
X		}
X
X	if( ac == i) ++nump, av[i]="";
X	if( options&DIR_UNIQ) {
X		if( ac-i!=2 )  { show_usage(NULL); return 20; }
X		i=0, nump=3;
X	}
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			if (lastlock) UnLock(lastlock), lastlock=0;
X		} else if (!(eav = expand(av[i], &eac)) && IoError) {
X			ierror(av[i],IoError);
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		if( options & DIR_BOT ) factor=-99999999;
X		if( options & DIR_TOP ) factor= 99999999;
X		DirQuickSort(eav, eac, func, reverse, factor);
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("%s\n",LinePos=LineBuf); col=0; }
X
X		if( LastWasDir )
X			printf(o_lolite), LastWasDir=0;
X
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	}
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
Xstatic int MultiCol=-1;
X
Xstatic void
Xdisplay_file( char *filestr )
X{
X	int isadir, len, collen;
X	char sc, *base, buf[130], *hilite;
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( !NoTitles && (lastlock==NULL || CompareLock(thislock,lastlock))) {
X		/* struct InfoData *id=AllocMem( sizeof(struct InfoData), 0); */
X		if (col) { quickscroll(); printf("%s\n",LinePos=LineBuf); col=0; }
X		quickscroll();
X		PathName(thislock, buf, 128L);
X		/* Info( thislock, id ); */
X		if( LastWasDir )
X			printf(o_lolite), LastWasDir=0;
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	*base    = sc;
X
X	info   = (struct file_info *)(filestr - sizeof(struct file_info));
X	isadir = info->size<0;
X
X	if((!(options & DIR_FILES) || isadir) && (!(options & DIR_DIRS) || !isadir))
X		return;
X
X	hilite="";
X	if (isadir!=LastWasDir && !(options & DIR_NOCOL)) 
X		hilite=isadir ? o_hilite : o_lolite, LastWasDir=isadir;
X
X	lformat(LFormat, buf, info);
X
X	if( MultiCol==-1 ) {
X		quickscroll();
X		printf("%s%s",hilite,buf);
X	} else {
X		len=strlen(buf);
X		if( col+len>wwidth ) {
X			quickscroll();
X			printf("%s\n",LineBuf);
X			LinePos=LineBuf; col=0;
X		}
X		if( MultiCol )
X			colw=MultiCol;
X		else if( colw==-1 )
X			colw=len;
X		collen= (len+colw-1)-(len+colw-1)%colw;
X		col+=collen;
X		LinePos+=sprintf(LinePos,"%s%-*s",hilite,collen,buf);
X	}
X
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
Xstatic void
Xlformat( char *s, char *d, struct file_info *info )
X{
X	long mi=0;
X	char buf[120], *w, *t, *class;
X	struct DPTR *dp;
X	int stat, i, form, sign, cut, size=info->size;
X	char *(*func)(int num);
X
X	MultiCol=-1;
X	while( *s ) {
X		if( *s!='%' ) { *d++=*s++; continue; }
X		sign=1; form=0; cut=0; s++;
X		if( *s=='-' ) s++, sign=-1;
X		if( *s=='.' ) s++, cut=1;
X		while( *s>='0' && *s<='9' ) form=10*form+*s++-'0';
X		w=buf; *w=0;
X		switch( *s ) {
X		case 'p': strcpy(w,(char *)(info+1));             break;
X		case 'b': sprintf(w,size>=0 ? "%d":"", info->blocks); break;
X		case 's': sprintf(w,size>=0 ? "%d":"<Dir>",size); break;
X		case 'i': *w++= size>=0 ? '-' : 'd'; *w=0;        break;
X		case 'r': 
X		case 'u':
X			func= *s=='r' ? itoa : itok;
X			strcpy( w,size>=0 ? (*func)(size) : "<Dir>");
X			break;
X		case 'n': 
X		case 'q':
X			strcpy(w,BaseName((char *)(info+1)));
X			if( *s=='q' && size<0 ) strcat(w,"/");
X			break;
X		case 'c':
X			*w++= info->flags & 1<<30 ? 'c' : '-'; *w=0;
X			break;
X		case 'f':
X			for (i=7; i>=0; i--)
X				*w++ = (info->flags^15) & (1L<<i) ? "hsparwed"[7-i] : '-';
X			*w=0;
X			break;
X		case 'a': 
X			if( Stamp.ds_Days!=0 ) {
X				mi =Stamp.ds_Days*1440 + Stamp.ds_Minute;
X				mi-=info->date.ds_Days*1440 + info->date.ds_Minute;
X			}
X			sprintf(w,mi>=0?"%4d days %02d:%02d":"Future    ",
X			          mi/1440,mi/60%60,mi%60);
X			break;
X		case 'o':
X			if( dp=dopen( (char *)(info+1), &stat )) {
X				strcpy( w, dp->fib->fib_Comment );
X				dclose( dp );
X			}
X			break;
X		case 'v':
X		case 'w':
X			func= *s=='v' ? itoa : itok;
X			dlen=dblocks=0;
X			if( size<0 ) {
X				recurse2( (char *)(info+1),count);
X				strcpy( w, (*func)(dlen));
X				size=dlen; info->blocks=dblocks;
X			} else 
X				strcpy( w, (*func)(size));
X			break;
X		case 'k':
X			if( *info->class!=1 )
X				strcpy(w,info->class);
X			else if( class=getclass((char *)(info+1)))
X				if( w=index(strncpy(w,class,50),0xA0) )
X					*w=0;
X			break;
X		case 'x':
X		case 'd':
X			sprintf(w,"%9s",dates(&info->date,*s=='x'));
X			if(t=index(w,' ')) *t=0;
X			break;
X		case 't': sprintf(w,"%8s", next_word(dates(&info->date,0))); break;
X		case 'm': MultiCol=form; form=0;      break;
X		case '%': *w++=*++s; *w=0;            break;
X		default : *w++='%';  *w++=*++s; *w=0; break;
X		}
X		if( cut ) buf[form]=0;
X		*d=0; s++;
X		d+=sprintf(d,sign<0?"%-*s":"%*s",form,buf);
X	}
X	if( MultiCol==-1 ) { *d++='\n'; }
X	*d=0;
X}
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 lines if they end in '\' */
X
X#define MAXLINE 512
X
Xstatic int
Xsrcgets(char **buf, int *buflen, FILE *file)
X{
X	char *bufptr=*buf, *new, concat=0, cont;
X	int   totlen=0;
X
X	do {
X		if( totlen+MAXLINE > *buflen ) {
X			new=salloc(*buflen *= 2);
X			memcpy( new, *buf, 1+bufptr-*buf );
X			bufptr+= new-*buf;
X			free(*buf);
X			*buf=new;
X		}
X		if (fgets(bufptr, MAXLINE, file)==NULL) {
X			if( concat )
X				fprintf(stderr,"Source: missing '}'\n");
X			else if (bufptr != *buf)
X				fprintf(stderr,"Source: file ends in '\\'\n");
X			return -1;
X		}
X		totlen+=strlen(bufptr);
X
X		cont=0;
X		bufptr+=strlen(bufptr)-1;
X		if( *bufptr=='\n') *bufptr--=0;
X		if( *bufptr=='\\') *bufptr--=0, cont=1;
X		else if( *bufptr=='{' ) concat++;
X		else if( *bufptr=='}' ) {
X			if( concat>0 ) {
X				concat--;
X				if( concat ) *++bufptr=';';
X			} else {
X				fprintf(stderr,"Source: unexpected '}'\n");
X				return -1;
X			}
X		} else if( concat ) *++bufptr=';';
X		bufptr++;
X	} while( cont || concat );
X	*bufptr=0;
X	return totlen;
X}
X
X
X
Xint
Xdo_source( char *str )
X{
X	FILE *fi;
X	char *buf;
X	ROOT *root;
X	int  retcode, len, bufsize=512+MAXLINE;
X
X	if (Src_stack == MAXSRC) {
X		ierror(NULL,217);
X		return -1;
X	}
X
X	if ((fi = fopen (av[1], "r")) == 0)
X		{ pError(av[1]); return -1;	}
X
X	push_locals(root=(ROOT *)salloc( sizeof(ROOT)));
X	buf=salloc(bufsize);
X
X	set_var(LEVEL_SET, v_passed, next_word(next_word(str)));
X	Src_pos  [Src_stack] = 0;
X	Src_abort[Src_stack] = 0;
X	Src_base [Src_stack] = fi;
X	Src_if[Src_stack]=If_stack;
X	++Src_stack;
X	while ((len=srcgets(&buf, &bufsize, fi))>=0&& !dobreak()&& !breakcheckd()){
X		Src_pos[Src_stack-1] += len;
X		if (Verbose&VERBOSE_SOURCE && !forward_goto)
X			if( Verbose&VERBOSE_HILITE )
X				fprintf(stderr,"%s)%s%s\n",o_hilite,buf,o_lolite);
X			else 
X				fprintf(stderr,")%s\n",buf);
X		retcode=execute(buf);
X		if( Src_abort[Src_stack-1] ) break; else retcode=0;
X	}
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	fclose (fi);
X
X	pop_locals();
X	free(buf);
X	free(root);
X
X	return retcode;
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 *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, p=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( (options&SEARCH_LEFT) && !left)
X		return 0;
X
X	if ( docr )
X		{ quickscroll(); printf("\n"); docr=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(!IsInteractive(Output())) 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
Xchar *NameCopy;
Xint (*Action)(char *);
Xint Level;
X
Xstatic void
Xtrue_recurse( char *name )
X{
X	BPTR lock, cwd;
X	FIB *fib=(FIB *)SAllocMem((long)sizeof(FIB),MEMF_PUBLIC);
X
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) { (*Action)(NameCopy); NameCopy[0]=0; }
X				if (fib->fib_DirEntryType==ST_USERDIR) {
X					true_recurse(fib->fib_FileName);
X					if (dirstoo) { strcpy(NameCopy,fib->fib_FileName); }
X				} else if( fib->fib_DirEntryType<0 )
X					strcpy(NameCopy,fib->fib_FileName);
X			}
X		if (*NameCopy) { (*Action)(NameCopy); NameCopy[0]=0; }
X
X		UnLock(CurrentDir(cwd));
X	} else
X		pError(name);
X	FreeMem(fib, (long)sizeof(FIB));
X}
X
Xstatic void
Xrecurse(char *name, int (*action)(char *))
X{
X	NameCopy=salloc(256);
X	Action=action;
X	true_recurse( name );
X	if (dirstoo) { (*Action)(name); }
X	free(NameCopy);
X}
X
X
Xstatic void
Xrecurse2( char *name, void (*action)(FIB *))
X{
X	BPTR lock, cwd;
X	FIB  *fib=(FIB *)SAllocMem(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==ST_USERDIR)
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:%10s\n",itoa(cfree));
X		else if( options & 2 ) printf("Free FAST memory:%10s\n",itoa(ffree));
X		else {
X			if(ffree) {
X				printf("FAST memory:%10s\n",itoa(ffree));
X				printf("CHIP memory:%10s\n",itoa(cfree));
X			}
X			printf("Total  %s:%10s\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	if( !strcmp(av[2],"STDIN") )
X		f=stdin;
X	else 
X		if(!(f=fopen(av[2],"r"))) { pError(av[2]); return 20; }
X
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	if( f!=stdin ) 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, vname[33];
X	char **fav;
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 **)salloc(sizeof(char *) * (ac));
X	for (i = cstart; i < cend; ++i) fav[i] = av[i];
X
X	cstr = compile_av (av, cend + 1, ac, ' ', 0);
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		execute(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,(char*)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,(char*)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<10; 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(20); /* 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
Xstatic char tday[10];
X
Xchar *
Xdates( struct DateStamp *dss, int flags )
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=flags ? DTF_SUBST : 0;
X	myds->ds_Days=dss->ds_Days;
X	myds->ds_Minute=dss->ds_Minute;
X	myds->ds_Tick=dss->ds_Tick;
X	if(StamptoStr(&dt))
X		strcpy(tdate,"<invalid>"), ttime[0]=0;
X	sprintf(timestr,"%-9s %-8s",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,0));
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 34186 -ne `wc -c <'comm1.c'`; then
    echo shar: \"'comm1.c'\" unpacked with wrong size!
fi
# end of 'comm1.c'
fi
if test -f 'comm2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'comm2.c'\"
else
echo shar: Extracting \"'comm2.c'\" \(29350 characters\)
sed "s/^X//" >'comm2.c' <<'END_OF_FILE'
X/*
X * COMM2.C
X *
X * (c)1986 Matthew Dillon     9 October 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/* comm2.c */
Xstatic long dptrtosecs(struct DPTR *d);
Xstatic long timeof(char *s);
Xstatic int evalif(void);
Xstatic int clinum(char *name);
Xstatic int copydir(long srcdir, long destdir, int recur);
Xstatic int copyfile(char *srcname, long srcdir, char *destname, long destdir);
Xstatic int file_date(struct DateStamp *date, char *name);
Xstatic void changedisk(struct MsgPort *task);
Xstatic int func_array( char *fav[], int fac);
Xstatic int func_int(int i);
Xstatic int func_bool(int i);
Xstatic int func_string(char *str);
Xstatic int commas(char *av[], int ac, int n);
Xstatic int wordset(char **av, int ac, char **(*func)(char **,int,char**,int,int*,int));
Xstatic int split_arg(char **av, int ac);
Xstatic char *info_part(char **av, int ac, int n, char *buf);
X
X/* Casting conveniences */
X#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
X#define PROC(task)              ((struct Process *)task)
X#define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
X
X/* Externs */
Xextern int has_wild;                    /* flag set if any arg has a ? or * */
X
X/* globals */
Xstatic int cp_update, cp_date, cp_flags, cp_fresh, cp_move;
X
Xdo_abortline( void )
X{
X	Exec_abortline = 1;
X	return 0;
X}
X
Xdo_error( void )
X{
X	return atoi(av[1]);
X}
X
Xdo_return( void )
X{
X	int retcode=(ac<2 ? 0 : atoi(av[1]));
X
X	Exec_abortline = 1;
X	if (Src_stack) {
X		Src_abort[Src_stack-1]=1;
X		return retcode;
X	} else
X		main_exit(retcode);
X	return 0;
X}
X
X/*
X * STRHEAD
X *
X * place a string into a variable removing everything after and including
X * the 'break' character
X *
X * strhead varname breakchar string
X *
X */
X
Xdo_strhead( void )
X{
X	char *s;
X	if (*av[2] && (s=index( av[3], *av[2]))) 
X		*s='\0';
X	set_var (LEVEL_SET, av[1], av[3]);
X	return 0;
X}
X
Xdo_strtail( void )
X{
X	char *s;
X	if (*av[2] && (s=index(av[3],*av[2]))) s++; else s=av[3];
X	set_var (LEVEL_SET, av[1], s);
X	return 0;
X}
X
Xstatic long
Xdptrtosecs(struct DPTR *d)
X{
X	struct DateStamp *ds=(&d->fib->fib_Date);
X	return ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/TICKS_PER_SECOND;
X}
X
Xstatic long
Xtimeof(char *s)
X{
X	struct DPTR *d;
X	int dummy;
X	long n;
X
X	if ( (d=dopen(s,&dummy))==NULL ) return 0L;
X	n=dptrtosecs(d);
X	dclose(d);
X	return n;
X}
X
X/*
X * if -f file (exists) or:
X *
X * if A < B   <, >, =, <=, >=, <>, where A and B are either:
X * nothing
X * a string
X * a value (begins w/ number)
X */
X
Xdo_if( char *garbage, int com )
X{
X	int result;
X
X	switch (com) {
X	case 0:
X		if (If_stack && If_base[If_stack - 1])
X			If_base[If_stack++] = 1;
X		else {
X			result=evalif();
X			If_base[If_stack++]=(options & 64 ? result : !result);
X		}
X		break;
X	case 1:
X		if (If_stack > 1 && If_base[If_stack - 2]) break;
X		if (If_stack) If_base[If_stack - 1] ^= 1;
X		break;
X	case 2:
X		if (If_stack) --If_stack;
X		break;
X	}
X	disable = (If_stack) ? If_base[If_stack - 1] : 0;
X	if (If_stack >= MAXIF) {
X		fprintf(stderr,"If's too deep\n");
X		disable = If_stack = 0;
X		return -1;
X	}
X	if (forward_goto) disable = If_base[If_stack - 1] = 0;
X	return 0;
X}
X
Xstatic int
Xevalif()
X{
X	char c, *str, *left, *right, *cmp;
X	long num, t0, isint, i=1;
X
X	switch(options & ~64) {
X	case 0:
X		for( i=1; i<ac; i++ )
X			if( strlen(str=av[i])<=2 && *str && index("<=>",*str) &&
X			       (!str[1] || index("<=>",str[1])))
X				break;
X
X		if ( i==ac )
X			return ac>1 && *av[1] && strcmp(av[1],"0");
X
X		left =av[1];
X		right=av[i+1];
X		if( 1+1!=i )    left = compile_av(av,1,i   ,0xA0, 0);
X		if( i+1+1!=ac ) right= compile_av(av,i+1,ac,0xA0, 0);
X		cmp  = av[i];
X		num  = Atol(left);
X		isint  = ! IoErr();
X		num -= Atol(right);
X		isint &= ! IoErr();
X		if (!isint) num=strcmp(left,right);
X		if( 1+1!=i )    free(left); 
X		if( i+1+1!=ac ) free(right);
X
X		if (num < 0)       c='<';
X		else if (num > 0)  c='>';
X		else               c='=';
X		return index(cmp, c) != NULL;
X	case 1:
X		return do_rpn(NULL,i);
X	case 2:
X		return exists(av[i]);
X	case 4:
X		t0=timeof(av[i++]);
X		for ( ; i<ac ; i++)
X			if (t0<=timeof(av[i])) return 1;
X		return 0;
X	case 8:
X		return AvailMem( MEMF_FAST )!=0;
X	case 16:
X		return isdir(av[i])!=0;
X	case 32:
X		return get_var(LEVEL_SET,av[i]) != 0;
X	default:
X		ierror(NULL,500);
X	}
X	return 0;
X}
X
X#if 0
Xdo_while( void )
X{
X	char *com=av[--ac];
X	int ret=0;
X
X	while( evalif() && ret==0 && !CHECKBREAK() )
X		ret=execute( com );
X	return ret;
X}
X#endif
X
X
Xdo_label( void )
X{
X	char aseek[32];
X
X	if (Src_stack == 0) {
X		ierror (NULL, 502);
X		return -1;
X	}
X
X	sprintf (aseek, "%ld %d", Src_pos[Src_stack-1], If_stack);
X	set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
X	if (!strcmp(av[1],get_var(LEVEL_SET,v_gotofwd)))
X		forward_goto = 0;
X	return 0;
X}
X
Xdo_goto( void )
X{
X	int new;
X	long pos;
X	char *lab;
X
X	if (Src_stack == 0) {
X		ierror (NULL, 502);
X	} else {
X		lab = get_var (LEVEL_LABEL + Src_stack - 1, av[1]);
X		if (lab == NULL) {
X			forward_goto = 1;
X			set_var (LEVEL_SET, v_gotofwd, av[1]);
X			return(0);
X		} else {
X			pos = atoi(lab);
X			fseek (Src_base[Src_stack - 1], pos, 0);
X			Src_pos[Src_stack - 1] = pos;
X			new = atoi(next_word(lab));
X			for (; If_stack < new; ++If_stack)
X				If_base[If_stack] = 0;
X			If_stack = new;
X		}
X	}
X	Exec_abortline = 1;
X	return (0);      /* Don't execute rest of this line */
X}
X
X
Xdo_inc(char *garbage, int com)
X{
X	char *var, num[32];
X
X	if (ac>2) com *= atoi(av[2]);
X	if (var = get_var (LEVEL_SET, av[1])) {
X		sprintf (num, "%d", atoi(var)+com);
X		set_var (LEVEL_SET, av[1], num);
X	}
X	return 0;
X}
X
XBPTR Input(void);
XBPTR Output(void);
Xlong IsInteractive(BPTR file);
X
Xdo_input( void )
X{
X	char *str, in[256], *get, *put;
X	int i, quote=0;
X
X	if( options&2 ) {
X		if( !IsInteractive(Input()) ) return 20;
X		setrawcon( -1, 0 );
X		in[1]=0;
X		for ( i=1; i<ac; ++i) {
X			in[0]=getchar();
X			set_var (LEVEL_SET, av[i], in);
X		}
X		setrawcon( 2, 0 );
X		return 0;
X	}
X
X	for ( i=1; i<ac; ++i)
X		if (fgets(in,256,stdin)) {
X			str=in, put=in+strlen(in)-1;
X			if( *put=='\n' ) *put=0;
X			if( !(options&1) ) {
X				while( *str==' ' ) str++;
X				for( put=get=str; *get; ) {
X					if( *get=='\"' )
X						quote=1-quote, get++;
X					else if( *get==' ' && !quote ) {
X						while( *get==' ' ) get++;
X						if( *get ) *put++=0xA0;
X					} else 
X						*put++=*get++;
X				}
X				*put=0;
X				while( put>str && *(put-1)==0xA0 ) *--put=0;
X			}
X			set_var (LEVEL_SET, av[i], str);
X		}
X	return 0;
X}
X
Xdo_ver( void )
X{
X	extern char shellname[];
X
X	puts(shellname);
X	puts("1.00 Lattice (c) 1986 Matthew Dillon\n"
X		 "2.05 Manx (M) versions by Steve Drew\n"
X		 "3.02 ARP (A) versions by Carlo Borreo, Cesare Dieni\n"
X		 "4.00 ARP 1.3 version by Carlo Borreo, Cesare Dieni\n"
X		 "5.00 Lattice version by Urban Mueller (umueller@iiic.ethz.ch)\n");
X	printf("Compiled: "__DATE__" "__TIME__" with "COMPILER"\n" );
X	return 0;
X}
X
X
Xstatic int
Xclinum( char *name )
X{
X	int ncli=(long)FindCLI(0L), count;
X	struct Task *task;
X	char cmd[40+1];
X
X	if( *name>='0' && *name<='9' )
X		return atoi( name );
X
X	Forbid();
X	for (count = 1; count <= ncli ; count++)
X		if (task = (struct Task *)FindCLI(count)) {
X			if ( !PROC(task)->pr_TaskNum || PROC(task)->pr_CLI == 0) continue;
X			BtoCStr(cmd,   CLI(PROC(task))->cli_CommandName, 40L);
X			if( !Strcmp( BaseName( cmd ), name ))
X				goto done;
X		}
X	count=-1;
Xdone:
X	Permit();
X	return count;
X}
X
Xdo_ps( void )
X{
X	/* this code fragment based on ps.c command by Dewi Williams */
X	int count;             /* loop variable         */
X	struct Task *task;     /* EXEC descriptor       */
X	char strbuf[64+1];     /* scratch for btocstr() */
X	char cmd[40+1], *com;  /* holds cmd name        */
X	long ncli,mycli,cli,i;
X
X	char onoff[80];
X	memset( onoff, 0, 80 );
X	for( i=1; i<ac; i++ )
X		onoff[ 1+clinum( av[i] ) ]=1;
X	if( options&2 )
X		for( i=0; i<80; i++ )
X			onoff[i]=1-onoff[i];
X
X	printf("Proc Command Name         CLI Type    Pri.  Address  Directory\n");
X	Forbid();
X
X	ncli=(long)FindCLI(0L);
X	mycli=interactive() ? Myprocess->pr_TaskNum : -1;
X	for (count = 1; count <= ncli ; count++)             /* or just assume 20?*/
X		if (task = (struct Task *)FindCLI((long)count)) {/* Sanity check      */
X			cli=PROC(task)->pr_TaskNum;
X			if( ac>1 && !onoff[1+cli] )
X				continue;
X			if ( cli==0 || PROC(task)->pr_CLI == 0) continue; /* or complain? */
X				BtoCStr(cmd,   CLI(PROC(task))->cli_CommandName, 40L);
X				BtoCStr(strbuf,CLI(PROC(task))->cli_SetName    , 64L);
X			com=cmd;
X			if( !(options&1) )
X				com=BaseName(com);
X			printf("%c%2d  %-20.20s %-11.11s %3d  %8lx  %s\n",
X				cli==mycli ? '*' : ' ',
X				count,
X				com,
X				task->tc_Node.ln_Name,
X				(signed char)task->tc_Node.ln_Pri,
X				task,
X				strbuf
X			);
X		}
X
X	Permit();
X	return 0;
X}
X
X/*
X * CP [-d] [-u] file file
X * CP [-d] [-u] file file file... destdir
X * CP [-r][-u][-d] dir dir dir... destdir
X */
X
Xchar *errstr;          /* let's be alittle more informative */
X
Xdo_copy( void )
X{
X	int recur, ierr;
X	char *destname;
X	char destisdir;
X	FIB *fib;
X	int i=1;
X
X	errstr = "";
X	ierr = 0;
X
X	fib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
X
X	recur     = (options & 0x01);
X	cp_update = (options & 0x02);
X	cp_date   =!(options & 0x04); /* the default is keep orignal file date */
X	cp_flags  =!(options & 0x08);
X	cp_fresh  = (options & 0x10);
X	cp_move   = (options & 0x20);
X
X	destname = av[ac - 1];
X
X	if (ac < i + 2) {
X		ierr = 500;
X		goto done;
X	}
X	destisdir = isdir(destname);
X	if (ac > i + 2 && !destisdir) {
X		ierr = 507;
X		goto done;
X	}
X
X/*
X * copy set:                        reduce to:
X *    file to file                     file to file
X *    dir  to file (NOT ALLOWED)
X *    file to dir                      dir to dir
X *    dir  to dir                      dir to dir
X *
X */
X
X	for (; i<ac-1 && !dobreak(); ++i) {
X		short srcisdir = isdir(av[i]);
X		if (srcisdir && has_wild && (ac >2)) /* hack to stop dir's from */
X			continue;                    /* getting copied if specified */
X		                                 /* from wild expansion         */
X		if (srcisdir) {
X			BPTR srcdir, destdir;
X			if (!destisdir) {
X				if (exists(destname)) {
X					ierr = 507;	/* disallow dir to file */
X					goto done;
X					}
X				if (destdir = CreateDir(destname)) UnLock(destdir);
X				destisdir = 1;
X			}
X			if (!(destdir = Lock(destname, ACCESS_READ))) {
X				ierr = 205;
X				errstr = destname;
X				goto done;
X			}
X			if (!(srcdir = Lock(av[i], ACCESS_READ))) {
X				ierr = 205;
X				errstr = av[i];
X				UnLock(destdir);
X				goto done;
X			}
X			ierr = copydir(srcdir, destdir, recur);
X			UnLock(srcdir);
X			UnLock(destdir);
X			if (ierr) break;
X		} else {                   /* FILE to DIR,   FILE to FILE   */
X			BPTR destdir, srcdir, tmp;
X			char *destfilename;
X
X			srcdir = (BPTR)(Myprocess->pr_CurrentDir);
X
X			if ((tmp = Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)) {
X				if (tmp) UnLock(tmp);
X				ierr = 205;
X				errstr = av[i];
X				goto done;
X			}
X			UnLock(tmp);
X			if (destisdir) {
X				destdir = Lock(destname, ACCESS_READ);
X				destfilename = fib->fib_FileName;
X			} else {
X				destdir = srcdir;
X				destfilename = destname;
X			}
X			printf(" %s..",av[i]);
X			fflush(stdout);
X			ierr = copyfile(av[i], srcdir, destfilename, destdir);
X			if (destisdir) UnLock(destdir);
X			if (ierr) break;
X		}
X	}
X
Xdone:
X
X	FreeMem(fib, (long)sizeof(FIB));
X	if (ierr) {
X		ierror(errstr, ierr);
X		return(20);
X	}
X	return 0;
X}
X
Xstatic int
Xcopydir(BPTR srcdir, BPTR destdir, int recur)
X{
X	static int level;
X	BPTR cwd;
X	FIB *srcfib;
X	BPTR destlock, srclock;
X	int ierr=0;
X
X	level++;
X
X	srcfib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
X	if( !Examine(srcdir, srcfib)) {
X		ierr=IoErr();
X		goto exit;
X	}
X
X	while (ExNext(srcdir, srcfib)) {
X		if (CHECKBREAK())
X			break;
X		if (srcfib->fib_DirEntryType < 0) {
X			printf("%*s%s..",(level-1) * 6," ",srcfib->fib_FileName);
X			fflush(stdout);
X			ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir);
X			if (ierr) break;
X		} else {
X			if ( srcfib->fib_DirEntryType!=ST_USERDIR ) {
X				printf("%*s%s (Dir)....[Skipped. Is a link]\n",(level-1) * 6,
X				               " ",srcfib->fib_FileName);
X				continue;
X			}
X			if (recur) {
X				cwd = CurrentDir(srcdir);
X				if (srclock = Lock(srcfib->fib_FileName, ACCESS_READ)) {
X					CurrentDir(destdir);
X					if (!(destlock = Lock(srcfib->fib_FileName,ACCESS_WRITE))) {
X						destlock = CreateDir(srcfib->fib_FileName);
X						printf("%*s%s (Dir)....[Created]\n",(level-1) * 6,
X					           " ",srcfib->fib_FileName);
X
X						/* UnLock and re Lock if newly created
X						 * for file_date() to work properly */
X						if (destlock)
X							UnLock(destlock);
X						destlock = Lock(srcfib->fib_FileName, ACCESS_WRITE);
X					} else
X						printf("%*s%s (Dir)\n",(level-1) * 6," ",srcfib->fib_FileName);
X					if (destlock) {
X						ierr = copydir(srclock, destlock, recur);
X						UnLock(destlock);
X					} else {
X						ierr = (int)((long)IoErr());
X					}
X					UnLock(srclock);
X				} else {
X					ierr = (int)((long)IoErr());
X				}
X				CurrentDir(cwd);
X				if (ierr)
X					break;
X			}
X		}
X	}
Xexit:
X	--level;
X	FreeMem(srcfib, (long)sizeof(FIB));
X	return(ierr);
X}
X
X#define COPYBUF 32768
X
Xstatic int
Xcopyfile(char *srcname, BPTR srcdir, char *destname, BPTR destdir)
X{
X	BPTR cwd;
X	BPTR f1, f2;
X	long i;
X	int stat,ierr;
X	char *buf;
X	struct DPTR *dp, *dps;
X
X	if ((buf = (char *)AllocMem(COPYBUF, MEMF_PUBLIC|MEMF_CLEAR))==NULL)
X		{ ierr = 103; goto fail2; }
X	ierr = 0;
X	cwd = CurrentDir(srcdir);
X	if ((f1=Open(srcname, MODE_OLDFILE))==NULL)
X		{ errstr = srcname; ierr = 205; goto fail; }
X	dps = dopen(srcname,&stat);
X	CurrentDir(destdir);
X	if (cp_update || cp_fresh) {
X		if( dp=dopen(destname, &stat) ) {
X			if ( dptrtosecs(dp) >= dptrtosecs(dps) &&
X			          !Strcmp(dps->fib->fib_FileName, dp->fib->fib_FileName))
X			{ dclose(dp); Close(f1); printf("..not newer\n"); goto fail; }
X			dclose(dp);
X		} else if( cp_fresh ) {
X			Close(f1); printf("..not there\n"); goto fail;
X		}
X	}
X	if ((f2=Open(destname, MODE_NEWFILE))==NULL)
X		{ Close(f1); ierr = (int)((long)IoErr()); errstr=destname; goto fail;  }
X	while (i = Read(f1, buf, COPYBUF))
X		if( dobreak() )
X			{ ierr=513; break; }
X		else if (Write(f2, buf, i) != i)
X			{ ierr = IoErr(); break; }
X	Close(f2);
X	Close(f1);
X	if (!ierr) {
X		if (cp_date) file_date(&dps->fib->fib_Date, destname);
X		if (cp_flags ) {
X			SetProtection( destname, dps->fib->fib_Protection&~FIBF_ARCHIVE);
X			if( *dps->fib->fib_Comment )
X				SetComment( destname, dps->fib->fib_Comment );
X		}
X		dclose(dps); dps=NULL;
X		if( cp_move ) {
X			CurrentDir(srcdir);
X			DeleteFile(srcname);
X			printf("..moved\n");
X		} else
X			printf("..copied\n");
X	} else {
X		DeleteFile(destname);
X	}
Xfail:
X	if( dps ) dclose(dps);
X	if (buf) FreeMem(buf, COPYBUF);
X	CurrentDir(cwd);
Xfail2:
X	return(ierr);
X}
X
Xdo_touch( void )
X{
X	struct DateStamp ds;
X	int i;
X	DateStamp(&ds);
X	for (i=1; i<ac; i++)
X		if (file_date(&ds, av[i]))
X			ierror(av[i],500);
X		else 
X			clear_archive_bit( av[i] );
X	return 0;
X}
X
X
Xstatic int
Xfile_date( struct DateStamp *date, char *name )
X{
X	long packargs[7];
X	struct MsgPort *task;
X	struct DPTR *tmp;
X	BPTR dirlock;
X	char *ptr;
X	int stat;
X
X	if (!(task = (struct MsgPort *)DeviceProc(name))) return(1);
X	if (tmp = dopen(name, &stat)) {
X		dirlock = ParentDir(tmp->lock);
X		ptr=SAllocMem(65L,MEMF_PUBLIC);
X		CtoBStr(tmp->fib->fib_FileName,(ULONG)ptr >> 2L,64L);
X		dclose(tmp);
X		packargs[1]=dirlock;
X		packargs[2]=(ULONG)ptr >> 2L;
X		packargs[3]=(long)date;
X		SendPacket(ACTION_SET_DATE,packargs,task);
X		UnLock(dirlock);
X		FreeMem(ptr,65L);
X	}
X	return 0;
X}
X
Xdo_addbuffers( void )
X{
X	long packargs[7], i;
X	struct MsgPort *task;
X
X	for( i=1; i<=ac-2; i+=2 ) {
X		if( i==ac-1 )
X			{ ierror( av[i], 500 ); return 20; }
X		if( !(task=(struct MsgPort *)DeviceProc(av[i])))
X			{ ierror(av[1],510); return 20; }
X		packargs[0]=myatoi(av[i+1],1,32767); if (atoierr) return 20;
X		SendPacket(ACTION_MORE_CACHE,packargs,task);
X	}
X	return 0;
X}
X
Xdo_relabel( void )
X{
X	long packargs[7];
X	struct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
X	char *ptr;
X
X	if (!task) { ierror(av[1],510); return 20; }
X	ptr=SAllocMem(65L,MEMF_PUBLIC);
X	CtoBStr(av[2],(ULONG)ptr >> 2L,64L);
X	packargs[0]=(ULONG)ptr >> 2L;
X	SendPacket(ACTION_RENAME_DISK,packargs,task);
X	FreeMem(ptr,65L);
X	Delay(10);
X	changedisk(task);
X	return 0;
X}
X
Xdo_diskchange( void )
X{
X	struct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
X
X	if (!task) { ierror(av[1],510); return 20; }
X	changedisk(task);
X	return 0;
X}
X
Xstatic void
Xchangedisk(struct MsgPort *task)
X{
X	long packargs[7];
X
X	packargs[0]=1L;
X	SendPacket(ACTION_INHIBIT,packargs,task);
X	packargs[0]=0L;
X	SendPacket(ACTION_INHIBIT,packargs,task);
X}
X
X
Xextern int atoierr;
X
Xstatic int
Xfunc_array( char *fav[], int fac)
X{
X	char *ret;
X	if( atoierr ) return 20;
X	if( fac ) {
X		ret=compile_av( fav, 0, fac, 0xa0, 0);
X		set_var( LEVEL_SET, v_value, ret );
X		free( ret );
X	} else 
X		unset_var( LEVEL_SET, v_value );
X	return 0;
X}
X
Xstatic int
Xfunc_int( int i )
X{
X	char buf[12];
X	if( atoierr ) return 20;
X	sprintf(buf,"%d",i);
X	set_var( LEVEL_SET, v_value, buf );
X	return 0;
X}
X
Xstatic int
Xfunc_bool( int i )
X{
X	if( atoierr ) return 20;
X	set_var( LEVEL_SET, v_value, i ? "1" : "0" );
X	return 0;
X}
X
Xstatic int
Xfunc_string( char *str )
X{
X	if( atoierr ) return 20;
X	set_var( LEVEL_SET, v_value, str ? str : "" );
X	return 0;
X}
X
Xstatic int
Xcommas( char *av[], int ac, int n )
X{
X	int i=0;
X
X	while( --ac>=0 )
X		if( !strcmp( *av++, ",") )
X			i++;
X	if( i-=n )
X		fprintf( stderr, "Need %d comma%s\n", n, (n==1) ? "" : "s" );
X	return i;
X}
X
Xstatic int
Xwordset( char *av[], int ac, char **(*func)(char **,int,char**,int,int*,int) )
X{
X	char **av1=av, **av2;
X	int  ac1=0, ac2, ret;
X
X	if( commas( av, ac, 1 ) ) return 20;
X	while( strcmp( *av++, ",") ) ac1++;
X	av2=av, ac2=ac-ac1-1;
X	av=(*func)( av1, ac1, av2, ac2, &ac, 0 );
X	ret=func_array( av, ac );
X	free( av );
X	return ret;
X}
X
Xstatic int
Xsplit_arg( char **av, int ac )
X{
X	char **arr, **old, *arg;
X	int i, j=1, ret;
X
X	for( i=strlen(av[0])-1; i>=0; i-- )
X		if( av[0][i]==' ' )
X			av[0][i]=0, j++;
X
X	arr=old=(char **)salloc( j*sizeof( char * ) );
X	arg=*av;
X	for( ; j>0; j-- ) {
X		*arr++=arg;
X		arg+=strlen(arg)+1;
X	}
X	ret=func_array( old, arr-old );
X	free(old);
X	return ret;
X}
X
Xstatic char *
Xinfo_part( char **av, int ac, int n, char *buf )
X{
X	char *str;
X	struct DPTR *dp;
X	int len=0, i, t;
X
X	buf[0]=0;
X	while( --ac>=0 ) {
X		if( dp=dopen( av[0], &t) ) {
X			if( n==0 ) {
X				for (str=buf, i=7; i>=0; i--)
X					*str++= (dp->fib->fib_Protection & (1L<<i) ?
X					        "hspa----" : "----rwed")[7-i];
X				*str=0;
X			} else len+= dp->fib->fib_NumBlocks+1;
X			dclose( dp );
X		}
X	}
X	if( n ) sprintf(buf, "%d", len);
X	return buf;
X}
X
Xstatic struct FileRequester freq;
X
Xstatic char *
Xfile_request(char **av, int ac, char *path)
X{
X	struct FileRequester fr;
X	char filebuf[128];
X
X	path[0]=0; filebuf[0]=0;
X	fr=freq; /* clear everything */
X	fr.fr_Hail="";
X	if( ac>0 ) {
X		fr.fr_Hail=av[0];
X		if( ac>1 ) {
X			strcpy( path,av[1]);
X			if( ac>2 )
X				strcpy(filebuf,av[2]);
X		}
X	}
X	fr.fr_File  = filebuf;
X	fr.fr_Dir   = path;
X	fr.fr_Flags2= FR2F_LongPath;
X	if( !FileRequest( &fr ) )
X		return NULL;
X	TackOn( path,filebuf );
X	return path;
X}
X
Xint
Xconfirm( char *title, char *file )
X{
X	char buf[80];
X
X	buf[0]=0;
X
X	if( !confirmed ) {
X		fprintf(stderr,"%s %s%-16s%s [YES/no/all/done] ? ",
X		                title,o_hilite,file,o_lolite);
X		strupr(fgets(buf,80,stdin));
X		if( *buf=='A' )
X			confirmed=1;
X		if( *buf=='D' || breakcheck() )
X			confirmed=2;
X	}
X
X	if( confirmed==2 )
X		return 0;
X	return confirmed || *buf != 'N';
X}
X
Xenum funcid {
X	FN_STUB=1, FN_MEMBER, FN_DIRS, FN_NAMEEXT, FN_NAMEROOT, FN_FILES,
X	FN_FILELEN, FN_SORTARGS, FN_UPPER, FN_WORDS, FN_ABBREV, FN_ABS,
X	FN_BINTODEC, FN_CENTER, FN_COMPARE, FN_DECTOHEX, FN_DELWORD,
X	FN_DELWORDS, FN_EXISTS, FN_INDEX, FN_STRCMP, FN_SUBWORDS,
X	FN_WORD, FN_MIN, FN_MAX, FN_DRIVES, FN_WITHOUT, FN_UNION, FN_INTERSECT,
X	FN_AVAILMEM, FN_UNIQUE, FN_RPN, FN_CONCAT, FN_SPLIT, FN_DRIVE,
X	FN_FILEPROT, FN_FILEBLKS, FN_LOWER, FN_HOWMANY, FN_COMPLETE, FN_FIRST,
X	FN_LAST, FN_MATCH, FN_CLINUM, FN_FREEBYTES, FN_FREEBLKS, FN_INFO,
X	FN_MEGS, FN_FREESTORE, FN_CHECKPORT, FN_PICKOPTS, FN_PICKARGS,
X	FN_FILEREQ, FN_VOLUME, FN_LOOKFOR, FN_APPSUFF, FN_PATHNAME, FN_AGE,
X	FN_GETCLASS, FN_CONFIRM, FN_WINWIDTH, FN_WINHEIGHT, FN_WINTOP,
X	FN_WINLEFT, FN_CONSOLE, FN_SORTNUM, FN_IOERROR, FN_MOUNTED
X};
X
X#define MAXAV		30000		/* Max. # of arguments			*/
X
Xstruct FUNCTION {
X	short id, minargs, maxargs;
X	char *name;
X} Function[]={
XFN_ABBREV,   2, 3,     "abbrev",
XFN_ABS,      1, 1,     "abs",
XFN_AGE,      1, 1,     "age",
XFN_APPSUFF,  2, 2,     "appsuff",
XFN_AVAILMEM, 0, 1,     "availmem",
XFN_STUB,     1, 1,     "basename",
XFN_CENTER,   2, 2,     "center",
XFN_CHECKPORT,1, 1,     "checkport",
XFN_CLINUM,   1, 1,     "clinum",
XFN_COMPLETE, 1, MAXAV, "complete",
XFN_CONCAT,   0, MAXAV, "concat",
XFN_CONFIRM,  1, MAXAV, "confirm",
XFN_CONSOLE,  1, 1,     "console",
XFN_DECTOHEX, 1, 1,     "dectohex",
XFN_DELWORD,  1, MAXAV, "delword",
XFN_DELWORDS, 2, MAXAV, "delwords",
XFN_DIRS,     0, MAXAV, "dirs",
XFN_DRIVE,    1, 1,     "drive",
XFN_DRIVES,   0, 0,     "drives",
XFN_EXISTS,   1, 1,     "exists",
XFN_FILEBLKS, 1, MAXAV, "fileblks",
XFN_FILELEN,  0, MAXAV, "filelen",
XFN_FILEPROT, 1, 1,     "fileprot",
XFN_FILEREQ,  0, 3,     "filereq",
XFN_FILES,    0, MAXAV, "files",
XFN_FREEBLKS, 1, 1,     "freeblks",
XFN_FREEBYTES,1, 1,     "freebytes",
XFN_FREESTORE,1, 1,     "freestore",
XFN_FIRST,    0, MAXAV, "first",
XFN_STUB,     1, 1,     "getenv",
XFN_GETCLASS, 1, 1,     "getclass",
XFN_HOWMANY,  0, 0,     "howmany",
XFN_IOERROR,  1, 1,     "ioerr",
XFN_INDEX,    2, 2,     "index",
XFN_INFO,     1, 1,     "info",
XFN_INTERSECT,1, MAXAV, "intersect",
XFN_LAST,     0, MAXAV, "last",
XFN_LOOKFOR,  2, 2,     "lookfor",
XFN_LOWER,    0, MAXAV, "lower",
XFN_MATCH,    1, MAXAV, "match",
XFN_MAX,      1, MAXAV, "max",
XFN_MEGS,     1, 1,     "megs",
XFN_MEMBER,   1, MAXAV, "member",
XFN_MIN,      1, MAXAV, "min",
XFN_MOUNTED,  1, 1,     "mounted",
XFN_NAMEEXT,  1, 1,     "nameext",
XFN_NAMEROOT, 1, 1,     "nameroot",
XFN_PATHNAME, 1, 1,     "pathname",
XFN_PICKARGS, 0, MAXAV, "pickargs",
XFN_PICKOPTS, 0, MAXAV, "pickopts",
XFN_RPN,      1, MAXAV, "rpn",
XFN_SORTARGS, 0, MAXAV, "sortargs",
XFN_SORTNUM,  0, MAXAV, "sortnum",
XFN_SPLIT,    0, MAXAV, "split",
XFN_STRCMP,   2, 2,     "strcmp",
XFN_STUB,     2, 2,     "strhead",
XFN_STUB,     2, 2,     "strleft",
XFN_STUB,     2, 3,     "strmid",
XFN_STUB,     2, 2,     "strright",
XFN_STUB,     2, 2,     "strtail",
XFN_SUBWORDS, 2, MAXAV, "subwords",
XFN_STUB,     2, 2,     "tackon",
XFN_UNION,    1, MAXAV, "union",
XFN_UNIQUE,   0, MAXAV, "unique",
XFN_UPPER,    0, MAXAV, "upper",
XFN_VOLUME,   1, 1,     "volume",
XFN_WINHEIGHT,0, 0,     "winheight",
XFN_WINLEFT,  0, 0,     "winleft",
XFN_WINTOP,   0, 0,     "wintop",
XFN_WINWIDTH, 0, 0,     "winwidth",
XFN_WITHOUT,  1, MAXAV, "without",
XFN_WORD,     1, MAXAV, "word",
XFN_WORDS,    0, MAXAV, "words",
X0,           0, NULL
X};
X
Xextern char shellctr[];
X
Xint
Xdofunc( int id, char **av, int ac)
X{
X	char **oldav=av, **get=av, buf[200], *str=buf;
X	int oldac=ac, i=0, j=0, n=0, n2=1, l;
X	buf[0]=0;
X	av[ac]=NULL;
X
X	switch( id ) {
X	case FN_ABBREV:
X		if( ac==3 ) i=posatoi(av[2] ); else i=strlen(av[0]);
X		return func_bool( !Strncmp( av[0], av[1], i ));
X	case FN_ABS:
X		i=unlatoi(av[0]);
X		return func_int( i>= 0 ? i : -i );
X	case FN_AGE: {
X		struct DateStamp ds; long time;
X		DateStamp( &ds ); if( ds.ds_Days==0 ) return 99999;
X		if( !(time=timeof(av[0]))) return 99999;
X		return func_int( (ds.ds_Days*86400+ds.ds_Minute*60-time)/86400 ); }
X	case FN_APPSUFF:
X		strcpy(buf,av[0]);
X		l=strlen(av[0])-strlen(av[1]);
X		if( l<0 || Strcmp(av[0]+l,av[1])) {
X			strcat(buf,".");
X			strcat(buf,av[1]);
X		}
X		return func_string( buf );
X	case FN_AVAILMEM:
X		if( ac==1 && !Strcmp(av[0],"chip")) n=MEMF_CHIP;
X		if( ac==1 && !Strcmp(av[0],"fast")) n=MEMF_FAST;
X		return func_int( AvailMem( n ));
X	case FN_CENTER:
X		if( (n=posatoi( av[1] )) > (l=strlen(av[0])) ) i=(n-l)/2, j=n-i-l;
X		sprintf( buf, "%*s%s%*s", i,"",av[0], j,"" );
X		return func_string( buf );
X	case FN_CHECKPORT:
X		return func_bool( (int)FindPort( av[0] ) );
X	case FN_GETCLASS:
X		if( str=getclass(av[0]) )
X			if( str=index(strncpy( buf,str,100 ),0xA0) )
X				*str=0;
X		return func_string(buf);
X	case FN_COMPLETE:
X		for( i=1, l=strlen(av[0]); i<ac; i++ )
X			if( !Strncmp( av[0], av[i], l ) )
X				{ str=av[i]; break; }
X		return func_string( str );
X	case FN_CONCAT:
X		return func_string( compile_av( av, 0, ac, ' ', 1));
X	case FN_CONFIRM:
X		for( i=1, get++, confirmed=0; i<ac; i++ )
X			if( confirm( av[0], av[i]) )
X				*get++=av[i];
X		return func_array( av+1, (get-av)-1 );
X	case FN_CONSOLE:
X		if( !strcmp(av[0],"STDIN")) i=IsInteractive(Input());
X		else if( !strcmp(av[0],"STDOUT")) i=IsInteractive(Output());
X		return func_bool(i);
X	case FN_DECTOHEX:
X		sprintf( buf, "%x", unlatoi( av[0] ));
X		return func_string( buf );
X	case FN_DELWORDS:
X		n2=posatoi( av[--ac] ); if( atoierr ) return 20;
X	case FN_DELWORD:
X		n=posatoi( av[--ac] )-1;
X		for( ; i<ac && i<n; i++ ) *av++=*get++;
X		for( ; i<ac && i<n+n2; i++ ) get++;
X		for( ; i<ac ; i++ ) *av++=*get++;
X		return func_array( oldav, av-oldav );
X	case FN_DIRS:
X		for( ; --ac>=0; get++ )
X			if( exists( *get ) && isdir( *get ) )
X				*av++=*get;
X		return func_array( oldav, av-oldav );
X	case FN_DRIVE:
X		return func_string( drive_name( av[0] ) );
X	case FN_DRIVES:
X		get_drives( buf );
X		return func_string( buf );
X	case FN_EXISTS:
X		return func_bool( exists( av[0] ));
X	case FN_FILEBLKS:
X		return func_string( info_part( av, ac, 1, buf ) );
X	case FN_FILELEN:
X		while( --ac>=0 )
X			i+=filesize( *av++ );
X		return func_int( i );
X	case FN_FILEPROT:
X		return func_string( info_part( av, ac, 0, buf ) );
X	case FN_FILEREQ:
X		return func_string( file_request( av, ac, buf ) );
X	case FN_FILES:
X		for( ; --ac>=0; get++ )
X			if( exists( *get ) && !isdir( *get ) )
X				*av++=*get;
X		return func_array( oldav, av-oldav );
X	case FN_FIRST:
X		return func_string( av[0] );
X	case FN_FREEBLKS:
X		return func_string( oneinfo( av[0], 3 ));
X	case FN_FREEBYTES:
X		return func_string( oneinfo( av[0], 2 ));
X	case FN_FREESTORE:
X		return func_string( oneinfo( av[0], 4 ));
X	case FN_HOWMANY:
X		Getenv( shellctr, buf, 10);
X		return func_string( buf );
X	case FN_IOERROR:
X		return func_string( ioerror( atoi( av[0] )));
X	case FN_INDEX:
X		str=strstr( av[0], av[1] );
X		return func_int( str ? (str-av[0])+1 : 0 );
X	case FN_INFO:
X		return func_string( oneinfo( av[0], 1 ));
X	case FN_INTERSECT:
X		return wordset( av, ac, and );
X	case FN_LAST:
X		return func_string( ac ? av[ac-1] : "" );
X	case FN_LOOKFOR:
X		return func_string( dofind( av[0], "", buf, av[1]));
X	case FN_LOWER:
X		while( --ac>=0 ) strlwr( *av++ );
X		return func_array( oldav, av-oldav );
X	case FN_MATCH:
X		for( str=av[--ac]; --ac>=0; get++ )
X			if( compare_ok( str, *get, 0 ) )
X				*av++=*get;
X		return func_array( oldav, av-oldav );
X	case FN_MAX:
X		for( n=MININT; i<ac; i++ ) 
X			{ if( (j=unlatoi(av[i] )) > n ) n=j; if( atoierr ) return 20; }
X		return func_int( n );
X	case FN_MEGS:
X		return func_string( itok( atoi( av[0] )));
X	case FN_MEMBER:
X		for( i=1; i<ac && Strcmp(av[0],av[i]) ; i++ ) ;
X		return func_bool( ac!=i );
X	case FN_MIN:
X		for( n=MAXINT; i<ac; i++ )
X			{ if( (j=unlatoi(av[i] )) < n ) n=j; if( atoierr ) return 20; }
X		return func_int( n );
X	case FN_MOUNTED:
X		get=expand_devs();
X		for( i=0; (str=get[i]) && Strcmp(str+1,av[0]); i++ ) ;
X		free_expand(get);
X		return func_bool((int)str);
X	case FN_NAMEEXT:
X		return func_string( rindex(av[0],'.')?rindex(av[0],'.')+1:(char *)NULL);
X	case FN_NAMEROOT:
X		if( rindex(av[0],'.') ) *rindex(av[0],'.')=0;
X		return func_string( av[0] );
X	case FN_PATHNAME:
X		str=av[0]+strlen(av[0])-1;
X		while( str>av[0] && *str!=':' && *str!='/' ) str--;
X		if( *str==':' ) str++;
X		*str=0;
X		return func_string(av[0]);
X	case FN_PICKARGS:
X		while( *get && **get=='-' ) get++;
X		while( *get )  *av++=*get++ ;
X		return func_array( oldav, av-oldav );
X	case FN_PICKOPTS:
X		while( *get && **get=='-' ) *av++=*get++;
X		return func_array( oldav, av-oldav );
X	case FN_CLINUM:
X		return func_int( clinum( av[0] ) );
X	case FN_RPN:
X		return func_int( eval_rpn( av, ac, 1 ));
X	case FN_SORTARGS:
X		QuickSort( av, ac );
X		return func_array( av, ac );
X	case FN_SORTNUM:
X		DirQuickSort( av, ac, numcmp, 0, 0 );
X		return func_array( av, ac );
X	case FN_SPLIT:
X		return split_arg( av, ac );
X	case FN_STRCMP:
X		return func_int( strcmp( av[0], av[1] ) );
X	case FN_UNION:
X		return wordset( av, ac, or );
X	case FN_UNIQUE:
X		QuickSort( av, ac );
X		while( *get )
X			{ *av++=*get++; while( *get && !Strcmp(*get,*(get-1)))
X				get++; }
X		return func_array( oldav, av-oldav );
X	case FN_UPPER:
X		while( --ac>=0 ) strupr( *av++ );
X		return func_array( oldav, oldac );
X	case FN_VOLUME:
X		return func_string( oneinfo( av[0], 5 ));
X	case FN_WINTOP:
X		return func_int( Win ? Win->TopEdge : 0 );
X	case FN_WINLEFT:
X		return func_int( Win ? Win->LeftEdge: 0 );
X	case FN_WINHEIGHT:
X		return func_int( Win ? Win->Height : 0 );
X	case FN_WINWIDTH:
X		return func_int( Win ? Win->Width  : 0 );
X	case FN_WORD:
X		n2=1; goto wordf;
X	case FN_SUBWORDS:
X		n2=posatoi( av[--ac] ); if( atoierr ) return 20;
X	wordf:
X		n=posatoi( av[--ac] )-1; if( atoierr ) return 20;
X		for( i=0; i<ac && i<n; i++ ) get++;
X		for(    ; i<ac && i<n+n2; i++ ) *av++=*get++;;
X		return func_array( oldav, av-oldav );
X	case FN_WITHOUT:
X		return wordset( av, ac, without );
X	case FN_WORDS:
X		return func_int( ac );
X	}
X	return func_string( "" );
X}
END_OF_FILE
if test 29350 -ne `wc -c <'comm2.c'`; then
    echo shar: \"'comm2.c'\" unpacked with wrong size!
fi
# end of 'comm2.c'
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
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.