#      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:
#      comm2.c
#      execom.c
# This archive created: Wed Mar 16 10:14:50 1988
echo shar: extracting comm2.c
cat << \SHAR_EOF > comm2.c
/*
 * COMM2.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * Version 2.07M by Steve Drew 10-Sep-87
 *
 * Version 2.08MI by Carlo Borreo & Cesare Dieni 13-Mar-88
 *
 */
 
#include "shell.h"
 
extern char *v_gotofwd;
 
typedef struct FileInfoBlock FIB;
 
/* Casting conveniences */
#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
#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 int has_wild;                    /* flag set if any arg has a ? or * */
extern struct DosLibrary *DOSBase;      /* dos library base pointer         */
 
/* globals */
int cp_update;
int cp_date;
 
do_abortline()
{
   Exec_abortline = 1;
   return (0);
}
 
do_return()
{
register int retcode=(ac<2 ? 0 : atoi(av[1]));
   Exec_abortline = 1;
   if (Src_stack) {
       FILE *ptr = (FILE *)Src_base[Src_stack - 1];
       ptr->_bp = ptr->_bend;
       ptr->_flags |= _EOF;
/*     fseek (Src_base[Src_stack - 1], 0L, 2); */
      return retcode;
   } else main_exit(retcode);
}
 
/*
 * 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);
}
 
long dptrtosecs(d)
struct DPTR *d;
{
register struct DateStamp *ds=(&d->fib->fib_Date);
return ds->ds_Days * 86400 + ds->ds_Minute * 60 + ds->ds_Tick/TICKS_PER_SECOND;
}
 
long timeof(s)
char *s;
{
struct DPTR *d;
int dummy;
long n;
 
if ( (d=dopen(s,&dummy))==NULL ) return 0L;
n=dptrtosecs(d);
dclose(d);
return n;
}
 
/*
 * if -f file (exists) or:
 *
 * if A < B   <, >, =, <=, >=, !=, where A and B are either:
 * nothing
 * a string
 * a value (begins w/ number)
 */
 
