[comp.sys.amiga] SHELL 2.04 PART 3 of 4

dillon@CORY.BERKELEY.EDU (Matt Dillon) (01/03/87)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	comm1.c
#	comm2.c
#	execom.c
#	fexec1.c
#	globals.c
#	hat.c
# This archive created: Sat Jan  3 01:01:30 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'comm1.c'" '(13314 characters)'
if test -f 'comm1.c'
then
	echo shar: "will not over-write existing file 'comm1.c'"
else
cat << \!Funky!Stuff! > 'comm1.c'

/*
 * COMM1.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    SLEEP
 *    NUMBER      -handles values as commands, actually a NULL command.
 *    CAT
 *    DIR         -also handles DEVINFO
 *    QUIT        -also handles EXIT
 *    ECHO
 *    SOURCE
 *    CD
 *    MKDIR
 *    MV
 *    RM
 *    HISTORY
 *    MEM
 *    FOREACH
 *    FOREVER
 *
 *    NOTE: SET/UNSET/ALIAS/UNALIAS handled in SET.C
 *
 */

#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <lattice/fcntl.h>
#include "shell.h"

typedef struct FileInfoBlock FIB;
typedef struct FileLock LOCK;

extern struct FileLock  *CreateDir(), *CurrentDir(), *ParentDir();
extern struct FileLock  *Lock(), *DupLock();
extern char *AllocMem();

extern long disp_entry();

struct FileLock *Clock;



do_sleep()
{
   register int i;

   if (ac == 2) {
      i = atoi(av[1]);
      while (i > 0) {
         Delay (50*2);
         i -= 2;
         if (CHECKBREAK())
            break;
      }
   }
   return (0);
}


do_number()
{
   return (0);
}

do_cat()
{
   long fi;
   short i;
   char buf[256];

   if (ac == 1) {
      while (Ogets(buf))
         Oputs(buf);
      return (0);
   }
   for (i = 1; i < ac; ++i) {
      if (fi = xopen (av[i], "r", 512)) {
         while (xgets (fi, buf, 256)) {
            Oputs(buf);
            if (CHECKBREAK())
               break;
         }
         xclose (fi);
      } else {
         fprintf (Cerr, "could not open %s\n", av[i]);
      }
   }
   return (0);
}


do_dir(garbage, com)
char *garbage;
{
   register struct DPTR          *dp;
   register struct InfoData      *info;
   char *name;
   register short i;
   int   stat;
   short longmode = 0;
   register long total = 0;

   if (strcmp(av[1], "-l") == 0)
      longmode = 1;
   if (ac == 1 + longmode)
      av[ac++] = "";
   for (i = longmode + 1; i < ac; ++i) {
      if ((dp = dopen (av[i], &stat)) == NULL)
         continue;
      if (com < 0) {
         info = (struct InfoData *)AllocMem(sizeof(struct InfoData), MEMF_PUBLIC);
         if (Info (dp->lock, info)) {
            int bpb = info->id_BytesPerBlock;
            fprintf (Cout, "Unit:%2ld  Errs:%3ld  Bytes: %-7ld Free: %-7ld %%full: %ld\n",
                  info->id_UnitNumber,
                  info->id_NumSoftErrors,
                  bpb * info->id_NumBlocks,
                  bpb * (info->id_NumBlocks - info->id_NumBlocksUsed),
                  info->id_NumBlocksUsed * 100 / info->id_NumBlocks);
         } else {
            perror (av[i]);
         }
         FreeMem (info, sizeof(*info));
      } else {
         if (stat) {
            while (dnext (dp, &name, &stat)) {
               total += disp_entry (dp->fib, longmode);
               if (CHECKBREAK())
                  break;
            }
         } else {
            total += disp_entry(dp->fib, longmode);
         }
      }
      dclose (dp);
   }
   fprintf (Cout, "TOTAL: %ld\n", total);
   return (0);
}


