[comp.sys.amiga] Shell 2.05m PART 2 of 2

drew@cgfsv2.dec.com (Steve Drew) (01/22/87)

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	comm1.c
#	comm2.c
#	execom.c
#	globals.c
#	main.c
#	rawconsole.c
#	run.c
#	set.c
#	sort.c
#	sub.c
#	shell.h
# This archive created: Thu Jan 22 09:35:07 1987
echo shar: extracting comm1.c
cat << \SHAR_EOF > comm1.c
/*
 * COMM1.C
 *
 * Matthew Dillon, August 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */

#include "shell.h"
typedef struct FileInfoBlock FIB;
 
#define DIR_SHORT 0x01
#define DIR_FILES 0x02
#define DIR_DIRS  0x04
#define DIR_EXCLUDE 0x08

#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
#define C_TO_BPTR(strtag, var)  ((struct strtag *)(((ULONG)var)>>2))

extern char *btocstr();
extern int has_wild;
char cwd[256];
struct FileLock *Clock;
  
do_sleep()
{
   register int i;
 
   if (ac == 2) {
      i = atoi(av[1]);
      while (i > 0) {
         Delay ((long)50*2);
         i -= 2;
         if (CHECKBREAK())
            break;
      }
   }
   return (0);
}
 
 
do_number()
{
   return (0);
}
 
do_cat()
{
   FILE *fopen(), *fi;
   int i;
   char buf[256];

   if (ac == 1) {
      while (gets(buf)) {
      	 if (CHECKBREAK()) break;
         puts(buf);
         }
      clearerr(stdin);
      return (0);
   }

   for (i = 1; i < ac; ++i) {
      if ((fi = fopen (av[i], "r")) != 0) {
           while (fgets(buf,256,fi)) {
            fputs(buf,stdout);
            fflush(stdout); 
            if (CHECKBREAK()) {
               breakreset();
               break;
            }
         }
         fclose (fi);
      } else {
         fprintf (stderr, "could not open %s\n", av[i]);
      }
   }
   return (0);
}

/* things shared with disp_entry */

int   filecount, col; 
long  bytes, blocks;

do_dir(garbage, com)
char *garbage;
{
   void   		disp_entry();
   struct DPTR          *dp;
   struct InfoData      *info;
   char                 *name;
   int                  i = 0, stat, clen, more;
   char                 options = 0;
   char                 *c;
   char			exclude[40];
   char                 lspec[256];
   char                 volume[40];
   char                 *volname();
   char			*dates();
  
   col = filecount = 0;
   bytes = blocks = 0L;
   
   while((++i < ac) && (av[i][0] == '-')) {
   	for (c = av[i]+1; *c ; c++) {
   		switch(*c) {
   			case 's':
   				options |= DIR_SHORT;
   				break;
   			case 'f':
   				options |= DIR_FILES;
   				break;
   			case 'd':
   				options |= DIR_DIRS;
   				break;
   			case 'e':
   				options |= DIR_EXCLUDE;
   				strcpy(exclude,"*");
   				strcat(exclude,av[++i]);
   				strcat(exclude,"*");
   				break;
   			default:
   				break;
   		}
   	}
   }
   
   if (ac == i) {
      ++ac;
      av[i] = "";
   if (has_wild)
      return(0);
   }
   if (!(options & (DIR_FILES | DIR_DIRS)))  options |= (DIR_FILES | DIR_DIRS);
   
   for (; i < ac; ++i) {
      if (!(dp = dopen (av[i], &stat)))
         continue;
      if (com < 0) {
         info = (struct InfoData *)AllocMem((long)sizeof(struct InfoData), MEMF_PUBLIC);
         if (Info (dp->lock, info)) {
            printf ("Unit:%2ld  Errs:%3ld  Used: %-4ld %3ld%% Free: %-4ld  Volume: %s\n",
                  info->id_UnitNumber,
                  info->id_NumSoftErrors,
                  info->id_NumBlocksUsed,
                  (info->id_NumBlocksUsed * 100)/ info->id_NumBlocks,
                  (info->id_NumBlocks - info->id_NumBlocksUsed),
                  volname(dp->lock,volume));

         } else {
            pError (av[i]);
         }
         FreeMem (info,(long) sizeof(*info));
         dclose(dp);
         continue;
         return(0);
      } 
 
     /* start of directory routine */
      
            c = av[i];
            clen = strlen(c);
            if (!stat || has_wild) {    /* if not wild and is a dir don't */
                                         /* extract dir from file name     */
               while (clen && c[clen] != '/' && c[clen] != ':') clen--;
               if (c[clen] == ':' || c[clen] == '/') clen++;
               c[clen] = '\0';
            }
            if (!clen)  c = cwd;
            if (strcmp (c, &lspec) != 0)  {
               strcpy(lspec, c);
               if (col)    printf("\n");
               printf ("Directory of %s\n", lspec);
               fflush(stdout);
               col = 0;
            } 
            more = stat;
            do {
            	if (more && !has_wild) {
            	    *lspec = '\0';
            	    if (!(more = dnext(dp, &name, &stat)))
            	    break;
            	}
                if (CHECKBREAK()) {
              	   i = ac;
              	   break;
                }
                disp_entry (dp->fib, options,exclude);
      } while(more && !has_wild);     
      dclose(dp); 
    }                /* end for */
   if (col)  printf("\n");    
   if (filecount > 1) {
       blocks += filecount;     /* account for dir blocks */
       printf (" %ld Blocks, %ld Bytes used in %d files\n", blocks, bytes, filecount);
   }
   return (0);
}

char *
volname(lock,buf)
struct FileLock *lock;
char *buf;
{

        struct    DeviceList    *dl;
        char                    *p;

     Forbid();
                /* Only way I know to get Volume label since InfoData  */
                /* seems to always have NULL for this string           */

        lock = BPTR_TO_C(FileLock, lock);
        dl = BPTR_TO_C(DeviceList, lock->fl_Volume);
        p = btocstr(dl->dl_Name,buf);

     Permit();
     return p;
}