do_if(garbage, com)
char *garbage;
{
int not;
register int result;
 
switch (com)
    {
    case 0:
       if (If_stack && If_base[If_stack - 1]) If_base[If_stack++] = 1;
       else
               if ( (result=evalif(&not)) > 1) ierror(NULL,result);
                       else If_base[If_stack++] = (not ? result : !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;
if (If_stack >= MAXIF)
       {
       fprintf(stderr,"If's too deep\n");
       disable = If_stack = 0;
       return(-1);
       }
if (forward_goto) disable = If_base[If_stack - 1] = 0;
return (0);
}
 
evalif(not)
int *not;
{
register char *a, *b, c;
register int flags;
int i;
long num;
struct FileLock *lock;
 
flags=get_opt("nfdm",&i);
*not=(flags & 1);
switch (ac-i)
    {
    case 0:
       if ( (flags & 8) && (a=(char *)AllocMem(1L,(long)MEMF_FAST)) )
               {
               FreeMem(a,1L);
               return 1;
               }
       return 0;
    case 1:
       a=av[i];
       if (flags & 2)
       {
       if (lock=(struct FileLock *)Lock(a, ACCESS_READ)) UnLock(lock);
       return lock!=NULL;
       }
       return (*a!=0 && strcmp(a," ")!=0);
    case 3:
       if (flags & 4) num=timeof(av[i])-timeof(av[i+2]);
       else
               {
               for (a=av[i  ]; *a==' '; a++);
               for (b=av[i+2]; *b==' '; b++);
               num=( *a>='0' && *b<='9' ? atoi(a)-atoi(b) : strcmp(a,b));
               }
       if (num < 0)      c='<';
       else if (num > 0) c='>';
       else if (num ==0) c='=';
       for (a=av[i+1]; *a; a++) if (c == *a) return 1;
       return 0;
    default:
       return 500;
    }
}
 
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);
   if (!strcmp(av[1],get_var(LEVEL_SET,v_gotofwd)))
      forward_goto = 0;
   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) {
         forward_goto = 1;
         set_var (LEVEL_SET, v_gotofwd, av[1]);
         return(0);
      } 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], *p,*s;
   int i;
 
   for (i=1; i < ac; ++i) {
      if ((gets(in)) != 0) {
         for(p = in; *p; p = s) {
            s = next_word(p);
            if (*s) *(s-1) = 0xA0;
         }
         set_var (LEVEL_SET, av[i], 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             cmd[40];       /* holds cmd name               */
        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? */
 
 
                        printf("%2d   %-20.20s %-11.11s %3d  %8lx  %s\n",
                           count,btocstr(CLI(PROC(task))->cli_CommandName, cmd),
                           task->tc_Node.ln_Name,
                           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 */
        movmem(s +1, buf, s[0]);
        buf[s[0]] = '\0';
        return buf;
}
 
 
/*
 * CP [-d] [-u] file file
 * CP [-d] [-u] file file file... destdir
 * CP [-r][-u][-d] dir dir dir... destdir
 */
 
char *errstr;          /* let's be alittle more informative */
do_copy()
{
   register int recur, ierr;
   register char *destname;
   register char destisdir;
   register FIB *fib;
   int i,opt;
 
   errstr = "";
   ierr = 0;
 
   fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
 
   opt = get_opt("rud",&i);
   recur     = (opt & 0x01);
   cp_update = (opt & 0x02);
   cp_date   = (!(opt & 0x04)); /* the default is keep orignal file date */
 
   destname = av[ac - 1];
 
   if (ac < i + 2) {
      ierr = 500;
      goto done;
   }
 
   destisdir = isdir(destname);
   if (ac > i + 2 && !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 < 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) {
            if (destdir = (struct FileLock *)Lock(destname, ACCESS_READ)) {
               UnLock(destdir);
               ierr = 507;                /* disallow dir to file */
               goto done;
            }
            if (destdir = (struct FileLock *)CreateDir(destname))
               UnLock(destdir);
            destisdir = 1;
         }
         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 *)(Myprocess->pr_CurrentDir);
 
         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);
         if (destisdir) {
            destdir = (struct FileLock *)Lock(destname, ACCESS_READ);
            destfilename = fib->fib_FileName;
         } else {
            destdir = srcdir;
            destfilename = destname;
         }
         printf(" %s..",av[i]);
         fflush(stdout);
         ierr = copyfile(av[i], srcdir, destfilename, destdir);
         if (destisdir)
            UnLock(destdir);
         if (ierr)
            break;
      }
   }
done:
   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);
            fflush(stdout);
            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);
 
                        /* UnLock and re Lock if newly created
                           for file_date() to work properly
                        */
                     if (destlock) UnLock(destlock);
                     destlock = (struct FileLock *)Lock(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 stat,ierr;
char *buf;
struct DPTR *dp, *dps = NULL;
 
if ((buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR))==NULL)
       { ierr = 103; goto fail; }
ierr = 0;
cwd = (struct FileLock *)CurrentDir(srcdir);
if ((f1=Open(srcname, MODE_OLDFILE))==NULL)
       { errstr = srcname; ierr = 205; goto fail; }
dps = dopen(srcname,&stat);
CurrentDir(destdir);
if (cp_update)
       {
       dp=dopen(destname, &stat);
       if ( dptrtosecs(dp) >= dptrtosecs(dps) &&
               !strcmp(dps->fib->fib_FileName, dp->fib->fib_FileName))
               { dclose(dp); Close(f1); printf("..not newer\n"); goto fail; }
       dclose(dp);
       }
if ((f2=Open(destname, MODE_NEWFILE))==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)
       {
       if (cp_date) file_date(&dps->fib->fib_Date, destname);
       printf("..copied\n");
       }
else DeleteFile(destname);
fail:
 dclose(dps);
 if (buf) FreeMem(buf, 8192L);
 CurrentDir(cwd);
 return(ierr);
}
 