char *
datetos(d)
register struct DateStamp *d;
{
   static char stamp[32];
   static char dim[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   static char *Month[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul",
                              "Aug","Sep","Oct","Nov","Dec" };
   register long day, month, year, scr;

   day = d->ds_Days;       /* iteration (could be done w/equations) */
   year = 1978;

   while (day >= (scr = ((year&3)|!(year%100)) ? 365 : 366)) {
      ++year;
      day -= scr;
   }
   dim[1] = ((year&3)|!(year%100)) ? 28 : 29;
   for (month = 0; day >= dim[month]; (day -= dim[month]), ++month);
   sprintf(stamp, "%2ld %s %2ld:%ld%ld %4ld",
      day + 1, Month[month], d->ds_Minute/60,
      d->ds_Minute%60/10, d->ds_Minute%10, year);
   return (stamp);
}



static long
disp_entry(fib, lengthy)
register struct FileInfoBlock *fib;
{
   char str[5];
   register char *dirstr;

   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) ? '-' : 'x';
   str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd';
   dirstr = (fib->fib_DirEntryType < 0) ? "   " : "DIR";

   fprintf (Cout, "%s %6ld %s  %-20s", str, (long)fib->fib_Size,
      dirstr, fib->fib_FileName);
   if (lengthy)
      fprintf (Cout, " %s\n", datetos(&fib->fib_Date));
   else
      fprintf (Cout, "\n");
   return ((long)fib->fib_Size);
}


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;
   }
   Write(Cout, ptr, strlen(ptr));
   if (nl)
      Oputs("");
   return (0);
}


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

   if (Src_stack == MAXSRC) {
      Eputs ("Too many source levels");
      return(-1);
   }
   fi = xopen (av[1], "r", 512);
   if (fi == 0) {
      fprintf (Cerr, "Cannot open %s\n", next_word(str));
      return(-1);
   }
   set_var(LEVEL_SET, V_PASSED, next_word(next_word(str)));
   ++H_stack;
   Src_pos[Src_stack] = 0;
   Src_base[Src_stack] = fi;
   ++Src_stack;
   while (xgets (fi, buf, 256)) {
      Src_pos[Src_stack - 1] += 1+strlen(buf);
      if (Verbose)
         Eputs(buf);
      exec_command (buf);
      if (CHECKBREAK())
         break;
   }
   --H_stack;
   --Src_stack;
   unset_level(LEVEL_LABEL + Src_stack);
   unset_var(LEVEL_SET, V_PASSED);
   xclose (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)
register char *str;
{
   static char cwd[256];
   register char sc, *ptr;
   char *name;

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

      fib = (FIB *)AllocMem(sizeof(FIB), 0);
      Clock = (struct FileLock *)((struct Process *)FindTask(0))->pr_CurrentDir;
      if (!Clock)
         CurrentDir(Clock = Lock(":", ACCESS_READ));
      lock = DupLock(Clock);
      cwd[i = 255] = '\0';
      while (lock) {
         newlock = 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, sizeof(FIB));
      bmov(cwd + i, cwd, 256 - i);
      if (str)
         Oputs(cwd);
      goto cdset;
   }
   str = next_word(str);
   if (*str == '\0')
      Oputs(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;
   }
cdset:
   set_var(LEVEL_SET, V_CWD, cwd);
   return (0);
}

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

   if (filelock = Lock(str, ACCESS_READ)) {
      if (isdir(str)) {
         if (oldlock = 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;
{
   register char *ptr = str + strlen(str) - 1;

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


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

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


do_mv()
{
   char dest[256];
   register short i;
   register 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("rm:", 507);
         return (-1);
      }
      if (Rename (av[1], av[2]))
         return (0);
   }
   perror (av[i]);
   return (-1);
}


do_rm()
{
   register short i, recur;

   recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;

   for (i = 1 + recur; i < ac; ++i) {
      if (isdir(av[i]) && recur)
         rmdir(av[i]);
      if (!DeleteFile(av[i]))
         perror(av[i]);
   }
   return (0);
}

rmdir(name)
char *name;
{
   register LOCK *lock, *cwd;
   register FIB *fib;
   register char *buf;

   buf = (char *)AllocMem(256, 0);
   fib = (FIB *)AllocMem(sizeof(FIB), 0);

   if (lock = Lock(name, ACCESS_READ)) {
      cwd = CurrentDir(lock);
      if (Examine(lock, fib)) {
         buf[0] = 0;
         while (ExNext(lock, fib)) {
            if (isdir(fib->fib_FileName))
               rmdir(fib->fib_FileName);
            if (buf[0]) {
               if (!DeleteFile(buf))
                  perror(buf);
            }
            strcpy(buf, fib->fib_FileName);
         }
         if (buf[0]) {
            if (!DeleteFile(buf))
               perror(buf);
         }
      }
      UnLock(CurrentDir(cwd));
   } else {
      perror(name);
   }
   FreeMem(fib, sizeof(FIB));
   FreeMem(buf, 256);
}


do_history()
{
   register struct HIST *hist;
   register short i = H_tail_base;
   register short 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) {
         fprintf (Cout, "%3ld ", i);
         Oputs (hist->line);
      }
      ++i;
      if (CHECKBREAK())
         break;
   }
   return (0);
}