void
disp_entry(fib, options, exclude)
char options;
char *exclude;
register struct FileInfoBlock *fib;
{

   char str[5];
   int italics;
   char s;   
   
   if (!(((options & DIR_FILES) && (fib->fib_DirEntryType < 0)) || 
         ((options & DIR_DIRS)  && (fib->fib_DirEntryType > 0))))
                return;

   if ((options & DIR_EXCLUDE) && (compare_ok(exclude,fib->fib_FileName)))
           return;
                
 if (!(options & DIR_SHORT)) { 
   str[4] = '\0';
   str[0] = (fib->fib_Protection & FIBF_READ) ? '-' : 'r';
   str[1] = (fib->fib_Protection & FIBF_WRITE) ? '-' : 'w';
   str[2] = (fib->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
   str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd';

   printf ("   %-24s  %s  ", fib->fib_FileName, str);
   if (fib->fib_DirEntryType < 0) printf("%6ld %4ld", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
    else printf("   Dir     ");
   printf("  %s", dates(&fib->fib_Date));
   fflush(stdout);
   } 
   else {
   
        if ((col == 3) && strlen(fib->fib_FileName)>18) {
            printf("\n");
            col = 0;
        } 
        if (fib->fib_DirEntryType > 0)  {
            printf ("\033[3m");
            italics = 1;
        }
        if (strlen(fib->fib_FileName)>18) {
            printf(" %-37s",fib->fib_FileName);
            col += 2;
        } 
        else { 
            printf(" %-18s",fib->fib_FileName);
            col++;
        } 
        if (col > 3) {
            printf("\n");
            col = 0;
        }
        if (italics) printf("\033[0m");
   }
   fflush(stdout);
   blocks += fib->fib_NumBlocks;
   bytes  += fib->fib_Size;
   filecount++;
   return;
}

/* converts dos date stamp to a time string of form dd-mmm-yy  */

char *
dates(dss)
struct DateStamp *dss;
{
   register struct tm tm;
   register long time, t;
   register int i;
   static char timestr[20];
   static char months[12][4] = {
   	"Jan","Feb","Mar","Apr","May","Jun",
   	"Jul","Aug","Sep","Oct","Nov","Dec"
   };
   static char days[12] = {
   	31,28,31,30,31,30,31,31,30,31,30,31
   };
   time = dss->ds_Days * 24 * 60 * 60 + dss->ds_Minute * 60 +
   				       dss->ds_Tick/TICKS_PER_SECOND;
   tm.tm_sec = time % 60; time /= 60;
   tm.tm_min = time % 60; time /= 60;
   tm.tm_hour= time % 24; time /= 24;
   tm.tm_wday= time %  7;
   tm.tm_year= 78 + (time/(4*365+1)) * 4; time %= 4 * 365 + 1;
   while (time) {
   	t = 365;
   	if ((tm.tm_year&3) == 0) t++;
   	if (time < t) break;
   	time -= t;
   	tm.tm_year++;
   }
   tm.tm_yday = ++time;
   for (i=0;i<12;i++) {
   	t = days[i];
   	if (i == 1 && (tm.tm_year&3) == 0) t++;
   	if (time <= t) break;
   	time -= t;
   }  
   tm.tm_mon = i;
   tm.tm_mday = time;
   
   sprintf(timestr,"%02d-%s-%2d %02d:%02d:%02d\n",tm.tm_mday,
   		months[tm.tm_mon],tm.tm_year,
   		tm.tm_hour,tm.tm_min,tm.tm_sec);
   return(timestr);
   
}
 
date()
{
   struct   DateStamp   dss;
   char *s, *dates();

   DateStamp(&dss);
   s = dates(&dss);
   printf("%s",s);
   return(0);
}
 
do_quit()
{
   if (Src_stack) {
      Quit = 1;
      return(do_return());
   }
   main_exit (0);
}
 
 
do_echo(str)
char *str;
{
   register char *ptr;
   char nl = 1;
 
   for (ptr = str; *ptr && *ptr != ' '; ++ptr);
   if (*ptr == ' ')
      ++ptr;
   if (av[1] && strcmp (av[1], "-n") == 0) {
      nl = 0;
      ptr += 2;
      if (*ptr == ' ')
         ++ptr;
   }
   printf("%s",ptr);
   fflush(stdout);
   if (nl)
      printf("\n");
   return (0);
}

do_source(str)
char *str;
{
   register FILE *fi;
   char buf[256];

   if (Src_stack == MAXSRC) {
      printf (stderr,"Too many source levels\n");
      return(-1);
   }
   if ((fi = fopen (av[1], "r")) == 0) {
      fprintf (stderr,"Cannot open %s\n", av[1]);
      return(-1);
   }   
   set_var(LEVEL_SET, V_PASSED, next_word(next_word(str)));
   ++H_stack;
   Src_pos[Src_stack] = 0;
   Src_base[Src_stack] = (long)fi;
   ++Src_stack;
   while (fgets (buf, 256, fi)) {
      buf[strlen(buf)-1] = '\0';
      Src_pos[Src_stack - 1] += 1+strlen(buf);
      if (Verbose)
         fprintf(stderr,"%s\n",buf);
      exec_command (buf);
      if (CHECKBREAK())
         break;
   }
   --H_stack;
   --Src_stack;
   unset_level(LEVEL_LABEL + Src_stack);
   unset_var(LEVEL_SET, V_PASSED);
   fclose (fi);
   return (0);
}

/*
 * CD
 *
 * CD(str, -1)      -do pwd and display current cd. if str = NULL don't disp.
 * CD(str, 0)       -do CD operation.
 *
 *    standard operation: breakup path by '/'s and process independantly
 *    x:    -reset cwd base
 *    ..    -remove last cwd element
 *    N     -add N or /N to cwd
 */

do_cd(str, com)
char *str;
{
   char sc, *ptr;
   char *name;

   if (com < 0) {
      struct FileLock *lock, *newlock;
      FIB *fib;
      int i, len;

      fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
      if ((Clock = (struct FileLock *)Myprocess->pr_CurrentDir) == 0) 
          attempt_cd(":"); /* if we just booted 0 = root lock */
      lock = (struct FileLock *)DupLock(Clock);
      cwd[i = 255] = '\0';
      
      while (lock) {
         newlock = (struct FileLock *)ParentDir(lock);
         Examine(lock, fib);
         name = fib->fib_FileName;
         if (*name == '\0')            /* HACK TO FIX RAM: DISK BUG */
            name = "ram";
         len = strlen(name);
         if (newlock) {
            if (i == 255) {
               i -= len;
               bmov(name, cwd + i, len);
            } else {
               i -= len + 1;
               bmov(name, cwd + i, len);
               cwd[i+len] = '/';
            }
         } else {
            i -= len + 1;
            bmov(name, cwd + i, len);
            cwd[i+len] = ':';
         }
         UnLock(lock);
         lock = newlock;
      }
      FreeMem(fib, (long)sizeof(FIB));
      bmov(cwd + i, cwd, 256 - i);
      if (str)
         puts(cwd);
      set_var(LEVEL_SET, V_CWD, cwd);
 
     /* put the current dir name in our CLI task structure */

      ptr = (char *)((ULONG)((struct CommandLineInterface *)
          BADDR(Myprocess->pr_CLI))->cli_SetName << 2);
      ptr[0] = strlen(cwd);
      movmem(cwd,ptr+1,(int)ptr[0]);
      return (0);
   }
   str = next_word(str);
   if (*str == '\0')
      puts(cwd);
   str[strlen(str)+1] = '\0';          /* add second \0 on end */
   while (*str) {
      for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr);
      switch (*ptr) {
      case ':':
         sc = ptr[1];
         ptr[1] = '\0';
         if (attempt_cd(str))
            strcpy(cwd, str);
         ptr[1] = sc;
         break;
      case '\0':
      case '/':
         *ptr = '\0';
         if (strcmp(str, "..") == 0 || str == ptr)
            str = "/";
         if (*str && attempt_cd(str)) {
            if (*str == '/') {
               rmlast(cwd);
            } else {
               if (cwd[0] == 0 || cwd[strlen(cwd)-1] != ':')
                  strcat(cwd, "/");
               strcat(cwd, str);
            }
         }
         break;
      }
      str = ptr + 1;
   }
   do_cd(NULL,-1);
}

attempt_cd(str)
char *str;
{
   struct FileLock *oldlock, *filelock;

   if (filelock = (struct FileLock *)Lock(str, ACCESS_READ)) {
      if (isdir(str)) {
         if (oldlock = (struct FileLock *)CurrentDir(filelock))
            UnLock(oldlock);
         Clock = filelock;
         return (1);
      }
      UnLock(filelock);
      ierror(str, 212);
   } else {
      ierror(str, 205);
   }
   return (0);
}


/*
 * remove last component. Start at end and work backwards until reach
 * a '/'
 */

rmlast(str)
char *str;
{
   char *ptr = str + strlen(str) - 1;
   while (ptr != str && *ptr != '/' && *ptr != ':')
      --ptr;
   if (*ptr != ':')
      ptr[0] = '\0';
   else
      ptr[1] = '\0';
}


do_mkdir()
{
   register int i;
   register struct FileLock *lock;

   for (i = 1; i < ac; ++i) {
      if (lock = (struct FileLock *)CreateDir (av[i])) {
         UnLock (lock);
         continue;
      }
      pError (av[i]);
   }
   return (0);
}


do_mv()
{
   char dest[256];
   register int i;
   char *str;

   --ac;
   if (isdir(av[ac])) {
      for (i = 1; i < ac; ++i) {
         str = av[i] + strlen(av[i]) - 1;
         while (str != av[i] && *str != '/' && *str != ':')
            --str;
         if (str != av[i])
            ++str;
         if (*str == 0) {
            ierror(av[i], 508);
            return (-1);
         }
         strcpy(dest, av[ac]);
         if (dest[strlen(dest)-1] != ':')
            strcat(dest, "/");
         strcat(dest, str);
         if (Rename(av[i], dest) == 0)
            break;
      }
      if (i == ac)
         return (1);
   } else {
      i = 1;
      if (ac != 2) {
         ierror("", 507);
         return (-1);
      }
      if (Rename (av[1], av[2]))
         return (0);
   }
   pError (av[i]);
   return (-1);
}

rm_file(file)
char *file;
{
      if (has_wild) printf("  %s...",file);
      fflush(stdout);
      if (!DeleteFile(file))
         pError (file);
      else 
         if (has_wild) printf("Deleted\n");
}

do_rm()
{
   register short i, recur;
 
   recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;
 
   for (i = 1 + recur; i < ac; ++i) {
      if (CHECKBREAK()) break;
      if (isdir(av[i]) && recur)
         rmdir(av[i]);
      if (!(recur && av[i][strlen(av[i])-1] == ':')) 
         rm_file(av[i]);
   }
   return (0);
}
 
rmdir(name)
char *name;
{
   register struct FileLock *lock, *cwd;
   register FIB *fib;
   register char *buf;
 
   buf = (char *)AllocMem(256L, MEMF_PUBLIC);
   fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
 
   if (lock = (struct FileLock *)Lock(name, ACCESS_READ)) {
      cwd = (struct FileLock *) CurrentDir(lock);
      if (Examine(lock, fib)) {
         buf[0] = 0;
         while (ExNext(lock, fib)) {
            if (CHECKBREAK()) break;
            if (isdir(fib->fib_FileName))
               rmdir(fib->fib_FileName);
            if (buf[0]) {
               rm_file(buf);
            }
            strcpy(buf, fib->fib_FileName);
         }
         if (buf[0] && !CHECKBREAK()) {
            rm_file(buf);
         }
      }
      UnLock(CurrentDir(cwd));
   } else {
      pError(name);
   }
   FreeMem(fib, (long)sizeof(FIB));
   FreeMem(buf, 256L);
}
 
 
 
do_history()
{
   register struct HIST *hist;
   register int i = H_tail_base;
   register int len = (av[1]) ? strlen(av[1]) : 0;
 
   for (hist = H_tail; hist; hist = hist->prev) {
      if (len == 0 || strncmp(av[1], hist->line, len) == 0) {
         printf ("%3d ", i);
         puts (hist->line);
      }
      ++i;
      if (CHECKBREAK())
         break;
   }
   return (0);
}
 
do_mem()
{
   long cfree, ffree;
   extern long AvailMem();

   Forbid();
   cfree = AvailMem (MEMF_CHIP);
   ffree = AvailMem (MEMF_FAST);
   Permit();

   if (ffree)       {
   printf ("FAST memory: %ld\n", ffree);  
   printf ("CHIP memory: %ld\n", cfree);   
   }
   printf ("Total  Free: %ld\n", cfree + ffree);
   return(0);
}

/*
 * foreach var_name  ( str str str str... str ) commands
 * spacing is important (unfortunetly)
 *
 * ac=0    1 2 3 4 5 6 7
 * foreach i ( a b c ) echo $i
 * foreach i ( *.c )   "echo -n "file ->";echo $i"
 */
 
do_foreach()
{
   register int i, cstart, cend, old;
   register char *cstr, *vname, *ptr, *scr, *args;
 
   cstart = i = (*av[2] == '(') ? 3 : 2;
   while (i < ac) {
      if (*av[i] == ')')
         break;
      ++i;
   }
   if (i == ac) {
      fprintf (stderr,"')' expected\n");
      return (-1);
   }
   ++H_stack;
   cend = i;
   vname = strcpy(malloc(strlen(av[1])+1), av[1]);
   cstr = compile_av (av, cend + 1, ac);
   ptr = args = compile_av (av, cstart, cend);
   while (*ptr) {
      while (*ptr == ' ' || *ptr == 9)
         ++ptr;
      scr = ptr;
      if (*scr == '\0')
         break;
      while (*ptr && *ptr != ' ' && *ptr != 9)
         ++ptr;
      old = *ptr;
      *ptr = '\0';
      set_var (LEVEL_SET, vname, scr);
      if (CHECKBREAK())
         break;
      exec_command (cstr);
      *ptr = old;
   }
   --H_stack;
   free (args);
   free (cstr);
   unset_var (LEVEL_SET, vname);
   free (vname);
   return (0);
}
 

do_forever(str)
char *str;
{
   int rcode = 0;
   char *ptr = next_word(str);

   ++H_stack;
   for (;;) {
      if (CHECKBREAK()) {
         rcode = 20;
         break;
      }
      if (exec_command (ptr) < 0) {
         str = get_var(LEVEL_SET, V_LASTERR);
         rcode = (str) ? atoi(str) : 20;
         break;
      }
   }
   --H_stack;
   return (rcode);
}


/*
 * CP file file
 * CP file file file... destdir
 * CP [-r] dir dir dir... destdir
 */

char *errstr;          /* let's be alittle more informative */
 
do_copy()
{
   register short recur, i, ierr;
   register char *destname;
   register char destisdir;
   register FIB *fib;
   
   errstr = "";
   ierr = 0;
   fib = (FIB *)AllocMem((long)sizeof(FIB), 0);
   recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;
   destname = av[ac - 1];
 
   if (ac < recur + 3) {
      ierr = 500;
      goto done;
   }
 
   destisdir = isdir(destname);
   if (ac > recur + 3 && !destisdir) {
      ierr = 507;
      goto done;
   }
 
   /*
    * copy set:                        reduce to:
    *    file to file                     file to file
    *    dir  to file (NOT ALLOWED)
    *    file to dir                      dir to dir
    *    dir  to dir                      dir to dir
    *
    */
 
   fflush(stdout);
   stdout->_buflen = 1;
   for (i = recur + 1; i < ac - 1; ++i) {
      short srcisdir = isdir(av[i]);
      if (srcisdir && has_wild && (ac >2)) /* hack to stop dir's from */
          continue;			   /* getting copied if specified */
          			           /* from wild expansion */
      if (CHECKBREAK())
         break;
      if (srcisdir) {
         struct FileLock *srcdir, *destdir;
         if (!destisdir) {        /* disallow dir to file */
            ierr = 507;
            goto done;
         }
         if (!(destdir = (struct FileLock *)Lock(destname, ACCESS_READ))) {
            ierr = 205;
            errstr = destname;
            goto done;
         }
         if (!(srcdir = (struct FileLock *)Lock(av[i], ACCESS_READ))) {
            ierr = 205;
            errstr = av[i];
            UnLock(destdir);
            goto done;
         }
         ierr = copydir(srcdir, destdir, recur);
         UnLock(srcdir);
         UnLock(destdir);
         if (ierr)
            break;
      } else {                      /* FILE to DIR,   FILE to FILE   */
         struct FileLock *destdir, *srcdir, *tmp;
         char *destfilename;

         srcdir = (struct FileLock *)((struct Process *)FindTask(0))->pr_CurrentDir;
         if (destisdir) {
            if ((tmp = (struct FileLock *)Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)){
               if (tmp) UnLock(tmp);
               ierr = 205;
               errstr = av[i];
               goto done;
            }
            UnLock(tmp);
            destdir = (struct FileLock *)Lock(destname, ACCESS_READ);
            destfilename = fib->fib_FileName;
         } else {
            destdir = srcdir;
            destfilename = destname;
         }
         printf(" %s..",av[i]);
         ierr = copyfile(av[i], srcdir, destfilename, destdir);
         if (destisdir)
            UnLock(destdir);
         if (ierr)
            break;
      }
   }
done:
   stdout->_buflen = STDBUF;            /* set back to buffr'd */
   FreeMem(fib, (long)sizeof(*fib));
   if (ierr) {
      ierror(errstr, ierr);
      return(20);
   }
   return(0);
}
 
 
copydir(srcdir, destdir, recur)
register struct FileLock *srcdir, *destdir;
{
   struct FileLock *cwd;
   register FIB *srcfib;
   register struct FileLock *destlock, *srclock;
   int ierr;
   static int level; 

   level++;
   ierr = 0;
   srcfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
   if (Examine(srcdir, srcfib)) {
      while (ExNext(srcdir, srcfib)) {
         if (CHECKBREAK())
	    break;
         if (srcfib->fib_DirEntryType < 0) {
	    printf("%*s%s..",(level-1) * 6," ",srcfib->fib_FileName);
            ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir);
            if (ierr)
               break;
         } else {
            if (recur) {
               cwd = (struct FileLock *)CurrentDir(srcdir);
               if (srclock = (struct FileLock *)Lock(srcfib->fib_FileName, ACCESS_READ)) {
                  CurrentDir(destdir);
                  if (!(destlock = (struct FileLock *)
				Lock(srcfib->fib_FileName))) {
                     destlock = (struct FileLock *)CreateDir(srcfib->fib_FileName);
  		     printf("%*s%s (Dir)....[Created]\n",(level-1) * 6,
  				" ",srcfib->fib_FileName); 
		  }
  		  else 
		     printf("%*s%s (Dir)\n",(level-1) * 6," ",srcfib->fib_FileName); 
                  if (destlock) {
                     ierr = copydir(srclock, destlock, recur);
                     UnLock(destlock);
                  } else {
                     ierr = (int)((long)IoErr());
                  }
                  UnLock(srclock);
               } else {
                  ierr = (int)((long)IoErr());
               }
               CurrentDir(cwd);
               if (ierr)
                  break;
            }
         }
      }
   } else {
      ierr = (int)((long)IoErr());
   }      
   --level;
   FreeMem(srcfib, (long)sizeof(FIB));
   return(ierr);
}
 
 
copyfile(srcname, srcdir, destname, destdir)
char *srcname, *destname;
struct FileLock *srcdir, *destdir;
{
   struct FileLock *cwd;
   struct FileHandle *f1, *f2;
   long i; 
   int ierr;
   char *buf;
 
   buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR);   
   if (buf == NULL) {
      ierr = 103;
      goto fail;
   }

   ierr = 0;
   cwd = (struct FileLock *)CurrentDir(srcdir);
   f1 = Open(srcname, MODE_OLDFILE);
   if (f1 == NULL) {
      errstr = srcname;
      ierr = 205;
      goto fail;
   }
   CurrentDir(destdir);
   f2 = Open(destname, MODE_NEWFILE);
   if (f2 == NULL) {
      Close(f1);
      ierr = (int)((long)IoErr());
      errstr = destname;
      goto fail;
   }
   while (i = Read(f1, buf, 8192L))
      if (Write(f2, buf, i) != i) {
         ierr = (int)((long)IoErr());
	 break;
      }
   Close(f2);
   Close(f1);
   if (!ierr)  {
      printf("..copied\n"); 
   }
   else {
      DeleteFile(destname);
      printf("..Not copied..");
   }
fail:
   if (buf) 
      FreeMem(buf, 8192L);
   CurrentDir(cwd);
   return(ierr);
}
SHAR_EOF
if test 23638 -ne "`wc -c comm1.c`"
then
echo shar: error transmitting comm1.c '(should have been 23638 characters)'
fi
echo shar: extracting comm2.c
cat << \SHAR_EOF > comm2.c

/*
 * COMM2.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */

#include "shell.h"

#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))

#define TO_ASC(n)       ((n) + '0')             /* make it printable! */

/* Casting conveniences */
#define PROC(task)              ((struct Process *)task)
#define ROOTNODE                ((struct RootNode *)DOSBase->dl_Root)
#define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))

/* Externs */
extern struct DosLibrary *DOSBase;      /* dos library base pointer */

do_abortline()
{
   Exec_abortline = 1;
   return (0);
}

do_return()
{
   Exec_abortline = 1;
   if (Src_stack) {
      fseek (Src_base[Src_stack - 1], 0, 2); 
      return ((ac < 2) ? 0 : atoi(av[1]));
   } else {
      main_exit ((ac < 2) ? 0 : atoi(av[1]));
   }
}

/*
 * STRHEAD
 *
 * place a string into a variable removing everything after and including
 * the 'break' character or until a space is found in the string.
 *
 * strhead varname breakchar string
 *
 */

do_strhead()
{
   register char *str = av[3];
   char bc = *av[2];

   while (*str && *str != bc)
      ++str;
   *str = '\0';
   set_var (LEVEL_SET, av[1], av[3]);
   return (0);
}

do_strtail()
{
   register char *str = av[3];
   char bc = *av[2];

   while (*str && *str != bc)
      ++str;
   if (*str)
      ++str;
   set_var (LEVEL_SET, av[1], str);
   return (0);
}



/*
 * if A < B   <, >, =, <=, >=, !=, where A and B are either:
 * nothing
 * a string
 * a value (begins w/ number)
 */

do_if(garbage, com)
char *garbage;
{
   char *v1, *v2, *v3, result, num;
   int n1, n2;

   switch (com) {
   case 0:
      if (If_stack && If_base[If_stack - 1]) {
         If_base[If_stack++] = 1;
         break;
      }
      result = num = 0;
      if (ac <= 2) {       /* if $var; */
         if (ac == 1 || strlen(av[1]) == 0 || (strlen(av[1]) == 1 && *av[1] == ' '))
            goto do_result;
         result = 1;
         goto do_result;
      }
      if (ac != 4) {
         ierror(NULL, 500);
         break;
      }
      v1 = av[1]; v2 = av[2]; v3 = av[3];
      while (*v1 == ' ')
         ++v1;
      while (*v2 == ' ')
         ++v2;
      while (*v3 == ' ')
         ++v3;
      if (*v1 >= '0' && *v1 <= '9') {
         num = 1;
         n1 = atoi(v1);
         n2 = atoi(v3);
      }
      while (*v2) {
         switch (*v2++) {
         case '>':
            result |= (num) ? (n1 >  n2) : (strcmp(v1, v3) > 0);
            break;
         case '<':
            result |= (num) ? (n1 <  n2) : (strcmp(v1, v3) < 0);
            break;
         case '=':
            result |= (num) ? (n1 == n2) : (strcmp(v1, v3) ==0);
            break;
         default:
            ierror (NULL, 503);
            break;
         }
      }
do_result:
      If_base[If_stack++] = !result;
      break;
   case 1:
      if (If_stack > 1 && If_base[If_stack - 2])
         break;
      if (If_stack)
         If_base[If_stack - 1] ^= 1;
      break;
   case 2:
      if (If_stack)
         --If_stack;
      break;
   }
   disable = (If_stack) ? If_base[If_stack - 1] : 0;
   return (0);
}

do_label()
{
   char aseek[32];

   if (Src_stack == 0) {
      ierror (NULL, 502);
      return (-1);
   }
   sprintf (aseek, "%ld %d", Src_pos[Src_stack-1], If_stack);
   set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
   return (0);
}

do_goto()
{
   int new;
   long pos;
   char *lab;

   if (Src_stack == 0) {
      ierror (NULL, 502);
   } else {
      lab = get_var (LEVEL_LABEL + Src_stack - 1, av[1]);
      if (lab == NULL) {
         ierror (NULL, 501);
      } else {
         pos = atoi(lab);
         fseek (Src_base[Src_stack - 1], pos, 0);
         Src_pos[Src_stack - 1] = pos;
         new = atoi(next_word(lab));
         for (; If_stack < new; ++If_stack)
            If_base[If_stack] = 0;
         If_stack = new;
      }
   }
   Exec_abortline = 1;
   return (0);      /* Don't execute rest of this line */
}


do_inc(garbage, com)
char *garbage;
{
   char *var;
   char num[32];

   if (ac == 3)
      com = atoi(av[2]);
   var = get_var (LEVEL_SET, av[1]);
   if (var) {
      sprintf (num, "%d", atoi(var)+com);
      set_var (LEVEL_SET, av[1], num);
   }
   return (0);
}

do_input()
{
   char in[256];

   if ((gets(in)) != 0)
      set_var (LEVEL_SET, av[1], in);
   return (0);
}

do_ver()
{
   puts (VERSION);
   return (0);
}


do_ps()
{
	/* this code fragment based on ps.c command by Dewi Williams */

        register ULONG   *tt;           /* References TaskArray         */
        register int     count;         /* loop variable                */
        register UBYTE   *port;         /* msgport & ptr arith          */
        register struct Task *task;     /* EXEC descriptor              */
        char             strbuf[64];   /* scratch for btocstr()        */
        char             *btocstr();    /* BCPL BSTR to ASCIIZ          */

        tt = (unsigned long *)(BADDR(ROOTNODE->rn_TaskArray));

        printf("Proc Command Name         CLI Type    Pri.  Address  Directory\n");
        Forbid();               /* need linked list consistency */
        
        for (count = 1; count <= (int)tt[0] ; count++) {/* or just assume 20?*/
                if (tt[count] == 0) continue;           /* nobody home */

                /* Start by pulling out MsgPort addresses from the TaskArray
                 * area. By making unwarranted assumptions about the layout
                 * of Process and Task structures, we can derive these
                 * descriptors. Every task has an associated process, since
                 * this loop drives off a CLI data area.
                 */

                port = (UBYTE *)tt[count];
                task = (struct Task *)(port - sizeof(struct Task));

                /* Sanity check just in case */
                if (PROC(task)->pr_TaskNum == 0 || PROC(task)->pr_CLI == 0)
                        continue;               /* or complain? */

                        btocstr(CLI(PROC(task))->cli_CommandName, strbuf);
			printf("%2d   %-21s",count,strbuf);
			strcpy(strbuf,task->tc_Node.ln_Name);
                        strbuf[11] = '\0';
                        printf("%-11s",strbuf);
                        printf(" %3d  %8lx  %s\n",
                           task->tc_Node.ln_Pri,task,
                           btocstr(CLI(PROC(task))->cli_SetName, strbuf));
        }
        Permit();               /* outside critical region */
        return(0);
}


char *
btocstr(b, buf)
ULONG   b;
char    *buf;
{
        register char   *s;

        s = (char *)BADDR(b);   /* Shift & get length-prefixed str */
        bmov(s +1, buf, s[0]);
        buf[s[0]] = '\0';
        return buf;
}