file_date(date,name)
struct DateStamp *date;
char *name;
{
    UBYTE *ptr;
    struct MsgPort *task;
    struct FileLock *dirlock;
    struct DPTR *tmp;
    int stat;
    long ret, dos_packet();
 
    if (!(task = (struct MsgPort *)DeviceProc(name)))
        return(1);
    if (tmp = dopen(name, &stat)) {
        dirlock = (struct FileLock *)ParentDir(tmp->lock);
        ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
        strcpy((ptr + 1),tmp->fib->fib_FileName);
        *ptr = strlen(tmp->fib->fib_FileName);
        dclose(tmp);
        ret = dos_packet(task,34L,NULL,dirlock,
                         (ULONG)&ptr[0] >> 2L,date);
        FreeMem(ptr,64L);
        UnLock(dirlock);
    }
}
SHAR_EOF
if test 15553 -ne "`wc -c comm2.c`"
then
echo shar: error transmitting comm2.c '(should have been 15553 characters)'
fi
echo shar: extracting execom.c
cat << \SHAR_EOF > execom.c
/*
 * EXECOM.C
 *
 * Matthew Dillon, 10 August 1986
 *    Finally re-written.
 *
 * Version 2.07M by Steve Drew 10-Sep-87
 *
 * Version 2.08MI by Carlo Borreo & Cesare Dieni 13-Mar-88
 *
 */
 
#include "shell.h"
 
extern char *v_histnum, *v_except;
 
#define F_EXACT 0
#define F_ABBR  1
 
#define ST_COND   0x01
#define ST_NORED  0x02
#define ST_NOEXP  0x04
#define ST_AV     0x08 /* delimit args within a variable */
 
int has_wild = 0;                 /* set if any arg has wild card */
 
 
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_pwd(), do_rm(), do_mkdir(), do_history();
extern int do_mem(), do_cat(), do_dir(), do_devinfo(), 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_protect(), do_ps();
extern int do_forever(), do_abortline();
extern int do_tiny(), do_big(), do_search(), do_filenote();
char *push_cpy();
 
static struct COMMAND Command[] = {
do_run      , 0,  ST_AV,      0,   "\001",   /* may call do_source */
do_number   , 0,  0,          0 ,   "\001",
do_set_var  , 0,  0, LEVEL_ALIAS,   "alias",  /* uses avline */
do_abortline, 0,  0,          0,    "abortline",
do_big      , 0,  0,          0 ,   "big",
do_cat      , 0,  0,          0 ,   "cat",
do_cd       , 0,  0,          0 ,   "cd",
do_copy     , 1,  0,          0 ,   "copy",
do_copy     , 1,  0,          0 ,   "cp",
date        , 0,  0,          0 ,   "date",
do_dir      , 0,  ST_NOEXP,   0 ,   "dir",
do_inc      , 1,  0,         -1 ,   "dec",
do_devinfo  , 0,  0,          0 ,   "devinfo",
do_echo     , 0,  0,          0 ,   "echo",  /* uses avline */
do_if       , 0,  ST_COND,    1 ,   "else",
do_if       , 0,  ST_COND,    2 ,   "endif",
do_filenote , 0,  0,          0 ,   "filenote",
do_foreach  , 3,  ST_NORED,   0 ,   "foreach",
do_forever  , 1,  ST_NORED,   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_dir      , 0,  ST_NOEXP,   0 ,   "ls",
do_mkdir    , 0,  0,          0 ,   "md",
do_mem      , 0,  0,          0 ,   "mem",
do_mkdir    , 0,  0,          0 ,   "mkdir",
do_mv       , 2,  0,          0 ,   "mv",
do_protect  , 0,  0,          0 ,   "protect",
do_ps       , 0,  0,          0,    "ps",
do_pwd      , 0,  0,          0 ,   "pwd",
do_quit     , 0,  ST_NORED,   0 ,   "quit",
do_return   , 0,  0,          0 ,   "return",
do_run      , 1,  ST_NORED,   0,    "run",
do_rm       , 0,  0,          0 ,   "rm",
do_search   , 0,  0,          0,    "search",
do_set_var  , 0,  ST_AV, LEVEL_SET, "set",
do_sleep    , 0,  0,          0,    "sleep",
do_source   , 0,  ST_NORED|ST_AV, 0,"source", /* uses avline */
do_strhead  , 3,  0,          0 ,   "strhead",
do_strtail  , 3,  0,          0 ,   "strtail",
do_tiny     , 0,  0,          0 ,   "tiny",
do_cat      , 0,  0,          0 ,   "type",
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;
   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);
   return (fcomm(scr, 1) ? -1 : 1);
}
 