do_mem()
{
   register long cfree, ffree;
   extern long AvailMem();

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

   if (ffree)
      fprintf (Cout, "FAST memory:%10ld\n", ffree);
   fprintf (Cout, "CHIP memory:%10ld\n", cfree);
   fprintf (Cout, "Total -----:%5ld K\n", (ffree + cfree) >> 10);
   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 short 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) {
      Eputs ("')' expected");
      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)
register char *str;
{
   long rcode = 0;
   register 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);
}


!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'comm2.c'" '(8650 characters)'
if test -f 'comm2.c'
then
	echo shar: "will not over-write existing file 'comm2.c'"
else
cat << \!Funky!Stuff! > 'comm2.c'

/*
 * COMM2.C
 *
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    ABORTLINE
 *    RETURN
 *    STRHEAD
 *    STRTAIL
 *    IF
 *    LABEL
 *    GOTO
 *    INC
 *    INPUT
 *    VER
 *    CP
 *
 */

#include "shell.h"
#include <libraries/dos.h>
#include <libraries/dosextens.h>

typedef struct FileInfoBlock FIB;
typedef struct FileLock LOCK;

extern LOCK *CurrentDir(), *Lock(), *CreateDir();

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

do_return()
{
   Exec_abortline = 1;
   if (Src_stack) {
      xseek (Src_base[Src_stack - 1], 0, 1);
      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];
   register 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];
   register 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;
{
   register char *v1, *v2, *v3, result, num;
   register 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 %ld", Src_pos[Src_stack-1], If_stack);
   set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
   return (0);
}

do_goto()
{
   register long new;
   register long pos;
   register 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);
         xseek (Src_base[Src_stack - 1], pos, -1);
         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;
{
   register char *var;
   char num[32];

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

do_input()
{
   char in[256];

   if (Ogets(in))
      set_var (LEVEL_SET, av[1], in);
   return (0);
}

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


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

do_cp()
{
   register short recur, i, ierr;
   register char *destname;
   register char destisdir;
   register FIB *fib;

   ierr = 0;
   fib = (FIB *)AllocMem(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
    *
    */


   for (i = recur + 1; i < ac - 1; ++i) {
      short srcisdir = isdir(av[i]);
      if (srcisdir) {
         struct FileLock *srcdir, *destdir;
         if (!destisdir) {        /* disallow dir to file */
            ierr = 507;
            goto done;
         }
         if (!(destdir = Lock(destname, ACCESS_READ))) {
            ierr = 205;
            goto done;
         }
         if (!(srcdir = Lock(av[i], ACCESS_READ))) {
            ierr = 205;
            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 = Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)){
               if (tmp) UnLock(tmp);
               ierr = 205;
               goto done;
            }
            UnLock(tmp);
            destdir = Lock(destname, ACCESS_READ);
            destfilename = fib->fib_FileName;
         } else {
            destdir = srcdir;
            destfilename = destname;
         }
         ierr = copyfile(av[i], srcdir, destfilename, destdir);
         if (destisdir)
            UnLock(destdir);
         if (ierr)
            break;
      }
   }
done:
   FreeMem(fib, sizeof(*fib));
   if (ierr) {
      ierror("cp", ierr);
      return(20);
   }
   return(0);
}