SHAR_EOF
if test 6803 -ne "`wc -c comm2.c`"
then
echo shar: error transmitting comm2.c '(should have been 6803 characters)'
fi
echo shar: extracting execom.c
cat << \SHAR_EOF > execom.c
/*
 * EXECOM.C
 *
 * Matthew Dillon, 10 August 1986
 *    Finally re-written.
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 *
 */
 
#include "shell.h"
 
#define F_EXACT 0
#define F_ABBR  1
 
#define ST_COND   0x03
#define ST_NAME   0x02
 
int has_wild = 0;                 /* set if any arg has wild card */

struct _dev	 {
		long  fd;
		short mode;
	};
 
struct COMMAND {
   int (*func)();
   short minargs;
   short stat;
   int   val;
   char *name;
};
 
extern char *format_insert_string();
extern char *mpush(), *exarg();
 
extern int do_run(), do_number();
extern int do_quit(), do_set_var(), do_unset_var();
extern int do_echo(), do_source(), do_mv();
extern int do_cd(), do_rm(), do_mkdir(), do_history();
extern int do_mem(), do_cat(), do_dir(), do_inc();
extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
extern int do_input(), do_ver(), do_sleep(), do_help();
extern int do_strhead(), do_strtail();
extern int do_copy(), date(),  do_ps();
extern int do_forever(), do_abortline();
 
static struct COMMAND Command[] = {
   do_run      , 0,  0,		 0 ,   "\001",
   do_number   , 0,  0,          0 ,   "\001",
   do_set_var  , 0,  0, LEVEL_ALIAS,   "alias",
   do_abortline, 0,  0,          0,    "abortline",   
   do_cd       , 0,  0,          0 ,   "cd",
   do_cat      , 0,  0,          0 ,   "cat",
   do_copy     , 1,  0,          0 ,   "copy",
   date        , 0,  0,          0 ,   "date",
   do_dir      , 0,  0,          0 ,   "dir",
   do_inc      , 1,  0,         -1 ,   "dec",
   do_dir      , 0,  0,         -1 ,   "devinfo",
   do_echo     , 0,  0,          0 ,   "echo",
   do_if       , 0,  ST_COND,    1 ,   "else",
   do_if       , 0,  ST_COND,    2 ,   "endif",
   do_foreach  , 3,  0,          0 ,   "foreach",
   do_forever  , 1,  0,          0 ,   "forever",   
   do_goto     , 1,  0,          0 ,   "goto",
   do_help     , 0,  0,          0 ,   "help",
   do_history  , 0,  0,          0 ,   "history",
   do_if       , 1,  ST_COND,    0 ,   "if",
   do_inc      , 1,  0,          1 ,   "inc",
   do_input    , 1,  0,          0 ,   "input",
   do_label    , 1,  ST_COND,    0 ,   "label",
   do_mem      , 0,  0,          0 ,   "mem",
   do_mkdir    , 0,  0,          0 ,   "mkdir",
   do_mv       , 2,  0,          0 ,   "mv",   
   do_ps       , 0,  0,          0,    "ps",
   do_cd       , 0,  0,         -1 ,   "pwd",
   do_quit     , 0,  0,          0 ,   "quit",
   do_return   , 0,  0,          0 ,   "return",
   do_rm       , 0,  0,          0 ,   "rm",
   do_run      , 1,  ST_NAME,    0 ,   "run",
   do_set_var  , 0,  0, LEVEL_SET  ,   "set",
   do_sleep    , 0,  0,          0,    "sleep",
   do_source   , 0,  0,          0 ,   "source",
   do_strhead  , 3,  0,          0 ,   "strhead",
   do_strtail  , 3,  0,          0 ,   "strtail",
   do_unset_var, 0,  0, LEVEL_ALIAS,   "unalias",
   do_unset_var, 0,  0, LEVEL_SET  ,   "unset",
   do_ver      , 0,  0,          0 ,   "version",
   '\0'        , 0,  0,          0 ,   NULL
};

  
static unsigned char elast;          /* last end delimeter */
static char Cin_ispipe, Cout_ispipe;
 
exec_command(base)
char *base;
{
   register char *scr;
   register int i;
   char buf[32];
 
   if (!H_stack) {
      add_history(base);
      sprintf(buf, "%d", H_tail_base + H_len);
      set_var(LEVEL_SET, V_HISTNUM, buf);
   }
   scr = malloc((strlen(base) << 2) + 2);    /* 4X */
   preformat(base, scr);
   i = fcomm(scr, 1);
   return ((i) ? -1 : 1);
}
 
isalphanum(c)
char c;
{
   if (c >= '0' && c <= '9')
      return (1);
   if (c >= 'a' && c <= 'z')
      return (1);
   if (c >= 'A' && c <= 'Z')
      return (1);
   if (c == '_')
      return (1);
   return (0);
}
 
preformat(s, d)
register char *s, *d;
{
   register int si, di, qm;
 
   si = di = qm = 0;
   while (s[si] == ' ' || s[si] == 9)
      ++si;
   while (s[si]) {
      if (qm && s[si] != '\"' && s[si] != '\\') {
         d[di++] = s[si++] | 0x80;
         continue;
      }
      switch (s[si]) {
      case ' ':
      case 9:
         d[di++] = ' ';
         while (s[si] == ' ' || s[si] == 9)
            ++si;
         if (s[si] == 0 || s[si] == '|' || s[si] == ';')
            --di;
         break;
      case '*':
      case '?':
         d[di++] = 0x80;
      case '!':
         d[di++] = s[si++];
         break;
      case '#':
         d[di++] = '\0';
         while (s[si])
            ++si;
         break;
      case ';':
      case '|':
         d[di++] = s[si++];
         while (s[si] == ' ' || s[si] == 9)
            ++si;
         break;
      case '\\':
         d[di++] = s[++si] | 0x80;
         if (s[si]) ++si;
         break;
      case '\"':
         qm = 1 - qm;
         ++si;
         break;
      case '^':
         d[di++] = s[++si] & 0x1F;
         if (s[si]) ++si;
         break;
      case '$':         /* search end of var name and place false space */
         d[di++] = 0x80;
         d[di++] = s[si++];
         while (isalphanum(s[si]))
            d[di++] = s[si++];
         d[di++] = 0x80;
         break;
      default:
         d[di++] = s[si++];
         break;
      }
   }
   d[di++] = 0;
   d[di]   = 0;
   if (debug & 0x01) {
      fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
   }
}
 
/*
 * process formatted string.  ' ' is the delimeter.
 *
 *    0: check '\0': no more, stop, done.
 *    1: check $.     if so, extract, format, insert
 *    2: check alias. if so, extract, format, insert. goto 1
 *    3: check history or substitution, extract, format, insert. goto 1
 *
 *    4: assume first element now internal or disk based command.
 *
 *    5: extract each ' ' or 0x80 delimited argument and process, placing
 *       in av[] list (except 0x80 args appended).  check in order:
 *
 *             '$'         insert string straight
 *             '>'         setup stdout
 *             '>>'        setup stdout flag for append
 *             '<'         setup stdin
 *             '*' or '?'  do directory search and insert as separate args.
 *
 *             ';' 0 '|'   end of command.  if '|' setup stdout
 *                          -execute command, fix stdin and out (|) sets
 *                           up stdin for next guy.
 */
 
 
fcomm(str, freeok)
register char *str;
{
   static int alias_count;
   int p_alias_count = 0;
   char *istr;
   char *nextstr;
   char *command;
   char *pend_alias = NULL;
   char err = 0;
   has_wild = 0;
   ++alias_count;
   
   mpush_base();
   if (*str == 0)
      goto done1;
step1:
   if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
      fprintf(stderr,"Alias Loop\n");
      err = 20;
      goto done1;
   }
   if (*str == '$') {
      if (istr = get_var (LEVEL_SET, str + 1))
         str = format_insert_string(str, istr, &freeok);
   }
   istr = NULL;
   if (*(unsigned char *)str < 0x80)
      istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
   *str &= 0x7F;                          /* remove \ teltail     */
   if (istr) {
      if (*istr == '%') {
         pend_alias = istr;
      } else {
         str = format_insert_string(str, istr, &freeok);
         goto step1;
      }
   }
   if (*str == '!') {
      char *p, c;		      /* fix to allow !cmd1;!cmd2 */
      for(p = str; *p && *p != ';' ; ++p);
      c = *p;
      *p = '\0';      
      istr = get_history(str);
      *p = c;
      replace_head(istr);		
      str = format_insert_string(str, istr, &freeok);
      goto step1;
   }
   nextstr = str;
   command = exarg(&nextstr);
   if (*command == 0)
      goto done0;
   if (pend_alias == 0) {
      register int ccno;
      ccno = find_command(command);
      if (Command[ccno].stat & ST_COND)
         goto skipgood;
   }
   if (disable) {
      while (elast && elast != ';' && elast != '|')
         exarg(&nextstr);
      goto done0;
   }
skipgood:
   {
      register char *arg, *ptr, *scr;
      short redir;
      short doexpand;
      short cont;
      short inc;
 
      ac = 1;
      av[0] = command;
step5:                                          /* ac = nextac */
      if (!elast || elast == ';' || elast == '|')
         goto stepdone;
 
      av[ac] = '\0';
      cont = 1;
      doexpand = redir = inc = 0;
 
      while (cont && elast) {
         ptr = exarg(&nextstr);
         inc = 1;
         arg = "";
         cont = (elast == 0x80);
         switch (*ptr) {
         case '<':
            redir = -2;
         case '>':
            if ((Command[find_command(command)].stat & ST_NAME) != 0) { 
            						/* don't extract   */
            	redir = 0;				/* <> stuff if its */
            	arg = ptr;				/* external cmd.   */
            	break;	
            }
            ++redir;
            arg = ptr + 1;
            if (*arg == '>') {
               redir = 2;        /* append >> (not impl yet) */
               ++arg;
            }            
            cont = 1;
            break;
         case '$':
            if ((arg = get_var(LEVEL_SET, ptr + 1)) == NULL)
               arg = ptr;
            break;
         case '*':
         case '?':
            doexpand = 1;
            arg = ptr;
            break;
         default:
            arg = ptr;
            break;
         }
 
         /* Append arg to av[ac] */
 
         for (scr = arg; *scr; ++scr)
            *scr &= 0x7F;
         if (av[ac]) {
            register char *old = av[ac];
            av[ac] = mpush(strlen(arg)+1+strlen(av[ac]));
            strcpy(av[ac], old);
            strcat(av[ac], arg);
         } else {
            av[ac] = mpush(strlen(arg)+1);
            strcpy(av[ac], arg);
         }
         if (elast != 0x80)
            break;
      }
 
      /* process expansion */
 
      if (doexpand) {
         char **eav, **ebase;
         int eac;
 	 has_wild = 1;
         eav = ebase = expand(av[ac], &eac);
         inc = 0;
         if (eav) {
            if (ac + eac + 2 > MAXAV) {
               ierror (NULL, 506);
               err = 1;
            } else {               
               QuickSort(eav, eac);
               for (; eac; --eac, ++eav)
                  av[ac++] = strcpy(mpush(strlen(*eav)+1), *eav);
            }
            free_expand (ebase);
         }
      }
 
      /* process redirection  */
 
      if (redir && !err) {
         register char *file = (doexpand) ? av[--ac] : av[ac];
 
         if (redir < 0)
            Cin_name = file;
         else {         	
            Cout_name = file;
            Cout_append = (redir == 2);
         }            
         inc = 0;
      }
 
      /* check elast for space */
 
      if (inc) {
         ++ac;
         if (ac + 2 > MAXAV) {
            ierror (NULL, 506);
            err = 1;                /* error condition */
            elast = 0;              /* don't process any more arguemnts */
         }
      }
      if (elast == ' ')
         goto step5;
   }