isalphanum(c)
register char c;
{
return (
       (c >= '0' && c <= '9') ||
       (c >= 'a' && c <= 'z') ||
       (c >= 'A' && c <= 'Z') ||
       (c == '_')
       );
}
 
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) 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[1] == '$') {
      if (istr = get_var (LEVEL_SET, str + 2))
         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) {
      if (cmd_stat(command) & ST_COND)
         goto skipgood;
   }
   if (disable || forward_goto) {
      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) {
         int cstat = cmd_stat(command);
 
         ptr = exarg(&nextstr);
         inc = 1;
         arg = "";
         cont = (elast == 0x80);
         switch (*ptr) {
         case '<':
            redir = -2;
         case '>':
            if (cstat & (ST_NORED | ST_COND)) {
                                                        /* don't extract   */
                redir = 0;                              /* <> stuff if its */
                arg = ptr;                              /* external cmd.   */
                break;
            }
            ++redir;
            arg = ptr + 1;
            if (*arg == '>') {
               redir = 2;        /* append >> */
               ++arg;
            }
            cont = 1;
            break;
         case '$':
            /* restore args if from set command or pend_alias */
            if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
               if (cstat & ST_COND) {
                  char *tp;
                  tp = push_cpy(arg);
                  arg = tp;
               }
               else {
                  char *pe, sv, *index();
                  while (pe = index(arg,0xA0)) {
                     sv = *pe;
                     *pe = '\0';
                     av[ac++] = push_cpy(arg);
                     *pe = sv;
                     av[ac] = '\0';
                     arg = pe+1;
                  }
               }
            }
            else
               arg = ptr;
            break;
         case '*':
         case '?':
            if ((cstat & ST_NOEXP) == 0)
               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)+strlen(av[ac]));
            strcpy(av[ac], old);
            strcat(av[ac], arg);
         } else {
            av[ac] = push_cpy(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++] = push_cpy(*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;
      char *compile_av();
      register char *avline;
      unsigned char delim = ' ';
 
      save_elast = elast;
      if (pend_alias || (cmd_stat(command) & ST_AV))
         delim = 0xA0;
      avline = compile_av(av,((pend_alias) ? 1 : 0), ac , delim);
 
 
      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  = Myprocess->pr_CIS;
         long  oldcout = Myprocess->pr_COS;
         char *Cin_buf;
         struct FileHandle *ci;
         long oldbuf;
         struct _dev *stdfp;
 
         fflush(stdout);
         ccno = find_command (command);
         if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
            if (Cin_name) {
               if ((Cin = (long)Open(Cin_name,1005L)) == 0L) {
                  ierror (NULL, 504);
                  err = 1;
                  Cin_name = '\0';
               } else {
                  Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
                  ci = (struct FileHandle *)(((long)Cin)<<2);
                  Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
                  oldbuf = ci->fh_Buf;
                  if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
                     ci->fh_Buf = (long)Cin_buf>>2;
               }
            }
            if (Cout_name) {
               if (Cout_append && (Cout =(long)Open(Cout_name, 1005L)) ) {
                     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 = _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 (E_stack == 0 && Lastresult != err) {
            Lastresult = err;
            seterr();
         }
         if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
            if (Cin_name) {
               fflush(stdin);
               clearerr(stdin);
               ci->fh_Buf = oldbuf;
               Close(Cin);
               FreeMem(Cin_buf, 202L);
            }
            if (Cout_name) {
               fflush(stdout);
               clearerr(stdout);
               stdout->_flags &= ~_DIRTY;    /* because of nil: device */
               Close(Cout);
               Cout_append = 0;
            }
         }
         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(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
   *(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);
}
 
cmd_stat(str)
char *str;
{
   return(Command[find_command(str)].stat);
}
 
find_command(str)
char *str;
{
   register unsigned 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);
}
 
 
char *
push_cpy(s)
char *s;
{
   return(strcpy(mpush(strlen(s)), s));
}
SHAR_EOF
if test 19149 -ne "`wc -c execom.c`"
then
echo shar: error transmitting execom.c '(should have been 19149 characters)'
fi
#      End of shell archive
exit 0
