[comp.sources.amiga] v91i029: CShell 5.00 - alternative command interface, Part03/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 029
Archive-name: shells/cshell-5.00/part03

#!/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 3 (of 6)."
# Contents:  comm2.c comm3.c
# Wrapped by tadguy@ab20 on Sun Mar  3 16:56:00 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'comm2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'comm2.c'\"
else
echo shar: Extracting \"'comm2.c'\" \(28015 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;
X
Xdo_abortline( void )
X{
X	Exec_abortline = 1;
X	return 0;
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#ifdef AZTEC_C
X		FILE *ptr = Src_base[Src_stack - 1];
X		ptr->_bp = ptr->_bend;
X		ptr->_flags |= _IOEOF;
X#else
X		fseek (Src_base[Src_stack - 1], 0L, 2);
X#endif
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 (s=index(av[3],*av[2])) *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 (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(void)
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 = compile_av(av,1,i   ,0xA0, 0);
X		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 (num < 0)       c='<';
X		else if (num > 0)  c='>';
X		else if (num == 0) 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
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
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; get++) {
X					if( *get=='\"' )
X						quote=1-quote;
X					else if( *get==' ' && !quote )
X						*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 *)AllocMem((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
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;
X
X	level++;
X	ierr = 0;
X	srcfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
X	if (Examine(srcdir, srcfib)) {
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 (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		}
X	} else {
X		ierr = IoErr();
X	}
X	--level;
X	FreeMem(srcfib, (long)sizeof(FIB));
X	return(ierr);
X}
X
X#define COPYBUF 8192
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 = NULL;
X
X	if ((buf = (char *)AllocMem(COPYBUF, MEMF_PUBLIC|MEMF_CLEAR))==NULL)
X		{ ierr = 103; goto fail; }
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 (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		printf("..copied\n");
X	} else
X		DeleteFile(destname);
Xfail:
X	dclose(dps);
X	if (buf) FreeMem(buf, 8192L);
X	CurrentDir(cwd);
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
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=AllocMem(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=AllocMem(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
Xextern char **without(), **and(), **or();
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 **)malloc( 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
X};
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_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_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_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_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[];
Xchar *strstr(), *rindex();
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_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_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_NAMEEXT:
X		return func_string( rindex(av[0],'.') ? rindex(av[0],'.')+1 : 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		for( ; *get ; get++ )
X			if( **get!='-' )
X				*av++=*get;
X		return func_array( oldav, av-oldav );
X	case FN_PICKOPTS:
X		for( ; *get ; get++ )
X			if( **get=='-' )
X				*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_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 28015 -ne `wc -c <'comm2.c'`; then
    echo shar: \"'comm2.c'\" unpacked with wrong size!
fi
# end of 'comm2.c'
fi
if test -f 'comm3.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'comm3.c'\"
else
echo shar: Extracting \"'comm3.c'\" \(26877 characters\)
sed "s/^X//" >'comm3.c' <<'END_OF_FILE'
X/*
X * COMM3.C
X *
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/* comm3.c */
Xstatic void doassign(char *log, char *phy);
Xstatic void assignlist(void);
Xstatic int strings_in_file(char *s);
Xstatic int htype_a_file(char *s);
Xstatic void install_menu(char **mav, int mac);
Xstatic int line_filter( char *(*line)(char *) );
X
Xstatic int
Xmyfgets( char *buf, FILE *in )
X{
X	int l;
X	char *ret;
X	if( ret=fgets(buf,253,in) ) {
X		l=strlen(buf);
X		if( buf[l-1]!='\n' )
X			buf[l]='\n', buf[l+1]=0;
X	}
X	return ret!=NULL && !dobreak();
X}
X
Xdo_tee( void )
X{
X	char buf[256];
X	FILE *out;
X
X	prepscroll( ac==1 );
X	if( ac>2 ) { ierror( av[2], 500 ); return 20; }
X	if( ac==1 ) out=stderr;
X	else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
X	while (myfgets(buf,stdin)) {
X		fputs(buf, stdout);
X		quickscroll();
X		fprintf(out, "%s", buf);
X	}
X	if( ac!=1 ) fclose( out );
X	return 0;
X}
X
Xdo_head( char *garbage, int com )
X{
X	int i, n;
X	FILE *f;
X	char buf[256];
X
X	if (ac>2) {
X		n=(int)(long)Atol(av[2]);
X		if (IoErr()) {
X			ierror(av[2],511);
X			return 20;
X		}
X	} else n=10;
X
X	f=fopen(av[1], "r");
X	if (f==NULL) {
X		pError(av[1]);
X		return 20;
X	}
X	if (com) {	/* tail specific part */
X		i=0;
X		while (fgets(buf, 256, f) && ! dobreak()) i++;
X		rewind(f);
X		if (n>i) n=i;
X		i=i-n;
X		while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
X	}
X	for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
X		printf("%s", buf);
X	fclose(f);
X	return 0;
X}
X
Xstatic int
Xexword( char **src, char *buf )
X{
X	*buf=0;
X	if( **src==0 ) return 0;
X	while( **src && **src!=',' )
X		*buf++=*(*src)++;
X	*buf=0; (*src)++;
X	return 1;
X}
X
Xstatic char helpfound=0;
X
Xvoid
Xman( FILE *f, char *s)
X{
X	char buf[140], entry[100];
X	int len=sprintf(entry, "    %s", s);
X
X	prepscroll(0);
X	rewind(f);
X	do                                  /* look for required argument */
X		if (fgets(buf, 140, f) == NULL)
X			return;
X	while ( Strncmp(entry, buf, len) );
X	helpfound=1;
X	do {                                /* display help */
X		quickscroll();
X		printf("%s", buf);
X		if (fgets(buf, 140, f) == NULL) return;
X	} while ( ( !isalphanum(*buf) ) && strncmp(buf, "    ", 4) && !dobreak() );
X}
X
X
Xdo_man( void )
X{
X	FILE *f;
X	int i;
X	char buf[200], name[60], *src, *var;
X
X	buf[0]=0;
X	if( var=get_var(LEVEL_SET,"_man" ) )
X		strcpy(buf,var);
X
X	if (ac==1) ac=2, av[1]="MAN";
X	for (i=1; i<ac; i++) {
X		src=buf, helpfound=0;
X		while( exword( &src, name) )
X			if( f=fopen(name, "r") ) {
X				man(f, av[i]);
X				fclose(f);
X			}
X		if( !helpfound )
X			fprintf(stderr, "Help not found for %s\n", av[i]);
X	}
X	return 0;
X}
X
Xdo_assign( void )
X{
X	int i;
X
X	if     (  ac==1  ) assignlist();
X	else if(  ac==2  ) doassign(av[1], NULL);
X	else if( !(ac&1) ) ierror(NULL, 500);
X	else
X		for( i=1; i<ac; i+=2 )
X			doassign( av[i],av[i+1] );
X	return 0;
X}
X
Xstatic char *assign_errors[4]={
X	"",
X	"Name %s is not valid\n",
X	"Weird error\n",
X	"Can't cancel %s\n"
X	};
X
X
Xstatic void
Xdoassign(char *log, char *phy)
X{
X	int last=strlen(log) - 1;
X
X	if (log[last] != ':') fprintf(stderr, "Bad name %s\n", log);
X	else {
X		log[last] = 0;
X		if( options && phy && o_kick20 ) {
X			int succ=0;
X			if     ( options&1 ) succ=AssignLate( log,phy );
X			else if( options&2 ) succ=AssignPath( log,phy );
X			if( !succ )
X				pError( log );
X		} else 
X			fprintf(stderr,assign_errors[Assign(log, phy)],phy);
X	}
X}
X
Xstatic void
Xassignlist()
X{
X	struct DirectoryEntry *de_head=NULL, *de;
X	char buf[256];
X	BPTR lock;
X	int ctr=0;
X
X	AddDADevs(&de_head, DLF_DEVICES | DLF_VOLUMES | DLF_DIRS);
X	printf("Devices:\n");
X	for (de=de_head; de && de->de_Type==DLX_DEVICE; de=de->de_Next) {
X		printf("%-8s",de->de_Name);
X		if (ctr++ == 5) { ctr=0; printf("\n"); }
X	}
X	printf("\n\nVolumes:\n");
X	for (	;
X		de && (de->de_Type==DLX_VOLUME || de->de_Type==DLX_UNMOUNTED);
X		de=de->de_Next
X	)
X	printf( "%-16s %s\n",
X		de->de_Name,
X		de->de_Type == DLX_VOLUME ? "[Mounted]" : ""
X	);
X	printf("\nDirectories:\n");
X	for (; de && de->de_Type==DLX_ASSIGN; de=de->de_Next) {
X		if (lock=Lock(de->de_Name, ACCESS_READ)) {
X			PathName(lock, buf, 256L);
X			UnLock(lock);
X		}
X		else
X			strcpy(buf,"Unexisting lock");
X		printf("%-20s%s\n",de->de_Name,buf);
X	}
X	FreeDAList(de_head);
X}
X
Xdo_join( void )
X{
X	BPTR sou, dest;
X	char *buffer;
X	int i;
X	long n;
X	char *namedest=av[--ac];
X
X	if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
X	if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
X	if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
X		{ pError(namedest); goto fail1; }
X	for (i=1; i<ac; i++) {
X		if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
X		else
X			while( (n=Read(sou, buffer, 8192L)) > 0 )
X				if (Write(dest, buffer, n) != n)
X					{ pError(namedest); Close(sou); goto fail2; }
X		Close(sou);
X	}
Xfail2:
X	Close(dest);
Xfail1:
X	free(buffer);
X	return 0;
X}
X
X#define BUFDIM 512L
X#define MAXSTR 256
X
Xint minstr;
X
Xstatic int
Xstrings_in_file(char *s)
X{
X	char c;
X	char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
X	int i, strctr=0;
X	BPTR fh;
X	int out, n;
X
X	prepscroll(0);
X	if ( fh=Open(s, MODE_OLDFILE) ) {
X		fprintf(stderr, "Strings in %s (len>=%d):\n",s,minstr);
X		while ( (n=(int)Read(fh, readbuf, BUFDIM)) > 0 && !CHECKBREAK() )
X			for (i=0; i<n; i++) {
X				c=readbuf[i];
X				if (c<0x20 || c>0x7f) {
X					out=(strctr>=minstr);
X					if (!out) strctr=0;
X				} else {
X					strbuf[strctr++]=c;
X					out=(strctr>=BUFDIM);
X				}
X				if (out) {
X					strbuf[strctr]='\0';
X					puts(strbuf);
X					quickscroll();
X					strctr=0;
X				}
X			}
X		Close(fh);
X	} else
X		pError(s);
X	return 0;
X}
X
Xdo_strings( void )
X{
X	minstr=myatoi(av[--ac],1,255);
X	all_args( strings_in_file, 0);
X	return 0;
X}
X
XBPTR myfile[MAXMYFILES];
X
Xdo_open( void )
X{
X	long mode;
X	int n;
X
X	switch (toupper(av[2][0])) {
X		case 'R': mode=MODE_OLDFILE; break;
X		case 'W': mode=MODE_NEWFILE; break;
X		default : ierror(NULL,500); return 1;
X	}
X	n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
X	if (myfile[n]) myclose(n);
X	myfile[n]=Open(av[1],mode);
X	return myfile[n]==NULL;
X}
X
Xdo_close( void )
X{
X	int i, n;
X
X	if (ac==1)
X		for (i=1; i<MAXMYFILES; i++)
X			myclose(i);
X	for (i=1; i<ac; i++) {
X		n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
X		myclose(n);
X	}
X	return 0;
X}
X
Xvoid
Xmyclose(int n)
X{
X	if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
X}
X
Xdo_fileslist( void )
X{
X	int i, flag=0;
X
X	printf("Open files:");
X	for (i=0; i<MAXMYFILES; i++)
X		if (myfile[i]) { printf(" %d",i); flag=1; }
X	if (!flag) printf(" None!");
X	printf("\n");
X	return 0;
X}
X
XBPTR
XextOpen( char *name, long mode )
X{
X	if (name[0]=='.') return myfile[atoi(name+1)];
X	return Open(name,mode);
X}
X
Xvoid
XextClose(BPTR fh)
X{
X	int i;
X
X	for (i=0; i<MAXMYFILES; i++)
X		if (myfile[i]==fh) return;
X	Close(fh);
X}
X
Xdo_basename( void )
X{
X	set_var(LEVEL_SET, av[1], BaseName(av[2]));
X	return 0;
X}
X
Xdo_tackon( void )
X{
X	char buf[256];
X
X	strcpy(buf, av[2]);
X	TackOn(buf, av[3]);
X	set_var(LEVEL_SET, av[1], buf);
X	return 0;
X}
X
Xextern char shellres[];
X
Xdo_resident( void )
X{
X	int i=1;
X	struct ResidentProgramNode *p;
X	char buf[256];
X
X	if (options==0 && ac>1) options=1;
X	switch (options) {
X	case 0:
X		ObtainSemaphore (& (ArpBase->ResPrgProtection) );
X		if (p=ArpBase->ResidentPrgList) {
X			printf("Name             Users Access\n");
X			for (; p; p=p->rpn_Next)
X				printf("%-17s%5d%6d\n",
X					p->rpn_Name, p->rpn_Usage, p->rpn_AccessCnt);
X		} else
X			printf("No resident program(s)\n");
X		ReleaseSemaphore(& (ArpBase->ResPrgProtection) );
X		break;
X	case 1:
X		for (; i<ac; i++)
X			if (loadres(av[i]))
X				printf("OK! %s is now resident\n", BaseName(av[i]));
X			else
X				pError(av[i]);
X		break;
X	case 2:
X		for (; i<ac; i++)
X			if (RemResidentPrg(av[i])) ierror(av[i],202);
X			else printf("Removed %s\n",av[i]);
X		break;
X	case 4:
X		for (; i<ac; i++) {
X			if( !o_resident ) {
X				Setenv(shellres,"1");
X				o_resident=1;
X			}
X			sprintf(buf,"res_%s",av[i]);
X			Setenv(buf,"1");
X		}
X		break;
X	default:
X		ierror(NULL,500);
X		break;
X	}
X	return 0;
X}
X
Xint
Xloadres(char *s)
X{
X	BPTR seg;
X
X	if (seg=(BPTR)LoadPrg(s)) AddResidentPrg(seg,BaseName(s));
X	return (seg != NULL);
X}
X
Xstruct ProcessControlBlock pcb={
X	4000,		/* pcb_StackSize	*/
X	0,			/* pcb_Pri			*/
X	};
X/* remaining field are NULL */
X	
Xdo_truerun(char *avline, int backflag)
X{
X	char name[200], *args;
X
X	if (backflag) {
X		pcb.pcb_Control=NULL;
X		pcb.pcb_Input=pcb.pcb_Output=Open("NIL:",MODE_OLDFILE);
X	} else {
X		pcb.pcb_Control=NULL;
X		pcb.pcb_Input=pcb.pcb_Output =NULL;
X	}
X	args=next_word(next_word(avline));
X
X	if(ASyncRun(av[1],args,&pcb)<0)
X		if (dofind(av[1], "", name,v_path))
X			ASyncRun(name,args,&pcb);
X		else
X			ierror(av[1],205);
X	return 0;
X}
X
Xint
Xexists( char *name )
X{
X	BPTR lock;
X
X	if (lock=Lock(name,ACCESS_READ)) {
X		UnLock(lock);
X		return 1;
X	}
X	return 0;
X}
X
Xdo_aset( void )
X{
X	Setenv(av[1],av[2]);
X	return 0;
X}
X
X#define HTYPELINE 16L
X
Xstatic int
Xhtype_a_file( char *s )
X{
X	BPTR fh;
X	long n, filesize=0;
X	char buf[HTYPELINE+1];
X	char out[80], *put;
X	int i;
X
X	if ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; }
X	prepscroll(0);
X	while ( (n=Read(fh,buf,HTYPELINE))>0 && !dobreak()) {
X		put=out;
X		put+=sprintf(put,"%06lx: ",filesize);
X		filesize+=n;
X		for (i=0; i<n; i++) {
X			put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
X			if ((buf[i]&127)<0x20) buf[i]='.';
X		}
X		for ( ; i<HTYPELINE; i++) {
X			put+=sprintf( put, (i&3) ? "  " : "   ");
X			buf[i]=' ';
X		}
X		buf[i]=0;
X		sprintf(put,"    %s",buf);
X		puts(out);
X		quickscroll();
X	}
X	Close(fh);
X	return 0;
X}
X
Xdo_htype( void )
X{
X	all_args( htype_a_file, 0);
X	return 0;
X}
X
Xdo_stack( void )
X{
X	long n;
X
X	if (ac>1) {
X		n=Atol(av[1]);
X		if (!IoErr()) Mycli->cli_DefaultStack=(long)(n >> 2L);
X	}
X	else printf("current stack size is %ld bytes\n",
X				(long)Mycli->cli_DefaultStack << 2L);
X	return 0;
X}
X
Xdo_fault( void )
X{
X	struct PERROR *p;
X	int i, n;
X
X	for (i=1; i<ac; i++) {
X		n=myatoi(av[i],0,32767);
X		if (!atoierr) {
X			for (p=Perror; p->errnum && p->errnum!=n; p++);
X			if (p->errnum)
X				printf("Fault %d: %s\n",n,p->errstr);
X			else
X				printf("Fault %d not recognized\n",n);
X		}
X	}
X	return 0;
X}
X
Xstruct rpncommand {
X	char *str;
X	int parsin, parsout;
X	};
X
Xstatic struct rpncommand rpn[]={
X	"+",	2,	1,
X	"-",	2,	1,
X	"*",	2,	1,
X	"/",	2,	1,
X	"%",	2,	1,
X	"&",	2,	1,
X	"|",	2,	1,
X	"~",	1,	1,
X	">",	2,	1,
X	"<",	2,	1,
X	"==",	2,	1,
X	"!",	1,	1,
X	"MAX",	2,	1,
X	"MIN",	2,	1,
X	"DUP",	1,	2,
X	"DROP",	1,	0,
X	"SWAP",	2,	2,
X	"HELP",	0,	0,
X	NULL,	0,	1,	/* this looks for a number */
X};
X
Xstatic long stack[50];
Xstatic int sp;
X
X
Xeval_rpn( char **av, int ac, int flag )
X{
X	char *zero="Division by zero\n";
X	struct rpncommand *temp;
X	long n0, n1, t;
X	int j, i=0, oldsp=sp;
X
X	for (; i<ac; i++) {
X		for (j=0; rpn[j].str && Strcmp(rpn[j].str,av[i]); j++) ;
X		n0=stack[sp-1];
X		n1=stack[sp-2];
X		sp -= (rpn[j].parsin);
X		if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
X		switch (j) {
X		  case 0:	n0 += n1;			break;
X		  case 1:	n0 = n1-n0;			break;
X		  case 2:	n0 *= n1;			break;
X		  case 3:	if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
X		  case 4:	if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
X		  case 5:	n0 &= n1;			break;
X		  case 6:	n0 |= n1;			break;
X		  case 7:	n0 =  ~n0	;		break;
X		  case 8:	n0 = (n1 > n0);		break;
X		  case 9:	n0 = (n1 < n0);		break;
X		  case 10:	n0 = (n0 == n1);	break;
X		  case 11:	n0 = !n0;			break;
X		  case 12:	n0=n1>n0 ? n1 : n0;	break;
X		  case 13:	n0=n1<n0 ? n1 : n0;	break;
X		  case 14:	n1=n0;				break;
X		  case 15:	t=n0; n0=n1; n1=t;	break;
X		  case 16:						break;
X		  case 17:	printf("In Commands Out\n");
X			for (temp=rpn; temp->str; temp++)
X			    printf(" %d %-10s%d\n",
X				temp->parsin,temp->str,temp->parsout);
X			break;
X		  default:	n0=Atol(av[i]);
X				if (IoErr()) {
X					fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
X					goto error;
X				}
X				break;
X		  }
X		stack[sp]=n0;
X		stack[sp+1]=n1;
X		sp += rpn[j].parsout;
X	}
X	if( flag && sp-1) fprintf( stderr, "RPN: Stack not empty\n" );
X
Xexit:
X	t=sp; sp=oldsp;
X	if( flag )
X		return stack[t-1]; /* return top value */
X	else 
X		return t-sp;
X
Xerror:
X	sp=oldsp;
X	return 0;
X}
X
X
Xdo_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
X{
X	int i=1;
X	long t;
X
X	t=eval_rpn( av+i, ac-i, ifflag );
X	if (ifflag) return t;              /* called from if: return top value */
X	for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
X
X	return t ? 0 : 20;
X}
X
Xdo_path( void )
X{
X	ULONG ll, ll1, *lp, new, *newp;
X	char buf[256];
X	char buf2[256];
X	BPTR lock;
X	int i;
X
X	if( options&1 ) {
X		Forbid();
X		for( ll= Mycli->cli_CommandDir; ll; ll= ll1 ) {
X			lp=(ULONG *)(4*ll);
X			ll1=*lp;
X			DosFreeMem( lp );
X		}
X		Mycli->cli_CommandDir=0;
X		Permit();
X	} else if( ac==1 ) {     /* Should Forbid() here, but puts() Permit()s */
X		puts("Current dir"); /* and failure here is not really harmful...  */
X		for( ll= Mycli->cli_CommandDir; ll; ll= *lp ) {
X			lp=(ULONG *)(4*ll);
X			PathName(lp[1], buf, 256L);
X			puts(buf);
X		}
X		puts("C:");
X		return 0;
X	}
X	Forbid();
X	for( i=1; i<ac; i++ ) {
X		if( !(lock=Lock(av[i],ACCESS_READ)) ) {
X			pError(av[i]);
X			continue;
X		}
X		PathName(lock, buf, 256L);
X		for( ll= Mycli->cli_CommandDir, lp=NULL; ll; ll= *lp ) {
X			lp=(ULONG *)(4*ll);
X			PathName(lp[1],buf2,256L);
X			if( !Strcmp(buf,buf2) ) {
X				UnLock(lock);
X				break;
X			}
X		}
X		if( !ll ) {
X			newp=DosAllocMem( 8 );
X			newp[1]=lock;
X			new =(ULONG)newp/4;
X			if( lp )
X				*lp=new;
X			else
X				Mycli->cli_CommandDir=new;
X		}
X	}
X	Permit();
X	return 0;
X}
X
Xdo_pri( void )
X{
X	int t, pri;
X	struct Process *proc;
X
X	t=(int)(long)FindCLI(0L);
X	t=myatoi(av[1],0,t); if (atoierr) return 20;
X	pri=myatoi(av[2],-128,127); if (atoierr) return 20;
X	Forbid();
X	proc=(t==0 ? Myprocess : FindCLI((long)t));
X	if (proc==NULL) fprintf(stderr, "process not found\n");
X	else SetTaskPri((struct Task *)proc, (long)pri);
X	Permit();
X	return 0;
X}
X
Xdo_strleft( void )
X{
X	int n;
X
X	n=posatoi(av[3]); if (atoierr) return 20;
X	set_var_n(LEVEL_SET, av[1], av[2], n);
X	return 0;
X}
X
Xdo_strright( void )
X{
X	int n, len=strlen(av[2]);
X
X	n=posatoi(av[3]); if (atoierr) return 20;
X	if( n>len ) n=len;
X	set_var(LEVEL_SET, av[1], av[2]+len-n );
X	return 0;
X}
X
Xdo_strmid( void )
X{
X	int n1, n2=999999, len=strlen(av[2]);
X
X	n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
X	if (n1>len) n1=len;
X	if (ac>4) {
X		n2=posatoi(av[4]); if (atoierr) return 20;
X	}
X	set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
X	return 0;
X}
X
Xdo_strlen( void )
X{
X	char buf[16];
X
X	sprintf(buf,"%d",strlen(av[2]));
X	set_var(LEVEL_SET, av[1], buf);
X	return 0;
X}
X
Xint atoierr;
X
Xmyatoi(s,min,max)
Xchar *s;
X{
X	int n;
X
X	n=Atol(s);
X	if (atoierr=IoErr())
X		ierror(s,511);
X	else if (n<min || n>max) {
X		atoierr=1; n=min;
X		fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,min,max );
X	}
X	return n;
X}
X
Xunlatoi(char *s)
X{
X	int n=Atol(s);
X	if (atoierr=IoErr())
X		ierror(s,511), n=0;
X	return n;
X}
X
Xposatoi(char *s)
X{
X	int n=Atol(s);
X	if (atoierr=IoErr())
X		ierror(s,511);
X	else if (n<0 )
X		atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
X	return n;
X}
X
X
Xdo_fltlower( void )
X{
X	return line_filter( strlwr );
X}
X
Xdo_fltupper( void )
X{
X	return line_filter( strupr );
X}
X
X#if 0
Xchar *
Xstripcr( char *get )
X{
X	char *old=get, *put;
X
X	for( put=get; *get; get++ )
X		if( *get!=13 )
X			*put++=*get;
X	*put++=0;
X	return old;
X}
X
Xdo_fltstripcr( void )
X{
X	return line_filter( stripcr );
X}
X#endif
X
Xint
Xline_filter( char *(*func)( char * ) )
X{
X	char buf[256];
X
X	while (!CHECKBREAK() && gets(buf))
X		puts((*func)(buf));
X	return 0;
X}
X
Xdo_linecnt( void )
X{
X	int count=0;
X	char buf[256];
X
X	while (!CHECKBREAK() && gets(buf)) ++count;
X	printf("%d lines\n",count);
X	return 0;
X}
X
Xdo_uniq( void )
X{
X	int firstline=1;
X	char buf[256], oldbuf[256];
X
X	while (!CHECKBREAK() && gets(buf)) {
X		if ( firstline || strcmp(buf, oldbuf)) {
X			strcpy(oldbuf, buf);
X			puts(buf);
X		}
X		firstline=0;
X	}
X	return 0;
X}
X
X
X#define RXFB_RESULT  17
X
Xstatic struct rexxmsg {
X	struct Message cm_Node;
X	LONG   RFU1;
X	LONG   RFU2;
X	LONG   rm_Action;
X	LONG   rm_Result1;
X	LONG   rm_Result2;
X	char   *cm_Args[16];
X	LONG   RFU7;
X	LONG   RFU8;
X	LONG   RFU9;
X	LONG   RFU10;
X	LONG   RFU11;
X	LONG   RFU12;
X} mymsg;
X
Xdo_rxsend( char *avline )
X{
X	int i;
X	long result;
X	struct MsgPort *port, *reply;
X	long len;
X	char buf[20], *resptr;
X
X	if (!(port = FindPort(av[1])))
X		{ fprintf(stderr, "No port %s!\n", av[1]); return 20; }
X	mymsg.cm_Node.mn_Node.ln_Type = NT_MESSAGE;
X	mymsg.cm_Node.mn_Length = sizeof(struct rexxmsg);
X	mymsg.rm_Action = (options&1 ? 1L << RXFB_RESULT : 0);
X	if (!(reply = CreatePort(NULL, 0L))) {
X		fprintf(stderr, "No reply port\n");
X		return 20;
X	}
X	mymsg.cm_Node.mn_ReplyPort = reply;
X
X	if( options&2 )
X		av[2]=compile_av( av,2,ac,' ',0), ac=3;
X	for ( i=2; i<ac; i++) {
X		mymsg.cm_Args[0] = av[i];
X		mymsg.rm_Result2 = 0;        /* clear out the last result. */
X		PutMsg(port, &mymsg.cm_Node);
X		WaitPort(reply);
X
X		if (options&1) {
X			if( (result=mymsg.rm_Result2)<1000000 ) { /* so does it AREXX */
X				sprintf(buf,"%d",result);              
X				set_var(LEVEL_SET,v_result,buf);
X			} else {
X				resptr=(char *)(result-4);
X				len=*(long *)resptr;
X				memmove(resptr,resptr+4,len);  /* Null terminate */
X				resptr[len]=0;      
X				set_var(LEVEL_SET,v_result,resptr);
X				FreeMem(resptr, len+4 );
X			}
X		} else 
X			unset_var( LEVEL_SET, v_result );
X	}
X	if( options&2 )
X		free( av[2] );
X
X	if (reply) DeletePort(reply);
X	return 0;
X}
X
Xstatic char *rxreturn;
X
Xdo_rxrec( void )
X{
X	struct MsgPort *port;
X	struct rexxmsg *msg;
X	char *portname, *str;
X
X	if (ac > 1)
X		portname=av[1];
X	else
X		portname="rexx_csh";
X
X	port=CreatePort(portname, 0L);
X	if (port==NULL) {
X		fprintf(stderr, "Can't have MsgPort %s\n", portname);
X		return 20;
X	}
X	for (;;) {
X		WaitPort(port);
X		while (msg=(struct rexxmsg *)GetMsg(port)) {
X			if ( ! Strcmp(msg->cm_Args[0], "bye")) {
X				ReplyMsg((struct Message *)msg);
X				DeletePort(port);
X				return 0;
X			}
X			rxreturn=NULL;
X			exec_command(msg->cm_Args[0]);
X			if (msg->rm_Action & (1L << RXFB_RESULT)) {
X				if( rxreturn ) {
X					str= AllocMem( strlen( rxreturn )+5 , 0 );
X					*(long *)str=strlen( rxreturn );
X					strcpy( str+4, rxreturn );
X					msg->rm_Result2=(long)str;
X				} else {
X					str = get_var(LEVEL_SET, v_lasterr);
X					msg->rm_Result2=(str) ? atoi(str) : 20;
X				}
X			}
X			ReplyMsg((struct Message *)msg);
X		}
X	}
X}
X
Xint
Xdo_waitport( void )
X{
X	int count=4*10;
X	struct MsgPort *port;
X
X	if( ac==3 ) 
X		{ count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
X
X	while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
X		Delay(12);
X
X	return port ? 0 : 20;
X}
X
Xint
Xdo_rxreturn( void )
X{
X	rxreturn=compile_av( av, 1, ac, ' ', 1 );
X	return 0;
X}
X
Xdo_ascii( void )
X{
X	int x=1, y, c, c1, t;
X	char *fmt1=" %3d %c%c |", *fmt2=" %4d";
X
X	if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
X	if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
X	if( ac==x )
X		for( y=0; y<32 && !dobreak(); y++ ) {
X			printf("|");
X			for( x=0; x<8; x++ ) {
X				c1=c=y+32*x; t=' ';
X				if( c<32 ) t='^', c1+=64;
X				printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
X			}
X			printf("\n");
X		}
X	else 
X		for( ; x<ac && !dobreak(); x++ ) {
X			for( y=0; y<strlen(av[x]); y++ )
X				printf(fmt2,av[x][y]);
X			printf("\n");
X		}
X	return 0;
X}
X
Xvoid
Xappendslash( char *path )
X{
X	int c;
X
X	if( (c=path[strlen(path)-1]) !='/' && c!=':' )
X		strcat(path,"/");
X}
X
Xstatic void
Xwhereis( char *path, char *file )
X{
X	char **eav, buf[100];
X	int  eac, j;
X
X	buf[0]=0;
X	if( path ) {
X		strcpy(buf,path);
X		appendslash(buf);
X	}
X	strcat(buf,".../");
X	strcat(buf,file);
X	if( !index( file, '*' ) && !index( file, '?') )
X		strcat(buf,"*");
X	if(eav=expand(buf,&eac)) {
X		for( j=0; j<eac && !dobreak(); j++ )
X			printf("%s\n",eav[j]);
X		free_expand(eav);
X	}
X}
X
Xdo_whereis( void )
X{
X	char buf[200], *prev, *devs;
X	int i;
X
X	if( index( av[1],':') || index( av[1],'/' ) )
X		{ fprintf(stderr,"No paths please\n"); return 20; };
X
X	if( options&1 ) {
X		Myprocess->pr_WindowPtr = (APTR)(-1);
X		get_drives( devs=buf );
X		do {
X			prev=devs; devs=index(devs,0xA0);
X			if( devs ) *devs++=0; 
X			whereis( prev, av[1] );
X		} while( devs );
X		Myprocess->pr_WindowPtr = (APTR) o_noreq;
X	} else if( ac==2 ) {
X		whereis( NULL, av[1] );
X	} else {
X		for( i=2; i<ac; i++ ) {
X			strcpy(buf,av[i]);
X			appendslash( buf );
X			whereis( buf, av[1] );
X		}
X	}
X	return 0;
X}
X
Xdo_usage( void )
X{
X	int i;
X
X	if( ac==1 ) {
X		printf("Usage: usage [command...command]\n");
X		printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
X	} else 
X		for( i=1; i<ac; i++ )
X			show_usage( av[i] );
X	return 0;
X}
X
Xint NumMenus;
X
Xdo_menu( void )
X{
X	if( o_nowindow )
X		return 5;
X
X	if( options&1 )
X		remove_menu();
X
X	if( ac==2 )
X		show_usage( NULL );
X	else if( NumMenus<MAXMENUS && ac!=1)
X		install_menu( av+1, ac-1 );
X
X	set_menu();
X	return 0;
X}
X
X#define NUMITE 40
X#define TITWID 90
X#define ITEWID 148
X
Xstatic struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
Xstatic struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
Xstatic struct MenuItem DefaultMenuItem=
X  {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
X
Xstruct Menu Menus[10];
Xchar *MenuCommand[MAXMENUS][MAXITEMS];
X
Xextern char *rindex();
X
Xstatic void
Xinstall_menu( char *mav[], int mac )
X{
X	struct TextAttr *ta;
X	struct Menu *m;
X	struct MenuItem *mi, **pmi;
X	struct IntuiText *it;
X	int y, i, fonthei;
X	char *p, *com;
X
X	if( o_nowindow || !Win )
X		return;
X
X	if( mac>=MAXITEMS )
X		mac=MAXITEMS-1;
X
X	ClearMenuStrip( Win );
X	Delay(3);
X
X	if( NumMenus )
X		Menus[NumMenus-1].NextMenu=Menus+NumMenus;
X	m  =&Menus[NumMenus];
X	*m =DefaultMenu;
X	m->LeftEdge  = NumMenus*TITWID;
X	m->MenuName  = strcpy(malloc(strlen(mav[0])+1),mav[0]);
X	if( strlen(m->MenuName)>TITWID/8 )
X		m->MenuName[TITWID/8+1]=0;
X	DefaultIntuiText.ITextFont=ta=Win->WScreen->Font;
X	DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
X
X	y=0;
X	pmi=&m->FirstItem;
X	for( i=1; i<mac; i++) {
X		it =(void *)malloc(sizeof(struct IntuiText));
X		*it=DefaultIntuiText;
X		mi =(void *)malloc(sizeof(struct MenuItem ));
X		*mi=DefaultMenuItem;
X
X		com=NULL;
X		if( p=index(mav[i],',')) {
X			*p=0; com=++p;
X			if( p=index(com,',')) {
X				*p=0;
X				mi->Command=p[1];
X				mi->Flags |=COMMSEQ;
X			}
X		}
X
X		if( !com || !*com) {
X			com=strcpy(malloc(strlen(mav[i])+2),mav[i]);
X			MenuCommand[NumMenus][i-1]=com;
X			com+=strlen(com);
X			*com++=13;
X			*com=0;
X		} else {
X			MenuCommand[NumMenus][i-1]=strcpy(malloc(strlen(com)+1),com);
X		}
X
X		it->IText=(UBYTE *)strcpy(malloc(strlen(mav[i])+2),mav[i]);
X
X		*pmi= mi;
X		pmi = &mi->NextItem;
X		mi->TopEdge = y;
X		mi->ItemFill= (APTR)it;
X
X		y+=DefaultMenuItem.Height;
X	}
X
X	NumMenus++;
XMError:
X	return;
X}
X
X
Xvoid
Xremove_menu()
X{
X	if( NumMenus>0 ) {
X		struct MenuItem *mi, *nextmi;
X		int i,j;
X
X		for( i=0; i<NumMenus; i++ ) {
X			for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
X				free( ((struct IntuiText *)mi->ItemFill)->IText );
X				free( ((struct IntuiText *)mi->ItemFill) );
X				nextmi=mi->NextItem;
X				free(mi);
X				free(MenuCommand[i][j]);
X			}
X		}
X
X		NumMenus=0;
X		set_menu();
X	}
X}
X
X
Xvoid
Xset_menu()
X{
X	if( o_nowindow || !Win )
X		return;
X
X	if( NumMenus>0 )
X		SetMenuStrip( Win, Menus );
X	else 
X		ClearMenuStrip( Win );
X
X	Delay(3);
X}
X
Xdo_getenv( void )
X{
X	char buf[256], *val=buf, *getenv();
X
X	if( ac!=3 && ac!=2 ) {
X		show_usage( NULL );
X		return 20;
X	}
X	if( !Getenv(av[ac-1],buf,256))
X		val="";
X
X	if( ac==2 )
X		printf( "%s\n", val );
X	else 
X		set_var( LEVEL_SET, av[1], val );
X	return 0;
X}
X
X
Xdo_setenv( void )
X{
X	if( ac!=3 ) {
X		show_usage( NULL );
X		return 20;
X	} else {
X#ifndef AZTEC_C
X		char buf[300];
X		sprintf(buf, "%s=%s", av[1], av[2] );
X		putenv( buf );
X#else
X		setenv( av[1], av[2] );
X#endif
X	}
X	return 0;
X}
X
Xchar **
Xread_name( char *name, int *ac )
X{
X	FILE *file;
X	char **av=NULL;
X
X	*ac=0;
X	if( file=name ? fopen( name, "r") : stdin ) {
X		av=read_file( file, ac );
X		if( name ) fclose( file );
X	} else 
X		pError( name );
X	return av;
X}
X
X
Xchar **
Xread_file( FILE *file, int *ac )
X{
X	int buflen=4096, lines=0, i, offs;
X	char *buf, *ptr, *got, **lineptr;
X
X	if( !(buf=ptr=malloc( buflen )))
X		goto error;
X	do {
X		while( ptr+400 < buf+buflen && (got=fgets( ptr, 400, file ) ) &&
X		       !dobreak()) {
X			ptr+=strlen(ptr)-1, lines++;
X			*ptr++=0;
X		}
X		if( ptr+256 < buf+buflen ) {
X			offs=ptr-buf;
X			if( !(buf=realloc( buf, buflen*=2 ) ) )
X				goto error;
X			ptr=buf+offs;
X		}
X	} while( got && !dobreak());
X	if( !(lineptr=(char **)malloc( (lines+1)*sizeof( char * ))))
X		goto error;
X	*lineptr++=buf;
X	for( ptr=buf, i=0; i<lines; i++ ) {
X		lineptr[i]=ptr;
X		ptr+=strlen(ptr)+1;
X	}
X	*ac=lines;
X	return lineptr;
X
Xerror:
X	if( buf ) free( buf );
X	fprintf( stderr, "Out of memory\n" );
X	*ac=0;
X	return NULL;
X}
X
Xvoid
Xfree_file( ptr )
X	char **ptr;
X{
X	if( ptr-- ) {
X		if( *ptr )
X			free( *ptr );
X		free(ptr);
X	}
X}
X
X
Xdo_qsort( void )
X{
X	char **lineptr;
X	int  lines, i;
X
X	if( ac==1 ) {
X		lineptr=read_file( stdin, &lines);
X		QuickSort( lineptr, lines );
X		prepscroll(0);
X		for( i=0; i<lines && !dobreak(); i++ ) {
X			quickscroll();
X			puts( lineptr[i] );
X		}
X		free_file( lineptr );
X	}
X	return 0;
X}
X
Xextern int w_width;
X
Xdo_truncate( void )
X{
X	char buf[256];
X	int  w=newwidth(), c;
X	char *ptr;
X
X	if( ac==2 )
X		w=atoi( av[1] );
X
X	prepscroll(0);
X	while( gets(buf) && !dobreak() ) {
X		for( c=0, ptr=buf; *ptr && c<w; ptr++ )
X			if( *ptr=='\t' )
X				c+=8-(c&7);
X			else if( *ptr==27 ) {
X				while( *ptr<'@' )
X					ptr++;
X			} else 
X				c++;
X		*ptr=0;
X		quickscroll();
X		puts(buf);
X	}
X	return 0;
X}
X
Xint
Xdo_readfile( void )
X{
X	char **rav, *str=NULL;
X	int rac;
X
X	if( rav= read_name( ac>2 ? av[2] : NULL, &rac ) ) {
X		if( rac>255 ) rac=255;
X		if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
X			set_var( LEVEL_SET, av[1], str );
X		free_file( rav );
X	}
X	return str ? 0 : 20;
X}
X
Xint
Xdo_split( void )
X{
X	int i;
X	char *val, *gap, *oldval;
X
X	if( !(val=get_var( LEVEL_SET, av[1] )))
X		{ fprintf( stderr, "%s undefined\n", av[0] ); return 20; }
X	oldval=val=strcpy(malloc(strlen(val)+1),val);
X	for( i=2; i<ac-1; i++ ) {
X		if( gap=index(val,0xA0 )) *gap=0;
X		set_var( LEVEL_SET, av[i], val );
X		val="";
X		if( gap ) *gap=0xA0, val=gap+1;
X	}
X	set_var( LEVEL_SET, av[ac-1], val );
X	free(oldval);
X	return 0;
X}
X
Xchar *
Xcopyof( char *str )
X{
X	return strcpy(malloc(strlen(str)+1),str);
X}
X
Xint
Xdo_class( char *avline )
X{
X	CLASS *new;
X
X	if( options&1 ) {
X		avline=next_word(avline);
X		for( new=CRoot,CRoot=NULL; new; new=new->next )
X			Free(new);
X	}
X
X	if( ac==1 ) {
X		for( new=CRoot; new; new=new->next )
X			printf("%s\n",new->name);
X		return 0;
X	}
X
X	avline=next_word(avline);
X	if(!(new=malloc( strlen(avline)+5)))
X		ierror( NULL, 512 );
X	else {
X		new->next=NULL;
X		strcpy( new->name,avline );
X		if( CRoot )
X			LastCRoot->next=new;
X		else 
X			CRoot=new;
X		LastCRoot=new;
X	}
X	return 0;
X}
X
Xdo_getcl( void )
X{
X	char *s=getclass(av[1]);
X	if( s ) printf("%s\n",s);
X	return 0;
X}
X
Xdo_action( char *argline )
X{
X	char *args, err;
X	int abort=options&1;
X
X	args=compile_av( av,3,ac,' ',0 );
X	err=doaction(av[2],av[1],args);
X	if( !abort )
X		if( err==10 )    fprintf(stderr,"Can't identify %s\n", av[2] );
X		else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
X	return abort ? !err : err;
X}
END_OF_FILE
if test 26877 -ne `wc -c <'comm3.c'`; then
    echo shar: \"'comm3.c'\" unpacked with wrong size!
fi
# end of 'comm3.c'
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
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.