stepdone:
   av[ac] = '\0';
 
   /* process pipes via files */
 
   if (elast == '|' && !err) {
      static int which;             /* 0 or 1 in case of multiple pipes */
      which = 1 - which;
      Cout_name = (which) ? Pipe1 : Pipe2;
      Cout_ispipe = 1;
   }
 
 
   if (err)
      goto done0;
 
   {
      register int i, len;
      char save_elast;
      register char *avline;
 
      save_elast = elast;
      for (i = len = 0; i < ac; ++i)
         len += strlen(av[i]) + 1;
      avline = malloc(len+1);
      for (len = 0, i = ((pend_alias) ? 1 : 0); i < ac; ++i) {
         if (debug & 0x02) { 
             fprintf (stderr, "AV[%2d] %d :%s:\n", i, strlen(av[i]), av[i]);
         }
         strcpy(avline + len, av[i]);
         len += strlen(av[i]);
         if (i + 1 < ac)
            avline[len++] = ' ';
      }
      avline[len] = 0;
      if (pend_alias) {                               /* special % alias */
         register char *ptr, *scr;
         for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
         set_var (LEVEL_SET, pend_alias + 1, avline);
         free (avline);
 
         scr = malloc((strlen(ptr) << 2) + 2);
         preformat (ptr, scr);
         fcomm (scr, 1);
         unset_var (LEVEL_SET, pend_alias + 1);
      } else {                                        /* normal command  */
         register int ccno;
         long  oldcin = (long)Input();
 	 long  oldcout = (long)Output();
	 extern struct _dev _devtab[];
	 struct _dev *stdfp;
	 
	 fflush(stdout);
         ccno = find_command (command);
         if ((Command[ccno].stat & ST_NAME) == 0) {
            if (Cin_name) {
               if ((Cin = (long)Open(Cin_name,1005L)) == 0L) {
                  ierror (NULL, 504);
                  err = 1;
                  Cin_name = '\0';
               } else {
                  Myprocess->pr_CIS = Cin;
 	          _devtab[stdin->_unit].fd = Cin;
               }
            }
            if (Cout_name) {               
               if (Cout_append) {
                  if ((Cout = (long)Open(Cout_name, 1005L)) != 0L)
                     Seek(Cout, 0L, 1L);
               } else {
                  Cout = (long)Open(Cout_name,1006L);
	       }
               if (Cout == NULL) {
                  err = 1;
                  ierror (NULL, 504);
                  Cout_name = '\0';
                  Cout_append = 0;
               } else {
                  Myprocess->pr_COS = Cout;
                  _devtab[stdout->_unit].fd = Cout;
               }
            }
         }
         if (ac < Command[ccno].minargs + 1) {
            ierror (NULL, 500);
            err = -1;
         } else if (!err) {
            i = (*Command[ccno].func)(avline, Command[ccno].val);
            if (i < 0)
               i = 20;
            err = i;
         }
         free (avline);
         if (Exec_ignoreresult == 0 && Lastresult != err) {
            Lastresult = err;
            seterr();
         }
         if ((Command[ccno].stat & ST_NAME) == 0) {
            if (Cin_name) {
               fflush(stdin); 
	       clearerr(stdin);
	       Close(Cin);
            }
            if (Cout_name) {
               fflush(stdout);
               clearerr(stdout);
               stdout->_flags &= ~_DIRTY;    /* because of nil: device */
               Close(Cout);
               Cout_append = 0;
            }
         }

   	 /* the next few lines solve a bug with fexecv and bcpl programs */
   	 /* that muck up the input/output streams  which causes GURUs	*/

         Myprocess->pr_CIS =  _devtab[stdin->_unit].fd = oldcin;
         Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;   	
      }
      if (Cin_ispipe && Cin_name)
         DeleteFile(Cin_name);
      if (Cout_ispipe) {
         Cin_name = Cout_name;         /* ok to assign.. static name */
         Cin_ispipe = 1;
      } else {
         Cin_name = '\0';
      }
      Cout_name = '\0';
      Cout_ispipe = 0;
      elast = save_elast;
   }
   mpop_tobase();                      /* free arguments   */
   mpush_base();                       /* push dummy base  */
 
done0:
   {
      char *str;
      if (err && E_stack == 0) {
         str = get_var(LEVEL_SET, V_EXCEPT);
         if (err >= ((str)?atoi(str):1)) {
            if (str) {
               ++H_stack;
               ++E_stack;
               exec_command(str);
               --E_stack;
               --H_stack;
            } else {
               Exec_abortline = 1;
            }
         }
      }
      if (elast != 0 && Exec_abortline == 0)
         err = fcomm(nextstr, 0);
      Exec_abortline = 0;
      if (Cin_name)
         DeleteFile(Cin_name);
      Cin_name = NULL;
      Cin_ispipe = 0;
   } 
done1:
   mpop_tobase();
   if (freeok)
      free(str);
   --alias_count;
   return ((int)err);                  /* TRUE = error occured    */
}
 
 
char *
exarg(ptr)
unsigned char **ptr;
{
   register unsigned char *end;
   register unsigned char *start;
 
   start = end = *ptr;
   while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
      ++end;
   elast = *end;
   *end = '\0';
   *ptr = end + 1;
   return ((char *)start);
}
 
static char **Mlist;
 
mpush_base()
{
   char *str;
 
   str = malloc(5);
   *(char ***)str = Mlist;
   str[4] = 0;
   Mlist = (char **)str;
}
 
char *
mpush(bytes)
{
   char *str;
 
   str = malloc(5 + bytes);
   *(char ***)str = Mlist;
   str[4] = 1;
   Mlist = (char **)str;
   return (str + 5);
}
 
mpop_tobase()
{
   register char *next;
   while (Mlist) {
      next = *Mlist;
      if (((char *)Mlist)[4] == 0) {
         free (Mlist);
         Mlist = (char **)next;
         break;
      }
      free (Mlist);
      Mlist = (char **)next;
   }
}
 

/*
 * Insert 'from' string in front of 'str' while deleting the
 * first entry in 'str'.  if freeok is set, then 'str' will be
 * free'd
 */



char *
format_insert_string(str, from, freeok)
char *str;
char *from;
int *freeok;
{
   register char *new1, *new2;
   register unsigned char *strskip;
   int len;

   for (strskip = (unsigned char *)str; *strskip && *strskip != ' ' && *strskip != ';' && *strskip != '|' && *strskip != 0x80; ++strskip);
   len = strlen(from);
   new1 = malloc((len << 2) + 2);
   preformat(from, new1);
   len = strlen(new1) + strlen(strskip);
   new2 = malloc(len+2);
   strcpy(new2, new1);
   strcat(new2, strskip);
   new2[len+1] = 0;
   free (new1);
   if (*freeok)
      free (str);
   *freeok = 1;
   return (new2);
}

find_command(str)
char *str;
{
   int i;
   int len = strlen(str);

   if (*str >= '0'  &&  *str <= '9')
      return (1);
   for (i = 0; Command[i].func; ++i) {
      if (strncmp (str, Command[i].name, len) == 0)
         return (i);
   }
   return (0);
}
 
do_help()
{
   register struct COMMAND *com;
   int i= 0;

    
   for (com = &Command[2]; com->func; ++com) {
      printf ("%-12s", com->name);
      if (++i  % 6 == 0) printf("\n");
   }
   printf("\n");
   return(0);
}

SHAR_EOF
if test 17838 -ne "`wc -c execom.c`"
then
echo shar: error transmitting execom.c '(should have been 17838 characters)'
fi
echo shar: extracting globals.c
cat << \SHAR_EOF > globals.c

/*
 * GLOBALS.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 *    Most global variables.
 *
 */


#include "shell.h"

struct HIST *H_head, *H_tail;                   /* HISTORY lists      */

struct PERROR Perror[] = {                      /* error code->string */
   103,  "insufficient free storage",
   105,  "task table full",
   120,  "argument line invalid or too long",
   121,  "file is not an object module",
   122,  "invalid resident library during load",
   201,  "no default directory",
   202,  "object in use",
   203,  "object already exists",
   204,  "directory not found",
   205,  "object not found",
   206,  "bad stream name",
   207,  "object too large",
   209,  "action not known",
   210,  "invalid stream component name",
   211,  "invalid object lock",
   212,  "object not of required type",
   213,  "disk not validated",
   214,  "disk write protected",
   215,  "rename across devices",
   216,  "directory not empty",
   217,  "too many levels",
   218,  "device not mounted",
   219,  "seek error",
   220,  "comment too long",
   221,  "disk full",
   222,  "file delete protected",
   223,  "file write protected",
   224,  "file read protected",
   225,  "not a DOS disk",
   226,  "no disk",
   232,  "no more entries in directory",

   /* custom error messages */

   500,  "bad arguments",
   501,  "label not found",
   502,  "must be within source file",
   503,  "Syntax Error",
   504,  "redirection error",
   505,  "pipe error",
   506,  "too many arguments",
   507,  "destination not a directory",
   508,  "cannot mv a filesystem",
     0,  NULL
};


char  *av[MAXAV];             /* Internal argument list                 */
long  Src_base[MAXSRC];       /* file pointers for source files         */
long  Src_pos[MAXSRC];        /* seek position storage for same         */
char  If_base[MAXIF];         /* If/Else stack for conditionals         */
int   H_len, H_tail_base;     /* History associated stuff               */
int   H_stack;                /* AddHistory disable stack               */
int   E_stack;                /* Exception disable stack                */
int   Src_stack, If_stack;    /* Stack Indexes                          */
int   ac;                     /* Internal argc                          */
int   debug;                  /* Debug mode                             */
int   disable;                /* Disable com. execution (conditionals)  */
int   Verbose;                /* Verbose mode for source files          */
int   Lastresult;             /* Last return code                       */
int   Exec_abortline;         /* flag to abort rest of line             */
int   Exec_ignoreresult;      /* flag to ignore result                  */
int   Quit;                   /* Quit flag                              */
long  Cout, Cin;              /* Current input and output file handles  */
long  Cout_append;            /* append flag for Cout                   */
long  Uniq;                   /* unique value                           */
char  *Cin_name, *Cout_name;  /* redirection input/output name or NULL  */
char  *Pipe1, *Pipe2;         /* the two pipe temp. files               */
struct Process *Myprocess;
int   S_histlen = 20;         /* Max # history entries                  */



SHAR_EOF
if test 3361 -ne "`wc -c globals.c`"
then
echo shar: error transmitting globals.c '(should have been 3361 characters)'
fi
echo shar: extracting main.c
cat << \SHAR_EOF > main.c

/*
 * MAIN.C
 *
 * Matthew Dillon, 24 Feb 1986
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */
 
#include "shell.h"

void cleanupconsole(), initconsole();
extern char *btocstr();
extern struct FileLock *Clock; 

