[comp.sources.amiga] v89i149: shell - csh-like shell v3.03a, Part01/02

page%swap@Sun.COM (Bob Page) (05/19/89)

Submitted-by: PERUGIA@ICNUCEVM.Bitnet (Cesare Dieni)
Posting-number: Volume 89, Issue 149
Archive-name: unix/shell303a.1

New to 3.03A:
- New filter commands fltlower, fltupper.
- Added configuration file feature: now if you have a file
  named S:.login, it will be sourced for every Shell you start.
- New option dir -c.
- New editing feature: shift-left(right) arrow move cursor to
  previous(next) word.
- Bugs fixed: alias command wasn't listed in help; typing a number
  as a command was interpreted like 'alias'.

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	comm1.c
#	comm2.c
#	comm3.c
#	execom.c
# This is archive 1 of a 2-part kit.
# This archive created: Thu May 18 12:17:53 1989
echo "extracting comm1.c"
sed 's/^X//' << \SHAR_EOF > comm1.c
X/*
X * COMM1.C
X *
X * Matthew Dillon, August 1986
X *
X * Version 2.07M by Steve Drew 10-Sep-87
X *
X * Version 3.03A by Carlo Borreo & Cesare Dieni 12-May-89
X *
X */
X
Xextern char *v_passed, *v_gotofwd, *v_cwd, *v_lasterr;
X
X#define DIR_SHORT 0x01
X#define DIR_FILES 0x02
X#define DIR_DIRS  0x04
X#define DIR_NOCOL 0x08
X
Xextern int has_wild;
Xchar cwd[256];
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{
Xint 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, *flags="DEWRAPSH";
Xregister unsigned int i;
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;
Xunsigned int size, free;
Xchar *p,*s,*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		s = get_pwd(lock);
X		if (p=index(s,':')) *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("%4d%c%6ld%7ld%7ld%4d%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			s);
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
Xchar lspec[128];
Xint filecount, col;
Xlong bytes, blocks;
X
X/*
X * the args passed to do_dir will never be expanded
X */
Xdo_dir()
X{
X   void display_file();
X   int i;
X
X   col = filecount = 0;
X   bytes = blocks = 0L;
X   *lspec = '\0';
X
X   get_opt("sfdc",&i);
X
X   if (ac == i) {
X      ++ac;
X      av[i] = "";
X   }
X   if (!(options & (DIR_FILES | DIR_DIRS)))  options|=(DIR_FILES | DIR_DIRS);
X
X   for (; i < ac && !CHECKBREAK(); ++i) {
X      char **eav;
X      int c,eac;
X      if (!(eav = expand(av[i], &eac))) continue;
X      QuickSort(eav, eac);
X      for(c=0;c < eac && !breakcheck();++c) display_file(options,eav[c]);
X      free_expand (eav);
X   }
X   if (col)  printf("\n");
X   if (filecount > 1) {
X      blocks += filecount; /* account for dir blocks */
X      printf (" %ld Blocks, %ld Bytes used in %d files\n", blocks, bytes, filecount);
X   }
X   return 0;
X}
X
Xvoid
Xdisplay_file(options,filestr)
Xint options;
Xchar *filestr;
X{
X   long atol();
X   int isadir,slen;
X   char sc;
X   char *c,*s,*fi;
X   BPTR lock;
X
X/*	if current dir different from lspec then
X	look for ':' or '/' if found lock it and get_pwd.
X	else then use cwd.
X*/
X   for(s = c = filestr; *c; ++c) if (*c == ':' || *c == '/') s = c;
X   if (*s == ':') ++s;
X   sc = *s;
X   *s = '\0';
X   c = filestr;
X   if (!*c) c = cwd;
X   if (strcmp (c, &lspec))  {
X	strcpy(lspec, c);
X	if (col) printf("\n");
X	if (lock=Lock(c,SHARED_LOCK)) {
X		printf("Directory of %s\n", get_pwd(lock));
X		UnLock(lock);
X		}
X	col = 0;
X	}
X   *s = sc;
X   if (sc == '/') s++;
X   slen = strlen(s);
X   fi = s + slen + 1;
X   isadir = (fi[12] =='D');
X
X   if (!(((options & DIR_FILES) && !isadir) ||
X	  ((options & DIR_DIRS) &&  isadir)))
X      return;
X   if (isadir && !(options & DIR_NOCOL)) printf ("\23333m");
X   if (options & DIR_SHORT) {
X	if (col==3 && slen>18) { printf("\n"); col = 0; }
X	if (slen>18) { printf(" %-37s",s); col+= 2; }
X		else { printf(" %-18s",s); col++; }
X	if (col > 3) { printf("\n"); col=0; }
X	}
X   else printf("   %-24s %s",s ,fi);
X   if (isadir && !(options & DIR_NOCOL)) printf("\2330m");
X   fflush(stdout);
X   fi[16] = fi[21] = '\0';
X   bytes  += atol(fi+10);
X   blocks += atol(fi+17);
X   filecount++;
X   return;
X}
X
Xdo_quit()
X{
Xif (Src_stack) {
X	Quit = 1;
X	return(do_return());
X	}
Xmain_exit(0);
X}
X
Xdo_echo(str)
Xregister char *str;
X{
Xchar nl=1;
X
Xfor (; *str && *str != ' '; ++str);
Xif (*str==' ') ++str;
Xif (av[1] && !strcmp(av[1],"-n")) {
X	nl = 0;
X	str += 2;
X	if (*str==' ') ++str;
X	}
Xprintf("%s",str);
Xif (nl) printf("\n");
Xfflush(stdout);
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];
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	int 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 * return ptr to string that contains full cwd spec.
X */
Xchar *get_pwd(flock)
XBPTR flock;
X{
Xstatic char pwdstr[130];
XPathName(flock, pwdstr, 128L);
Xreturn pwdstr;
X}
X
X/*
X * set process cwd name and $_cwd, if str != NULL also print it.
X */
Xdo_pwd(str)
Xchar *str;
X{
Xif (Myprocess->pr_CurrentDir == 0)
X	attempt_cd(":"); /* if we just booted 0 = root lock */
Xstrcpy(cwd,get_pwd(Myprocess->pr_CurrentDir,1));
Xif (str) puts(cwd);
Xset_var(LEVEL_SET, v_cwd, cwd);
X/* put the current dir name in our CLI task structure */
XCtoBStr(cwd, Mycli->cli_SetName, 128L);
X}
X
X/*
X * CD
X *
X * CD(str, 0)      -do CD operation.
X *
X *    standard operation: breakup path by '/'s and process independantly
X *    x:    -reset cwd base
X *    ..    -remove last cwd element
X *    N     -add N or /N to cwd
X */
X
Xdo_cd(str)
Xchar *str;
X{
X   char sc, *ptr;
X   int err=0;
X
X   str = next_word(str);
X   if (*str == '\0') {
X      puts(cwd);
X      return(0);
X   }
X   str[strlen(str)+1] = '\0';		/* add second \0 on end */
X   while (*str) {
X      for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr);
X      switch (*ptr) {
X      case ':':
X	  sc = ptr[1];
X	  ptr[1] = '\0';
X	  err = attempt_cd(str);
X	  ptr[1] = sc;
X	  break;
X      case '\0':
X      case '/':
X	  *ptr = '\0';
X	  if (strcmp(str, "..") == 0 || str == ptr)
X	     str = "/";
X	  if (*str) err = attempt_cd(str);
X	  break;
X      }
X      if (err) break;
X      str = ptr + 1;
X   }
X   do_pwd(NULL);	  /* set $_cwd */
X   return err;
X}
X
Xattempt_cd(str)
Xchar *str;
X{
XBPTR oldlock, filelock;
X
Xif (filelock=Lock(str, ACCESS_READ)) {
X	if (isdir(str)) {
X		if (oldlock=CurrentDir(filelock)) UnLock(oldlock);
X		return (0);
X		}
X	UnLock(filelock);
X	ierror(str, 212);
X	}
Xelse ierror(str, 205);
Xreturn -1;
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;
Xunsigned int lctr, len=strlen(searchstring);
Xint yesno;
Xchar buf[256], lowbuf[256], first;
Xregister char *p, *l, *t;
X
Xif (!(options & 2)) for (t=searchstring; *t=Toupper(*t); t++);
Xfirst=*searchstring;
Xif ((fi=fopen(s, "r"))==NULL) { pError(s); return; }
Xlctr=0;
Xif (!(options & 32)) printf("Examining %s...\n",s);
Xwhile (fgets(buf,256,fi) && !dobreak()) {
X	lctr++;
X	if (options & 4) yesno=compare_ok(searchstring,buf);
X	else {
X		yesno=0;
X		p=buf;
X		if (!(options & 2)) {
X			l=lowbuf;			/* p is already =buf */
X			while (*l++=Toupper(*p++));	/* lowbuf=upper(buf) */
X			p=lowbuf;
X			}
X		while (p=index(p,first))
X			if (!strncmp(p++,searchstring,len)) { yesno=1; break; }
X		}
X	if (yesno ^ ((options & 16)!=0) ) {
X			/* default: print line numbers */
X		if (!(options & 8)) printf("%4d ",lctr);
X		printf("%s",buf);
X		}
X	}
Xfclose (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
X/* forline i RAM:temp echo line $_linenum: $i */
X
Xdo_forline()
X{
Xchar vname[33], buf[256];
Xregister unsigned short lctr;
XFILE *f;
Xchar *cstr;
Xstatic char *linenumname="_linenum";
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, ' ');
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, linenumname, buf);
X	exec_command(cstr);
X	}
Xfclose(f);
X--H_stack;
Xfree (cstr);
Xunset_var (LEVEL_SET, vname);
Xunset_var (LEVEL_SET, linenumname);
Xreturn 0;
X}
X
X/* fornum i 1 10 echo $i */
X
Xdo_fornum()
X{
Xchar vname[33], buf[16];
Xint n1, n2;
Xchar *cstr;
Xregister int i;
X
Xstrcpy(vname,av[1]);
Xn1=myatoi(av[2],0 ,32767); if (Errno) return 20;
Xn2=myatoi(av[3],n1,    32767); if (Errno) return 20;
X++H_stack;
Xcstr = compile_av (av, 4, ac, ' ');
Xfor (i=n1; i<=n2 && !CHECKBREAK(); 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;
X
Xget_opt("v",&i);
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, ' ');
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 (options & 1) printf("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);
X		if (Errno) 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
Xdate()
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}
SHAR_EOF
echo "extracting comm2.c"
sed 's/^X//' << \SHAR_EOF > comm2.c
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 3.03A by Carlo Borreo & Cesare Dieni 12-May-89
X *
X */
X
Xextern char *v_gotofwd;
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("rftmdn",&i);
X		result=evalif(i);
X		If_base[If_stack++]=(options & 32 ? 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;
Xlong AvailMem();
X
Xswitch(options & ~32) {
X    case 0:
X	if (ac-i != 3) return (ac>i && *av[i]);
X	Errno=0;
X	num=Atol(av[i])-Atol(av[i+2]);
X	if (Errno) 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    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{
Xputs("Shell V3.03A\n\
X)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))) {
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);
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 (Errno) 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}
SHAR_EOF
echo "extracting comm3.c"
sed 's/^X//' << \SHAR_EOF > comm3.c
X/*
X * COMM3.C
X *
X * Version 3.03A by Carlo Borreo & Cesare Dieni 12-May-89
X *
X */
X
Xdo_assign() {
Xswitch(ac) {
X	case 1:  assignlist();
X		 break;
X	case 2:  doassign(av[1], NULL);
X		 break;
X	case 3:  doassign(av[1], av[2]);
X		 break;
X	default: ierror(NULL, 500);
X		 break;
X	}
Xreturn 0;
X}
X
Xchar *assign_errors[4]={
X	"",
X	"Name %s is not valid\n",
X	"Weird error\n",
X	"Can't cancel %s\n"
X	};
X
Xdoassign(log, phy)
Xchar *log, *phy;
X{
Xint last=strlen(log) - 1;
X
Xif (log[last] != ':') fprintf(stderr, "Bad name %s\n", log);
Xelse {
X	log[last] = 0;
X	fprintf(stderr,assign_errors[Assign(log, phy)],log);
X	}
X}
X
Xassignlist()
X{
Xstruct DirectoryEntry *de_head=NULL, *de;
Xchar buf[256];
XBPTR lock;
Xint ctr=0;
X
XAddDADevs(&de_head, DLF_DEVICES | DLF_VOLUMES | DLF_DIRS);
Xprintf("Devices:\n");
Xfor (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	}
Xprintf("\n\nVolumes:\n");
Xfor (	;
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		);
Xprintf("\nDirectories:\n");
Xfor (; 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	}
XFreeDAList(&de_head);
X}
X
Xdo_join()
X{
XBPTR sou, dest;
Xchar *buffer;
Xunsigned int i;
Xlong n;
Xchar *namedest=av[--ac];
X
Xget_opt("r", &i);
Xif (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
Xif ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
Xif ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
X	{ pError(namedest); goto fail1; }
Xfor (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
Xstrings_in_file(s)
Xchar *s;
X{
Xchar c;
Xchar readbuf[BUFDIM+1], strbuf[MAXSTR+1];
Xregister unsigned int i, strctr=0;
XBPTR fh;
Xint out, n;
X
Xif ( 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			}
X		else {
X			strbuf[strctr++]=c;
X			out=(strctr>=BUFDIM);
X			}
X		if (out) {
X			strbuf[strctr]='\0';
X			puts(strbuf);
X			strctr=0;
X			}
X		}
X	Close(fh);
X	}
Xelse pError(s);
X}
X
Xdo_strings()
X{
Xminstr=myatoi(av[--ac],1,255);
Xall_args("r", strings_in_file, 0);
Xreturn 0;
X}
X
XBPTR myfile[MAXMYFILES];
X
Xdo_open()
X{
Xlong mode;
Xunsigned int n;
X
Xswitch (av[2][0]) {
X	case 'r': mode=MODE_OLDFILE; break;
X	case 'w': mode=MODE_NEWFILE; break;
X	default : ierror(NULL,500); return;
X	}
XErrno=0;
Xn=(unsigned int)myatoi(av[3],0,MAXMYFILES); if (Errno) return 20;
Xmyfile[n]=Open(av[1],mode);
Xreturn (myfile[n]==NULL);
X}
X
Xdo_close()
X{
Xregister unsigned int i;
Xint n;
X
Xfor (i=1; i<ac; i++) {
X	Errno=0;
X	n=myatoi(av[i],0,MAXMYFILES); if (Errno) return 20;
X	myclose(n);
X	}
Xreturn 0;
X}
X
Xmyclose(n)
X{
Xif (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
X}
X
Xdo_fileslist()
X{
Xregister unsigned short i;
Xint flag=0;
X
Xprintf("Open files:");
Xfor (i=0; i<MAXMYFILES; i++)
X	if (myfile[i]) { printf(" %d",i); flag=1; }
Xif (!flag) printf(" None!");
Xprintf("\n");
Xreturn 0;
X}
X
XBPTR extOpen(name,mode)
Xchar *name;
Xlong mode;
X{
Xif (name[0]=='.') return myfile[atoi(name+1)];
Xreturn Open(name,mode);
X}
X
XextClose(fh)
XBPTR fh;
X{
Xregister unsigned short i;
X
Xfor (i=0; i<MAXMYFILES; i++)
X	if (myfile[i]==fh) return;
XClose(fh);
X}
X
Xdo_resident(avline)
Xchar *avline;
X{
Xunsigned int i;
XBPTR seg;
Xstruct ResidentPrgNode *p;
X
Xget_opt("ar", &i);
Xswitch (options) {
X    case 0:
X	ObtainSemaphore (& (ArpBase->ResPrgProtection) );
X	if (p=ArpBase->ResidentPrgList) {
X		printf("Name             Users\n");
X		for (; p; p=p->rpn_Next)
X			printf("%-16s %-3ld\n",p->rpn_Name,p->rpn_Usage);
X		}
X	else printf("No resident program(s)\n");
X	ReleaseSemaphore(& (ArpBase->ResPrgProtection) );
X	break;
X    case 1:
X	for (; i<ac; i++)
X		if ( (seg=(BPTR)LoadPrg(av[i])) && AddResidentPrg(seg,av[i]) )
X			printf("OK! %s is now resident\n", BaseName(av[i]));
X		else 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    default:
X	ierror(NULL,500);
X	break;
X    }
Xreturn 0;
X}
X
Xstruct ProcessControlBlock pcb={
X	4000,		/* pcb_StackSize	*/
X	0,		/* pcb_Pri		*/
X	};
X/* remaining field are NULL */
X	
Xdo_truerun(avline, backflag)
Xchar *avline;
X{
Xchar name[200];
Xchar *FindIt();
X
Xif (backflag) {
X	pcb.pcb_Control=NULL;
X	pcb.pcb_Input=pcb.p_Output=Open("NIL:",MODE_OLDFILE);
X	}
Xelse {
X	pcb.pcb_Control=NULL;
X	pcb.pcb_Input=pcb.p_Output =NULL;
X	}
Xif (FindIt(av[1], "", name))
X	ASyncRun(name,next_word(next_word(avline)),&pcb);
Xelse
X	ierror(av[1],205);
Xreturn 0;
X}
X
Xint exists(name)
Xchar *name;
X{
XBPTR lock;
X
Xif (lock=Lock(name,ACCESS_READ)) {
X	UnLock(lock);
X	return 1;
X	}
Xreturn 0;
X}
X
Xdo_aset()
X{
XSetenv(av[1],av[2]);
Xreturn 0;
X}
X
X#define HTYPELINE 16L
X
Xhtype_a_file(s)
Xchar *s;
X{
XBPTR fh;
Xlong n, filesize=0;
Xchar buf[HTYPELINE+1];
Xregister unsigned int i;
X
Xif ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; }
Xwhile ( (n=Read(fh,buf,HTYPELINE))>0 && !dobreak()) {
X	printf("%06lx: ",filesize);
X	filesize+=n;
X	for (i=0; i<n; i++) {
X		printf( (i&3) ? "%02x" : " %02x",(int)(unsigned char)buf[i]);
X		if (buf[i]<=0x20) buf[i]='.';
X		}
X	for ( ; i<HTYPELINE; i++) {
X		printf( (i&3) ? "  " : "   ");
X		buf[i]=' ';
X		}
X	buf[i]=0;
X	printf("    %s\n",buf);
X	}
XClose(fh);
Xreturn 0;
X}
X
Xdo_htype()
X{
Xall_args("", htype_a_file, 0);
Xreturn 0;
X}
X
Xdo_stack()
X{
Xlong n;
X
Xif (ac>1) {
X	Errno=0;
X	n=Atol(av[1]);
X	if (!Errno) Mycli->cli_DefaultStack=(long)(n >> 2L);
X	}
Xelse printf("current stack size is %ld bytes\n",
X				(long)Mycli->cli_DefaultStack << 2L);
Xreturn 0;
X}
X
Xdo_fault()
X{
Xstruct PERROR *p;
Xregister unsigned int i;
Xint n;
X
Xfor (i=1; i<ac; i++) {
X	n=myatoi(av[i],0,32767);
X	if (!Errno) {
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	}
Xreturn 0;
X}
X
Xstruct rpncommand {
X	char *str;
X	int parsin, parsout;
X	};
X
Xstruct 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	"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
Xdo_rpn(garbage,ifflag) /* ifflag!=0 if called from if */
Xchar *garbage;
X{
Xregister long n0, n1;
Xlong t;
Xunsigned int i, j;
Xint sp=0;
Xlong stack[100];
Xstruct rpncommand *temp;
X
Xi=1;
Xif (ifflag) get_opt("rn",&i);
Xfor (; 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"); return 1; }
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:	n0 = n1/n0;		break;
X	  case 4:	n0 = n1%n0;		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:	n1=n0;			break;
X	  case 13:	t=n0; n0=n1; n1=t;	break;
X	  case 14:				break;
X	  case 15:	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:	Errno=0;
X			n0=Atol(av[i]);
X			if (Errno) {
X				fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
X				return 20;
X				}
X			break;
X	  }
X	stack[sp]=n0;
X	stack[sp+1]=n1;
X	sp += rpn[j].parsout;
X	}
Xif (ifflag) return (int)(stack[sp-1]);	/* called from if: return top value */
Xfor (i=sp-1;(int)i>=0;i--) printf("%ld\n", stack[i]); /* else print stack */
Xreturn 0;
X}
X
Xdo_path()
X{
Xunion {	long *lp; long ll; } l;
Xchar buf[256];
X
Xputs("Current dir");
Xl.lp = (long *) Mycli->cli_CommandDir;
Xwhile (l.ll) {
X	l.ll <<= 2;
X	PathName(l.lp[1], buf, 256L);
X	puts(buf);
X	l.ll = *l.lp;
X	}
Xputs("C:");
Xreturn 0;
X}
X
Xdo_pri()
X{
Xint t, pri;
Xstruct Process *proc;
X
Xt=myatoi(av[1],0,20); if (Errno) return 20;
Xpri=myatoi(av[2],-128,127); if (Errno) return 20;
XForbid();
Xproc=(t==0 ? Myprocess : FindCLI((long)t));
Xif (proc==NULL) fprintf(stderr, "process not found\n");
X	else SetTaskPri(proc, (long)pri);
XPermit();
Xreturn 0;
X}
X
Xdo_strleft()
X{
Xchar buf[256];
Xint n;
X
Xstrcpy(buf,av[2]);
Xn=myatoi(av[3],1,strlen(buf)); if (Errno) return 20;
Xbuf[n]='\0';
Xset_var(LEVEL_SET, av[1], buf);
Xreturn 0;
X}
X
Xdo_strright()
X{
Xchar buf[256];
Xint n;
X
Xstrcpy(buf, av[2]);
Xn=myatoi(av[3],1,strlen(buf)); if (Errno) return 20;
Xset_var(LEVEL_SET, av[1], buf+strlen(buf)-n);
Xreturn 0;
X}
X
Xdo_strmid()
X{
Xchar buf[256];
Xint n1, n2;
X
Xstrcpy(buf, av[2]);
Xn1=myatoi(av[3],1,strlen(buf))-1; if (Errno) return 20;
Xif (ac>4) {
X	n2=myatoi(av[4],1,strlen(buf)-n1);
X	if (Errno) return 20;
X	buf[n1+n2]='\0';
X	}
Xset_var(LEVEL_SET, av[1], buf+n1);
Xreturn 0;
X}
X
Xdo_strlen()
X{
Xchar buf[16];
X
Xsprintf(buf,"%d",strlen(av[2]));
Xset_var(LEVEL_SET, av[1], buf);
Xreturn 0;
X}
X
Xmyatoi(s,min,max)
Xchar *s;
X{
Xlong n;
X
XErrno=0;
Xn=Atol(s);
Xif (Errno==ERRBADINT) ierror(s,511);
X	else if (n<min || n>max) {
X		Errno=ERRBADINT;
X		printf("%s not in (%d,%d)\n",s,min,max);
X		}
Xreturn (int)n;
X}
X
Xdo_fltlower()
X{
Xchar buf[256], *s;
X
Xwhile (!CHECKBREAK() && gets(buf)) {
X	for (s=buf; *s; s++) *s=tolower(*s);
X	puts(buf);
X	}
Xreturn 0;
X}
X
Xdo_fltupper()
X{
Xchar buf[256], *s;
X
Xwhile (!CHECKBREAK() && gets(buf)) {
X	for (s=buf; *s; s++) *s=toupper(*s);
X	puts(buf);
X	}
Xreturn 0;
X}
SHAR_EOF
echo "extracting execom.c"
sed 's/^X//' << \SHAR_EOF > execom.c
X/*
X * EXECOM.C
X *
X * Matthew Dillon, 10 August 1986
X *    Finally re-written.
X *
X * Version 2.07M by Steve Drew 10-Sep-87
X *
X * Version 3.03A by Carlo Borreo & Cesare Dieni 12-May-89
X *
X */
X
Xextern char *v_histnum, *v_except;
X
X#define F_EXACT 0
X#define F_ABBR  1
X
X#define ST_COND   0x01
X#define ST_NORED  0x02
X#define ST_NOEXP  0x04
X#define ST_AV     0x08 /* delimit args within a variable */
X
Xint has_wild = 0;                 /* set if any arg has wild card */
X
Xstruct COMMAND {
X	int (*func)();
X	short minargs;
X	short stat;
X	int val;
X	char *name;
X};
X
Xextern char *format_insert_string();
Xextern char *mpush(), *exarg();
X
Xextern int do_fltupper(), do_fltlower();
Xextern int do_strleft(), do_strright(), do_strmid(), do_strlen();
Xextern int do_fornum(), do_forline(), do_exec();
Xextern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
Xextern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
Xextern int do_open(), do_close(), do_fileslist(), do_htype();
Xextern int do_run(), do_number(), do_assign(), do_join();
Xextern int do_quit(), do_set_var(), do_unset_var();
Xextern int do_echo(), do_source(), do_mv(), do_addbuffers();
Xextern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
Xextern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
Xextern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
Xextern int do_input(), do_ver(), do_sleep(), do_help();
Xextern int do_strhead(), do_strtail(), do_relabel();
Xextern int do_copy(), date(), do_protect(), do_ps();
Xextern int do_forever(), do_abortline(), do_strings(), do_touch();
Xextern int do_window(), do_search(), do_filenote();
Xchar *push_cpy();
X
Xstatic struct COMMAND Command[] = {
Xdo_run,		0, ST_AV,	0,	"\001",   /* may call do_source */
Xdo_set_var,	0, 0, LEVEL_ALIAS,	"alias",  /* uses avline */
Xdo_abortline,	0, 0,		0,	"abortline",
Xdo_addbuffers,	2, 0,		0,	"addbuffers",
Xdo_aset,	1, 0,		0,	"aset",
Xdo_assign,	0, 0,		0,	"assign",
Xdo_cat,		0, 0,		0,	"cat",
Xdo_cd,		0, 0,		0,	"cd",
Xdo_close,	0, 0,		0,	"close",
Xdo_copy,	1, 0,		0,	"copy",
Xdo_copy,	1, 0,		0,	"cp",
Xdate,		0, 0,		0,	"date",
Xdo_rm,		0, 0,		0,	"delete",
Xdo_dir,		0, ST_NOEXP,	0,	"dir",
Xdo_diskchange,	1, 0,		0,	"diskchange",
Xdo_inc,		1, 0,		-1,	"dec",
Xdo_echo,	0, 0,		0,	"echo", /* uses avline */
Xdo_if,		0, ST_COND,	1,	"else",
Xdo_if,		0, ST_COND,	2,	"endif",
Xdo_exec,	1, 0,		0,	"exec",
Xdo_fault,	1, 0,		0,	"fault",
Xdo_filenote,	2, 0,		0,	"filenote",
Xdo_fileslist,	0, 0,		0,	"flist",
Xdo_fltlower,	0, 0,		0,	"fltlower",
Xdo_fltupper,	0, 0,		0,	"fltupper",
Xdo_foreach,	3, ST_NORED,	0,	"foreach",
Xdo_forever,	1, ST_NORED,	0,	"forever",
Xdo_forline,	3, ST_NORED,	0,	"forline",
Xdo_fornum,	4, ST_NORED,	0,	"fornum",
Xdo_goto,	1, 0,		0,	"goto",
Xdo_help,	0, 0,		0,	"help",
Xdo_history,	0, 0,		0,	"history",
Xdo_howmany,	0, 0,		0,	"howmany",
Xdo_htype,	1, 0,		0,	"htype",
Xdo_if,		1, ST_COND|ST_NORED,0,	"if",
Xdo_inc,		1, 0,		1,	"inc",
Xdo_info,	0, 0,		0,	"info",
Xdo_join,	2, 0,		1,	"join",
Xdo_input,	1, 0,		0,	"input",
Xdo_label,	1, ST_COND,	0,	"label",
Xdo_dir,		0, ST_NOEXP,	0,	"ls",
Xdo_mkdir,	0, 0,		0,	"md",
Xdo_mem,		0, 0,		0,	"mem",
Xdo_mkdir,	0, 0,		0,	"mkdir",
Xdo_mv,		2, 0,		0,	"mv",
Xdo_open,	3, 0,		0,	"open",
Xdo_path,	0, 0,		0,	"path",
Xdo_pri,		2, 0,		0,	"pri",
Xdo_protect,	2, 0,		0,	"protect",
Xdo_ps,		0, 0,		0,	"ps",
Xdo_pwd,		0, 0,		0,	"pwd",
Xdo_quit,	0, ST_NORED,	0,	"quit",
Xdo_truerun,	1, ST_NORED,	1,	"rback",
Xdo_mv,		2, 0,		0,	"rename",
Xdo_relabel,	2, 0,		0,	"relabel",
Xdo_resident,	0, 0,		0,	"resident",
Xdo_return,	0, 0,		0,	"return",
Xdo_rm,		0, 0,		0,	"rm",
Xdo_rpn,		0, ST_NOEXP|ST_NORED,0,	"rpn",
Xdo_truerun,	1, ST_NORED,	0,	"run",
Xdo_search,	2, 0,		0,	"search",
Xdo_set_var,	0, ST_AV, LEVEL_SET,	"set",
Xdo_sleep,	0, 0,		0,	"sleep",
Xdo_source,	0, ST_NORED|ST_AV, 0,	"source", /* uses avline */
Xdo_stack,	0, 0,		0,	"stack",
Xdo_strhead,	3, 0,		0,	"strhead",
Xdo_strings,	1, 0,		0,	"strings",
Xdo_strleft,	3, 0,		0,	"strleft",
Xdo_strlen,	2, 0,		0,	"strlen",
Xdo_strmid,	3, 0,		0,	"strmid",
Xdo_strright,	3, 0,		0,	"strright",
Xdo_strtail,	3, 0,		0,	"strtail",
Xdo_touch,	0, 0,		0,	"touch",
Xdo_cat,		0, 0,		0,	"type",
Xdo_unset_var,	0, 0, LEVEL_ALIAS,	"unalias",
Xdo_unset_var,	0, 0, LEVEL_SET  ,	"unset",
Xdo_ver,		0, 0,		0,	"version",
Xdo_window,	0, ST_NOEXP,	0,	"window",
X'\0',		0, 0,		0,	NULL
X};
X
Xstatic unsigned char elast;		/* last end delimeter */
Xstatic char Cin_ispipe, Cout_ispipe;
X
Xexec_command(base)
Xchar *base;
X{
Xregister char *scr;
Xchar buf[32];
X
Xif (!H_stack) {
X	add_history(base);
X	sprintf(buf, "%d", H_tail_base + H_len);
X	set_var(LEVEL_SET, v_histnum, buf);
X	}
Xscr = malloc((strlen(base) << 2) + 2);
Xpreformat(base, scr);
Xreturn (fcomm(scr, 1) ? -1 : 1);
X}
X
Xisalphanum(c)
Xregister char c;
X{
Xreturn (
X	(c >= '0' && c <= '9') ||
X	(c >= 'a' && c <= 'z') ||
X	(c >= 'A' && c <= 'Z') ||
X	(c == '_')
X	);
X}
X
Xpreformat(s, d)
Xregister char *s, *d;
X{
Xregister int si, di, qm;
X
Xsi = di = qm = 0;
Xwhile (s[si] == ' ' || s[si] == 9) ++si;
Xwhile (s[si]) {
X	if (qm && s[si] != '\"' && s[si] != '\\') {
X		d[di++] = s[si++] | 0x80;
X		continue;
X		}
X	switch (s[si]) {
X		case ' ':
X		case 9:
X			d[di++] = ' ';
X			while (s[si] == ' ' || s[si] == 9) ++si;
X			if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di;
X			break;
X		case '*':
X		case '?':
X			d[di++] = 0x80;
X		case '!':
X			d[di++] = s[si++];
X			break;
X		case '#':
X			d[di++] = '\0';
X			while (s[si]) ++si;
X			break;
X		case ';':
X		case '|':
X			d[di++] = s[si++];
X			while (s[si] == ' ' || s[si] == 9) ++si;
X			break;
X		case '\\':
X			d[di++] = s[++si] | 0x80;
X			if (s[si]) ++si;
X			break;
X		case '\"':
X			qm = 1 - qm;
X			++si;
X			break;
X		case '^':
X			d[di++] = s[++si] & 0x1F;
X			if (s[si]) ++si;
X			break;
X		case '$': /* search end of var name and place false space */
X			d[di++] = 0x80;
X			d[di++] = s[si++];
X			while (isalphanum(s[si])) d[di++] = s[si++];
X			d[di++] = 0x80;
X			break;
X		default:
X			d[di++] = s[si++];
X			break;
X		}
X	}
Xd[di++]=0;
Xd[di]=0;
Xif (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
X}
X
Xextern BPTR extOpen();
X
X/*
X * process formatted string.  ' ' is the delimeter.
X *
X *    0: check '\0': no more, stop, done.
X *    1: check $.     if so, extract, format, insert
X *    2: check alias. if so, extract, format, insert. goto 1
X *    3: check history or substitution, extract, format, insert. goto 1
X *
X *    4: assume first element now internal or disk based command.
X *
X *    5: extract each ' ' or 0x80 delimited argument and process, placing
X *       in av[] list (except 0x80 args appended).  check in order:
X *
X *             '$'         insert string straight
X *             '>'         setup stdout
X *             '>>'        setup stdout flag for append
X *             '<'         setup stdin
X *             '*' or '?'  do directory search and insert as separate args.
X *
X *             ';' 0 '|'   end of command.  if '|' setup stdout
X *                          -execute command, fix stdin and out (|) sets
X *                           up stdin for next guy.
X */
X
X
Xfcomm(str, freeok)
Xregister char *str;
X{
X   static int alias_count;
X   int p_alias_count = 0;
X   char *istr;
X   char *nextstr;
X   char *command;
X   char *pend_alias = NULL;
X   char err = 0;
X   has_wild = 0;
X
X   ++alias_count;
X
X   mpush_base();
X   if (*str == 0)
X      goto done1;
Xstep1:
X   if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
X      fprintf(stderr,"Alias Loop\n");
X      err = 20;
X      goto done1;
X   }
X/*
X   if (str[1] == '$') {
X      if (istr = get_var (LEVEL_SET, str + 2))
X         str = format_insert_string(str, istr, &freeok);
X   }
X*/
X   istr = NULL;
X   if (*(unsigned char *)str < 0x80)
X      istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
X   *str &= 0x7F;                          /* remove \ teltail     */
X   if (istr) {
X      if (*istr == '%') {
X         pend_alias = istr;
X      } else {
X         str = format_insert_string(str, istr, &freeok);
X         goto step1;
X      }
X   }
X   if (*str == '!') {
X      char *p, c;                     /* fix to allow !cmd1;!cmd2 */
X      for(p = str; *p && *p != ';' ; ++p);
X      c = *p;
X      *p = '\0';
X      istr = get_history(str);
X      *p = c;
X      replace_head(istr);
X      str = format_insert_string(str, istr, &freeok);
X      goto step1;
X   }
X   nextstr = str;
X   command = exarg(&nextstr);
X   if (*command == 0)
X      goto done0;
X   if (pend_alias == 0) {
X      if (cmd_stat(command) & ST_COND)
X         goto skipgood;
X   }
X   if (disable || forward_goto) {
X      while (elast && elast != ';' && elast != '|')
X         exarg(&nextstr);
X      goto done0;
X   }
Xskipgood:
X   {
X      register char *arg, *ptr, *scr;
X      short redir;
X      short doexpand;
X      short cont;
X      short inc;
X
X      ac = 1;
X      av[0] = command;
Xstep5:                                          /* ac = nextac */
X      if (!elast || elast == ';' || elast == '|')
X         goto stepdone;
X
X      av[ac] = '\0';
X      cont = 1;
X      doexpand = redir = inc = 0;
X
X      while (cont && elast) {
X         int cstat = cmd_stat(command);
X
X         ptr = exarg(&nextstr);
X         inc = 1;
X         arg = "";
X         cont = (elast == 0x80);
X         switch (*ptr) {
X         case '<':
X            redir = -2;
X         case '>':
X            if (cstat & (ST_NORED | ST_COND)) {
X                                                        /* don't extract   */
X                redir = 0;                              /* <> stuff if its */
X                arg = ptr;                              /* external cmd.   */
X                break;
X            }
X            ++redir;
X            arg = ptr + 1;
X            if (*arg == '>') {
X               redir = 2;        /* append >> */
X               ++arg;
X            }
X            cont = 1;
X            break;
X         case '$':
X            /* restore args if from set command or pend_alias */
X            if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
X               if (cstat & ST_COND) {
X                  char *tp;
X                  tp = push_cpy(arg);
X                  arg = tp;
X               }
X               else {
X                  char *pe, sv;
X                  while (pe = index(arg,0xA0)) {
X                     sv = *pe;
X                     *pe = '\0';
X                     av[ac++] = push_cpy(arg);
X                     *pe = sv;
X                     av[ac] = '\0';
X                     arg = pe+1;
X                  }
X               }
X            }
X            else
X               arg = ptr;
X            break;
X         case '*':
X         case '?':
X            if ((cstat & ST_NOEXP) == 0)
X               doexpand = 1;
X            arg = ptr;
X            break;
X         default:
X            arg = ptr;
X            break;
X         }
X
X         /* Append arg to av[ac] */
X
X         for (scr = arg; *scr; ++scr)
X            *scr &= 0x7F;
X         if (av[ac]) {
X            register char *old = av[ac];
X            av[ac] = mpush(strlen(arg)+strlen(av[ac]));
X            strcpy(av[ac], old);
X            strcat(av[ac], arg);
X         } else {
X            av[ac] = push_cpy(arg);
X         }
X         if (elast != 0x80)
X            break;
X      }
X
X      /* process expansion */
X
X      if (doexpand) {
X         char **eav, **ebase;
X         int eac;
X         has_wild = 1;
X         eav = ebase = expand(av[ac], &eac);
X         inc = 0;
X         if (eav) {
X            if (ac + eac + 2 > MAXAV) {
X               ierror (NULL, 506);
X               err = 1;
X            } else {
X               QuickSort(eav, eac);
X               for (; eac; --eac, ++eav)
X                  av[ac++] = push_cpy(*eav);
X            }
X            free_expand (ebase);
X         }
X      }
X
X      /* process redirection  */
X
X      if (redir && !err) {
X         register char *file = (doexpand) ? av[--ac] : av[ac];
X
X         if (redir < 0)
X            Cin_name = file;
X         else {
X            Cout_name = file;
X            Cout_append = (redir == 2);
X         }
X         inc = 0;
X      }
X
X      /* check elast for space */
X
X      if (inc) {
X         ++ac;
X         if (ac + 2 > MAXAV) {
X            ierror (NULL, 506);
X            err = 1;                /* error condition */
X            elast = 0;              /* don't process any more arguemnts */
X         }
X      }
X      if (elast == ' ')
X         goto step5;
X   }
Xstepdone:
X   av[ac] = '\0';
X
X   /* process pipes via files */
X
X   if (elast == '|' && !err) {
X      static int which;             /* 0 or 1 in case of multiple pipes */
X      which = 1 - which;
X      Cout_name = (which) ? Pipe1 : Pipe2;
X      Cout_ispipe = 1;
X   }
X
X
X   if (err)
X      goto done0;
X
X   {
X      register int i;
X      char save_elast;
X      char *compile_av();
X      register char *avline;
X      unsigned char delim = ' ';
X
X      save_elast = elast;
X      if (pend_alias || (cmd_stat(command) & ST_AV))
X         delim = 0xA0;
X      avline = compile_av(av,((pend_alias) ? 1 : 0), ac , delim);
X
X
X      if (pend_alias) {                               /* special % alias */
X         register char *ptr, *scr;
X         for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
X         set_var (LEVEL_SET, pend_alias + 1, avline);
X         free (avline);
X
X         scr = malloc((strlen(ptr) << 2) + 2);
X         preformat (ptr, scr);
X         fcomm (scr, 1);
X         unset_var (LEVEL_SET, pend_alias + 1);
X      } else {                                        /* normal command  */
X         register int ccno;
X         long  oldcin  = Myprocess->pr_CIS;
X         long  oldcout = Myprocess->pr_COS;
X         char *Cin_buf;
X         struct FileHandle *ci;
X         long oldbuf;
X
X         fflush(stdout);
X         ccno = find_command (command);
X         if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
X            if (Cin_name) {
X               if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) {
X                  ierror (NULL, 504);
X                  err = 1;
X                  Cin_name = '\0';
X               } else {
X                  Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
X                  ci = (struct FileHandle *)(((long)Cin)<<2);
X                  Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
X                  oldbuf = ci->fh_Buf;
X                  if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
X                     ci->fh_Buf = (long)Cin_buf>>2;
X               }
X            }
X            if (Cout_name) {
X               if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) {
X                     Seek(Cout, 0L, 1L);
X               } else {
X                  Cout = (long)extOpen(Cout_name,1006L);
X               }
X               if (Cout == NULL) {
X                  err = 1;
X                  ierror (NULL, 504);
X                  Cout_name = '\0';
X                  Cout_append = 0;
X               } else {
X                  Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout;
X               }
X            }
X         }
X         if (ac < Command[ccno].minargs + 1) {
X            ierror (NULL, 500);
X            err = -1;
X         } else if (!err) {
X            i = (*Command[ccno].func)(avline, Command[ccno].val);
X            if (i < 0)
X               i = 20;
X            err = i;
X         }
X         free (avline);
X         if (E_stack == 0 && Lastresult != err) {
X            Lastresult = err;
X            seterr();
X         }
X         if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
X            if (Cin_name) {
X               fflush(stdin);
X               clearerr(stdin);
X               ci->fh_Buf = oldbuf;
X               extClose(Cin);
X               FreeMem(Cin_buf, 202L);
X            }
X            if (Cout_name) {
X               fflush(stdout);
X               clearerr(stdout);
X               stdout->_flags &= ~_DIRTY;    /* because of nil: device */
X               extClose(Cout);
X               Cout_append = 0;
X            }
X         }
X         Myprocess->pr_CIS =  _devtab[stdin->_unit].fd  = oldcin;
X         Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;
X      }
X
X      if (Cin_ispipe && Cin_name)
X         DeleteFile(Cin_name);
X      if (Cout_ispipe) {
X         Cin_name = Cout_name;         /* ok to assign.. static name */
X         Cin_ispipe = 1;
X      } else {
X         Cin_name = '\0';
X      }
X      Cout_name = '\0';
X      Cout_ispipe = 0;
X      elast = save_elast;
X   }
X   mpop_tobase();                      /* free arguments   */
X   mpush_base();                       /* push dummy base  */
X
Xdone0:
X   {
X      char *str;
X      if (err && E_stack == 0) {
X         str = get_var(LEVEL_SET, v_except);
X         if (err >= ((str)?atoi(str):1)) {
X            if (str) {
X               ++H_stack;
X               ++E_stack;
X               exec_command(str);
X               --E_stack;
X               --H_stack;
X            } else {
X               Exec_abortline = 1;
X            }
X         }
X      }
X      if (elast != 0 && Exec_abortline == 0)
X         err = fcomm(nextstr, 0);
X      Exec_abortline = 0;
X      if (Cin_name)
X         DeleteFile(Cin_name);
X      Cin_name = NULL;
X      Cin_ispipe = 0;
X   }
Xdone1:
X   mpop_tobase();
X   if (freeok)
X      free(str);
X   --alias_count;
X   return ((int)err);                  /* TRUE = error occured    */
X}
X
X
Xchar *
Xexarg(ptr)
Xunsigned char **ptr;
X{
X   register unsigned char *end;
X   register unsigned char *start;
X
X   start = end = *ptr;
X   while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
X      ++end;
X   elast = *end;
X   *end = '\0';
X   *ptr = end + 1;
X   return ((char *)start);
X}
X
Xstatic char **Mlist;
X
Xmpush_base()
X{
X   char *str;
X
X   str = malloc(5);
X   *(char ***)str = Mlist;
X   str[4] = 0;
X   Mlist = (char **)str;
X}
X
Xchar *
Xmpush(bytes)
X{
X   char *str;
X
X   str = malloc(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
X   *(char ***)str = Mlist;
X   str[4] = 1;
X   Mlist = (char **)str;
X   return (str + 5);
X}
X
Xmpop_tobase()
X{
X   register char *next;
X   while (Mlist) {
X      next = *Mlist;
X      if (((char *)Mlist)[4] == 0) {
X         free (Mlist);
X         Mlist = (char **)next;
X         break;
X      }
X      free (Mlist);
X      Mlist = (char **)next;
X   }
X}
X
X
X/*
X * Insert 'from' string in front of 'str' while deleting the
X * first entry in 'str'.  if freeok is set, then 'str' will be
X * free'd
X */
X
Xchar *format_insert_string(str, from, freeok)
Xchar *str;
Xchar *from;
Xint *freeok;
X{
Xregister char *new1, *new2;
Xregister unsigned char *strskip;
Xint len;
X
Xfor (strskip = (unsigned char *)str;
X		*strskip && *strskip != ' ' 
X		&& *strskip != ';' && *strskip != '|'
X		&& *strskip != 0x80; ++strskip);
Xlen = strlen(from);
Xnew1 = malloc((len << 2) + 2);
Xpreformat(from, new1);
Xlen = strlen(new1) + strlen(strskip);
Xnew2 = malloc(len+2);
Xstrcpy(new2, new1);
Xstrcat(new2, strskip);
Xnew2[len+1] = 0;
Xfree (new1);
Xif (*freeok) free (str);
X*freeok = 1;
Xreturn new2;
X}
X
Xcmd_stat(str)
Xchar *str;
X{
Xreturn(Command[find_command(str)].stat);
X}
X
Xfind_command(str)
Xchar *str;
X{
Xregister unsigned short i;
Xint len = strlen(str);
X
Xfor (i = 0; Command[i].func; ++i)
X	if ( ! strncmp(str, Command[i].name, len)) return (int)i;
Xreturn 0;
X}
X
Xdo_help()
X{
Xregister struct COMMAND *com;
Xint i=0;
X
Xfor (com = &Command[1]; com->func; ++com) {
X	printf ("%-12s", com->name);
X	if (++i % 6 == 0) printf("\n");
X	}
Xprintf("\n");
Xreturn 0;
X}
X
Xchar *push_cpy(s)
Xchar *s;
X{
Xreturn strcpy(mpush(strlen(s)), s);
X}
SHAR_EOF
echo "End of archive 1 (of 2)"
# if you want to concatenate archives, remove anything after this line
exit