copydir(srcdir, destdir, recur)
register struct FileLock *srcdir, *destdir;
{
   LOCK *cwd;
   register FIB *srcfib;
   register LOCK *destlock, *srclock;
   int ierr;

   ierr = 0;
   srcfib = (FIB *)AllocMem(sizeof(FIB), 0);
   if (Examine(srcdir, srcfib)) {
      while (ExNext(srcdir, srcfib)) {
         if (srcfib->fib_DirEntryType < 0) {
            ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir);
            if (ierr)
               break;
         } else {
            if (recur) {
               cwd = CurrentDir(srcdir);
               if (srclock = Lock(srcfib->fib_FileName, ACCESS_READ)) {
                  CurrentDir(destdir);
                  if (!(destlock = Lock(srcfib->fib_FileName)))
                     destlock = CreateDir(srcfib->fib_FileName);
                  if (destlock) {
                     ierr = copydir(srclock, destlock, recur);
                     UnLock(destlock);
                  } else {
                     ierr = IoErr();
                  }
                  UnLock(srclock);
               } else {
                  ierr = IoErr();
               }
               CurrentDir(cwd);
               if (ierr)
                  break;
            }
         }
      }
   } else {
      ierr = IoErr();
   }
   FreeMem(srcfib, sizeof(FIB));
   return(ierr);
}


copyfile(srcname, srcdir, destname, destdir)
char *srcname, *destname;
struct FileLock *srcdir, *destdir;
{
   struct FileLock *cwd;
   long f1, f2;
   int i, ierr;
   char buf[256];

   ierr = 0;
   cwd = (LOCK *)CurrentDir(srcdir);
   f1 = xopen(srcname, "r", 8192);
   if (f1 == NULL) {
      ierr = 205;
      goto fail;
   }
   CurrentDir(destdir);
   f2 = xopen(destname, "w", 8192);
   if (f2 == NULL) {
      xclose(f1);
      ierr = IoErr();
      goto fail;
   }
   while (i = xread(f1, buf, 256))
      xwrite(f2, buf, i);
   xclose(f2);
   xclose(f1);
fail:
   CurrentDir(cwd);
   return(ierr);
}


!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'execom.c'" '(16586 characters)'
if test -f 'execom.c'
then
	echo shar: "will not over-write existing file 'execom.c'"
else
cat << \!Funky!Stuff! > 'execom.c'

/*
 * EXECOM.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    Handles command parsing.
 *
 *
 */

#include "shell.h"

#define F_EXACT 0
#define F_ABBR  1

#define ST_COND   0x01
#define ST_NAME   0x02


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();
extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
extern int do_forever(), do_inc(), do_abortline();
extern int do_input(), do_ver(), do_sleep(), do_help();
extern int do_strhead(), do_strtail(), do_cp();