char Inline[256];
char stdout_buff[STDBUF]; 
main(argc, argv)
register char *argv[];
{
   char *rawgets();
   char *prompt;
   register int i;
   extern int Enable_Abort;
   init_vars();
   init();
   seterr();
   do_cd(NULL, -1);
   
   Enable_Abort = 0;
     
   for (i = 1; i < argc; ++i) {
      if (argv[i][0] == '-' && argv[i][1] == 'c') {
	    Inline[0] = ' ';
	    Inline[1] = '\000';
	    while (++i < argc) {
		strcat(Inline,argv[i]);
		strcat(Inline," ");
		}
	    exec_command(Inline);
	    main_exit(0);
	    }
      strcpy (Inline, "source ");
      strcat (Inline, argv[i]);
      av[1] = argv[i];
      do_source (Inline);
   }
   
   for (;;) {
      if ((prompt = get_var (LEVEL_SET, V_PROMPT)) == NULL)
         prompt = "$ ";
      if (breakcheck()) {
         while (WaitForChar(Input(), 1L))
            gets(Inline);
      }
      if (Quit || !rawgets(Inline, prompt))
         main_exit(0);
      breakreset();
      if (*Inline)
         exec_command(Inline);
   }
}
 
init_vars()
{
   if (IsInteractive(Input()))
      set_var (LEVEL_SET, V_PROMPT, "$ ");
   else
      set_var (LEVEL_SET, V_PROMPT, "");
   set_var (LEVEL_SET, V_HIST,   "20");
   set_var (LEVEL_SET, V_LASTERR, "0");
   set_var (LEVEL_SET, V_PATH, "ram:,ram:c/,c:,df1:c/,df0:c/");
}
 
init()
{


   static char pipe1[32], pipe2[32];

   initconsole();

   stdout->_buff = stdout_buff;
   stdout->_buflen = STDBUF;  

   Myprocess = (struct Process *)FindTask(0L);
   Uniq  = (long)Myprocess;
   Pipe1 = pipe1;
   Pipe2 = pipe2;
   sprintf (pipe1, "ram:pipe1_%ld", Uniq);
   sprintf (pipe2, "ram:pipe2_%ld", Uniq);
}
 
 
main_exit(n)
{
   cleanupconsole(0);
   exit (n);
}
 
breakcheck()
{
   if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
      return (1);
   else
      return (0);
}
 
breakreset()
{
   SetSignal(0L, SIGBREAKF_CTRL_C);
}


/* this routine causes manx to use this Chk_Abort() rather than it's own */
/* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
/* is zero).  Since we want to check for our own ^C's 			 */

Chk_Abort()
{
return(0);
}


SHAR_EOF
if test 2363 -ne "`wc -c main.c`"
then
echo shar: error transmitting main.c '(should have been 2363 characters)'
fi
echo shar: extracting rawconsole.c
cat << \SHAR_EOF > rawconsole.c
/*
 * RawConsole.c
 *
 * Shell 2.05M  20-Jan-87
 * console handling, command line editing support for Shell
 * using new console packets from 1.2.
 * Written by Steve Drew. (c) 14-Oct-86.
 * 16-Dec-86 Slight mods to rawgets() for Disktrashing.
 *
 */
#include "shell.h" 

#define ACTION_SCREEN_MODE 994L
#define DOSTRUE 	    -1L

struct MsgPort        *replyport, *conid;
struct StandardPacket *packet;

initconsole()
{
    struct Process *myprocess;
  
    if (IsInteractive(Input())) {
        myprocess = (struct Process *) FindTask(NULL);      
        replyport = (struct MsgPort *) CreatePort(NULL,NULL);
        if(!replyport) exit(10);
        packet = (struct StandardPacket *) 
            AllocMem((long)sizeof(*packet),MEMF_PUBLIC | MEMF_CLEAR);
        conid = (struct MsgPort *) myprocess->pr_ConsoleTask; /* get console handler */
        printf("\23312{");
        set_var (LEVEL_SET, "_insert", "1");
    }
}

void
cleanupconsole()
{

    if (IsInteractive(Input())) {
       FreeMem(packet,(long)sizeof(*packet)); 
       DeletePort(replyport); 
    }
}

void 
setraw(onoff)
int onoff; 
{
 
 packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt); /* link packet- */
 packet->sp_Pkt.dp_Link         = &(packet->sp_Msg);        /* to message    */
 packet->sp_Pkt.dp_Port         = replyport;         /* set-up reply port   */
 packet->sp_Pkt.dp_Type = ACTION_SCREEN_MODE;        /* function */

 if (onoff) { 
     packet->sp_Pkt.dp_Arg1 = DOSTRUE; 
     fflush(stdout);             /* I had previously set stdout to buf'rd */
     stdout->_buflen = 1;        /* but for raw mode we need single char */
     }
 else {
     packet->sp_Pkt.dp_Arg1 = FALSE;
     stdout->_buflen = STDBUF;            /* set back to buffr'd */
 }
 PutMsg(conid,packet);  /* send packet */
 WaitPort(replyport); /* wait for packet to come back */
 GetMsg(replyport);   /* pull message */
 
}
 

char *
rawgets(line,prompt)
char *line, *prompt;
{
    char *get_var();
    char *gets();
    register int n, pl;
    register int max, i;
    unsigned char c1,c2,c3;
    char fkeys[5];
    char *s;
    int fkey;
    int insert = 1;
    char rep[14];
    static int width;
    int recall = -1;
    struct HIST *hist;

    if (!IsInteractive(Input())) return(gets(line));
    if (WaitForChar((long)Input(), 100L)) {   /* don't switch to 1L ...*/
    /*  printf("%s",prompt); */               /* else causes read err's  */
	gets(line);
	return(line);
    } 
    setraw(1);
    printf("%s",prompt);
    max = pl = i = strlen(prompt);
    strcpy(line,prompt);
    if (!width) width = 77;
    if (s = get_var (LEVEL_SET, "_insert"))
        insert = atoi(s) ? 1 : 0;

    while((c1 = getchar()) != 255) {
	if (c1 < 156) switch(c1) {	
	    case 155:
		 c2 = getchar();
		 switch(c2) {
		     case 'A':			/* up arrow   */
			n = ++recall;
		     case 'B':			/* down arrow */
			line[pl] = '\0';
			if (recall >= 0 || c2 == 'A') {
			    if (c2 == 'B') n = --recall;
			    if (recall >= 0) {
			        for(hist = H_head; hist && n--; 
			            hist = hist->next);
			        if (hist) strcpy(&line[pl],hist->line);
			        else recall = H_len;
			    }
			}
			if (i != pl) 
			    printf("\233%dD",i);
			printf("\015\233J%s",line);
			i = max = strlen(line);
			break;
		     case 'C':			/* right arrow*/
			if (i < max) {
			    i++;
			    printf("\233C");
			}
			break;
		     case 'D':			/* left arrow */
			if (i > pl) {
			    i--;
			    printf("\233D");
			}
			break;
		    case 'T':			/* shift up   */
		    case 'S':			/* shift down */
			break;
		    case ' ':			/* shift -> <-*/
			c3 = getchar();
			break;
		    default:
			c3 = getchar();
			if (c3 == '~') {
			    fkey = c2;
                            fkeys[0] = 'f';
			    if (c2 == 63) {
				strcpy(&line[pl],"help");
				goto done;
			    }
			}
			else if (getchar() != '~') { /* window was resized */
		            while(getchar() != '|');
       	                    printf("\2330 q"); /* get window bounds */
    		            n = 0;
		            while((rep[n] = getchar()) != 'r' && n++ < 14 );
		            width = (rep[n-3] - 48) * 10 + rep[n-2] - 48;
		            rep[n-1] = '\0';
		            set_var (LEVEL_SET, "_width", &rep[n-3]);
                            break;
		    	}
		    	else {
                            fkey = c3;
                            fkeys[0] = 'F';
                        }
			sprintf(fkeys+1,"%d",fkey - 47);
			if (!(s = get_var(LEVEL_SET, fkeys))) break;
			strcpy(&line[pl], s);
			printf("%s",&line[pl]);
			goto done;
			break;
		    } 
		break;
	    case 8:
		if (i > pl) {
		    i--;
		    printf("\010");
		}
		else break;
	    case 127:
		if (i < max) {
		    int j,t,l = 0;
		    movmem(&line[i+1],&line[i],max-i);
		    --max;
		    printf("\233P");
		    j = width - i % width - 1;	 /* amount to end     */
		    t = max/width - i/width;	 /* no of lines       */
		    for(n = 0; n < t; n++) {
			l += j;			 /* no. of char moved */
			if (j) printf("\233%dC",j); /* goto eol       */
			printf("%c\233P",line[width*(i/width+n+1)-1]);
			j = width-1;
		    }
		    if (t)
		    printf("\233%dD",l+t);   /* get back */
		}
		break;
	    case 18:
		n = i/width;
		if (n) printf("\233%dF",n);
		printf("\015\233J%s",line);
		i = max;
		break;
	    case 27:
	    case 10:
		break;
	    case 1:
		insert ^= 1;
		break;
	    case 21:
	    case 24:
	    case 26:
		if (i > pl)
		    printf("\233%dD",i-pl);
		i = pl;
		if (c1 == 26) break;
		printf("\233J");
		max = i;
		line[i] = '\0';
		break;
	    case 11:        /* ^K */
	        printf("\233J");
	        max = i;
	        line[i] = '\0';
	        break; 
            case 28:        /* ^\ */
                setraw(0);
                return(NULL);
	    case 5:
		printf("\233%dC",max - i);
		i = max;
		break;
	    case 13:
		line[max] = '\0';
done:		printf("\233%dC\n",max - i);

		setraw(0);
		strcpy(line, &line[pl]);
		return(line);
	    default:
		if (c1 == 9) c1 = 32;
		if (c1 > 31 & i < 256) {
		    if (i < max && insert) {
			int j,t,l = 0;
			movmem(&line[i], &line[i+1], max - i);
			printf("\233@%c",c1);
			t = max/width - i/width;
			j = width - i % width - 1;
			for(n = 0; n < t; n++) {
			    l += j;
			    if (j) printf("\233%dC",j);
			    printf("\233@%c",line[width*(i/width+n+1)]);
			    j = width-1;
			}
			if (t) printf("\233%dD",l + t);
			++max;				
		    }
		    else {
			if (i == pl && max == i) printf("\015%s",line);
			putchar(c1);
		    }
		    line[i++] = c1;
		    if (max < i) max = i;
		    line[max] = '\0';
		}
	}
    }
    setraw(0);
    return(NULL);
}

SHAR_EOF
if test 6579 -ne "`wc -c rawconsole.c`"
then
echo shar: error transmitting rawconsole.c '(should have been 6579 characters)'
fi
echo shar: extracting run.c
cat << \SHAR_EOF > run.c

/*
 * RUN.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    RUN   handles running of external commands.
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */

#include "shell.h"

char *FindIt();

do_run(str)
char *str;
{
   int i, try = -1;
   int run = 0;
   char buf[128];
   char runcmd[128];
   char *save, *path;


   if (path = FindIt(av[0],"",buf)) {   
      if (!strcmp(av[0],"run")) {
         if (FindIt(av[1],"",runcmd)) {
            run = 1;
            save = av[1];
            av[1] = runcmd;
         }
      }
      if ((try = fexecv(path, av)) == 0)
         i = wait();
      if (run) av[1] = save;      
   } 
   if (try) {
      long lock;
      char *copy;

      if ((path = FindIt(av[0],".sh",buf)) == NULL) {
         fprintf(stderr,"Command Not Found %s\n",av[0]);
         return (-1);
      }
      av[1] = buf;               /* particular to do_source() */
      copy = malloc(strlen(str)+3);
      strcpy(copy+2,str);
      copy[0] = 'x';
      copy[1] = ' ';
      i = do_source(copy);
      free(copy);
   }
   return (i);
}


