#      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:
#      makefile
#      shell.h
#      sub.c
# This archive created: Wed Mar 16 10:14:50 1988
echo shar: extracting makefile
cat << \SHAR_EOF > makefile
######################################################################
#
# Makefile to build Shell 2.08MI
# by Carlo Borreo & Cesare Dieni 13-Mar-88
#
######################################################################
 
OBJS    = run.o main.o comm1.o comm2.o execom.o set.o sub.o \
          globals.o rawconsole.o sort.o
 
INCL    = shell.h
 
Shell   : $(OBJS)
        ln  +q -m -o Shell $(OBJS) -lc
 
rawconsole.o : rawconsole.c $(INCL)
        cc    +IShell.syms rawconsole.c
 
run.o   : run.c $(INCL)
        cc    +HShell.syms run.c
 
main.o  : main.c $(INCL)
        cc    +IShell.syms main.c
 
comm1.o : comm1.c $(INCL)
        cc    +IShell.syms comm1.c
 
comm2.o : comm2.c $(INCL)
        cc    +IShell.syms comm2.c
 
set.o   : set.c $(INCL)
        cc    +IShell.syms set.c
 
sub.o   : sub.c $(INCL)
        cc    +IShell.syms sub.c
 
globals.o : globals.c $(INCL)
        cc    +IShell.syms globals.c
 
execom.o : execom.c $(INCL)
        cc    +IShell.syms execom.c
SHAR_EOF
if test 970 -ne "`wc -c makefile`"
then
echo shar: error transmitting makefile '(should have been 970 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
 *
 * Version 2.07M by Steve Drew 10-Sep-87
 *
 * Version 2.08MI by Carlo Borreo & Cesare Dieni 13-Mar-88
 *
 */
 
#define RAW_CONSOLE 1   /* Set to 0 to compile out Cmd Line Editing */
 
#include <stdio.h>
#include <exec/exec.h>
#include <time.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuitionbase.h>
#include <functions.h>
#include <fcntl.h>
 
#define bmov   movmem
 
#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
 
            /* 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.08MI (c)1986 Matthew Dillon. Manx (M) versions by \
Steve Drew\n(I) versions by Carlo Borreo & Cesare Dieni\n"
 
#ifndef NULL
#define NULL 0L
#endif
 
/* #define CHECKBREAK() ( breakcheck() ? (printf("^C\n"),1) : 0) */
#define CHECKBREAK() dobreak()
 
#ifndef AZTEC_C
struct _dev      {
                long  fd;
                short mode;
        };
#endif
 
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, forward_goto;
extern int  ac;
extern int  debug, Rval, Verbose, disable, Quit;
extern int  Lastresult;
extern int  Exec_abortline;
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 3027 -ne "`wc -c shell.h`"
then
echo shar: error transmitting shell.h '(should have been 3027 characters)'
fi
echo shar: extracting sub.c
cat << \SHAR_EOF > sub.c
 
/*
 * SUB.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_lasterr, *v_stat;
 
#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 && (unsigned char)*str != 0xA0)
      ++str;
   while (*str  && (*str == ' ' || *str == 9 || (unsigned char)*str == 0xA0))
      ++str;
   return (str);
}
 
char *
compile_av(av, start, end, delim)
char **av;
unsigned char delim;
{
   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) {
      if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
      strcat (cstr, av[i]);
      if (i + 1 < end)
         strncat(cstr, &delim, 1);
   }
   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 %d %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 ((struct FileLock *)
                                             Myprocess->pr_CurrentDir);
   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(base,pac)
 *    base           - char * (example: "df0:*.c")
 *    pac            - int  *  will be set to # of arguments.
 *
 * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
 *                 simple directory/file lookups. Returns a pointer to
 *                 an array of pointers that contains the full file spec
 *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
 *
 *                 Now no longer necessary to Examine the files a second time
 *                 in do_dir since expand will return the full file info
 *                 appended to the file name. Set by formatfile().
 *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
 *
 *                 Caller must call free_expand when done with the array.
 *
 * base             bname =       ename =
 * ------           -------       -------
 *  "*"               ""            "*"
 *  "!*.info"         ""            "*.info" (wild_exclude set)
 *  "su*d/*"          ""            "*"      (tail set)
 *  "file.*"          ""            "file.*"
 *  "df0:c/*"         "df0:c"       "*"
 *  ""                ""            "*"
 *  "df0:.../*"       "df0:"        "*"      (recur set)
 *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
 *
 * ---the above base would be provided by execom.c or do_dir().
 * ---the below base would only be called from do_dir().
 *
 *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
 *  "df0:"            "df0:"        "*"
 *  "file/file"       "file/file"   ""       (dp == 0) so fail
 *  "df0:.../"        "df0:"        "*"      (recur set)
 *
 */
 
 