static struct COMMAND Command[] = {
   do_run      , 0,  ST_NAME,    0 ,   "\001",
   do_number   , 0,  0,          0 ,   "\001",
   do_quit     , 0,  0,          0 ,   "quit",
   do_quit     , 0,  0,          0 ,   "exit",
   do_set_var  , 0,  0, LEVEL_SET  ,   "set",
   do_unset_var, 0,  0, LEVEL_SET  ,   "unset",
   do_set_var  , 0,  0, LEVEL_ALIAS,   "alias",
   do_unset_var, 0,  0, LEVEL_ALIAS,   "unalias",
   do_echo     , 0,  0,          0 ,   "echo",
   do_source   , 0,  0,          0 ,   "source",
   do_mv       , 2,  0,          0 ,   "mv",
   do_cd       , 0,  0,          0 ,   "cd",
   do_cd       , 0,  0,         -1 ,   "pwd",
   do_rm       , 0,  0,          0 ,   "rm",
   do_mkdir    , 0,  0,          0 ,   "mkdir",
   do_history  , 0,  0,          0 ,   "history",
   do_mem      , 0,  0,          0 ,   "mem",
   do_cat      , 0,  0,          0 ,   "cat",
   do_cp       , 2,  0,          0 ,   "cp",
   do_dir      , 0,  0,          0 ,   "dir",
   do_dir      , 0,  0,         -1 ,   "devinfo",
   do_foreach  , 3,  0,          0 ,   "foreach",
   do_forever  , 1,  0,          0 ,   "forever",
   do_return   , 0,  0,          0 ,   "return",
   do_if       , 1,  ST_COND,    0 ,   "if",
   do_if       , 0,  ST_COND,    1 ,   "else",
   do_if       , 0,  ST_COND,    2 ,   "endif",
   do_label    , 1,  ST_COND,    0 ,   "label",
   do_goto     , 1,  0,          0 ,   "goto",
   do_strhead  , 3,  0,          0 ,   "strhead",
   do_strtail  , 3,  0,          0 ,   "strtail",
   do_inc      , 1,  0,          1 ,   "inc",
   do_inc      , 1,  0,          -1,   "dec",
   do_input    , 1,  0,          0,    "input",
   do_ver      , 0,  0,          0,    "version",
   do_sleep    , 0,  0,          0,    "sleep",
   do_help     , 0,  0,          0,    "help",
   do_abortline, 0,  0,          0,    "abortline",
   NULL        , 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, "%ld", 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 short 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;      /* follow thru */
      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 (Cerr, "PREFORMAT: %ld :%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 short alias_count;
   char *istr;
   char *nextstr;
   char *command;
   char *pend_alias = NULL;
   char err = 0;

   ++alias_count;
   mpush_base();
   if (*str == 0)
      goto done1;
step1:
   if (alias_count == MAXALIAS) {
      Eputs("Alias Loop");
      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 == '!') {
      istr = get_history(str);
      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] = NULL;
      cont = 1;
      doexpand = redir = inc = 0;

      while (cont && elast) {
         ptr = exarg(&nextstr);
         inc = 1;
         arg = "";
         cont = (elast == 0x80);
         switch (*ptr) {
         case '<':
            redir = -2;          /* -2 so ++ still keeps it negative */
         case '>':
            ++redir;             /* normal >  */
            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;

         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] = NULL;

   /* 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 long 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 (Cerr, "AV[%2ld] %ld :%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 short ccno;
         register long cin, cout;

         ccno = find_command (command);
         if ((Command[ccno].stat & ST_NAME) == 0) {
            if (Cin_name) {
               cin = Cin;
               Cin = Open(Cin_name, 1005);
               if (Cin == 0) {
                  ierror (NULL, 504);
                  err = 1;
                  Cin = cin;
                  Cin_name = NULL;
               }
            }
            if (Cout_name) {
               cout = Cout;
               if (Cout_append) {
                  if (Cout = Open(Cout_name, 1005))
                     Seek(Cout, 0, 1);
               } else {
                  Cout = Open(Cout_name, 1006);
               }
               if (Cout == NULL) {
                  err = 1;
                  ierror (NULL, 504);
                  Cout = cout;
                  Cout_name = NULL;
                  Cout_append = 0;
               }
            }
         }
         if (ac < Command[ccno].minargs + 1) {
            ierror (NULL, 500);
            err = -1;
         } else {
            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) {
               Close(Cin);
               Cin = cin;
            }
            if (Cout_name) {
               Close(Cout);
               Cout = cout;
               Cout_append = 0;
            }
         }
      }
      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 = NULL;
      }
      Cout_name = NULL;
      Cout_ispipe = Cout_append = 0;
      elast = save_elast;
   }
   mpop_tobase();                      /* free arguments   */
   mpush_base();                       /* push dummy base  */

done0:
   {
      register char *str;
      if (Debug & 0x10)
         printf ("err = %ld, E_stack = %ld\n", err, E_stack);
      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 (Debug & 0x10) {
         printf ("elast = %ld  Exec_abortline = %ld\n", elast, Exec_abortline);
         printf ("nextstr = %s\n", nextstr);
      }
      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()
{
   register char *str;

   str = malloc(5);
   *(char ***)str = Mlist;
   str[4] = 0;
   Mlist = (char **)str;
}

char *
mpush(bytes)
{
   register 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;
   register short len;

   for (strskip = 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;
{
   short i;
   short 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 ((int)i);
   }
   return (0);
}


do_help()
{
   register struct COMMAND *com;

   for (com = &Command[2]; com->func; ++com)
      fprintf (Cout, "%s ", com->name);
   Oputs ("");
   return (0);
}

!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'fexec1.c'" '(3985 characters)'
if test -f 'fexec1.c'
then
	echo shar: "will not over-write existing file 'fexec1.c'"
else
cat << \!Funky!Stuff! > 'fexec1.c'

/*
 * FEXEC1.C
 *
 *    wait() and fexecv()
 *
 *    This code originated from Manx's fexecv code.  I claim credit only
 *    for the major modifications I've done to it.
 *
 */

#include "shell.h"
#include <libraries/dosextens.h>

typedef struct FileHandle           FH;
typedef struct CommandLineInterface CLI;
typedef struct Process              PROC;

static int ret_val;

extern PROC *FindTask();
extern char *AllocMem();

wait()
{
   return(ret_val);
}


fexecv(cmd, argv, stdin_str, stdout_str, stdout_append)
char *cmd, **argv;
char *stdin_str, *stdout_str;
{
   register CLI *cli;
   register char **ap, *cp, *arg;
   PROC *pp;
   APTR sav_ret;
   BPTR sav_CIS, sav_COS;
   long save_stdin_buf, save_stdin_pos, save_stdin_end;
   long len, seg, sav_seg;
   long openmode;
   long *stk;
   FH *fhp, *stdin, *stdout;
   char buf[40];

   pp = FindTask(0L);
   if ((cli = (CLI *)((long)pp->pr_CLI << 2)) == 0)
      return(-1);
   if ((seg = LoadIt(cmd)) == 0)
      return(-3);
   stdin = (FH *)((stdin_str)? Open(stdin_str, 1005) : pp->pr_CIS);
   if (!stdin) {
      fprintf(Cerr, "Input redirection error\n");
      return(-4);
   }
   openmode = (stdout_append) ? 1005 : 1006;
   stdout= (FH *)((stdout_str)? Open(stdout_str, openmode) : pp->pr_COS);
   if (!stdout) {
      fprintf(Cerr, "Output redirection error\n");
      if (stdin_str)
         Close(stdin);
      return(-5);
   }
   if (stdout_append)
      Seek(stdout, 0, 1);
   sav_seg = cli->cli_Module;
   cli->cli_Module = seg;
   stk = (long *)AllocMem(4 * cli->cli_DefaultStack + 8, 0);
   *stk = 4 * cli->cli_DefaultStack + 8;
   stk = (long *)((long)stk + 4 * cli->cli_DefaultStack);
   stk[0] = 4 * cli->cli_DefaultStack;
   stk[1] = ((long *)pp->pr_ReturnAddr)[1];
   sav_ret = pp->pr_ReturnAddr;
   pp->pr_ReturnAddr = (APTR)stk;

   for (len = 1, ap = argv + 1; *ap; ++ap)
      len += strlen(*ap) + 1;
   cp = arg = AllocMem(len, 0);
   for (ap = argv + 1; *ap; ++ap) {
      strcpy(cp, *ap);
      strcat(cp, " ");
      cp += strlen(cp);
   }
   arg[len-1] = '\n';
   cp = (char *)((long)cli->cli_CommandName << 2);
   movmem(cp, buf, 40);
   strcpy(cp + 1, cmd);
   cp[0] = strlen(cmd);

   fhp = (FH *)((long)stdin << 2);
   save_stdin_buf = fhp->fh_Buf;
   save_stdin_pos = fhp->fh_Pos;
   save_stdin_end = fhp->fh_End;

   fhp->fh_Buf = (long)AllocMem(202, 0) >> 2;
   strncpy(fhp->fh_Buf<<2, arg, (int)((len < 200)?len:199));
   fhp->fh_Pos = 0;
   fhp->fh_End = (len < 200)?len:199;

   sav_CIS = pp->pr_CIS;
   sav_COS = pp->pr_COS;

   pp->pr_CIS = (BPTR)stdin;
   pp->pr_COS = (BPTR)stdout;

   ret_val = doexec(len, arg, (seg+1)<<2, stk);

   FreeMem(fhp->fh_Buf<<2, 202);
   fhp->fh_Buf = save_stdin_buf;
   fhp->fh_Pos = save_stdin_pos;
   fhp->fh_End = save_stdin_end;
   /*
   fhp->fh_Pos = fhp->fh_End;
   */

   if (stdin_str)
      Close(stdin);
   if (stdout_str)
      Close(stdout);
   pp->pr_CIS = sav_CIS;
   pp->pr_COS = sav_COS;

   UnLoadSeg(cli->cli_Module);
   pp->pr_ReturnAddr = sav_ret;
   cli->cli_Module = sav_seg;
   FreeMem(arg, len);
   movmem(buf, cp, 40);
   return(0);
}


LoadIt(cmd)
char *cmd;
{
   char buf[128];
   long seg;

   seg = LoadSeg(FindIt(cmd, "", buf));
   return (seg);
}


char *
FindIt(cmd, ext, buf)
char *cmd;
char *ext;
char *buf;
{
   int n;
   long lock = 0;
   APTR original;
   PROC *myproc = FindTask(0);
   char *ptr;
   char *p;

   original = myproc->pr_WindowPtr;
   myproc->pr_WindowPtr = (APTR)(-1);

   if ((p = get_var(LEVEL_SET, V_PATH)) == NULL)
      p = "";
   for (ptr = cmd; *ptr; ++ptr) {
      if (*ptr == '/' || *ptr == ':')
         p = "";
   }

   strcpy(buf, cmd);
   strcat(buf, ext);
   while ((lock = Lock(buf, ACCESS_READ)) == 0) {
      if (*p == '\0')
         break;
      for (n = 0; p[n] && p[n] != ','; ++n);
      strncpy(buf, p, n);
      strcat(buf, cmd);
      strcat(buf, ext);
      p += n + (*p != 0);
   }
   myproc->pr_WindowPtr = original;
   if (lock)
      UnLock(lock);
   return(buf);
}


!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'globals.c'" '(3262 characters)'
if test -f 'globals.c'
then
	echo shar: "will not over-write existing file 'globals.c'"
else
cat << \!Funky!Stuff! > 'globals.c'

/*
 * GLOBALS.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *
 *    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                 */
int   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         */
short H_len, H_tail_base;     /* History associated stuff               */
short H_stack;                /* AddHistory disable stack               */
short E_stack;                /* Exception disable stack                */
short Src_stack, If_stack;    /* Stack Indexes                          */
short ac;                     /* Internal argc                          */
short Debug;                  /* Debug mode                             */
short Disable;                /* Disable com. execution (conditionals)  */
short Verbose;                /* Verbose mode for source files          */
long  Lastresult;             /* Last return code                       */
short Exec_abortline;         /* flag to abort rest of line             */
short Exec_ignoreresult;      /* flag to ignore result                  */
short Quit;                   /* Quit flag                              */
long  Cout, Cin, Cerr;        /* 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               */

short S_histlen = 20;         /* Max # history entries                  */


!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'hat.c'" '(1111 characters)'
if test -f 'hat.c'
then
	echo shar: "will not over-write existing file 'hat.c'"
else
cat << \!Funky!Stuff! > 'hat.c'

/*
 *    HAT.C
 *
 *    Modify the last history entry ^search^replace.  Called from
 *    MAIN.C
 *
 */

extern char *last_history_entry();

hat_replace(buf)
char *buf;
{
   char res[256];
   char *ptr, *hb, *repstr, *srchstr;
   int searchlen, replacelen;

   srchstr = buf + 1;
   for (repstr = srchstr; *repstr && *repstr != '^'; ++repstr);
   if (*repstr) {
      searchlen = repstr - srchstr;
      *repstr = '\0';
      ++repstr;
   }
   replacelen = strlen(repstr);

   for (ptr = hb = last_history_entry(); *ptr; ++ptr) {
      if (strncmp(ptr, srchstr, searchlen) == 0) {
         bmov(hb, res, ptr - hb);         /* first part of history   */
         res[ptr-hb] = '\0';              /* add 0                   */
         strcat(res, repstr);             /* add replace string      */
         strcat(res, ptr+searchlen);      /* add rest of history     */
         strcpy(buf, res);                /* copy                    */
         puts (buf);
         return(1);                       /* done                    */
      }
   }
   puts ("modifier failed");
   *buf = '\0';
   return(0);
}


!Funky!Stuff!
fi  # end of overwriting check
exit 0
#	End of shell archive