char *
FindIt(cmd, ext, buf)
char *cmd;
char *ext;
char *buf;
{
   long lock = 0;
   char hasprefix = 0;
   APTR original;
   char *ptr, *s = NULL;

   original = Myprocess->pr_WindowPtr;

   for (ptr = cmd; *ptr; ++ptr) {
      if (*ptr == '/' || *ptr == ':')
         hasprefix = 1;
   }
   
   if (!hasprefix) {
   	Myprocess->pr_WindowPtr = (APTR)(-1);
   	s = get_var(LEVEL_SET, V_PATH);
   }

   strcpy(buf, cmd);
   strcat(buf, ext);
   while ((lock = (long)Lock(buf, ACCESS_READ)) == 0) {
      if (*s == NULL || hasprefix) break;
      for(ptr = s; *s && *s != ','; s++) ;
      strcpy(buf, ptr);
      buf[s-ptr] = '\0';
      strcat(buf, cmd);
      strcat(buf, ext);
      if (*s) s++;
   }
   Myprocess->pr_WindowPtr = original;
   if (lock) {
      UnLock(lock);
      return(buf);
   }
   return(NULL);
}


SHAR_EOF
if test 1919 -ne "`wc -c run.c`"
then
echo shar: error transmitting run.c '(should have been 1919 characters)'
fi
echo shar: extracting set.c
cat << \SHAR_EOF > set.c

/*
 * SET.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */

#include "shell.h"
#define MAXLEVELS (3 + MAXSRC)

struct MASTER {
   struct MASTER *next;
   struct MASTER *last;
   char *name;
   char *text;
};

static struct MASTER *Mbase[MAXLEVELS];

char *
set_var(level, name, str)
register char *name, *str;
{
   register struct MASTER *base = Mbase[level];
   register struct MASTER *last;
   register int len;

   for (len = 0; isalphanum(name[len]); ++len);
   while (base != NULL) {
      if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
         Free (base->text);
         goto gotit;
      }
      last = base;
      base = base->next;
   }
   if (base == Mbase[level]) {
      base = Mbase[level] = (struct MASTER *)malloc (sizeof(struct MASTER));
      base->last = NULL;
   } else {
      base = (struct MASTER *)malloc (sizeof(struct MASTER));
      base->last = last;
      last->next = base;
   }
   base->name = malloc (len + 1);
   bmov (name, base->name, len);
   base->name[len] = 0;
   base->next = NULL;
gotit:
   base->text = malloc (strlen(str) + 1);
   strcpy (base->text, str);
   return (base->text);
}

char *
get_var (level, name)
register char *name;
{
   register struct MASTER *base = Mbase[level];
   register unsigned char *scr;
   register int len;

   for (scr = (unsigned char *)name; *scr && *scr != 0x80 && *scr != ' ' && *scr != ';' && *scr != '|'; ++scr);
   len = scr - name;

   while (base != NULL) {
      if (strlen(base->name) == len && strncmp (name, base->name, len) == 0)
         return (base->text);
      base = base->next;
   }
   return (NULL);
}

unset_level(level)
{
   register struct MASTER *base = Mbase[level];

   while (base) {
      Free (base->name);
      Free (base->text);
      Free (base);
      base = base->next;
   }
   Mbase[level] = NULL;
}

unset_var(level, name)
char *name;
{
   register struct MASTER *base = Mbase[level];
   register struct MASTER *last = NULL;
   register int len;

   for (len = 0; isalphanum(name[len]); ++len);
   while (base) {
      if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
         if (base != Mbase[level])
            last->next = base->next;
         else
            Mbase[level] = base->next;
         if (base->next != NULL)
            base->next->last = last;
         if (base == Mbase[level])
            Mbase[level] = base->next;
         Free (base->name);
         Free (base->text);
         Free (base);
         return (1);
      }
      last = base;
      base = base->next;
   }
   return (-1);
}


do_unset_var(str, level)
char *str;
{
   register int i;

   for (i = 1; i < ac; ++i)
      unset_var (level, av[i]);
   return (0);
}

do_set_var(command, level)
char *command;
{
   register struct MASTER *base = Mbase[level];
   register char *str;

   if (ac == 1) {
      while (base) {
	 if (CHECKBREAK())
	     return(0);
         printf ("%-10s ", base->name);
         puts (base->text);
         base = base->next;
      }
      return (0);
   }
   if (ac == 2) {
      str = get_var (level, av[1]);
      if (str) {
         printf ("%-10s ", av[1]);
         puts(str);
      } else if (level == LEVEL_SET) { /* only create var if set command */
         set_var (level, av[1], "");
      }
   }
   if (ac > 2)
      set_var (level, av[1], next_word (next_word (command)));
   if (*av[1] == '_') {
      S_histlen = (str = get_var(LEVEL_SET, V_HIST))   ? atoi(str) : 0;
      debug     = (str = get_var(LEVEL_SET, V_DEBUG))  ? atoi(str) : 0;
      Verbose   = (get_var(LEVEL_SET, V_VERBOSE)) ? 1 : 0;
      if (S_histlen < 2)   S_histlen = 2;
   }
   return (0);
}
SHAR_EOF
if test 3735 -ne "`wc -c set.c`"
then
echo shar: error transmitting set.c '(should have been 3735 characters)'
fi
echo shar: extracting sort.c
cat << \SHAR_EOF > sort.c

/*
 * SORT.C
 *
 * a QuickSort is used for speed, simplicity, and small code size.
 *
 */


QuickSort(av, n)
char *av[];
short n;
{
   short b;

   if (n > 0) {
      b = QSplit(av, n);
      QuickSort(av, b);
      QuickSort(av+b+1, n - b - 1);
   }
}


/*
 * QSplit called as a second routine so I don't waste stack on QuickSort's
 * recursivness.
 */

QSplit(av, n)
register char *av[];
short n;
{
   register short i, b;
   register char *element, *scr;

   element = av[0];
   for (b = 0, i = 1; i < n; ++i) {
      if (strcmp(av[i], element) < 0) {
         ++b;
         scr = av[i]; av[i] = av[b]; av[b] = scr;
      }
   }
   scr = av[0]; av[0] = av[b]; av[b] = scr;
   return (b);
}
SHAR_EOF
if test 694 -ne "`wc -c sort.c`"
then
echo shar: error transmitting sort.c '(should have been 694 characters)'
fi
echo shar: extracting sub.c
cat << \SHAR_EOF > sub.c

/*
 * SUB.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
 *
 */

#include "shell.h"

#define HM_STR 0              /* various HISTORY retrieval modes */
#define HM_REL 1
#define HM_ABS 2

extern struct FileLock *Clock;
seterr()
{
   char buf[32];
   int stat;

   sprintf(buf, "%d", Lastresult);
   set_var(LEVEL_SET, V_LASTERR, buf);
   stat = atoi(get_var(LEVEL_SET, V_STAT));
   if (stat < Lastresult)
      stat = Lastresult;
   sprintf(buf, "%d", stat);
   set_var(LEVEL_SET, V_STAT, buf);
}


char *
next_word(str)
register char *str;
{
   while (*str  &&  *str != ' '  &&  *str != 9)
      ++str;
   while (*str  && (*str == ' ' || *str == 9))
      ++str;
   return (str);
}


char *
compile_av(av, start, end)
char **av;
{
   char *cstr;
   int i, len;

   len = 0;
   for (i = start; i < end; ++i)
      len += strlen(av[i]) + 1;
   cstr = malloc(len + 1);
   *cstr = '\0';
   for (i = start; i < end; ++i) {
      strcat (cstr, av[i]);
      strcat (cstr, " ");
   }
   return (cstr);
}

/*
 * FREE(ptr)   --frees without actually freeing, so the data is still good
 *               immediately after the free.
 */


Free(ptr)
char *ptr;
{
   static char *old_ptr;

   if (old_ptr)
      free (old_ptr);
   old_ptr = ptr;
}

/*
 * Add new string to history (H_head, H_tail, H_len,
 *  S_histlen
 */

add_history(str)
char *str;
{
   register struct HIST *hist;

   if (H_head != NULL && strcmp(H_head->line, str) == 0)
       return(0);
   while (H_len > S_histlen)
      del_history();
   hist = (struct HIST *)malloc (sizeof(struct HIST));
   if (H_head == NULL) {
      H_head = H_tail = hist;
      hist->next = NULL;
   } else {
      hist->next = H_head;
      H_head->prev = hist;
      H_head = hist;
   }
   hist->prev = NULL;
   hist->line = malloc (strlen(str) + 1);
   strcpy (hist->line, str);
   ++H_len;
}

del_history()
{
   if (H_tail) {
      --H_len;
      ++H_tail_base;
      free (H_tail->line);
      if (H_tail->prev) {
         H_tail = H_tail->prev;
         free (H_tail->next);
         H_tail->next = NULL;
      } else {
         free (H_tail);
         H_tail = H_head = NULL;
      }
   }
}

char *
get_history(ptr)
char *ptr;
{
   register struct HIST *hist;
   register int len;
   int mode = HM_REL;
   int num  = 1;
   char *str;
   char *result = NULL;

   if (ptr[1] >= '0' && ptr[1] <= '9') {
      mode = HM_ABS;
      num  = atoi(&ptr[1]);
      goto skip;
   }
   switch (ptr[1]) {
   case '!':
      break;
   case '-':
      num += atoi(&ptr[2]);
      break;
   default:
      mode = HM_STR;
      str  = ptr + 1;
      break;
   }
skip:
   switch (mode) {
   case HM_STR:
      len = strlen(str);
      for (hist = H_head; hist; hist = hist->next) {
         if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
            result = hist->line;
            break;
         }
      }
      break;
   case HM_REL:
      for (hist = H_head; hist && num--; hist = hist->next);
      if (hist)
         result = hist->line;
      break;
   case HM_ABS:
      len = H_tail_base;
      for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
      if (hist)
         result = hist->line;
      break;
   }
   if (result) {
      fprintf(stderr,"%s\n",result);
      return(result);
   }
   printf("History failed\n");
   return ("");
}

replace_head(str)
char *str;
{
   if (str == NULL)
      str = "";
   if (H_head) {
      free (H_head->line);
      H_head->line = malloc (strlen(str)+1);
      strcpy (H_head->line, str);
   }
}


pError(str)
char *str;
{
   int ierr = (long)IoErr();
   ierror(str, ierr);
}