char **
expand(base, pac)
char *base;
int *pac;
{
   register char *ptr;
   char **eav = (char **)malloc(sizeof(char *) * (2));
   short eleft, eac;
   char *name;
   char *svfile();
   char *bname, *ename, *tail;
   int stat, recur, scr, bl;
   register struct DPTR *dp;
 
   *pac = recur = eleft = eac = 0;
 
   base = strcpy(malloc(strlen(base)+1), base);
   for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
 
   if (!*ptr)   /* no wild cards */
      --ptr;
   else
      for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
 
   if (ptr < base) {
      bname = strcpy (malloc(1), "");
   } else {
      scr = ptr[1];
      ptr[1] = '\0';
      if (!strcmp(ptr-3,".../")) {
         recur = 1;
         *(ptr-3) = '\0';
      }
      bname = strcpy (malloc(strlen(base)+2), base);
      ptr[1] = scr;
   }
   bl = strlen(bname);
   ename = ++ptr;
   for (; *ptr && *ptr != '/'; ++ptr);
   scr = *ptr;
   *ptr = '\0';
   if (scr) ++ptr;
   tail = ptr;
 
   if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
      free (bname);
      free (base);
      free (eav);
      return (NULL);
   }
 
   if (!stat) {                /* eg. 'dir file' */
      char *p,*s;
      for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
      if (s != bname) ++s;
      *s ='\0';
      eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
      goto done;
   }
   if (!*ename) ename = "*";    /* eg. dir df0: */
   if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
      bname[bl] = '/';
      bname[++bl] = '\0';
   }
   while ((dnext (dp, &name, &stat)) && !breakcheck()) {
        int match = compare_ok(ename,name);
      if (match && !(!recur && *tail)) {
         if (eleft < 2) {
               char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
               movmem (eav, scrav, (eac + 1) << 2);
               free (eav);
               eav = scrav;
               eleft = 10;
         }
         eav[eac++] = svfile(bname,name,dp->fib);
         --eleft;
      }
      if ((*tail && match) || recur) {
         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 (dp->lock);
         search = malloc(strlen(ename)+strlen(name)+strlen(tail)+5);
         strcpy (search, name);
         strcat (search, "/");
         if (recur) {
            strcat(search, ".../");
            strcat(search, ename);
         }
         strcat (search, tail);
         scrav = alt_av = expand (search, &alt_ac);
         /* free(search); */
         CurrentDir (lock);
         if (scrav) {
            while (*scrav) {
               int l;
               if (eleft < 2) {
                  char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
                  movmem (eav, scrav, (eac + 1) << 2);
                  free (eav);
                  eav = scrav;
                  eleft = 10;
               }
 
               l = strlen(*scrav);
               scrav[0][l] = ' ';
               eav[eac] = malloc(bl+l+40);
               strcpy(eav[eac], bname);
               strcat(eav[eac], *scrav);
               eav[eac][l+bl] = '\0';
 
               free (*scrav);
               ++scrav;
               --eleft, ++eac;
            }
            free (alt_av);
         }
      }
   }
done:
   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 *back0[MAXB], *back1[MAXB];
int bi=0, queryflag;
 
if (*w=='!') return !compare_ok(wild+1,name);
else if (queryflag=(*w=='&')) w++;
while (*n || *w)
   {
   switch (*w)
      {
      case '*':
       if (bi==MAXB) { printf(stderr,"Too many levels of '*'\n"); return 0; }
       back0[bi] = w;
       back1[bi] = n;
       ++bi;
       ++w;
       continue;
goback:
       --bi;
       while (bi >= 0 && *back1[bi] == '\0') --bi;
       if (bi < 0) return 0;
       w = back0[bi] + 1;
       n = ++back1[bi];
       ++bi;
       continue;
      case '?':
       if (!*n) goto goback;
       break;
      default:
       if (TOLOWER(*n)!=TOLOWER(*w)) goto goback;
       break;
      }
   if (*n) ++n;
   if (*w) ++w;
   }
if (queryflag)
       {
       char in[256];
       printf("Select \23337m%-16s\2330m [y/n] ? ",name);
       gets(in);
       return (TOLOWER(*in)=='y');
       }
return 1;
}
 
char *
svfile(s1,s2,fib)
char *s1,*s2;
struct FileInfoBlock *fib;
{
   char *p;
   p = malloc (strlen(s1)+strlen(s2)+40);
   strcpy(p, s1);
   strcat(p, s2);
   formatfile(p,fib);
   return(p);
}
 
/* will have either of these formats:
 *
 *    fullfilename'\0'arwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
 *    fullfilename'\0'arwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
 *                    01234567890123456789012345678901234567 8 9
 *
 */
formatfile(str,fib)
char *str;
register struct FileInfoBlock *fib;
{
char *dates();
 
while(*str++);
*str++ = (fib->fib_Protection & FIBF_ARCHIVE)        ? 'a' : ' ';
*str++ = (fib->fib_Protection & FIBF_READ)           ? '-' : 'r';
*str++ = (fib->fib_Protection & FIBF_WRITE)          ? '-' : 'w';
*str++ = (fib->fib_Protection & FIBF_EXECUTE)        ? '-' : 'e';
*str++ = (fib->fib_Protection & FIBF_DELETE)         ? '-' : 'd';
if (fib->fib_DirEntryType < 0)
  sprintf(str,"  %6ld %4ld  ", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
else strcpy(str,"   <Dir>       ");
strcat(str,dates(&fib->fib_Date));
}
SHAR_EOF
if test 13937 -ne "`wc -c sub.c`"
then
echo shar: error transmitting sub.c '(should have been 13937 characters)'
fi
#      End of shell archive
exit 0
