[comp.sources.amiga] v90i015: CShell 4.00A - alternative command interface, Part02/04

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (01/16/90)

Submitted-by: PERUGIA@ICNUCEVM.CNUCE.CNR.IT (Carlo & Cesare)
Posting-number: Volume 90, Issue 015
Archive-name: unix/cshell-4.00a/part02

#! /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 2 (of 4)."
# Contents:  comm1.c comm2.c sub.c
# Wrapped by tadguy@xanth on Mon Jan 15 11:28:09 1990
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'\" \(16508 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 *
X * Version 4.00A by Carlo Borreo & Cesare Dieni 13-Jan-90
X *
X */
X
X#define DIR_SHORT 0x01
X#define DIR_FILES 0x02
X#define DIR_DIRS  0x04
X#define DIR_NOCOL 0x08
X#define DIR_NAMES 0x10
X
Xextern int has_wild;
X
X/*
X	Parse the options specified in sw[]
X	Setting a bit in global variable options
X	for each one found
X*/
X
Xget_opt(sw,count)
Xchar *sw;
Xint *count;
X{
Xregister char *c,*s;
Xunsigned int l,i = 0;
X
Xoptions=0;
Xwhile((++i < ac) && (av[i][0] == '-')) {
X	for (c = av[i]+1; *c ; c++) {
X		for(l = 0,s = sw;*s && *s != *c; ++s) ++l;
X		if (*s) options |= (1 << l);
X		}
X	}
X*count = i;
X}
X
Xdo_sleep()
X{
Xregister int i;
X
Xif (ac == 2) for (i=atoi(av[1]); i>0 && !CHECKBREAK(); i-=2) Delay(100L);
Xreturn 0;
X}
X
Xdo_protect()
X{
Xregister long mask=0xf;
Xregister char *s, *p;
Xstatic char flags[]="DEWRAPSH";
Xregister unsigned short i;
X
Xfor (s=av[--ac]; *s; s++)
X	if (p=index(flags, toupper(*s))) mask^=(1 << (p-flags));
X	else ierror(av[ac],500);
Xfor (i=1; i<ac; i++) if (!SetProtection(av[i],mask)) pError(av[i]);
Xreturn 0;
X}
X
Xdo_filenote()
X{
Xchar *note=av[--ac];
Xregister unsigned int i;
X
Xfor (i=1; i<ac; i++) if (!SetComment(av[i], note)) pError(av[i]);
Xreturn 0;
X}
X
Xdo_cat()
X{
XFILE *fopen(), *fi;
Xregister unsigned int lctr;
Xunsigned int i;
Xchar buf[256];
X
Xget_opt("n",&i);
Xif (i>=ac) {
X	if (has_wild) { printf("No files matching\n"); return 20; }
X	lctr=0;
X	while (gets(buf) && !dobreak()) {
X		if (options) printf("%4d ",++lctr);
X		puts(buf);
X		}
X	}
Xfor (; i<ac; i++)
X	if (fi = fopen (av[i], "r")) {
X		lctr=0;
X		while (fgets(buf,256,fi) && !dobreak()) {
X			if (options) printf("%4d ",++lctr);
X			printf("%s",buf);
X			}
X		fclose (fi);
X		}
X	else pError(av[i]);
Xreturn 0;
X}
X
Xdo_info()
X{
XBPTR lock;
Xstruct InfoData *info;
Xlong size, free;
Xchar *p, buf[130], *state;
Xstruct DirectoryEntry *de_head=NULL, *de;
X
Xinfo=(struct InfoData *)AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC);
XAddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
XMyprocess->pr_WindowPtr = (APTR)(-1);
Xprintf ("Unit  Size  Bytes  Used Blk/By-Free Full Errs  Status    Name\n");
Xfor (de=de_head; de; de=de->de_Next) {
X	printf("%-5s",de->de_Name);
X	if (lock=Lock(de->de_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)/ 1024;
X		free = (((info->id_NumBlocks-info->id_NumBlocksUsed))*
X			   info->id_BytesPerBlock)/ 1024;
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		printf("%4ld%c%6ld%7ld%7ld%4ld%c%4ld%%%4ld  %s %s\n",
X			(size>1024) ? ((size+512) >> 10) : size,
X			(size>1024) ? 'M' : 'K',
X			info->id_BytesPerBlock,
X			info->id_NumBlocksUsed,
X			info->id_NumBlocks-info->id_NumBlocksUsed,
X			(free>1024) ? ((free+512) >> 10) : free,
X			(free>1024) ? 'M' : 'K',
X			(info->id_NumBlocksUsed * 100)/info->id_NumBlocks,
X			info->id_NumSoftErrors,
X			state,
X			buf);
X		}
X	    else pError (de->de_Name);
X	    UnLock(lock);
X	    }
X	else puts("  No disk present");
X	}
XFreeDAList(&de_head);
XMyprocess->pr_WindowPtr = NULL;
XFreeMem(info,(long)sizeof(struct InfoData));
Xreturn 0;
X}
X
X/* things shared with display_file */
X
XBPTR lastlock;
Xint filecount, col;
Xlong bytes, blocks;
X
X/*
X * the args passed to do_dir will never be expanded
X */
Xdo_dir()
X{
Xint i, c, eac;
Xchar **eav;
X
Xcol = filecount = 0;
Xbytes = blocks = 0L;
Xlastlock=NULL;
X
Xget_opt("sfdcn",&i);
X
Xif (ac == i) { ++ac; av[i]=""; }
Xif (!(options & (DIR_FILES | DIR_DIRS))) options|=(DIR_FILES | DIR_DIRS);
X
Xfor (; i<ac && !CHECKBREAK(); ++i)
X	if (eav = expand(av[i], &eac)) {
X		QuickSort(eav, eac);
X		for(c=0; c<eac && !CHECKBREAK(); ++c)
X			if (options & DIR_NAMES)
X				puts(eav[c]);
X			else
X				display_file(eav[c]);
X		free_expand (eav);
X		}
Xif (col) printf("\n");
Xif (filecount>1) {
X	blocks += filecount; /* account for dir blocks */
X	printf(" %ld Blocks, %ld Bytes used in %d files\n",
X		blocks, bytes, filecount);
X	}
Xif (lastlock) UnLock(lastlock);
Xreturn 0;
X}
X
Xdisplay_file(filestr)
Xchar *filestr;
X{
Xlong atol();
Xint isadir,slen;
Xchar sc, *fi, *base, buf[130];
XBPTR thislock;
X
Xbase=BaseName(filestr);
Xsc = *base;
X*base = '\0';
Xthislock=Lock(filestr,SHARED_LOCK);
X/* if (thislock==NULL) return; */
Xif (lastlock==NULL || CompareLock(thislock,lastlock)) {
X	if (col) printf("\n");
X	col = 0;
X	PathName(thislock, buf, 128L);
X	printf("Directory of %s\n", buf);
X	if (lastlock) UnLock(lastlock);
X	lastlock=thislock;
X	}
Xelse UnLock(thislock);
X*base = sc;
Xslen = strlen(base);
Xfi = base + slen + 1;
Xisadir = (fi[12] =='D');
X
Xif (!(((options & DIR_FILES) && !isadir) ||
X	((options & DIR_DIRS) &&  isadir)))
X		return;
Xif (isadir && !(options & DIR_NOCOL)) printf ("\23333m");
Xif (options & DIR_SHORT) {
X	if (col==3 && slen>18) { printf("\n"); col = 0; }
X	if (slen>18) { printf(" %-37s",base); col+= 2; }
X		else { printf(" %-18s",base); col++; }
X	if (col > 3) { printf("\n"); col=0; }
X	}
Xelse printf("   %-24s %s",base ,fi);
Xif (isadir && !(options & DIR_NOCOL)) printf("\2330m");
Xfi[16] = fi[21] = '\0';
Xbytes  += atol(fi+10);
Xblocks += atol(fi+17);
Xfilecount++;
X}
X
Xdo_quit()
X{
Xif (Src_stack) {
X	Quit = 1;
X	return(do_return());
X	}
Xmain_exit(0);
X}
X
Xdo_echo()
X{
Xint i;
X
Xget_opt("n",&i);
Xfor ( ; i<ac; i++) {
X	printf("%s", av[i]);
X	if (i != ac-1) printf(" ");
X	}
Xif (!options) printf("\n");
Xreturn 0;
X}
X
X/* gets a line from file, joining two lines if the first ends in '\' */
X
Xchar *myfgets(buf, buflen, file)
Xchar *buf;
XFILE *file;
X{
Xchar *bufptr=buf;
Xint remain=buflen, n, flag;
X
Xdo {
X	if (fgets(bufptr, remain, file)==NULL) {
X		if (remain != buflen)
X			fprintf(stderr,"Source: file ends in '\\'\n");
X		return NULL;
X		}
X	n=strlen(buf);
X	bufptr += n;
X	if (flag= (*(bufptr-2)=='\\')) bufptr-=2;
X	remain -= (n+2);
X    } while (flag);
Xreturn buf;
X}
X
Xdo_source(str)
Xchar *str;
X{
Xregister FILE *fi;
Xchar buf[256];
Xint len;
X
Xif (Src_stack == MAXSRC) {
X	ierror(NULL,217);
X	return -1;
X	}
Xif ((fi = fopen (av[1], "r")) == 0) { pError(av[1]); return -1;	}
Xset_var(LEVEL_SET, v_passed, next_word(next_word(str)));
X++H_stack;
XSrc_pos[Src_stack] = 0;
XSrc_base[Src_stack] = (long)fi;
X++Src_stack;
Xwhile (myfgets (buf, 256, fi) && !dobreak()) {
X	len = strlen(buf);
X	buf[len-1] = '\0';
X	Src_pos[Src_stack - 1] += len;
X	if (Verbose && !forward_goto) fprintf(stderr,"%s\n",buf);
X	exec_command (buf);
X	}
X--H_stack;
X--Src_stack;
Xif (forward_goto) ierror(NULL,501);
Xforward_goto = 0;
Xunset_level(LEVEL_LABEL + Src_stack);
Xunset_var(LEVEL_SET, v_gotofwd);
Xunset_var(LEVEL_SET, v_passed);
Xfclose (fi);
Xreturn 0;
X}
X
X/*
X * set process cwd name and $_cwd, if str != NULL also print it.
X */
Xdo_pwd(str)
Xchar *str;
X{
Xchar pwd[130];
X
XPathName(Myprocess->pr_CurrentDir, pwd, 128L);
Xif (str) puts(pwd);
Xset_var(LEVEL_SET, v_cwd, pwd);
X/* put the current dir name in our CLI task structure */
XCtoBStr(pwd, Mycli->cli_SetName, 128L);
Xreturn 0;
X}
X
X/*
X * CD
X *
X * CD(str, 0)      -do CD operation.
X *
X */
X
Xdo_cd(str)
Xchar *str;
X{
XBPTR oldlock, filelock;
X
Xstr=next_word(str);
Xif (!strcmp("..",str)) str="/";
Xfilelock=Lock(str,ACCESS_READ);
Xif (filelock==NULL) { pError(str); return 20; }
Xif (!isdir(str)) { UnLock(filelock); ierror(str,212); return 20; }
Xif (oldlock=CurrentDir(filelock)) UnLock(oldlock);
Xdo_pwd(NULL);
Xreturn 0;
X}
X
Xdo_mkdir()
X{
Xregister unsigned int i;
XBPTR lock;
X
Xfor (i=1; i<ac; ++i) {
X	if (exists(av[i])) ierror(av[i],203);
X	else if (lock=CreateDir(av[i])) UnLock (lock);
X	else pError(av[i]);
X	}
Xreturn 0;
X}
X
Xdo_mv()
X{
Xchar *dest, buf[256];
Xint dirflag;
Xregister unsigned int i;
X
Xdirflag=isdir(dest=av[--ac]);
Xif (ac>3 && !dirflag) { ierror(dest, 507); return (-1); }
Xfor (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	}
Xreturn 0;
X}
X
Xint dirstoo;
X
Xall_args(args, action, dirsflag)
Xchar *args;
Xint (*action)();
X{
Xunsigned int i;
X
Xget_opt(args, &i);
Xdirstoo=dirsflag;
Xfor (; 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		}
X	else (*action)(av[i]);
Xreturn 0;
X}
X
Xchar *searchstring;
X
Xsearch_file(s)
Xchar *s;
X{
XFILE *fopen(), *fi;
Xregister char *p;
Xregister unsigned int
X	nocasedep, lctr, len, excl=((options & 16) !=0 ), yesno;
Xchar buf[256], lowbuf[256], searchit[256], first;
X
Xif (strcmp("STDIN",s)) fi=fopen(s,"r"); else fi=stdin;
Xif (fi==NULL) { pError(s); return; }
Xnocasedep=!(options & 2);
Xlctr=0;
Xif (!(options & 32)) printf("Examining %s...\n",s);
Xstrcpy(searchit,searchstring);
Xif (options & 4) strcat(searchit,"\n");
Xlen=strlen(searchit);
Xif (nocasedep) strupr(searchit);
Xfirst=*searchit;
Xwhile (fgets(buf,256,fi) && !dobreak()) {
X	lctr++;
X	if (options & 4) yesno=compare_ok(searchit, buf, options & 2);
X	else {
X		if (nocasedep) {
X			strcpy(lowbuf,buf);
X			strupr(lowbuf);
X			p=lowbuf;
X			}
X		else p=buf;
X		while ((p=index(p,first)) && strncmp(p++,searchit,len)) ;
X		yesno= (p!=NULL);
X		}
X	if (yesno ^ excl) {
X			/* default: print line numbers */
X		if (!(options & 8)) printf("%4d ",lctr);
X		printf("%s",buf);
X		}
X	}
Xif (fi!=stdin) fclose (fi);
X}
X
Xdo_search()
X{
Xsearchstring=av[--ac];
Xall_args("rcwneq", search_file, 0);
Xreturn 0;
X}
X
Xrm_file(file)
Xchar *file;
X{
Xif (has_wild) printf(" %s...",file);
Xif (options & 2) SetProtection(file,0L);
Xif (!DeleteFile(file)) pError (file); else if (has_wild) printf("Deleted\n");
X}
X
Xdo_rm()
X{
Xall_args("rp", rm_file, 1);
Xreturn 0;
X}
X
Xrecurse(name, action)
Xchar *name;
Xint (*action)();
X{
Xregister BPTR lock, cwd;
Xregister FIB *fib=(FIB *)AllocMem((long)sizeof(FIB),MEMF_PUBLIC);
Xchar *namecopy=malloc(256);
X
Xif (name[0] =='\0') return;
Xnamecopy[0]=0;
Xif (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>=0) recurse(fib->fib_FileName,action);
X		else strcpy(namecopy,fib->fib_FileName);
X	    }
X    if (*namecopy) (*action)(namecopy);
X    UnLock(CurrentDir(cwd));
X    if (dirstoo) (*action)(name);
X    }
Xelse pError(name);
Xfree(namecopy);
XFreeMem(fib, (long)sizeof(FIB));
X}
X
Xdo_history()
X{
Xregister struct HIST *hist;
Xint i = H_tail_base;
Xint len = (av[1]) ? strlen(av[1]) : 0;
X
Xfor (hist = H_tail; hist && !dobreak(); hist = hist->prev)
X	if (len == 0 || !strncmp(av[1], hist->line, len))
X		printf("%3d %s\n", i++, hist->line);
Xreturn 0;
X}
X
Xdo_mem()
X{
Xlong cfree, ffree;
Xextern long AvailMem();
X
XForbid();
Xcfree = AvailMem (MEMF_CHIP);
Xffree = AvailMem (MEMF_FAST);
XPermit();
Xif (ffree) printf ("FAST memory: %ld\nCHIP memory: %ld\n", ffree, cfree);
Xprintf("Total  Free: %ld\n", cfree+ffree);
Xreturn 0;
X}
X
Xdo_forline()
X{
Xchar vname[33], buf[256];
Xregister unsigned short lctr;
XFILE *f;
Xchar *cstr;
X
Xstrcpy(vname,av[1]);
Xf=fopen(av[2],"r");
Xif (f==NULL) pError(av[2]);
Xlctr=0;
X++H_stack;
Xcstr = compile_av (av, 3, ac, ' ', 0);
Xwhile (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	}
Xfclose(f);
X--H_stack;
Xfree (cstr);
Xunset_var (LEVEL_SET, vname);
Xunset_var (LEVEL_SET, v_linenum);
Xreturn 0;
X}
X
Xdo_fornum()
X{
Xchar vname[33], buf[16];
Xint n1, n2, step, i, verbose;
Xchar *cstr;
X
Xget_opt("vs",&i);
Xverbose=(options & 1);
Xstrcpy(vname,av[i++]);
Xn1=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
Xn2=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
Xif (options & 2) {
X	step=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
X	}
Xelse
X	step=1;
X++H_stack;
Xcstr = compile_av (av, i, ac, ' ', 0);
Xfor (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;
Xfree (cstr);
Xunset_var (LEVEL_SET, vname);
Xreturn 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
Xdo_foreach()
X{
Xregister int cstart, cend;
Xregister char *cstr;
Xchar **fav;
Xchar vname[33];
Xint i, verbose;
X
Xget_opt("v",&i);
Xverbose=(options & 1);
Xstrcpy(vname, av[i++]);
Xif (*av[i] == '(') i++;
Xcstart = i;
Xwhile (i<ac && *av[i] != ')') i++;
Xif (i > ac) { fprintf(stderr,"')' expected\n"); return 20; }
X++H_stack;
Xcend = i;
X
Xfav = (char **)malloc(sizeof(char *) * (ac));
Xcstr = compile_av (av, cend + 1, ac, ' ', 0);
X
Xfor (i = cstart; i < cend; ++i) fav[i] = av[i];
X
Xfor (i = cstart; i<cend && !CHECKBREAK(); ++i) {
X	set_var (LEVEL_SET, vname, fav[i]);
X	if (verbose) fprintf(stderr, "foreach: %s\n", fav[i]);
X	exec_command(cstr);
X	}
X--H_stack;
Xfree (fav);
Xfree (cstr);
Xunset_var (LEVEL_SET, vname);
Xreturn 0;
X}
X
Xdo_forever(str)
Xchar *str;
X{
Xint rcode = 0;
Xchar *ptr = next_word(str);
X
X++H_stack;
Xfor (;;) {
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;
Xreturn rcode;
X}
X
Xdo_exec(str)
Xchar *str;
X{
Xreturn exec_command(next_word(str));
X}
X
Xextern struct Window *w;
Xextern struct IntuitionBase *IntuitionBase;
X
Xdo_window()
X{
Xlong x, y, maxwidth, maxheight, arg[5];
Xunsigned int i;
Xstruct Screen *screen;
Xstruct Window *window;
X
Xget_opt("slfbaq", &i);
Xif (options & 1)
X	SizeWindow(w, (long)(w->MinWidth-w->Width), (long)(w->MinHeight-w->Height));
Xif (options & 2) {
X	x=-w->LeftEdge;
X	y=-w->TopEdge;
X	MoveWindow(w,x,y);
X	x=IntuitionBase->ActiveScreen->Width -w->Width;
X	y=IntuitionBase->ActiveScreen->Height-w->Height;
X	SizeWindow(w,x,y);
X	}
Xif (options & 4) WindowToFront(w);
Xif (options & 8) WindowToBack(w);
Xif (options & 16) ActivateWindow(w);
Xif(ac >= 5) {
X	for(i=1; i<5; i++) {
X		arg[i] = myatoi(av[i],0,1023); if (atoierr) return 20;
X		}
X	maxwidth = w->WScreen->Width;
X	maxheight= w->WScreen->Height;
X	if (arg[3] > maxwidth - arg[1] || arg[4] > maxheight- arg[2]) {
X		ierror(NULL, 500);
X		return 20;
X		}
X	x = -w->LeftEdge;
X	y = -w->TopEdge;
X	MoveWindow(w, x, y);
X	x = arg[3] - w->Width;
X	y = arg[4] - w->Height;
X	SizeWindow(w, x, y);
X	x = arg[1];
X	y = arg[2];
X	MoveWindow(w, x, y);
X	}
Xif(options & 32) {
X	for (screen=IntuitionBase->FirstScreen; screen; screen=screen->NextScreen) {
X	    printf("\nScreen \"%s\" (%d,%d,%dx%d):\n",
X			screen->Title,
X			screen->LeftEdge,
X			screen->TopEdge,
X			screen->Width,
X			screen->Height
X			);
X		for (window=screen->FirstWindow; window; window=window->NextWindow) {
X		printf("\tWindow\t\"%s\" (%d,%d,%dx%d)\n",
X			window->Title,
X			window->LeftEdge,
X			window->TopEdge,
X			window->Width,
X			window->Height
X			);
X		}
X	    }
X	return 0;
X	}
XDelay(25L); /* pause 1/2 sec. before trying to print */
Xprintf("\014");
Xreturn 0;
X}
X
Xsetsystemtime(ds)
Xstruct DateStamp *ds;
X{
Xstruct timerequest tr;
Xlong secs= ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/TICKS_PER_SECOND;
X
Xif (OpenDevice(TIMERNAME, UNIT_VBLANK, &tr, 0L)) {
X	fprintf(stderr,"Clock error: can't open timer device\n");
X	return;
X	}
Xtr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
Xtr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
Xtr.tr_node.io_Message.mn_Node.ln_Name = NULL;
Xtr.tr_node.io_Message.mn_ReplyPort = NULL;
Xtr.tr_node.io_Command = TR_SETSYSTIME;
Xtr.tr_time.tv_secs = secs;
Xtr.tr_time.tv_micro = 0L;
Xif (DoIO (&tr)) fprintf(stderr,"Clock error: can't talk to timer device\n");
XCloseDevice (&tr);
X}
X
Xchar tday[10];
X
Xchar *dates(dss)
Xstruct DateStamp *dss;
X{
Xstatic char timestr[40];
Xchar tdate[10], ttime[10];
Xstruct DateTime dt;
Xstruct DateStamp *myds=&(dt.dat_Stamp);
X
Xdt.dat_Format=FORMAT_DOS;
Xdt.dat_StrDay=tday;
Xdt.dat_StrDate=tdate;
Xdt.dat_StrTime=ttime;
Xdt.dat_Flags=NULL;
Xmyds->ds_Days=dss->ds_Days;
Xmyds->ds_Minute=dss->ds_Minute;
Xmyds->ds_Tick=dss->ds_Tick;
XStamptoStr(&dt);
Xsprintf(timestr,"%s %s\n",tdate,ttime);
Xtimestr[18]='\n';
Xtimestr[19]='\0';	/* protection against bad timestamped files */
Xreturn timestr;
X}
X
Xdo_date()
X{
Xstruct DateStamp dss;
Xregister unsigned short i;
Xstruct DateTime dt;
X
Xdt.dat_Format=FORMAT_DOS;
Xif (ac==1) {
X	DateStamp(&dss);
X	printf("%s %s",tday,dates(&dss));
X	}
Xelse {
X	DateStamp(& (dt.dat_Stamp));
X	for (i=1; 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	}
Xreturn 0;
X}
END_OF_FILE
if test 16508 -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'\" \(13095 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 *
X * Version 4.00A by Carlo Borreo & Cesare Dieni 13-Jan-90
X *
X */
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 */
Xint cp_update;
Xint cp_date;
X
Xdo_abortline()
X{
XExec_abortline = 1;
Xreturn 0;
X}
X
Xdo_return()
X{
Xregister int retcode=(ac<2 ? 0 : atoi(av[1]));
X   Exec_abortline = 1;
X   if (Src_stack) {
X       FILE *ptr = (FILE *)Src_base[Src_stack - 1];
X       ptr->_bp = ptr->_bend;
X       ptr->_flags |= _EOF;
X/*     fseek (Src_base[Src_stack - 1], 0L, 2); */
X      return retcode;
X   } else main_exit(retcode);
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()
X{
Xchar *s;
Xif (s=index(av[3],*av[2])) *s='\0';
Xset_var (LEVEL_SET, av[1], av[3]);
Xreturn 0;
X}
X
Xdo_strtail()
X{
Xchar *s;
Xif (s=index(av[3],*av[2])) s++; else s=av[3];
Xset_var (LEVEL_SET, av[1], s);
Xreturn 0;
X}
X
Xlong dptrtosecs(d)
Xstruct DPTR *d;
X{
Xregister struct DateStamp *ds=(&d->fib->fib_Date);
Xreturn ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/TICKS_PER_SECOND;
X}
X
Xlong timeof(s)
Xchar *s;
X{
Xstruct DPTR *d;
Xint dummy;
Xlong n;
X
Xif ( (d=dopen(s,&dummy))==NULL ) return 0L;
Xn=dptrtosecs(d);
Xdclose(d);
Xreturn 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(garbage, com)
Xchar *garbage;
X{
Xint result;
Xint i;
X
Xswitch (com) {
X    case 0:
X	if (If_stack && If_base[If_stack - 1]) If_base[If_stack++] = 1;
X	else {
X		get_opt("rftmdvn",&i);
X		result=evalif(i);
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     }
Xdisable = (If_stack) ? If_base[If_stack - 1] : 0;
Xif (If_stack >= MAXIF) {
X	fprintf(stderr,"If's too deep\n");
X	disable = If_stack = 0;
X	return -1;
X	}
Xif (forward_goto) disable = If_base[If_stack - 1] = 0;
Xreturn 0;
X}
X
Xevalif(i)
Xregister unsigned int i;
X{
Xchar c;
Xlong num, t0, isint;
Xlong AvailMem();
X
Xswitch(options & ~64) {
X    case 0:
X	if (ac-i != 3) return (ac>i && *av[i]);
X	num  = Atol(av[i]);
X	isint  = ! IoErr();
X	num -= Atol(av[i+2]);
X	isint &= ! IoErr();
X	if (!isint) num=strcmp(av[i],av[i+2]);
X	if (num < 0)	   c='<';
X	else if (num > 0)  c='>';
X	else if (num == 0) c='=';
X	return index(av[i+1], 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( (long)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	return 0;
X    }
X}
X
Xdo_label()
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()
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(garbage, com)
Xchar *garbage;
X{
Xchar *var, num[32];
X
Xif (ac>2) com *= atoi(av[2]);
Xif (var = get_var (LEVEL_SET, av[1])) {
X	sprintf (num, "%d", atoi(var)+com);
X	set_var (LEVEL_SET, av[1], num);
X	}
Xreturn 0;
X}
X
Xdo_input()
X{
Xchar in[256], *p,*s;
Xunsigned int i;
X
Xfor (i=1; i < ac; ++i)
X    if (gets(in)) {
X	for(p = in; *p; p = s) {
X		s = next_word(p);
X		if (*s) *(s-1) = 0xA0;
X		}
X	set_var (LEVEL_SET, av[i], in);
X	}
Xreturn 0;
X}
X
Xdo_ver()
X{
Xextern char shellname[];
X
Xputs(shellname);
Xputs("(c)1986 Matthew Dillon\n\
XManx (M) versions by Steve Drew\n\
XARP (A) versions by Carlo Borreo & Cesare Dieni\n");
Xreturn 0;
X}
X
Xdo_ps()
X{
X/* this code fragment based on ps.c command by Dewi Williams */
X
Xregister int	count;		/* loop variable		*/
Xstruct Task	*task;		/* EXEC descriptor		*/
Xchar		strbuf[64+1];	/* scratch for btocstr()	*/
Xchar		cmd[40+1];	/* holds cmd name		*/
Xlong ncli;
X
Xprintf("Proc Command Name         CLI Type    Pri.  Address  Directory\n");
XForbid();
X
Xncli=(long)FindCLI(0L);
Xfor (count = 1; count <= ncli ; count++)
X		/* or just assume 20?*/
X    if (task = (struct Task *)FindCLI((long)count)) {
X	if (task==NULL) continue;
X	/* Sanity check just in case */
X	if (PROC(task)->pr_TaskNum == 0 || PROC(task)->pr_CLI == 0) continue;
X							/* or complain? */
X	BtoCStr(cmd,   CLI(PROC(task))->cli_CommandName, 40L);
X	BtoCStr(strbuf,CLI(PROC(task))->cli_SetName    , 64L);
X	printf("%2d   %-20.20s %-11.11s %3d  %8lx  %s\n",
X		count,
X		cmd,
X		task->tc_Node.ln_Name,
X		task->tc_Node.ln_Pri,
X		task,
X		strbuf);
X	}
XPermit();
Xreturn 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()
X{
Xregister int recur, ierr;
Xregister char *destname;
Xregister char destisdir;
Xregister FIB *fib;
Xint i;
X
Xerrstr = "";
Xierr = 0;
X
Xfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
X
Xget_opt("rud",&i);
Xrecur     = (options & 0x01);
Xcp_update = (options & 0x02);
Xcp_date   = (!(options & 0x04)); /* the default is keep orignal file date */
X
Xdestname = av[ac - 1];
X
Xif (ac < i + 2) {
X	ierr = 500;
X	goto done;
X	}
Xdestisdir = isdir(destname);
Xif (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
Xfor (; 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		}
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			}
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
XFreeMem(fib, (long)sizeof(FIB));
Xif (ierr) {
X	ierror(errstr, ierr);
X	return(20);
X	}
Xreturn 0;
X}
X
X
Xcopydir(srcdir, destdir, recur)
Xregister BPTR srcdir, destdir;
X{
X   BPTR cwd;
X   register FIB *srcfib;
X   register BPTR destlock, srclock;
X   int ierr;
X   static int level;
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)
X               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                        */
X                     if (destlock) UnLock(destlock);
X                     destlock = Lock(srcfib->fib_FileName, ACCESS_WRITE);
X                  }
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 = (int)((long)IoErr());
X   }
X   --level;
X   FreeMem(srcfib, (long)sizeof(FIB));
X   return(ierr);
X}
X
X
Xcopyfile(srcname, srcdir, destname, destdir)
Xchar *srcname, *destname;
XBPTR srcdir, destdir;
X{
XBPTR cwd;
XBPTR f1, f2;
Xlong i;
Xint stat,ierr;
Xchar *buf;
Xstruct DPTR *dp, *dps = NULL;
X
Xif ((buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR))==NULL)
X	{ ierr = 103; goto fail; }
Xierr = 0;
Xcwd = CurrentDir(srcdir);
Xif ((f1=Open(srcname, MODE_OLDFILE))==NULL)
X	{ errstr = srcname; ierr = 205; goto fail; }
Xdps = dopen(srcname,&stat);
XCurrentDir(destdir);
Xif (cp_update)
X	{
X	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	}
Xif ((f2=Open(destname, MODE_NEWFILE))==NULL)
X    { Close(f1); ierr = (int)((long)IoErr()); errstr=destname; goto fail;  }
Xwhile (i = Read(f1, buf, 8192L))
X	if (Write(f2, buf, i) != i) { ierr = (int)((long)IoErr()); break; }
XClose(f2);
XClose(f1);
Xif (!ierr)
X	{
X	if (cp_date) file_date(&dps->fib->fib_Date, destname);
X	printf("..copied\n");
X	}
Xelse DeleteFile(destname);
Xfail:
X dclose(dps);
X if (buf) FreeMem(buf, 8192L);
X CurrentDir(cwd);
X return(ierr);
X}
X
Xdo_touch()
X{
Xstruct DateStamp ds;
Xregister unsigned int i;
XDateStamp(&ds);
Xfor (i=1; i<ac; i++) if (file_date(&ds, av[i])) ierror(av[i],500);
Xreturn 0;
X}
X
Xfile_date(date,name)
Xstruct DateStamp *date;
Xchar *name;
X{
Xlong packargs[7];
XUBYTE *ptr;
Xstruct MsgPort *task;
XBPTR dirlock;
Xstruct DPTR *tmp;
Xint stat;
X
Xif (!(task = (struct MsgPort *)DeviceProc(name))) return(1);
Xif (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	}
Xreturn 0;
X}
X
Xdo_addbuffers()
X{
Xlong packargs[7];
Xlong n;
Xstruct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
X
Xif (!task) { ierror(av[1],510); return 20; }
Xn=myatoi(av[2],1,32767); if (atoierr) return 20;
Xpackargs[0]=n;
XSendPacket(ACTION_MORE_CACHE,packargs,task);
Xreturn 0;
X}
X
Xdo_relabel()
X{
Xlong packargs[7];
XUBYTE *ptr;
Xstruct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
X
Xif (!task) { ierror(av[1],510); return 20; }
Xptr=AllocMem(65L,MEMF_PUBLIC);
XCtoBStr(av[2],(ULONG)ptr >> 2L,64L);
Xpackargs[0]=(ULONG)ptr >> 2L;
XSendPacket(ACTION_RENAME_DISK,packargs,task);
XFreeMem(ptr,65L);
Xchangedisk(task);
Xreturn 0;
X}
X
Xdo_diskchange()
X{
Xstruct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
X
Xif (!task) { ierror(av[1],510); return 20; }
Xchangedisk(task);
Xreturn 0;
X}
X
Xchangedisk(task)
Xstruct MsgPort *task;
X{
Xlong packargs[7];
X
Xpackargs[0]=1L;
XSendPacket(ACTION_INHIBIT,packargs,task);
Xpackargs[0]=0L;
XSendPacket(ACTION_INHIBIT,packargs,task);
X}
END_OF_FILE
if test 13095 -ne `wc -c <'comm2.c'`; then
    echo shar: \"'comm2.c'\" unpacked with wrong size!
fi
# end of 'comm2.c'
fi
if test -f 'sub.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sub.c'\"
else
echo shar: Extracting \"'sub.c'\" \(13255 characters\)
sed "s/^X//" >'sub.c' <<'END_OF_FILE'
X
X/*
X * SUB.C
X *
X * (c)1986 Matthew Dillon     9 October 1986
X *
X * Version 2.07M by Steve Drew 10-Sep-87
X *
X * Version 4.00A by Carlo Borreo & Cesare Dieni 13-Jan-90
X *
X */
X
X#define HM_STR 0              /* various HISTORY retrieval modes */
X#define HM_REL 1
X#define HM_ABS 2
X
Xseterr()
X{
Xchar buf[32];
Xint stat;
X
Xsprintf(buf, "%d", Lastresult);
Xset_var(LEVEL_SET, v_lasterr, buf);
Xstat = atoi(get_var(LEVEL_SET, v_stat));
Xif (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
X}
X
X#define ISSPACE(c) ((c)==' ' || (c)==9 || (unsigned char)(c)==0xA0)
X
Xchar *next_word(str)
Xregister char *str;
X{
Xwhile (*str && ! ISSPACE(*str)) ++str;
Xwhile (*str &&   ISSPACE(*str)) ++str;
Xreturn str;
X}
X
Xhasspace(s)
Xregister char *s;
X{
Xfor ( ; *s; s++)
X	if (ISSPACE(*s)) return 1;
Xreturn 0;
X}
X
Xchar *compile_av(av, start, end, delim, quote)
Xchar **av;
Xunsigned char delim;
X{
Xregister char *cstr, *p;
Xint len;
Xregister unsigned int i;
X
Xlen = 1;
Xfor (i = start; i < end; ++i) len += strlen(av[i]) + 3;
Xp = cstr = malloc(len);
X*cstr = '\0';
Xfor (i = start; i < end; ++i) {
X	if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
X	if (quote && hasspace(av[i]))
X		p += sprintf(p, "\"%s\"", av[i]);
X	else
X		p += sprintf(p, "%s",     av[i]);
X	if (i+1 < end) *p++=delim;
X	}
X*p='\0';
Xreturn cstr;
X}
X
X/*
X * FREE(ptr)   --frees without actually freeing, so the data is still good
X *               immediately after the free.
X */
X
X
XFree(ptr)
Xchar *ptr;
X{
Xstatic char *old_ptr;
X
Xif (old_ptr) free (old_ptr);
Xold_ptr = ptr;
X}
X
X/*
X * Add new string to history (H_head, H_tail, H_len,
X *  S_histlen
X */
X
Xadd_history(str)
Xchar *str;
X{
X   register struct HIST *hist;
X
X   if (H_head != NULL && strcmp(H_head->line, str) == 0)
X       return(0);
X   while (H_len > S_histlen)
X      del_history();
X   hist = (struct HIST *)malloc (sizeof(struct HIST));
X   if (H_head == NULL) {
X      H_head = H_tail = hist;
X      hist->next = NULL;
X   } else {
X      hist->next = H_head;
X      H_head->prev = hist;
X      H_head = hist;
X   }
X   hist->prev = NULL;
X   hist->line = malloc (strlen(str) + 1);
X   strcpy (hist->line, str);
X   ++H_len;
X}
X
Xdel_history()
X{
X   if (H_tail) {
X      --H_len;
X      ++H_tail_base;
X      free (H_tail->line);
X      if (H_tail->prev) {
X         H_tail = H_tail->prev;
X         free (H_tail->next);
X         H_tail->next = NULL;
X      } else {
X         free (H_tail);
X         H_tail = H_head = NULL;
X      }
X   }
X}
X
Xchar *
Xget_history(ptr)
Xchar *ptr;
X{
X   register struct HIST *hist;
X   register int len;
X   int mode = HM_REL;
X   int num  = 1;
X   char *str;
X   char *result = NULL;
X
X   if (ptr[1] >= '0' && ptr[1] <= '9') {
X      mode = HM_ABS;
X      num  = atoi(&ptr[1]);
X      goto skip;
X   }
X   switch (ptr[1]) {
X   case '!':
X      break;
X   case '-':
X      num += atoi(&ptr[2]);
X      break;
X   default:
X      mode = HM_STR;
X      str  = ptr + 1;
X      break;
X   }
Xskip:
X   switch (mode) {
X   case HM_STR:
X      len = strlen(str);
X      for (hist = H_head; hist; hist = hist->next) {
X         if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
X            result = hist->line;
X            break;
X         }
X      }
X      break;
X   case HM_REL:
X      for (hist = H_head; hist && num--; hist = hist->next);
X      if (hist)
X         result = hist->line;
X      break;
X   case HM_ABS:
X      len = H_tail_base;
X      for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
X      if (hist)
X         result = hist->line;
X      break;
X   }
X   if (result) {
X      fprintf(stderr,"%s\n",result);
X      return(result);
X   }
X   printf("History failed\n");
X   return ("");
X}
X
Xreplace_head(str)
Xchar *str;
X{
X   if (str == NULL)
X      str = "";
X   if (H_head) {
X      free (H_head->line);
X      H_head->line = malloc (strlen(str)+1);
X      strcpy (H_head->line, str);
X   }
X}
X
X
XpError(str)
Xchar *str;
X{
Xint ierr = (long)IoErr();
Xierror(str, ierr);
X}
X
Xierror(str, err)
Xregister char *str;
X{
X   register struct PERROR *per = Perror;
X
X   if (err) {
X      for (; per->errstr; ++per) {
X         if (per->errnum == err) {
X            fprintf (stderr, "%s%s%s\n",
X                  per->errstr,
X                  (str) ? ": " : "",
X                  (str) ? str : "");
X            return ((short)err);
X         }
X      }
X      fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
X   }
X   return ((short)err);
X}
X
X/*
X * Disk directory routines
X *
X * dptr = dopen(name, stat)
X *    struct DPTR *dptr;
X *    char *name;
X *    int *stat;
X *
X * dnext(dptr, name, stat)
X *    struct DPTR *dptr;
X *    char **name;
X *    int  *stat;
X *
X * dclose(dptr)                  -may be called with NULL without harm
X *
X * dopen() returns a struct DPTR, or NULL if the given file does not
X * exist.  stat will be set to 1 if the file is a directory.  If the
X * name is "", then the current directory is openned.
X *
X * dnext() returns 1 until there are no more entries.  The **name and
X * *stat are set.  *stat = 1 if the file is a directory.
X *
X * dclose() closes a directory channel.
X *
X */
X
Xstruct DPTR *
Xdopen(name, stat)
Xchar *name;
Xint *stat;
X{
Xstruct DPTR *dp;
X
X*stat = 0;
Xdp = (struct DPTR *)malloc(sizeof(struct DPTR));
Xif (*name == '\0')
X	dp->lock = DupLock(Myprocess->pr_CurrentDir);
Xelse
X	dp->lock = Lock (name,ACCESS_READ);
Xif (dp->lock == NULL) {
X	free (dp);
X	return NULL;
X	}
Xdp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
Xif (!Examine (dp->lock, dp->fib)) {
X	pError (name);
X	dclose (dp);
X	return NULL;
X	}
Xif (dp->fib->fib_DirEntryType >= 0) *stat = 1;
Xreturn dp;
X}
X
Xdnext(dp, pname, stat)
Xstruct DPTR *dp;
Xchar **pname;
Xint *stat;
X{
Xif (dp == NULL) return (0);
X   if (ExNext (dp->lock, dp->fib)) {
X      *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
X      *pname = dp->fib->fib_FileName;
X      return (1);
X   }
X   return (0);
X}
X
X
Xdclose(dp)
Xstruct DPTR *dp;
X{
X   if (dp == NULL)
X      return (1);
X   if (dp->fib)
X      FreeMem (dp->fib,(long)sizeof(*dp->fib));
X   if (dp->lock)
X      UnLock (dp->lock);
X   free (dp);
X   return (1);
X}
X
X
Xisdir(file)
Xchar *file;
X{
X   register struct DPTR *dp;
X   int stat;
X
X   stat = 0;
X   if (dp = dopen (file, &stat))
X      dclose(dp);
X   return (stat == 1);
X}
X
X
Xfree_expand(av)
Xregister char **av;
X{
X   char **base = av;
X
X   if (av) {
X      while (*av) {
X         free (*av);
X         ++av;
X      }
X      free (base);
X   }
X}
X
X/*
X * EXPAND(base,pac)
X *    base           - char * (example: "df0:*.c")
X *    pac            - int  *  will be set to # of arguments.
X *
X * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
X *                 simple directory/file lookups. Returns a pointer to
X *                 an array of pointers that contains the full file spec
X *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
X *
X *                 Now no longer necessary to Examine the files a second time
X *                 in do_dir since expand will return the full file info
X *                 appended to the file name. Set by formatfile().
X *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
X *
X *                 Caller must call free_expand when done with the array.
X *
X * base             bname =       ename =
X * ------           -------       -------
X *  "*"               ""            "*"
X *  "!*.info"         ""            "*.info" (wild_exclude set)
X *  "su*d/*"          ""            "*"      (tail set)
X *  "file.*"          ""            "file.*"
X *  "df0:c/*"         "df0:c"       "*"
X *  ""                ""            "*"
X *  "df0:.../*"       "df0:"        "*"      (recur set)
X *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
X *
X * ---the above base would be provided by execom.c or do_dir().
X * ---the below base would only be called from do_dir().
X *
X *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
X *  "df0:"            "df0:"        "*"
X *  "file/file"       "file/file"   ""       (dp == 0) so fail
X *  "df0:.../"        "df0:"        "*"      (recur set)
X *
X */
X
X
Xchar **
Xexpand(base, pac)
Xchar *base;
Xint *pac;
X{
X   register char *ptr;
X   char **eav = (char **)malloc(sizeof(char *) * (2));
X   short eleft, eac;
X   char *name;
X   char *svfile();
X   char *bname, *ename, *tail;
X   int stat, recur, scr, bl;
X   register struct DPTR *dp;
X
X   *pac = recur = eleft = eac = 0;
X
X   base = strcpy(malloc(strlen(base)+1), base);
X   for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
X
X   if (!*ptr)   /* no wild cards */
X      --ptr;
X   else
X      for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
X
X   if (ptr < base) {
X      bname = strcpy (malloc(1), "");
X   } else {
X      scr = ptr[1];
X      ptr[1] = '\0';
X      if (!strcmp(ptr-3,".../")) {
X         recur = 1;
X         *(ptr-3) = '\0';
X      }
X      bname = strcpy (malloc(strlen(base)+2), base);
X      ptr[1] = scr;
X   }
X   bl = strlen(bname);
X   ename = ++ptr;
X   for (; *ptr && *ptr != '/'; ++ptr);
X   scr = *ptr;
X   *ptr = '\0';
X   if (scr) ++ptr;
X   tail = ptr;
X
X   if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
X      free (bname);
X      free (base);
X      free (eav);
X      return (NULL);
X   }
X
X   if (!stat) {                /* eg. 'dir file' */
X      char *p,*s;
X      for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
X      if (s != bname) ++s;
X      *s ='\0';
X      eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
X      goto done;
X   }
X   if (!*ename) ename = "*";    /* eg. dir df0: */
X   if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
X      bname[bl] = '/';
X      bname[++bl] = '\0';
X   }
X   while ((dnext (dp, &name, &stat)) && !breakcheck()) {
X        int match = compare_ok(ename,name,0);
X      if (match && !(!recur && *tail)) {
X         if (eleft < 2) {
X               char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
X               movmem (eav, scrav, (eac + 1) << 2);
X               free (eav);
X               eav = scrav;
X               eleft = 10;
X         }
X         eav[eac++] = svfile(bname,name,dp->fib);
X         --eleft;
X      }
X      if ((*tail && match) || recur) {
X         int alt_ac;
X         char *search, **alt_av, **scrav;
X         BPTR lock;
X
X         if (!stat)           /* expect more dirs, but this not a dir */
X            continue;
X         lock = CurrentDir (dp->lock);
X         search = malloc(strlen(ename)+strlen(name)+strlen(tail)+5);
X         strcpy (search, name);
X         strcat (search, "/");
X         if (recur) {
X            strcat(search, ".../");
X            strcat(search, ename);
X         }
X         strcat (search, tail);
X         scrav = alt_av = expand (search, &alt_ac);
X         /* free(search); */
X         CurrentDir (lock);
X         if (scrav) {
X            while (*scrav) {
X               int l;
X               if (eleft < 2) {
X                  char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
X                  movmem (eav, scrav, (eac + 1) << 2);
X                  free (eav);
X                  eav = scrav;
X                  eleft = 10;
X               }
X
X               l = strlen(*scrav);
X               scrav[0][l] = ' ';
X               eav[eac] = malloc(bl+l+45);
X               strcpy(eav[eac], bname);
X               strcat(eav[eac], *scrav);
X               eav[eac][l+bl] = '\0';
X
X               free (*scrav);
X               ++scrav;
X               --eleft, ++eac;
X            }
X            free (alt_av);
X         }
X      }
X   }
Xdone:
X   dclose (dp);
X   *pac = eac;
X   eav[eac] = NULL;
X   free (bname);
X   free (base);
X   if (eac) {
X      return (eav);
X   }
X   free (eav);
X   return (NULL);
X}
X
Xstrupr(s)
Xregister char *s;
X{
Xwhile (*s) *s=toupper(*s), s++;
X}
X
X/*
X * Compare a wild card name with a normal name
X */
X
Xcompare_ok(wild, name, casedep)
Xchar *wild, *name;
X{
Xint queryflag;
Xchar buf[260], wildbuf[260], *lowname;
X
Xif (queryflag=(*wild=='&')) wild++;
Xif (*wild=='!') *wild='~';
X
Xif (! casedep) {
X	strupr(wild);
X	strcpy(buf,name);
X	strupr(buf);
X	lowname=buf;
X	}
Xelse lowname=name;
X
XPreParse(wild, wildbuf);
Xif ( ! PatternMatch(wildbuf,lowname)) return 0;
X
Xif (queryflag) {
X	printf("Select \23337m%-16s\2330m [y/n] ? ",name);
X	gets(buf);
X	return (toupper(*buf)=='Y');
X	}
Xreturn 1;
X}
X
Xchar *svfile(s1,s2,fib)
Xchar *s1,*s2;
XFIB *fib;
X{
Xchar *p = malloc (strlen(s1)+strlen(s2)+45);
Xstrcpy(p, s1);
Xstrcat(p, s2);
Xformatfile(p,fib);
Xreturn p;
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  NNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
X *                              1111111111222222222233333333334 4  4
X *                    01234567890123456789012345678901234567890 1  2
X */
Xformatfile(str,fib)
Xchar *str;
XFIB *fib;
X{
Xchar *dates();
Xint i;
Xwhile(*str++);
Xfor (i=7; i>=0; i--)
X    *str++ = ((fib->fib_Protection & (1L<<i)) ? "hspa----" : "----rwed")[7-i];
Xif (fib->fib_DirEntryType < 0)
X  sprintf(str,"  %6ld %4ld  ", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
Xelse strcpy(str,"   <Dir>       ");
Xstrcat(str,dates(&fib->fib_Date));
X}
X
X/* Sort routines */
X
Xlong cmp(s1, s2)
Xchar **s1, **s2;
X{
Xreturn (long)Strcmp(*s1, *s2);
X}
X
XCmp() {
X#asm
X	public	_geta4
X	movem.l	d2-d3/a4/a6,-(sp)
X	movem.l	a0/a1,-(sp)
X	bsr	_geta4
X	bsr	_cmp
X	addq.l	#8,sp
X	movem.l	(sp)+,d2-d3/a4/a6
X#endasm
X}
X
XQuickSort(av, n)
Xchar *av[];
Xint n;
X{
XQSort(av, (long)n, 4L, Cmp);
X}
END_OF_FILE
if test 13255 -ne `wc -c <'sub.c'`; then
    echo shar: \"'sub.c'\" unpacked with wrong size!
fi
# end of 'sub.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 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
-- 
Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
	amiga@cs.odu.edu	
or	amiga@xanth.cs.odu.edu	( obsolescent mailers may need this address )
or	...!uunet!xanth!amiga	( very obsolescent mailers need this address )

Comments, questions, and suggestions s should be addressed to ``amiga-request''
(only use ``amiga'' for submissions) at the above addresses.