ierror(str, err)
register char *str;
{
   register struct PERROR *per = Perror;

   if (err) {
      for (; per->errstr; ++per) {
         if (per->errnum == err) {
            fprintf (stderr, "%s%s%s\n",
                  per->errstr,
                  (str) ? ": " : "",
                  (str) ? str : "");
            return ((short)err);
         }
      }
      fprintf (stderr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
   }
   return ((short)err);
}

/*
 * Disk directory routines
 *
 * dptr = dopen(name, stat)
 *    struct DPTR *dptr;
 *    char *name;
 *    int *stat;
 *
 * dnext(dptr, name, stat)
 *    struct DPTR *dptr;
 *    char **name;
 *    int  *stat;
 *
 * dclose(dptr)                  -may be called with NULL without harm
 *
 * dopen() returns a struct DPTR, or NULL if the given file does not
 * exist.  stat will be set to 1 if the file is a directory.  If the
 * name is "", then the current directory is openned.
 *
 * dnext() returns 1 until there are no more entries.  The **name and
 * *stat are set.  *stat = 1 if the file is a directory.
 *
 * dclose() closes a directory channel.
 *
 */

struct DPTR *
dopen(name, stat)
char *name;
int *stat;
{
   struct DPTR *dp;

   *stat = 0;
   dp = (struct DPTR *)malloc(sizeof(struct DPTR));
   if (*name == '\0')
      dp->lock = (struct FileLock *)DupLock (Clock);
   else
      dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
   if (dp->lock == NULL) {
      free (dp);
      return (NULL);
   }
   dp->fib = (struct FileInfoBlock *)
         AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
   if (!Examine (dp->lock, dp->fib)) {
      pError (name);
      dclose (dp);
      return (NULL);
   }
   if (dp->fib->fib_DirEntryType >= 0)
      *stat = 1;
   return (dp);
}

dnext(dp, pname, stat)
struct DPTR *dp;
char **pname;
int *stat;
{
   if (dp == NULL)
      return (0);
   if (ExNext (dp->lock, dp->fib)) {
      *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
      *pname = dp->fib->fib_FileName;
      return (1);
   }
   return (0);
}


dclose(dp)
struct DPTR *dp;
{
   if (dp == NULL)
      return (1);
   if (dp->fib)
      FreeMem (dp->fib,(long)sizeof(*dp->fib));
   if (dp->lock)
      UnLock (dp->lock);
   free (dp);
   return (1);
}


isdir(file)
char *file;
{
   register struct DPTR *dp;
   int stat;

   stat = 0;
   if (dp = dopen (file, &stat))
      dclose(dp);
   return (stat == 1);
}


free_expand(av)
register char **av;
{
   char **base = av;

   if (av) {
      while (*av) {
         free (*av);
         ++av;
      }
      free (base);
   }
}

/*
 * EXPAND(wild_name, pac)
 *    wild_name      - char * (example: "df0:*.c")
 *    pac            - int  *  will be set to # of arguments.
 *
 * Standalone, except in requires Clock to point to the Current-Directory
 * lock.
 */


char **
expand(base, pac)
char *base;
int *pac;
{
   register char *ptr;
   char **eav = (char **)malloc (sizeof(char *));
   short eleft, eac;
   char *name;
   char *bname, *ename, *tail;
   int stat, scr;
   register struct DPTR *dp;

   *pac = eleft = eac = 0;

   base = strcpy(malloc(strlen(base)+1), base);
   for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
   for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
   if (ptr < base) {
      bname = strcpy (malloc(1), "");
   } else {
      scr = ptr[1];
      ptr[1] = '\0';
      bname = strcpy (malloc(strlen(base)+1), base);
      ptr[1] = scr;
   }
   ename = ptr + 1;
   for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
   scr = *ptr;
   *ptr = '\0';
   tail = (scr) ? ptr + 1 : NULL;

   if ((dp = dopen (bname, &stat)) == NULL  ||  stat == 0) {
      free (bname);
      free (base);
      free (eav);
      fprintf(stderr,"Could not open directory\n");
      return (NULL);
   }
   while (dnext (dp, &name, &stat)) {
      if (compare_ok(ename, name)) {
         if (tail) {
            int alt_ac;
            char *search, **alt_av, **scrav;
            struct FileLock *lock;

            if (!stat)           /* expect more dirs, but this not a dir */
               continue;
            lock = (struct FileLock *)CurrentDir (Clock = dp->lock);
            search = malloc(strlen(name)+strlen(tail)+2);
            strcpy (search, name);
            strcat (search, "/");
            strcat (search, tail);
            scrav = alt_av = expand (search, &alt_ac);
            CurrentDir (Clock = lock);
            if (scrav) {
               while (*scrav) {
                  if (eleft < 2) {
                     char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
                     bmov (eav, scrav, (eac + 1) << 2);
                     free (eav);
                     eav = scrav;
                     eleft = 10;
                  }
                  eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
                  strcpy(eav[eac], bname);
                  strcat(eav[eac], *scrav);
                  free (*scrav);
                  ++scrav;
                  --eleft, ++eac;
               }
               free (alt_av);
            }
         } else {
            if (eleft < 2) {
               char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
               bmov (eav, scrav, (eac + 1) << 2);
               free (eav);
               eav = scrav;
               eleft = 10;
            }
            eav[eac] = malloc (strlen(bname)+strlen(name)+1);
            eav[eac] = strcpy(eav[eac], bname);
            strcat(eav[eac], name);
            --eleft, ++eac;
         }
      }
   }
   dclose (dp);
   *pac = eac;
   eav[eac] = NULL;
   free (bname);
   free (base);
   if (eac) {
      return (eav);
   }
   free (eav);
   return (NULL);
}

/*
 * Compare a wild card name with a normal name
 */

#define MAXB   8

compare_ok(wild, name)
char *wild, *name;
{
   register char *w = wild;
   register char *n = name;
   char *back[MAXB][2];
   register char s1, s2;
   int  bi = 0;

   while (*n || *w) {
      switch (*w) {
      case '*':
         if (bi == MAXB) {
            printf(stderr,"Too many levels of '*'\n");
            return (0);
         }
         back[bi][0] = w;
         back[bi][1] = n;
         ++bi;
         ++w;
         continue;
goback:
         --bi;
         while (bi >= 0 && *back[bi][1] == '\0')
            --bi;
         if (bi < 0)
            return (0);
         w = back[bi][0] + 1;
         n = ++back[bi][1];
         ++bi;
         continue;
      case '?':
         if (!*n) {
            if (bi)
               goto goback;
            return (0);
         }
         break;
      default:
         s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
         s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
         if (s1 != s2) {
            if (bi)
               goto goback;
            return (0);
         }
         break;
      }
      if (*n)  ++n;
      if (*w)  ++w;
   }
   return (1);
}
SHAR_EOF
if test 10571 -ne "`wc -c sub.c`"
then
echo shar: error transmitting sub.c '(should have been 10571 characters)'
fi
echo shar: extracting shell.h
cat << \SHAR_EOF > shell.h

/*
 * SHELL.H
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *
 * SHELL include file.. contains shell parameters and extern's
 *
 *
 */

#include <stdio.h>
#include <time.h> 
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <functions.h>

#define bmov   movmem
#define STDBUF 256

#define MAXAV        256            /* Max. # arguments             */
#define MAXSRC       5              /* Max. # of source file levels */
#define MAXIF        10             /* Max. # of if levels          */
#define MAXALIAS     20             /* Max. # of alias levels       */

#define LEVEL_SET    0              /* which variable list to use   */
#define LEVEL_ALIAS  1
#define LEVEL_LABEL  2

#define V_PROMPT     "_prompt"      /* your prompt (ascii command)   */
#define V_HIST       "_history"     /* set history depth (value)     */
#define V_HISTNUM    "_histnum"     /* set history numbering var     */
#define V_DEBUG      "_debug"       /* set debug mode                */
#define V_VERBOSE    "_verbose"     /* set verbose for source files  */
#define V_STAT       "_maxerr"      /* worst return value to date    */
#define V_LASTERR    "_lasterr"     /* return value from last comm.  */
#define V_CWD        "_cwd"         /* current directory             */
#define V_EXCEPT     "_except"      /* "nnn;command"                 */
#define V_PASSED     "_passed"      /* passed arguments to source fle*/
#define V_PATH       "_path"        /* search path for external cmds */

            /* EXECOM.C defines */

#define FL_DOLLAR    0x01  /* One of the following */
#define FL_BANG      0x02
#define FL_PERCENT   0x04
#define FL_QUOTE     0x08
#define FL_IDOLLAR   0x10  /* Any or all of the following may be set */
#define FL_EOC       0x20
#define FL_EOL       0x40
#define FL_OVERIDE   0x80
#define FL_WILD      0x100
#define FL_MASK      (FL_DOLLAR|FL_BANG|FL_PERCENT|FL_QUOTE)


#define VERSION   "V2.05M  (c)1986 Matthew Dillon.  Manx version by Steve Drew"

#ifndef NULL
#define NULL 0L
#endif

#define CHECKBREAK() ( breakcheck() ? (printf("^C\n"),1) : 0)


struct HIST {
   struct HIST *next, *prev;     /* doubly linked list */
   char *line;                   /* line in history    */
};

struct PERROR {
   int errnum;                   /* Format of global error lookup */
   char *errstr;
};

struct DPTR {                    /* Format of directory fetch pointer */
   struct FileLock *lock;        /* lock on directory   */
   struct FileInfoBlock *fib;    /* mod'd fib for entry */
};

extern struct HIST *H_head, *H_tail;
extern struct PERROR Perror[];
extern struct DPTR *dopen();
extern char *set_var(), *get_var(), *next_word();
extern char *get_history(), *compile_av();
extern char *malloc(), *strcpy(), *strcat();
extern char **expand();
extern char *av[];
extern char *Current;
extern int  H_len, H_tail_base, H_stack;
extern int  E_stack;
extern int  Src_stack, If_stack;
extern int  ac;
extern int  debug, Rval, Verbose, disable, Quit;
extern int  Lastresult;
extern int  Exec_abortline, Exec_ignoreresult;
extern int   S_histlen;
extern long  Uniq;
extern long  Cin, Cout, Cout_append;
extern char *Cin_name, *Cout_name;
extern char  Cin_type,  Cout_type;  /* these variables are in transition */
extern char *Pipe1, *Pipe2;

extern long Src_base[MAXSRC];
extern long Src_pos[MAXSRC];
extern char If_base[MAXIF];
extern struct Process *Myprocess;

SHAR_EOF
if test 3542 -ne "`wc -c shell.h`"
then
echo shar: error transmitting shell.h '(should have been 3542 characters)'
fi
#	End of shell archive
exit 0

stever@videovax.UUCP (01/24/87)

In article <7743@decwrl.DEC.COM>, Steve Drew (drew@cgfsv2.dec.com)
posted the source for the latest version (2.05M) of the Manx shell.
By the time it reached us, it had been truncated.  Are we the only
ones this happened to, or is it net-wide?

The truncation occurred in the middle of comm2.c (see the list of files).
The last few lines of the file are included, as well, to show where the
truncation occurred.

*> # shar:	Shell Archiver
*> #	Run the following text with /bin/sh to create:
*> #	comm1.c
*> #	comm2.c
*> #	execom.c
*> #	globals.c
*> #	main.c
*> #	rawconsole.c
*> #	run.c
*> #	set.c
*> #	sort.c
*> #	sub.c
*> #	shell.h
*> # This archive created: Thu Jan 22 09:35:07 1987

*> . . .

*> 
*> /*
*>  * STRHEAD
*>  *
*>  * pla

If you received it intact, please let me know by email -- I would like to
get a copy!  Thanks.

					Steve Rice

----------------------------------------------------------------------------
{decvax | hplabs | ihnp4 | uw-beaver}!tektronix!videovax!stever