Files com074d/28.com and com075/28.com are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/alias.c com075/alias.c
--- com074d/alias.c	Thu Jul 16 10:57:22 1998
+++ com075/alias.c	Fri Aug  7 08:44:26 1998
@@ -5,54 +5,58 @@
  *
  *  Comments:
  *
- *  02/02/1996 (Oliver Mueller) --------------------------------------------
+ *  02/02/1996 (Oliver Mueller)
  *    started.
  *
- *  02/03/1996 (Oliver Mueller) --------------------------------------------
+ *  02/03/1996 (Oliver Mueller)
  *    Added sorting algorithm and case sensitive substitution by using
  *    partstrupr().
  *
+ * 27 Jul 1998  John P. Price
+ * - added config.h include
+ * - added ifdef's to disable aliases
+ *
  */
 
-#ifdef __TURBOC__
-#include <alloc.h>
-#else
-#include <malloc.h>
-#endif
+#include "config.h"
+
+#ifdef FEATURE_ALIASES
+
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
 #include <mem.h>
 #include <ctype.h>
+
 #include "tempfile.h"
 #include "alias.h"
 
+
 typedef struct TAlias
 {
   char *name,
    *subst;
   unsigned short used;
   struct TAlias *next;
-}
-TAlias;
+} TAlias;
 
 static unsigned short useFlag = 0;
-static TAlias *first = 0,
- *last = 0;
+static TAlias *first = 0, *last = 0;
 static FILE *tmp;
 
 /* module internal functions */
-void
-partstrupr(char *str)           /* strupr only for first word in string */
+void partstrupr(char *str)           /* strupr only for first word in string */
 {
-  int m;
-  for (m = 0; str[m] != '\0' && !isspace(str[m]); m++)
-    if (str[m] >= 'a' && str[m] <= 'z')
-      str[m] -= 32;
+  char *c = str;
+  while (*c && !isspace(*c))
+  {
+    *c = toupper(*c);
+    c++;
+  }
 }
 
-void
-aliasprint(void)
+void aliasprint(void)
 {
   TAlias *ptr = first;
   while (ptr)
@@ -62,8 +66,7 @@
   }
 }
 
-void
-aliasdel(char *name)
+void aliasdel(char *name)
 {
   TAlias *ptr = first,
    *prev = 0;
@@ -84,8 +87,7 @@
   }
 }
 
-int
-aliasadd(char *name, char *subst)
+int aliasadd(char *name, char *subst)
 {
   TAlias *ptr = first,
    *prev,
@@ -140,7 +142,7 @@
 
   ptr->used = 0;
 
-  /* Alias table must be sortet!
+  /* Alias table must be sorted!
    * Here a little example:
    *   command line = "ls -c"
    * If the entries are
@@ -187,8 +189,7 @@
 }
 
 /* specified routines */
-void
-aliasexpand(char *cmd, int maxlen)
+void aliasexpand(char *cmd, int maxlen)
 {
   unsigned n = 0,
     m,
@@ -248,8 +249,7 @@
   }
 }
 
-int
-aliasswapout(void)
+int aliasswapout(void)
 {
   TAlias *ptr = first,
    *old;
@@ -281,17 +281,16 @@
   return 0;
 }
 
-int
-aliasswapin(void)
+int aliasswapin(void)
 {
   char buf[1024];
 
   fseek(tmp, 0, SEEK_SET);      /* reset file pointer */
 
-  while (fgets(buf, 1024, tmp))
+  while (fgets(buf, sizeof(buf), tmp))
   {
     buf[strlen(buf) - 1] = '\0';
-    if (alias(0, buf) == -1)
+    if (cmd_alias(0, buf) == -1)
       return -1;
   }
   useFlag = 0;
@@ -303,8 +302,7 @@
 }
 
 #pragma argsused
-int
-alias(char *first, char *rest)
+int cmd_alias(char *first, char *rest)
 {
   char *ptr;
   int n = 0;
@@ -315,7 +313,7 @@
     return 0;
   }
 
-  if ((ptr = strstr(rest, "=")) == 0)
+  if ((ptr = strchr(rest, '=')) == 0)
   {
     errno = EINVAL;
     return -1;
@@ -333,3 +331,5 @@
 
   return n;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/alias.h com075/alias.h
--- com074d/alias.h	Thu Jul 16 10:57:22 1998
+++ com075/alias.h	Fri Aug  7 08:44:26 1998
@@ -11,6 +11,6 @@
 void aliasexpand(char *cmd, int maxlen);
 int aliasswapout(void);
 int aliasswapin(void);
-int alias(char *first, char *rest);
+int cmd_alias(char *first, char *rest);
 
 #endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/batch.c com075/batch.c
--- com074d/batch.c	Thu Jul 16 10:57:22 1998
+++ com075/batch.c	Fri Aug  7 08:44:26 1998
@@ -1,391 +1,414 @@
 /*
  *  BATCH.C - batch file processor for COMMAND.COM.
  *
- *
- *
  *  Comments:
  *
- *  ??/??/?? (Evan Jeffrey) -------------------------------------------------
+ * ??/??/?? (Evan Jeffrey)
  *    started.
  *  
- *  07/15/95 (Tim Norman) ---------------------------------------------------
+ * 15 Jul 1995 (Tim Norman)
  *    modes and bugfixes.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
- *    i have cleaned up the source code. changes now bring this source into
- *    guidelines for recommended programming practice.
+ * 08 Aug 1995 (Matt Rains)
+ *   i have cleaned up the source code. changes now bring this source
+ *   into guidelines for recommended programming practice.
  *
  *    i have added some constants to help making changes easier.
  *
- *  01/29/96 (Steffan Kaiser) -----------------------------------------------
+ * 29 Jan 1996 (Steffan Kaiser)
  *    made a few cosmetic changes
  *
- *  02/05/96 (Tim Norman) ---------------------------------------------------
+ * 05 Feb 1996 (Tim Norman)
  *    changed to comply with new first/rest calling scheme
  *
- *  06/14/97 (Steffen Kaiser) -----------------------------------------------
+ * 14 Jun 1997 (Steffen Kaiser)
  *    bug fixes.  added error level expansion %?.  ctrl-break handling
  *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   Totally reorganised in conjunction with COMMAND.C (cf) to implement
+ *   proper BATCH file nesting and other improvements.
+ *
+ * 16 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+ *   Seperated commands into individual files.
+ *
+ * 19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *   Preserve state of echo flag across batch calls.
+ *
+ * 19 Jul 1998 (Hans B Pufal) [HBP_002]
+ *   Implementation of FOR command
+ *
+ * 20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *  added error checking after malloc calls
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 02-Aug-1998 (Hans B Pufal) [HBP_003]
+ *  Fixed bug in ECHO flag restoration at exit from batch file
+ *
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <io.h>
+#include <dos.h>
+#include <dir.h>
 #include <conio.h>
 
 #include "command.h"
+#include "batch.h"
 
-#define D_LABELERR   "ERROR: label not found!"
-#define D_SYNTAXERR  "ERROR: syntax error!"
-#define D_PAUSEMSG   "[press any key to continue]"
-#define D_BEEP       "beep"
-#define D_CALL       "call"
-#define D_DOWN       "down"
-#define D_ECHO       "echo"
-#define D_ERRORLEVEL "errorlevel"
-#define D_EXIST      "exist"
-#define D_GOTO       "goto"
-#define D_IF         "if"
-#define D_NOT        "not"
-#define D_ON         "on"
-#define D_OFF        "off"
-#define D_PAUSE      "pause"
-#define D_REM        "rem"
-#define D_SHIFT      "shift"
-
-/* function decls */
-int split(char *, char **);
-char *parse_firstarg(char *);
-void printprompt(void);
-
-/*
- * append src to dest, but don't reach endDest.
- * return NULL, if failure;
- * return one byte behind the last copied byte, otherwise
+struct bcontext
+ *bc = NULL;                    /*  The stack of current batch contexts.
+                                 * NULL when no batch is active
  */
-char *
-appendString(char *dest, char *src, char *endDest)
-{
-  size_t len;
 
-  if (!src)
-    return dest;
+unsigned int echo = 1;          /* The echo flag */
 
-  len = strlen(src);
-  if (dest + len >= endDest)
-    return NULL;
-
-  return stpcpy(dest, src);
-}
+#define BUFFSIZE  512
+char
+  textline[BUFFSIZE];           /* Buffer for reading Batch file lines */
 
-/*
- * process a batch file
- *
+char *find_arg(int n)
+{
+/* Returns a pointer to the n'th parameter of the current batch file.
+ * If no such parameter exists returns pointer to empty string.
+ * If no batch file is current, returns NULL
  *
  */
-int
-batch(char *firstword, char *restofline)
-{
-  FILE *bfile;
-
-  int argc;                     /* argc for call to this batch file */
-  char *argv[128];              /* argv not including name of batch file */
 
-  char *first,
-   *rest;                       /* first and rest of read-in line */
+  char *pp;
 
-  int realnum;                  /* the actual number of the parameter we want */
-  char *var;                    /* pointer to env. var. value */
-  char *tmp;                    /* temporary string pointer */
+  dprintf(("[find_arg (%d)]\n", n));
 
-  static int nestlevel = 0;
-  static int called;
-  static int echo = 1;
-  int shiftlevel = 0;           /* number of times we've shifted the parameters */
-  char textline[128];
-  char cmdline[128];
-
-  /* varibles found within code */
-  int notval;
-  int found;
-
-  nestlevel++;                  /* keep track of how many batch files are running */
+  if (bc == NULL)
+    return NULL;
 
-  /* open the batch file */
-  if ((bfile = fopen(firstword, "rt")) == NULL)
-  {
-    return (1);
-  }
+  n += bc->shiftlevel;
+  pp = bc->params;
 
-  /* split our command-line params */
-  split(restofline, argv + 1);
-  argv[0] = firstword;
-  for (argc = 0; argv[++argc];)
-    ;
+  while (*pp && n--)            /* Step up the strings till we reach the end
+                                 * or the one we want */
+    pp += strlen(pp) + 1;
 
-  /* set the called flag to 1.  This indicates that a batch file has been */
-  /* run.  Used for determining what to do when a batch file is called */
-  /* from within another batch file */
-  called = 1;
-
-  /* cycle through each line of the batch file */
-  while (fgets(textline, sizeof(textline), bfile) != NULL)
-  {
-    /* copy textline[] -> cmdline[] and */
-    /* 1) expand the variables */
-    /* 2) replace control codes by spaces */
-    char *p,
-     *q;
+  return pp;
+}
 
-    /* check for ctrl-break */
-    if (chkCBreak(BREAK_BATCHFILE))
-      break;
+/* HBP_002 { FOR command support */
 
-    if (!strchr(textline, '\n'))
-      p = NULL;
-    else
-    {
-      for (q = textline; isspace(*q); q++)
-        ;
+char *batch_params(char *s1, char *s2)
+{
+  /*
+     * Batch_params builds a parameter list in newlay allocated memory.
+     * The parameters consist of null terminated strings with a final
+     * NULL character signalling the end of the parameters.
+     *
+   */
 
-      /* ignore labels and empty lines */
-      if (*q == ':' || *q == '\n' || *q == 0)
-        continue;
+  char
+   *dp = (char *)malloc(strlen(s1) + strlen(s2) + 3);
 
-      for (p = cmdline; p && (*p = *q++) != 0;)
-      {
-        if (*p == '%')
-        {
-          if (isdigit(*q))      /* argument */
+  /* JPP 20-Jul-1998 added error checking */
+  if (dp == NULL)
           {
-            realnum = *q - '0' + shiftlevel;
-            if ((unsigned)realnum <= argc)
-              p = appendString(p, argv[realnum], cmdline + sizeof(cmdline));
-            ++q;
+    error_out_of_memory();
+    return NULL;
           }
-          else if (*q == '?')   /* non-standard: error level */
-          {
-            char buf[4];
 
-            ++q;
-            sprintf(buf, "%u", errorlevel);
-            p = appendString(p, buf, cmdline + sizeof(cmdline));
+  if (s1 && *s1)
+  {
+    s1 = stpcpy(dp, s1);
+    *s1++ = '\0';
           }
           else
-            /* possibly a variable */
-          {
-            char *endvar;
+    s1 = dp;
 
-            if ((endvar = strchr(q, '%')) != NULL)
+  while (*s2)
             {
-              *endvar = 0;
-              if ((var = getenv(q)) == NULL)
-                var = getenv(strupr(q));
-              p = appendString(p, var, cmdline + sizeof(cmdline));
-              q = endvar + 1;
-            }
-          }
-        }
-        else
+    if (isspace(*s2) || strchr(",;", *s2))
         {
-          if (iscntrl(*p))
-            *p = ' ';
-          if ((unsigned)++p >= (unsigned)(cmdline + sizeof(cmdline)))
-            p = NULL;
-        }
-      }
+      *s1++ = '\0';
+      s2++;
+      while (*s2 && strchr(" ,;", *s2))
+        s2++;
+      continue;
     }
 
-    if (!p)
+    if ((*s2 == '"') || (*s2 == '\''))
     {
-      fputs("Command line too long.\n", stderr);
-      printf("%s\n%s\n", cmdline, textline);
-      fclose(bfile);
-      --nestlevel;
-      return -1;
+      char
+        st = *s2;
+
+      do
+        *s1++ = *s2++;
+      while (*s2 && (*s2 != st));
     }
 
-    /* strip trailing spaces */
-    while (--p >= cmdline && isspace(*p))
-      ;
-    p[1] = 0;
+    *s1++ = *s2++;
+  }
 
-    /* ignore empty lines */
-    if (!*cmdline)
-      continue;
+  *s1++ = '\0';
+  *s1 = '\0';
+
+  return dp;
+}
+
+/* HBP_002 } */
+
+void exit_batch(char *msg)
+{
+/*
+ * If a batch file is current, exits it, freeing the context block and
+ * chaining back to the previous one.
+ *
+ * If no new batch context is found, sets ECHO back ON.
+ *
+ * If the parameter is non-null or not empty, it is printed as an exit
+ * message
+ */
 
-    /* make a copy that we can use to pass to parsecommandline if nothing */
-    /* else matches */
-    strcpy(textline, first = cmdline);
+  dprintf(("exit_batch (..)\n"));
 
-    /* check for non-echo character */
-    if (*first == '@')
+  if (bc)
     {
-      first++;
-      while (isspace(*first))
-        first++;
+    struct bcontext
+     *t = bc;
+
+    if (bc->bfile)
+      fclose(bc->bfile);
+
+    if (bc->params)
+      free(bc->params);
+
+/* HBP_002 { FOR command support */
+
+    if (bc->forproto)
+      free(bc->forproto);
+
+    if (bc->ffind)
+      free(bc->ffind);
+
+/* HBP_002 } */
+
+/* HBP_003 { fix echo restore */
+
+    echo = bc->echo;              /* Preserve echo state across batch calls */
+
+/* HBP_003 fix echo restore } */
+
+    bc = bc->prev;
+    free(t);
     }
-    else if (echo)
+
+/* HBP_001 } */
+
+  if (msg && *msg)
+    printf("%s\n", msg);
+}
+
+int batch(char *fullname, char *firstword, char *param)
+{
+  /*
+   * Start batch file execution
+   *
+   * The firstword parameter is the full filename of the batch file.
+   *
+   */
+
+  FILE *bf = fopen(fullname, "rt");
+
+  dprintf(("batch ('%s', '%s', '%s')  bf = %x\n", fullname, firstword,
+           param, bf));
+
+  if (bf == NULL)
     {
-      printprompt();
-      puts(cmdline);
+    perror("opening batch file");
+    return 1;
     }
 
-    /* find the rest of the line and delimit the first word */
-    rest = parse_firstarg(first);
-    /* POST condition: rest may be NULL */
+/* HBP_002 { FOR command support */
+
+  while (bc && bc->forvar)      /* Kill any and all FOR contexts */
+    exit_batch(NULL);
+
+/* HBP_002 } */
 
-    /* check for SHIFT instruction */
-    if (strcmpi(first, D_SHIFT) == 0)
+  if (bc == NULL)               /* No curent batch file, create a new context */
     {
-      /* check if we are shifting down rather than up */
-      if (rest && strncmpi(rest, D_DOWN, sizeof(D_DOWN)) == 0)
-        /* only shift down if shiftlevel != 0 */
-        shiftlevel = shiftlevel ? shiftlevel - 1 : 0;
-      else
-        /* shift up */
-        shiftlevel++;
-    }
-    /* check for PAUSE instruction */
-    else if (strcmpi(first, D_PAUSE) == 0)
+    struct bcontext
+     *n = (struct bcontext *)malloc(sizeof(struct bcontext));
+
+    /* JPP 20-Jul-1998 added error checking */
+    if (n == NULL)
     {
-      puts(D_PAUSEMSG);
-      cgetchar();
-    }
-    /* check for ECHO instruction */
-    else if (strcmpi(first, D_ECHO) == 0)
-    {
-      if (rest)
-      {
-        if (stricmp(rest, D_OFF) == 0)
-          echo = 0;
-        else if (stricmp(rest, D_ON) == 0)
-          echo = 1;
-        else if (!rest)
-          printf("ECHO is %s\n", echo ? D_ON : D_OFF);
-        else
-          puts(rest);
+      error_out_of_memory();
+      return 1;
       }
+    n->prev = bc;
+    bc = n;
     }
-    /* check for GOTO instruction */
-    else if (strcmpi(first, D_GOTO) == 0)
-    {
-      if (!rest || !*rest)
+  else if (bc->bfile)           /* Then we are transferring to another batch */
       {
-        fprintf(stderr, "No label specified for GOTO\n");
-        fclose(bfile);
-        nestlevel--;
-        return 1;
+    fclose(bc->bfile);
+    free(bc->params);
       }
 
-      /* extract the label that we're going to */
-      parse_firstarg(rest);
+  bc->bfile = bf;
+  bc->echo = echo;              /* Preserve echo across batch calls [HBP_001] */
+  bc->shiftlevel = 0;
 
-      /* now search for the label */
-      rewind(bfile);
+/* HBP_002 { FOR command support */
+  bc->ffind = NULL;
+  bc->forvar = '\0';
+  bc->forproto = NULL;
+  bc->params = batch_params(firstword, param);
 
-      found = 0;
+/* HBP_002 } */
 
-      while (fgets(textline, sizeof(textline), bfile) != NULL)
-      {
-        tmp = textline;
+  return 0;
+}
+
+char *readbatchline(int *eflag)
+{
+  /*
+   * Read and return the next executable line form the current batch file
+   *
+   * If no batch file is current or no further executable lines are found
+   * return NULL.
+   *
+   * Here we also look out for FOR bcontext structures which trigger the
+   * FOR expansion code.
+   *
+   * Set eflag to 0 if line is not to be echoed else 1
+   */
 
-        while (isspace(*tmp))
-          tmp++;
+  char
+   *first,
+   *ip;
 
-        if (*tmp == ':')
-        {
-          tmp++;
+  if (bc == NULL)               /* No batch */
+    return NULL;
 
-          parse_firstarg(tmp);
+  dprintf(("readbatchline ()\n"));
 
-          if (strcmp(tmp, rest) == 0)
+  while (1)
           {
-            found = 1;
-            break;
-          }
-        }
-      }
-
-      if (!found)
+    if (chkCBreak(BREAK_BATCHFILE)) /* User halt */
       {
-        printf("Label not found: %s\n", rest);
-        fclose(bfile);
-        nestlevel--;
-        return (1);
-      }
+      while (bc)
+        exit_batch(NULL);
+      return NULL;
     }
-    /* check for IF command */
-    else if (strcmpi(first, D_IF) == 0)
-    {
-      puts("IF not implemented yet");
 
-#if 0
-      if (strcmpi(p[1], D_NOT) == 0)
+    /* HBP_002 { FOR command support */
+
+    if (bc == NULL)             /* No batch */
+      return NULL;
+
+    if (bc->forvar)             /* If its a FOR context... */
       {
-        notval++;
-      }
-      if (!strcmpi(p[1 + notval], D_ERRORLEVEL))
+      char
+       *sp = bc->forproto,      /* pointer to prototype command */
+       *dp = textline,          /* Place to expand protoype */
+       *fv = find_arg(0);       /* Next list element */
+
+      if ((fv == NULL) || (*fv == '\0'))  /* End of list so... */
       {
-        ;
+        exit_batch(NULL);       /* just exit this context */
+        continue;
       }
-      else if (!strcmpi(p[1 + notval], D_EXIST))
+
+      if (strcspn(fv, "?*") == strlen(fv))  /* element is wild file */
+        bc->shiftlevel++;       /* No use it and shift list */
+      else
+        /* Wild file spec, find first (or next) file name */
       {
-        ;
-      }
+        if (bc->ffind)          /* First already done fo do next */
+          fv = !findnext(bc->ffind) ? bc->ffind->ff_name : NULL;
       else
+          /*  For first find, allocate a find first block */
       {
-        ;
+          if ((bc->ffind = (struct ffblk *)malloc(sizeof(struct ffblk))) == NULL)
+          {
+            error_out_of_memory();  /* JPP 20-Jul-1998 added error checking */
+            return NULL;
       }
-#endif
+
+          fv = !findfirst(fv, bc->ffind, FA_NORMAL) ?
+              bc->ffind->ff_name : NULL;
     }
-    /* check for BEEP command */
-    else if (strcmpi(first, D_BEEP) == 0)
+
+        if (fv == NULL)         /* Null indicates no more files.. */
     {
-      printf("\a");
+          free(bc->ffind);      /* free the buffer */
+          bc->ffind = NULL;
+          bc->shiftlevel++;     /* On to next list element */
+          continue;
     }
-    /* check for CALL command */
-    else if (strcmpi(first, D_CALL) == 0)
-    {
-      parsecommandline(rest);
     }
-    else
-    {
-      char *place;
-
-      /* clear the call flag */
-      called = 0;
 
-      /* strip \n and \r before calling parsecommandline */
-      place = &textline[strlen(textline) - 1];
-      while ((*place == '\n' || *place == '\r') && place > textline)
-        *place-- = 0;
-      parsecommandline(textline);
+      /* At this point, fv points to parameter string */
 
-      /* if a batch file was called, then return */
-      if (called)
+      while (*sp)
       {
-        fclose(bfile);
-        nestlevel--;
-        return (0);
+        if ((*sp == '%') && (*(sp + 1) == bc->forvar))  /* replace % var */
+          dp = stpcpy(dp, fv), sp += 2;
+        else
+          *dp++ = *sp++;        /* Else just copy */
       }
 
-      /* set the call flag back */
-      called = 1;
+      *dp = '\0';
+
+      *eflag = echo;
+
+      return textline;
     }
+
+    /* HBP_002 } */
+
+    if (fgets(textline, BUFFSIZE, bc->bfile) == NULL) /* End of file.... */
+    {
+      exit_batch(NULL);
+
+      if (bc == NULL)
+        return NULL;
+
+      continue;
   }
 
-  /* close the file and decrease the nesting level */
-  fclose(bfile);
-  nestlevel--;
+    /* Strip leading spaces and trailing space/control chars */
+
+    for (first = textline; isspace(*first); first++)
+      ;
+
+    for (ip = first + strlen(first) - 1; isspace(*ip) || iscntrl(*ip);
+         ip--)
+      ;
+
+    *++ip = '\0';
 
-  if (nestlevel == 0)
+    /* ignore labels and empty lines */
+
+    if (*first == ':' || *first == 0)
+      continue;
+
+    if (*first == '@')          /* don't echo this line */
   {
-    /* reset the echo when the main calling batch file quits */
-    echo = 1;
-    chkCBreak(BREAK_OUTOFBATCH);
+      do
+        first++;
+      while (isspace(*first));
+
+      *eflag = 0;
+    }
+    else
+      *eflag = echo;
+
+    break;
   }
 
-  return (0);
+  return first;
 }
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/batch.h com075/batch.h
--- com074d/batch.h	Wed Dec 31 18:00:00 1969
+++ com075/batch.h	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,38 @@
+/* A structure to preserve the context of a batch file */
+
+/* HBP_002 { FOR comamnd support */
+
+#include <dir.h>
+
+struct bcontext
+{
+  struct bcontext *prev;
+  FILE *bfile;
+  char *forproto;
+  char *params;
+  struct ffblk *ffind;
+  int shiftlevel;
+  int echo;                     /* Preserve echo flag across batch calls [HBP_001] */
+  char forvar;
+};
+
+/* HBP_002 } */
+
+/*  The stack of current batch contexts.
+ * NULL when no batch is active
+ */
+extern struct bcontext *bc;
+
+extern unsigned int echo;       /* The echo flag */
+
+#define BUFFSIZE  512
+
+extern char textline[BUFFSIZE]; /* Buffer for reading Batch file lines */
+
+void exit_batch(char *msg);
+
+/* HBP_002 { FOR comamnd support */
+
+extern char *batch_params(char *s1, char *s2);
+
+/* HBP_002 } */
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/beep.c com075/beep.c
--- com074d/beep.c	Wed Dec 31 18:00:00 1969
+++ com075/beep.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,51 @@
+
+/*
+ *  BEEP.C - beep command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_BEEP
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_beep(char *cmd, char *param)
+{
+/*
+ * Perform BEEP command.
+ *
+ * FREEDOS extension
+ */
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  putchar('\a');
+
+  return 0;
+}
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/bugs.txt com075/bugs.txt
--- com074d/bugs.txt	Thu Jul 16 10:57:22 1998
+++ com075/bugs.txt	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,5 @@
+         ****  Please report bugs to command@gcfl.net!  ****
+
 Known Bugs
 ~~~~~~~~~~
 COMMAND.COM has problems when loaded from CONFIG.SYS
@@ -6,23 +8,22 @@
 you get garbage.
 
 Command-Line editing is really slow because it redraws each time.
+(JP-actually, not that slow)
 
 COMMAND.COM (specifically the set command, but maybe others) wastes
 memory by not freeing back what it doesn't use.
 
 The exec function that was being used by version 0.73 and earlier
-does not copy the envirnment to the child process.  In 0.74 this was
+does not copy the environment to the child process.  In 0.74 this was
 changed to use spawnl, but the exec function should probably be fixed
 instead.
 
+
 Reported Bugs
 ~~~~~~~~~~~~~
 
 From: rschanke@falcon.lhup.edu (Robert C. Schanke)
 o  the "/?" help option does not work
-o  if you type <tab> and multiple names exist it goes beep. If you
-   type tab again it beeps but does not show all the possibilities
-   like bash does.
 
 From: Steffan
 o  let set work with or without the '=' sign.  People like it that way.
@@ -34,11 +35,5 @@
 "alias v = dir" doesn't work because of the spaces.
 
 
-From: John P. Price (linux-guru@gcfl.net)
- Environment variable references do not get expanded on the command
- line.  For example:
-
- set path=%path%;c:\tc\bin
 
- sets path to "%path%;c:\tc\bin" instead of adding to the current
- path.
+         ****  Please report bugs to command@gcfl.net!  ****
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/call.c com075/call.c
--- com074d/call.c	Wed Dec 31 18:00:00 1969
+++ com075/call.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,79 @@
+/*
+ *  CALL.C - batch file call command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 04-Aug-1998 (Hans B Pufal)
+ * - added lines to initialize for pointers (HBP004)  This fixed the
+ *   lock-up that happened sometimes when calling a batch file from
+ *   another batch file.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_call(char *cmd, char *param)
+{
+/*
+ * Perform CALL command.
+ *
+ * Allocate a new batch context and add it to the current chain.
+ * Call parsecommandline passing in our param string
+ * If No batch file was opened then remove our newly allocted
+ * context block.
+ */
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  {
+    struct bcontext
+     *n = (struct bcontext *)malloc(sizeof(struct bcontext));
+
+    if (n == NULL)
+    {
+      error_out_of_memory();
+      return 1;
+    }
+
+    n->prev = bc;
+    bc = n;
+
+    bc->bfile = NULL;
+    bc->params = NULL;
+    bc->shiftlevel = 0;
+    bc->forvar = 0;        /* HBP004 */
+    bc->forproto = NULL;   /* HBP004 */
+
+    parsecommandline(param);
+
+    if (bc->bfile == NULL)      /* Wasn't a batch file so remove conext */
+    {
+      bc = bc->prev;
+      free(n);
+    }
+  }
+
+  return 0;
+}
Files com074d/clean.bat and com075/clean.bat are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/cls.c com075/cls.c
--- com074d/cls.c	Wed Dec 31 18:00:00 1969
+++ com075/cls.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,28 @@
+/*
+ *  CLS.C - clear screen internal command
+ *
+ *  Comments:
+ *
+ *  07/27/1998 (John P. Price)
+ *    started.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CLS
+
+#include <conio.h>
+
+#include "command.h"
+
+#pragma argsused
+int cmd_cls(char *first, char *rest)
+{
+  clrscr();
+  return 0;
+}
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/cmdinput.c com075/cmdinput.c
--- com074d/cmdinput.c	Thu Jul 16 10:57:22 1998
+++ com075/cmdinput.c	Fri Aug  7 08:44:26 1998
@@ -63,15 +63,35 @@
  *    changed my code to use _setcursortype until I can figure out why
  *    my code is crashing on some machines.  It doesn't crash on mine :)
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - put ifdef's around filename completion code.
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - moved filename completion code to filecomp.c
+ * - made second TAB display list of filename matches
+ *
+ * 31-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - Fixed bug where if you typed something, then hit HOME, then tried to
+ *   type something else in insert mode, it crashed.
+ *
+ * 07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ * - Fixed carrage return output to better match MSDOS with echo on or off.
+ *   (marked with "JPP 19980708")
+ *
  */
 
+#include "config.h"
+
 #include <conio.h>
-#include <dos.h>
 #include <stdio.h>
 #include <string.h>
-#include <dir.h>
-#include <conio.h>
+#include <dos.h>
+
 #include "command.h"
+#include "batch.h"
 
 #define D_BS      8
 #define D_DELETE  256+83
@@ -85,9 +105,17 @@
 #define D_RIGHT   256+77
 #define D_ENTER   13
 #define D_ESC     27
-#define D_BEEP    printf("\a")
+#define D_BEEP    putchar('\a')
 
+#ifdef FEATURE_HISTORY
 void history(int, char *);      /* prototype for the command-line history */
+#endif
+
+
+#ifdef FEATURE_FILENAME_COMPLETION
+void complete_filename(char *str, unsigned charcount);
+int show_completion_matches(char *str, unsigned charcount);
+#endif
 
 /*
  * maxx, maxy
@@ -98,74 +126,23 @@
 unsigned char far *maxy = (unsigned char far *)0x00000484;
 
 /*
- * There is a problem with this code.
- * If anyone knows why it crashes on some machines, plus let me
- * know!  (normat@rpi.edu)
- */
-#if 0
-/*
- * getmatrixheight
- *
- * return the height of the character matrix
- */
-void
-getmatrixheight(unsigned *mh)
-{
-  unsigned tmp;
-
-  /*
-   * save the BP register since that's used for the stack,
-   * and this interrupt overwrites it
-   */
-  asm {
-    mov si, bp
-    mov ah, 11h
-    mov al, 30h
-    mov bh, 02h
-    int 10h
-    mov bp, si
-    mov tmp,cx
-  }
-
-  *mh = tmp;
-}
-
-/*
- * setcursor
- *
- * set the starting and ending lines of the cursor
- */
-void
-setcursor(unsigned char start, unsigned char end)
-{
-  asm {
-    mov ah, 01h
-    mov ch, start
-    mov cl, end
-    int 10h
-  }
-}
-#endif
-
-/*
  * goxy
  *
  * move the cursor on the screen.  Needs to be in ASM because of bugs with
  * gotoxy()
  */
-void
-goxy(unsigned char x, unsigned char y)
+void goxy(unsigned char x, unsigned char y)
 {
+  union REGS regs;
+
   y--;
   x--;
 
-  asm {
-    mov ah, 2
-    mov bh, 0
-    mov dh, y
-    mov dl, x
-    int 10h
-  }
+  regs.h.ah = 2;                /* set cursor position */
+  regs.h.dh = y;
+  regs.h.dl = x;
+  regs.h.bh = 0;                /* video page 0 */
+  int86(0x10, &regs, &regs);
 }
 
 /*
@@ -173,8 +150,7 @@
  *
  *
  */
-void
-clrcmdline(char *str, int maxlen, unsigned orgx, unsigned orgy)
+void clrcmdline(char *str, int maxlen, unsigned orgx, unsigned orgy)
 {
   int count;
   goxy(orgx, orgy);
@@ -185,41 +161,26 @@
 }
 
 /* read in a command line */
-void
-readcommand(char *str, int maxlen)
+void readcommand(char *str, int maxlen)
 {
-  struct ffblk file;
-
-  // varibles found within code
-  int found_dot = 0;
-  int curplace = 0;
-  int start;
-  int perfectmatch = 1;
-  char path[128];
-  char fname[14];
-  char maxmatch[13] = "";
-  char directory[128];
-
-  unsigned char insert = 0;
+  unsigned char insert = 1;    /* JPP changed default to insert on */
   unsigned ch;
+  unsigned lastch=0;
   unsigned orgx;                // origin x/y
-
   unsigned orgy;
   unsigned curx;
   unsigned cury;
   int count;
   unsigned current = 0;
   unsigned charcount = 0;
-  unsigned matrixheight;
+
+  /* JPP 19980807 - if echo off, don't print prompt */
+  if (echo) printprompt();
 
   orgx = wherex();
   orgy = wherey();
   memset(str, 0, maxlen);
 
-#if 0                           /* crashes on some machines */
-  getmatrixheight(&matrixheight);
-  setcursor(matrixheight * 6 / 7 - 1, matrixheight * 6 / 7);
-#endif
   _setcursortype(_NORMALCURSOR);
 
   do
@@ -231,10 +192,9 @@
     switch (ch)
     {
       case D_BS:               // delete character to left of cursor
-
         if (current > 0 && charcount > 0)
         {
-          if (current == charcount)
+          if (current == charcount)  //if at end of line
           {
             str[current - 1] = 0;
             if (wherex() != 1)
@@ -263,23 +223,16 @@
           current--;
         }
         break;
+
       case D_INSERT:           /* toggle insert/overstrike mode */
         insert ^= 1;
-#if 0                           /* crashes on some machines */
         if (insert)
-          setcursor(matrixheight / 2, matrixheight * 6 / 7);
+          _setcursortype(_NORMALCURSOR);
         else
-          setcursor(matrixheight * 6 / 7 - 1, matrixheight * 6 / 7);
-#endif
-
-        if (insert)
           _setcursortype(_SOLIDCURSOR);
-        else
-          _setcursortype(_NORMALCURSOR);
-
         break;
-      case D_DELETE:           // delete character under cursor
 
+      case D_DELETE:           // delete character under cursor
         if (current != charcount && charcount > 0)
         {
           for (count = current; count < charcount; count++)
@@ -291,16 +244,16 @@
           goxy(curx, cury);
         }
         break;
-      case D_HOME:             // goto beginning of string
 
+      case D_HOME:             // goto beginning of string
         if (current != 0)
         {
           goxy(orgx, orgy);
           current = 0;
         }
         break;
-      case D_END:              // goto end of string
 
+      case D_END:              // goto end of string
         if (current != charcount)
         {
           goxy(orgx, orgy);
@@ -308,90 +261,15 @@
           current = charcount;
         }
         break;
-      case D_TAB:
-        maxmatch[0] = 0;
-        found_dot = 0;
-        curplace = 0;
-        perfectmatch = 1;
 
+#ifdef FEATURE_FILENAME_COMPLETION
+      case D_TAB:
         // expand current file name
         if (current == charcount) // only works at end of line
-
         {
-          count = charcount - 1;
-          if (count < 0)
-            count = 0;
-
-          while (count > 0 && str[count] != ' ')  // find front of word
-
-            count--;
-
-          if (str[count] == ' ')  // if not at beginning, go forward 1
-
-            count++;
-
-          start = count;
-
-          // extract directory from word
-          strcpy(directory, &str[start]);
-          curplace = strlen(directory) - 1;
-          while (curplace >= 0 && directory[curplace] != '\\' &&
-                 directory[curplace] != ':')
-          {
-            directory[curplace] = 0;
-            curplace--;
-          }
-
-          strcpy(path, &str[start]);
-
-          // look for a . in the filename
-          for (count = strlen(directory); path[count] != 0; count++)
-            if (path[count] == '.')
-            {
-              found_dot = 1;
-              break;
-            }
-          if (found_dot)
-            strcat(path, "*");
-          else
-            strcat(path, "*.*");
-
-          curplace = 0;         // current fname
-
-          if (findfirst(path, &file, 0x3F) == 0)
-          {                     // find anything
-
-            do
+          if (lastch != D_TAB) // if first TAB, complete filename
             {
-              if (file.ff_name[0] == '.') // ignore . and ..
-
-                continue;
-
-              strcpy(fname, file.ff_name);
-
-              if (file.ff_attrib == FA_DIREC)
-                strcat(fname, "\\");
-              else
-                strcat(fname, " ");
-
-              if (!maxmatch[0] && perfectmatch)
-                strcpy(maxmatch, fname);
-
-              else
-              {
-                for (count = 0; maxmatch[count] && fname[count]; count++)
-                  if (maxmatch[count] != fname[count])
-                  {
-                    perfectmatch = 0;
-                    maxmatch[count] = 0;
-                    break;
-                  }
-              }
-            }
-            while (findnext(&file) == 0);
-
-            strcpy(&str[start], directory);
-            strcat(&str[start], maxmatch);
+            complete_filename(str, charcount);
             charcount = strlen(str);
             current = charcount;
 
@@ -399,44 +277,55 @@
             printf("%s", str);
             if ((strlen(str) > (*maxx - orgx)) && (orgy == *maxy + 1))
               orgy--;
-
-            if (!perfectmatch)
-              D_BEEP;
           }
-          else
-            D_BEEP;
+          else  //if second TAB, list matches
+          {
+            if (show_completion_matches(str, charcount))
+            {
+              printprompt();
+              orgx = wherex();
+              orgy = wherey();
+              printf("%s", str);
+            }
+          }
         }
         else
           D_BEEP;
         break;
+#endif
+
       case D_ENTER:            // end input, return to main
 
+#ifdef FEATURE_HISTORY
         if (str[0])
           history(0, str);      // add to the history
+#endif
 
         putchar('\n');
         break;
-      case D_ESC:              // clear str  Make this callable!
 
+      case D_ESC:              // clear str  Make this callable!
         clrcmdline(str, maxlen, orgx, orgy);
         current = charcount = 0;
         break;
-      case D_UP:               // get previous command from buffer
 
+#ifdef FEATURE_HISTORY
+      case D_UP:               // get previous command from buffer
         clrcmdline(str, maxlen, orgx, orgy);
         history(-1, str);
         current = charcount = strlen(str);
         printf("%s", str);
         break;
-      case D_DOWN:             // get next command from buffer
 
+      case D_DOWN:             // get next command from buffer
         clrcmdline(str, maxlen, orgx, orgy);
         history(1, str);
         current = charcount = strlen(str);
         printf("%s", str);
         break;
-      case D_LEFT:             // move cursor left
+#endif
 
+      case D_LEFT:             // move cursor left
         if (current > 0)
         {
           current--;
@@ -448,8 +337,8 @@
         else
           D_BEEP;
         break;
-      case D_RIGHT:            // move cursor right
 
+      case D_RIGHT:            // move cursor right
         if (current != charcount)
         {
           current++;
@@ -459,13 +348,13 @@
             goxy(wherex() + 1, wherey());
         }
         break;
-      default:                 // insert character into string...
 
+      default:                 // insert character into string...
         if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
         {
           if (insert && current != charcount)
           {
-            for (count = charcount; count >= current; count--)
+            for (count = charcount; count > current; count--)
               str[count] = str[count - 1];
             str[current++] = ch;
             curx = wherex() + 1;
@@ -490,11 +379,9 @@
           D_BEEP;
         break;
     }
+    lastch = ch;
   }
   while (ch != D_ENTER);
 
-#if 0
-  setcursor(matrixheight * 6 / 7 - 1, matrixheight * 6 / 7);
-#endif
   _setcursortype(_NORMALCURSOR);
 }
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/cmdtable.c com075/cmdtable.c
--- com074d/cmdtable.c	Wed Dec 31 18:00:00 1969
+++ com075/cmdtable.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,215 @@
+/*
+ *  CMDTABLE.C - table of internal commands.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *   New file to keep the internal command table. I plan on
+ *   getting rid of the table real soon now and replacing it
+ *   with a dynamic mechnism.
+ *
+ *
+ * 27 Jul 1998  John P. Price
+ * - added config.h include
+ *
+ *
+ */
+
+#include <stdlib.h>
+
+#include "config.h"
+#include "command.h"
+
+/* a list of all the internal commands, associating their command names */
+/* to the functions to process them                                     */
+
+/* Lines marked
+ *
+ * $$ are external commands
+ * !! internal commands which are not yet implemented
+ * ** special FREEDOS specific implementation
+ */
+
+struct CMD
+  cmds[] =
+{
+#ifdef FEATURE_ALIASES
+  {"alias",    0, cmd_alias},      /* **   */
+#endif
+
+#ifdef INCLUDE_CMD_BEEP
+  {"beep",     0, cmd_beep},        /* **   */
+#endif
+
+/*{"break",    0,             cmd_break     },    !!    */
+
+  {"call", CMD_BATCHONLY, cmd_call},
+
+#ifdef INCLUDE_CMD_CHDIR
+  {"cd", CMD_SPECIAL, cmd_chdir},
+  {"chdir", CMD_SPECIAL, cmd_chdir},
+#endif
+
+/*    { "chcp",     0,             cmd_chcp      },    !!    */
+
+#ifdef INCLUDE_CMD_CLS
+  {"cls",      0,             cmd_cls       },
+#endif
+
+/*    { "copy",     0,             cmd_copy      },    !!    */
+
+/*    { "ctty",     0,             cmd_ctty      },    !!    */
+
+#ifdef INCLUDE_CMD_DATE
+  {"date", 0, cmd_date},
+#endif
+
+#ifdef INCLUDE_CMD_DEL
+  {"del", 0, cmd_del},
+#endif
+
+#ifdef INCLUDE_CMD_DIR
+  {"dir", CMD_SPECIAL, cmd_dir},
+#endif
+
+#ifdef FEATURE_HISTORY
+  {"doskey", 0, cmd_doskey},    /* **   */
+#endif
+
+  {"echo", 0, cmd_echo},
+
+#ifdef INCLUDE_CMD_DEL
+  {"erase", 0, cmd_del},
+#endif
+
+  {"exit", 0, internal_exit},
+
+  {"for", 0, cmd_for},
+
+  {"goto", CMD_BATCHONLY, cmd_goto},
+
+  {"if", 0, cmd_if},
+
+#ifdef INCLUDE_CMD_LOADHIGH
+  {"lh", 0, cmd_loadhigh},
+#endif
+
+#ifdef INCLUDE_CMD_LOADFIX
+  {"loadfix", 0, cmd_loadfix},
+#endif
+
+#ifdef INCLUDE_CMD_LOADHIGH
+  {"loadhigh", 0, cmd_loadhigh},
+#endif
+
+#ifdef INCLUDE_CMD_MKDIR
+  {"md", CMD_SPECIAL, cmd_mkdir},
+  {"mkdir", CMD_SPECIAL, cmd_mkdir},
+#endif
+
+#ifdef INCLUDE_CMD_PATH
+  {"path", 0, cmd_path},
+#endif
+
+#ifdef INCLUDE_CMD_PAUSE
+  {"pause", 0, cmd_pause},
+#endif
+
+#ifdef INCLUDE_CMD_PROMPT
+  {"prompt", 0, cmd_prompt},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+  {"rd", CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_REM
+  {"rem", 0, cmd_rem},
+#endif
+
+#ifdef INCLUDE_CMD_RENAME
+  {"ren", 0, cmd_rename},
+  {"rename", 0, cmd_rename},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+  {"rmdir", CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_SET
+  {"set", 0, cmd_set},
+#endif
+
+  {"shift", CMD_BATCHONLY, cmd_shift},
+
+#ifdef INCLUDE_CMD_TIME
+  {"time", 0, cmd_time},
+#endif
+
+#ifdef INCLUDE_CMD_TRUENAME
+  {"truename", 0, cmd_truename},
+#endif
+
+#ifdef INCLUDE_CMD_TYPE
+  {"type", 0, cmd_type},
+#endif
+
+#ifdef INCLUDE_CMD_VER
+  {"ver", 0, cmd_ver},
+#endif
+
+#ifdef INCLUDE_CMD_VERIFY
+  { "verify",   0,             cmd_verify    },
+#endif
+
+  {NULL, 0, NULL}
+};
+
+/*    append,                             $$    */
+/*    assign,                             $$    */
+/*    attrib,                             $$    */
+/*    backup,                             $$    */
+/*    chkdsk,                             $$    */
+/*    command,                              $$    */
+/*    comp,                               $$    */
+/*    debug,                              $$    */
+/*    diskcomp,                           $$    */
+/*    diskcopy,                           $$    */
+/*    doskey,                             **    */
+/*    dosshell,                           $$    */
+/*    edit,                               $$    */
+/*    edlin,                              $$    */
+/*    emm386,                             $$    */
+/*    exe2bin,                              $$    */
+/*    expand,                             $$    */
+/*    fastopen,                           $$    */
+/*    fc,                                 $$    */
+/*    fdisk,                              $$    */
+/*    find,                               $$    */
+/*    format,                             $$    */
+/*    graftabl,                           $$    */
+/*    graphics,                           $$    */
+/*    help,                               $$    */
+/*    join,                               $$    */
+/*    keyb,                               $$    */
+/*    label,                              $$    */
+/*    mem,                                $$    */
+/*    mirror,                             $$    */
+/*    mode,                               $$    */
+/*    more,                               $$    */
+/*    nlsfunc,                              $$    */
+/*    print,                              $$    */
+/*    qbasic,                             $$    */
+/*    recover,                              $$    */
+/*    replace,                              $$    */
+/*    restore,                              $$    */
+/*    setver,                             $$    */
+/*    share,                              $$    */
+/*    sort,                               $$    */
+/*    subst,                              $$    */
+/*    sys,                                $$    */
+/*    tree,                                $$    */
+/*    undelete,                           $$    */
+/*    unformat,                           $$    */
+/*    xcopy,                              $$    */
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/command.c com075/command.c
--- com074d/command.c	Thu Jul 16 10:57:22 1998
+++ com075/command.c	Fri Aug  7 08:44:26 1998
@@ -3,70 +3,90 @@
  *
  *  Comments:
  *
- *  06/17/94 (Tim Norman) ---------------------------------------------------
+ * 17 Jun 1994 (Tim Norman)
  *    started.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
- *    i have cleaned up the source code. changes now bring this source into
- *    guidelines for recommended programming practice.
+ * 08 Aug 1995 (Matt Rains)
+ *   I have cleaned up the source code. changes now bring this source
+ *   into guidelines for recommended programming practice.
  *
- *    i have added the the standard FreeDOS GNU licence test to the
+ *   A added the the standard FreeDOS GNU licence test to the
  *    initialize() function.
  *
- *    i have started to replease puts() with printf(). this will help
+ *   Started to replease puts() with printf(). this will help
  *    standardize output. please follow my lead.
  *
- *    i have added some constants to help making changes easier.
+ *   I have added some constants to help making changes easier.
  *
- *  12/15/95 (Tim Norman) ---------------------------------------------------
+ * 15 Dec 1995 (Tim Norman)
  *    major rewrite of the code to make it more efficient and add
  *    redirection support (finally!)
  *
- *  1/6/96 (Tim Norman) -----------------------------------------------------
- *    finished adding redirection support!!!  Changed to use our own exec
+ * 6 Jan 1996 (Tim Norman)
+ *   finished adding redirection support!  Changed to use our own exec
  *    code (MUCH thanks to Svante Frey!!)
  *
- *  1/29/96 (Tim Norman) ----------------------------------------------------
- *    added support for CHDIR, RMDIR, MKDIR, and ERASE, as per the suggestion
+ * 29 Jan 1996 (Tim Norman)
+ *   added support for CHDIR, RMDIR, MKDIR, and ERASE, as per suggestion
  *    of Steffan Kaiser
  *
- *    changed the "file not found" error message to "bad command or filename"
+ *   changed "file not found" error message to "bad command or filename"
  *    thanks to Dustin Norman for noticing that confusing message!
  *
- *    changed the format to call internal commands (again!) so that if they
+ *   changed the format to call internal commands (again) so that if they
  *    want to split their commands, they can do it themselves (none of the
  *    internal functions so far need that much power, anyway)
  *
- *  8/27/96 (Tim Norman) ----------------------------------------------------
+ *
+ * 27 Aug 1996 (Tim Norman)
  *    added in support for Oliver Mueller's ALIAS command
  *
- *  6/14/97 (Steffan Kaiser) ------------------------------------------------
+ * 14 Jun 1997 (Steffan Kaiser)
  *    added ctrl-break handling and error level
  *
- * 06/16/98 (Rob Lake) ------------------------------------------------------
+ * 16 Jun 1998 (Rob Lake)
  *    Runs command.com if /P is specified in command line.  Command.com
  *    also stays permanent.  If /C is in the command line, starts the
  *    program next in the line.
  *
- * 06/21/98 (Rob Lake) ------------------------------------------------------
+ * 21 Jun 1998 (Rob Lake)
  *    Fixed up /C so that arguments for the program
  *
- *  07/08/1998 (John P. Price)
+ * 08-Jul-1998 (John P. Price)
  *  - Now sets COMSPEC environment variable
  *  - misc clean up and optimization
  *  - added date and time commands
  *  - changed to using spawnl instead of exec.  exec does not copy the
  *     environment to the child process!
  *
- *  07/09/1998 (John P. Price)
- *  - fixed call to spawnl so it would pass arguments correctly
+ * 14 Jul 1998 (Hans B Pufal)
+ *   Reorganised source to be more efficient and to more closely follow
+ *   MS-DOS conventions. (eg %..% environment variable replacement
+ *   works form command line as well as batch file.
+ *
+ *   New organisation also properly support nested batch files.
+ *
+ *   New command table structure is half way towards providing a
+ *   system in which COMMAND will find out what internal commands
+ *   are loaded
+ *
+ * 24 Jul 1998 (Hans B Pufal) [HBP_003]
+ *   Fixed return value when called with /C option
+ *
+ * 27 Jul 1998  John P. Price
+ * - added config.h include
  *
- *  07/12/98 (Rob Lake)
- *  - Changed error messages
+ * 28 Jul 1998  John P. Price
+ * - added showcmds function to show commands and options available
  *
+ * 07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ * - Fixed carrage return output to better match MSDOS with echo on or off.
+ *   (marked with "JPP 19980708")
  *
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -81,304 +101,98 @@
 #include <sys\stat.h>
 
 #include "command.h"
-
-/* define the internal commands */
-#define ALIAS   "alias"
-#define CD        "cd"
-#define CHDIR     "chdir"
-#define DEL       "del"
-#define DIR       "dir"
-#define DOSKEY    "doskey"
-#define ERASE     "erase"
-#define EXIT      "exit"
-#define LH        "lh"
-#define LOADFIX   "loadfix"
-#define LOADHIGH  "loadhigh"
-#define MD        "md"
-#define MKDIR     "mkdir"
-#define PATH      "path"
-#define PROMPT    "prompt"
-#define RD        "rd"
-#define REM       "rem"
-#define REN       "ren"
-#define RMDIR     "rmdir"
-#define SET       "set"
-#define VER       "ver"
-#define DATE      "date"
-#define TIME      "time"
-#define TYPE      "type"
+#include "batch.h"
 
 int exitflag = 0;               /* indicates EXIT was typed */
 int canexit = 1;                /* indicates if this shell is exitable */
 int ctrlBreak = 0;              /* Ctrl-Break or Ctrl-C hit */
 int errorlevel = 0;             /* Errorlevel of last launched external program */
 
-/*
+extern struct CMD
+  cmds[];                       /* The internal command table */
+
+void fatal_error(char *s)
+{
+  /*
  *  fatal error handler.
  *
- *
  */
-void
-fatal_error(char *s)
-{
+
   printf("fatal_error() : %s\n", s);
+
   exit(100);
 }
 
-/*
+static char is_delim(char c)
+{
+  /*
  *  is character a delimeter when used on first word?
  *
- *
  */
-char
-is_delim(char c)
-{
+
   return (c == '/' || c == '=' || c == 0 || isspace(c));
 }
 
-/*
- * execute this as an external program
+static void execute(char *first, char *rest)
+{
+  /*
+   * This command (in first) was not found in the command table
+   *
  *
  * first - first word on command line
  * rest  - rest of command line
  *
  */
-void
-execute(char *first, char *rest)
-{
-  char *paths[129],
-    fullname[128];
-  int r;
 
-  /* check the command line for drive changes and commands run without */
-  /* spaces, like CD\DOS, etc */
+  char *fullname;
 
   /* check for a drive change */
-  if (first[0] && first[1] == ':' && first[2] == 0)
+  if ((strcmp(first + 1, ":") == 0) && isalpha(*first))
   {
-    if (isalpha(first[0]))
-    {
-      setdisk(toupper(first[0]) - 'A');
-    }
+    setdisk(toupper(*first) - 'A');
+
+    if (getdisk() != toupper(*first) - 'A')
+      puts(INVALIDDRIVE);
 
-    if (getdisk() != toupper(first[0]) - 'A')
-    {
-      printf("%s\n", INVALIDDRIVE);
-    }
-    return;
-  }
-  /* this scary piece of code simply checks for CD or CHDIR without a */
-  /* space after it.  E.g. CD\DOS */
-  else if ((memicmp(first, CD, sizeof(CD) - 1) == 0 &&
-         (first[sizeof(CD) - 1] == '\\' || first[sizeof(CD) - 1] == '.')) ||
-           (memicmp(first, CHDIR, sizeof(CHDIR) - 1) == 0 &&
-     (first[sizeof(CHDIR) - 1] == '\\' || first[sizeof(CHDIR) - 1] == '.')))
-  {
-    cd(first, rest);
-    return;
-  }
-  /* checks for MD or MKDIR w/o a space */
-  else if ((memicmp(first, MD, sizeof(MD) - 1) == 0 &&
-         (first[sizeof(MD) - 1] == '\\' || first[sizeof(MD) - 1] == '.')) ||
-           (memicmp(first, MKDIR, sizeof(MKDIR) - 1) == 0 &&
-     (first[sizeof(MKDIR) - 1] == '\\' || first[sizeof(MKDIR) - 1] == '.')))
-  {
-    md(first, rest);
-    return;
-  }
-  /* checks for RD or RMDIR w/o a space */
-  else if ((memicmp(first, RD, sizeof(RD) - 1) == 0 &&
-         (first[sizeof(RD) - 1] == '\\' || first[sizeof(RD) - 1] == '.')) ||
-           (memicmp(first, RMDIR, sizeof(RMDIR) - 1) == 0 &&
-     (first[sizeof(RMDIR) - 1] == '\\' || first[sizeof(RMDIR) - 1] == '.')))
-  {
-    rd(first, rest);
     return;
   }
 
   /* get the PATH environment variable and parse it */
-  get_paths(paths);
-
   /* search the PATH environment variable for the binary */
-  if (!find_which(paths, first, fullname))
+  fullname = find_which(first);
+
+  if (!fullname)
   {
-    //fprintf(stderr, "%s\n", BADCOMMAND);
-    badcommand();
+    error_bad_command();
     return;
   }
 
   /* check if this is a .BAT file */
-  if (stricmp(strrchr(fullname, '.') + 1, "bat") == 0)
+
+  if (stricmp(strrchr(fullname, '.'), ".bat") == 0)
   {
-    batch(fullname, rest);
+    dprintf(("[BATCH: %s %s]\n", fullname, rest));
+    batch(fullname, first, rest);
   }
-  /* else exec the program */
-  /* JPP 07/08/1998 changed to using spawnl.  exec does not copy environment
-   * to the child process! */
-  /* JPP 07/09/1998 fixed call to spawnl so it would pass arguments correctly */
+
   else
+    /* exec the program */
   {
-    if (spawnl(P_WAIT, fullname, fullname, rest, NULL) == -1)
-    {
+    int result;
+
+    dprintf(("[EXEC: %s %s]\n", fullname, rest));
+    result = spawnl(P_WAIT, fullname, fullname, rest, NULL);
+
+    if (result == -1)
       perror("executing spawnl function");
+    else
+      errorlevel = result;
     }
-  }
-/*
- * else if ((r = exec(fullname, rest, EnvSeg)) != 0)
- * {
- * switch (r)
- * {
- * case 1:
- * {
- * printf("%s\n", INVALIDFUNCTION);
- * break;
- * }
- * case 2:
- * {
- * printf("%s\n", FILENOTFOUND);
- * break;
- * }
- * case 5:
- * {
- * printf("%s\n", ACCESSDENIED);
- * break;
- * }
- * case 8:
- * {
- * printf("%s\n", NOTENOUGHMEMORY);
- * break;
- * }
- * case 10:
- * {
- * printf("%s\n", BADENVIROMENT);
- * break;
- * }
- * case 11:
- * {
- * printf("%s\n", BADFORMAT);
- * break;
- * }
- * default:
- * {
- * printf("ERROR: unknown error %d.\n", errno);
- * break;
- * }
- * }
- * }
- */
 }
 
-/* a list of all the internal commands, associating their command names */
-/* to the functions to process them                                     */
-static struct CMD
-{
-  char *name;
-  int (*func) (char *, char *);
-}
-cmds[] =
+static void docommand(char *line)
 {
-  {
-    DIR, dir
-  }
-  ,
-  {
-    CD, cd
-  }
-  ,
-  {
-    CHDIR, cd
-  }
-  ,
-  {
-    RD, rd
-  }
-  ,
-  {
-    RMDIR, rd
-  }
-  ,
-  {
-    MD, md
-  }
-  ,
-  {
-    MKDIR, md
-  }
-  ,
-  {
-    DEL, del
-  }
-  ,
-  {
-    ERASE, del
-  }
-  ,
-  {
-    REN, ren
-  }
-  ,
-  {
-    REM, rem
-  }
-  ,
-  {
-    DOSKEY, doskey
-  }
-  ,
-  {
-    EXIT, internal_exit
-  }
-  ,
-  {
-    VER, ver
-  }
-  ,
-  {
-    SET, set
-  }
-  ,
-  {
-    PROMPT, prompt
-  }
-  ,
-  {
-    PATH, path
-  }
-  ,
-  {
-    LH, loadhigh
-  }
-  ,
-  {
-    LOADHIGH, loadhigh
-  }
-  ,
-  {
-    LOADFIX, loadfix
-  }
-  ,
-  {
-    ALIAS, alias
-  }
-  ,
-  {
-    DATE, cmd_date
-  }
-  ,
-  {
-    TIME, cmd_time
-  }
-  ,
-  {
-    TYPE, cmd_type
-  }
-  ,
-  {
-    NULL, NULL
-  }
-};
-
-/*
+  /*
  * look through the internal commands and determine whether or not this
  * command is one of them.  If it is, call the command.  If not, call
  * execute to run it as an external program.
@@ -386,50 +200,71 @@
  * line - the command line of the program to run
  *
  */
-void
-command(char *line)
-{
-  char com[128];                /* the first word in the command                */
-  int count,                    /* counter                                      */
-    start;                      /* index to start of first word on command line */
-  int executed = 0;             /* whether the command was executed             */
-  char *rest;                   /* pointer to the rest of the command line      */
-
-  /* skip over the initial whitespace on the command line */
-  start = 0;
-  while (isspace(line[start]))
-    start++;
 
-  /* count to the end of the first word */
-  for (count = start; !is_delim(line[count]); count++)
-    ;
+  char
+    com[128],                   /* the first word in the command                */
+   *cp = com,
+   *cstart,
+   *rest = line;                /* pointer to the rest of the command line      */
 
-  /* store the rest of the command line in rest */
-  rest = &line[count];
-  while (isspace(*rest))
+  int
+    cl;
+
+  struct CMD
+   *cmdptr;
+
+  while (isspace(*rest))        /* Skip over initial white space */
     rest++;
 
-  /* copy the first word into com */
-  memcpy(com, &line[start], count - start);
-  com[count - start] = 0;
+  cstart = rest;
 
-  /* check for empty command line */
-  if (!com[0])
-    return;
+  if (*rest)                    /* Anything to do ? */
+  {
+    while (!is_delim(*rest))    /* Copy over 1st word as lower case */
+      *cp++ = tolower(*rest++);
 
-  /* look through the command table and call the appropriate function */
-  for (count = 0; cmds[count].name; count++)
-    if (strcmpi(com, cmds[count].name) == 0)
+    *cp = '\0';                 /* Terminate first word */
+
+    while (isspace(*rest))      /* Skip over whitespace to rest of line */
+      rest++;
+
+    for (cmdptr = cmds;; cmdptr++)  /* Scan internal command table */
     {
-      cmds[count].func(com, rest);
+      if (cmdptr->name == NULL) /* If end of table execute ext cmd */
+      {
+        execute(com, rest);
+        break;
+      }
 
-      executed = 1;
+      if (strcmp(com, cmdptr->name) == 0)
+      {
+        cmdptr->func(com, rest);
       break;
     }
 
-  /* if none of those work, try calling it as an external program */
-  if (!executed)
-    execute(com, rest);
+      /* The following code handles the case of commands like CD which
+       * are recognised even when the command name and parameter are
+       * not space separated.
+       *
+       * e.g dir..
+       * cd\freda
+       */
+
+      cl = strlen(cmdptr->name);  /* Get length of command name */
+
+      if ((cmdptr->flags & CMD_SPECIAL) &&
+          (strncmp(cmdptr->name, com, cl) == 0) &&
+          (strchr("\\.", *(com + cl))))
+      {
+        // OK its one of the specials...
+
+        com[cl] = '\0';         /* Terminate first word properly */
+
+        cmdptr->func(com, cstart + cl); /* Call with new rest */
+        break;
+      }
+    }
+  }
 }
 
 /*
@@ -437,217 +272,244 @@
  * full input/output redirection and piping are supported
  *
  */
-void
-parsecommandline(char *s)
+void parsecommandline(char *s)
 {
-  char in[128] = "",
-    out[128] = "",
-   *pipes[128];
-  int num,
-    count;
-  int oldinfd,
-    oldoutfd,
-    prevfd = -1,
-    infd,
-    outfd;
-  char tempdir[128],
-    fname[2][128] =
-  {"", ""},
-   *t;
-  int curfname = 0;
+  char in[128] = "";
+  char out[128] = "";
+  char tempdir[128] = ".\\";
+  char fname[2][128] = {"", ""};
+  char *t = NULL;
+
+  int
+    of_attrib = O_CREAT | O_TRUNC | O_TEXT | O_WRONLY,
+    num,
+    oldinfd,
+    oldoutfd;
+
+  dprintf(("[parsecommandline ('%s')]\n", s));
 
   /* first thing we do is alias expansion */
+
+#ifdef FEATURE_ALIASES
   aliasexpand(s, 127);
+#endif
 
   /* find the temp directory to store temporary files */
-  t = getenv("TEMP");
-  if (t)
+
+  if (NULL != (t = getenv("TEMP")))
+  {
     strcpy(tempdir, t);
-  else
-    strcpy(tempdir, ".");
 
   if (tempdir[strlen(tempdir) - 1] != '\\')
     strcat(tempdir, "\\");
+  }
 
   /* get the redirections from the command line */
-  get_redirection(s, in, out, pipes, &num);
 
-  /* inefficient, but oh well for now */
-  while (isspace(in[0]))
-    memmove(in, &in[1], strlen(in));
-  while (isspace(out[0]))
-    memmove(out, &out[1], strlen(out));
+  num = get_redirection(s, in, out, &of_attrib);
 
-  if (in[0])
-  {
-    infd = open(in, O_TEXT | O_RDONLY, S_IREAD);
-    if (infd == EOF)
-    {
-      printf("Can't redirect from file %s\n", in);
-      return;
-    }
-  }
-  else
-    infd = -1;
+  /* more efficient, but do we really need to do this? */
+
+  for (t = in; isspace(*t); t++)
+    ;
+  strcpy(in, t);
+
+  for (t = out; isspace(*t); t++)
+    ;
+  strcpy(out, t);
 
-  if (out[0])
+  /* Set up the initial conditions ... */
+
+  oldinfd = oldoutfd = -1;
+
+  if (in[0] || (num > 1))       /* Need to preserve stdin */
+    oldinfd = dup(0);
+
+  if (in[0])                    /* redirect input from this file name */
   {
-    outfd = open(out, O_CREAT | O_TRUNC | O_TEXT | O_WRONLY,
-                 S_IREAD | S_IWRITE);
-    if (outfd == EOF)
+    close(0);
+    if (0 != open(in, O_TEXT | O_RDONLY, S_IREAD))
     {
-      printf("Can't redirect to file %s\n", out);
-      close(infd);
+      printf("Can't redirect input from file %s\n", in);
       return;
     }
   }
-  else
-    outfd = -1;
 
-  for (count = 0; count < num; count++)
-  {
-    if (count == 0)             /* make backups of stdin and stdout */
-    {
-      oldinfd = dup(0);
+  if (out[0] || (num > 1))      /* Need to preserve stdout */
       oldoutfd = dup(1);
-    }
 
-    if (count == 0)             /* first pipe gets input redirection */
-    {
-      if (infd != -1)
-      {
-        close(0);
-        dup2(infd, 0);
-        close(infd);
-      }
-    }
-    else
-      /* input from last pipe's output */
-    {
-      close(prevfd);
-      prevfd = open(fname[1 - curfname], O_TEXT | O_RDONLY, S_IREAD);
-      if (prevfd == EOF)
+  /* Now do all but the last pipe command */
+
+  *fname[1] = '\0';
+
+  while (num-- > 1)
       {
-        close(0);
-        dup2(oldinfd, 0);
-        close(oldinfd);
+    close(1);                   /* Close currrent output file */
+    open(tmpnam(fname[0]), O_CREAT | O_TRUNC | O_TEXT | O_WRONLY,
+         S_IREAD | S_IWRITE);
 
-        close(1);
-        dup2(oldoutfd, 1);
-        close(oldoutfd);
+    docommand(s);
 
-        /* this might leave some temporary files around... oh well */
-        //fprintf(stderr, "Error!  Cannot pipe!  Cannot open temporary file!\n");
-        no_pipe();
-        close(outfd);
-        return;
-      }
+    if (*fname[1])
+      remove(fname[1]);
 
       close(0);
-      dup2(prevfd, 0);
-      close(prevfd);
+    strcpy(fname[1], fname[0]);
+    open(fname[1], O_TEXT | O_RDONLY, S_IREAD);
 
-      if (fname[curfname][0])
-      {
-        unlink(fname[curfname]);
-      }
+    s = s + strlen(s) + 1;
     }
 
-    if (count == num - 1)       /* last pipe gets output redirection */
-    {
-      if (outfd != -1)
+  /* Now set up the end conditions... */
+
+  if (out[0])                   /* Final output to here */
       {
         close(1);
-        dup2(outfd, 1);
-        close(outfd);
-      }
-      else
+    if (1 != open(out, of_attrib, S_IREAD | S_IWRITE))
       {
-        close(1);
-        dup2(oldoutfd, 1);
-        close(oldoutfd);
+      printf("Can't redirect to file %s\n", out);
+      return;
       }
+
+    if (of_attrib & O_APPEND)
+      lseek(1, 0, SEEK_END);
+
     }
-    else
-    {
-      strcpy(fname[curfname], tempdir);
-      prevfd = creattemp(fname[curfname], 0);
-      if (prevfd == EOF)
+  else if (oldoutfd != -1)      /* Restore original stdout */
       {
-        close(0);
-        dup2(oldinfd, 0);
-        close(oldinfd);
-
         close(1);
         dup2(oldoutfd, 1);
         close(oldoutfd);
-
-        /* might leave some temp files around */
-        //fprintf(stderr, "Error!  Cannot pipe!  Cannot create temporary file!\n");
-        no_pipe();
-        close(infd);
-        close(outfd);
-        return;
-      }
-
-      close(1);
-      dup2(prevfd, 1);
-      /* closing prevfd here causes things to not work for some reason */
-
-      curfname = 1 - curfname;  /* switch to other fname for next time */
-    }
-
-    /* process this command */
-    command(pipes[count]);
+    oldoutfd = -1;
   }
 
-  if (prevfd != -1)
-    close(prevfd);
+  docommand(s);                   /* process final command */
 
-  if (fname[1 - curfname][0])
-  {
-    unlink(fname[1 - curfname]);
-  }
+  if (*fname[1])
+    remove(fname[1]);
 
-  if (in[0] || num > 1)
+  if (oldinfd != -1)            /* Restore original STDIN */
   {
     close(0);
     dup2(oldinfd, 0);
     close(oldinfd);
   }
-  else
-    close(oldinfd);
 
-  if (out[0])
+  if (oldoutfd != -1)           /* Restore original STDOUT */
   {
     close(1);
     dup2(oldoutfd, 1);
     close(oldoutfd);
   }
-  else
-    close(oldoutfd);
 }
 
 /*
  * do the prompt/input/process loop
  *
- *
  */
-int
-process_input(void)
+
+static int process_input(int xflag)
 {
-  char commandline[1024];
+  char
+    commandline[512],
+    readline[129],
+   *evar,
+   *tp,
+   *ip,
+   *cp;
+
+  /* JPP 19980807 - changed name so not to conflict with echo global */
+  int echothisline;
 
   do
   {
+    if (NULL == (ip = readbatchline(&echothisline)))  /* if no batch input then... */
+    {
+      if (xflag)
+        return 0;
+
+      readcommand(readline, 128);
+      ip = readline;
+      echothisline = 0;
+    }
+
+    cp = commandline;
+    while (*ip)
+    {
+      if (*ip == '%')
+      {
+        switch (*++ip)
+        {
+          case '%':
+            *cp++ = *ip++;
+            break;
+
+          case '0':
+          case '1':
+          case '2':
+          case '3':
+          case '4':
+          case '5':
+          case '6':
+          case '7':
+          case '8':
+          case '9':
+            if (NULL != (tp = find_arg(*ip - '0')))
+            {
+              cp = stpcpy(cp, tp);
+              ip++;
+            }
+            else
+              *cp++ = '%';
+
+            break;
+
+          case '?':
+            cp += sprintf(cp, "%u", errorlevel);
+            ip++;
+            break;
+
+          default:
+            if ((tp = strchr(ip, '%')) != NULL)
+            {
+              *tp = '\0';
+
+              if (((evar = getenv(ip)) != NULL) ||
+                  ((evar = getenv(strupr(ip))) != NULL))
+                cp = stpcpy(cp, evar);
+
+              ip = tp + 1;
+            }
+            break;
+        }
+
+        continue;
+      }
+
+      if (iscntrl(*ip))
+        *ip = ' ';
+
+      *cp++ = *ip++;
+    }
+
+    *cp = '\0';
+
+    while ((--cp >= commandline) && isspace(*cp)) /* strip trailing spaces */
+      ;
+
+    *(cp + 1) = '\0';
+
+    /* JPP 19980807 */
+    if (echothisline)                 /* Echo batch file line */
+    {
     printprompt();
-    readcommand(commandline, 128);
+      puts(commandline);
+    }
 
-    /* JPP 07/08/1998 make things closer to MS-DOS */
     if (*commandline)
     {
       parsecommandline(commandline);
-      putchar('\n');
+      if (echo) putchar('\n');    /* JPP 19980807 */
     }
   }
   while (!canexit || !exitflag);
@@ -657,42 +519,93 @@
 
 /*
  *  control-break handler.
- *
- *
  */
-int
-c_brk(void)
+int c_brk(void)
 {
   ctrlBreak = 1;                /* indicate the break condition */
   return 1;                     /* continue execution */
 }
 
 /*
+ * show commands and options that are available.
+ *
+ */
+static void showcmds(void)
+{
+  struct CMD *cmdptr;
+  unsigned char y;
+
+  printf("\nInternal commands available:\n");
+  y = 0;
+  cmdptr = cmds;
+  while (cmdptr->name)
+  {
+    if (++y == 8)
+    {
+      puts(cmdptr->name);
+      y = 0;
+    }
+    else
+     printf("%-10s", cmdptr->name);
+
+    cmdptr++;
+  }
+  if (y != 0) putchar('\n');
+  printf("\nFeatures available: ");
+#ifdef FEATURE_ALIASES
+  printf("[aliases] ");
+#endif
+#ifdef FEATURE_HISTORY
+  printf("[history] ");
+#endif
+#ifdef FEATURE_FILENAME_COMPLETION
+  printf("[filename completion] ");
+#endif
+  putchar('\n');
+  putchar('\n');
+}
+
+
+/*
  * set up global initializations and process parameters
  *
  * argc - number of parameters to command.com
  * argv - command-line parameters
  *
  */
-#pragma argsused
-void
-initialize(int argc, char *argv[])
+static void initialize(int argc, char *argv[])
 {
   char temp[256];
 
-  ctrlbrk(c_brk);
-
-  init_error_handler();
-
   /* Added by Rob Lake 06/16/98.  This enables the command.com
    * to run the autoexec.bat at startup */
+
+#ifdef DEBUG
+  int x;
+
+  dprintf(("[command args:\n"));
+  for (x = 0; x < argc; x++)
+  {
+    dprintf(("%d. %s\n", x, argv[x]));
+  }
+  dprintf(("]\n"));
+#endif
+
   if (argc >= 2)
+  {
     if (strcmpi(argv[1], "/p") == 0)
     {
       if (!exist("\\autoexec.bat"))
       {
-        cmd_date(NULL, NULL);
-        cmd_time(NULL, NULL);
+/* figure out if we're a permanent shell... and make it do this */
+//        OwnerPSP = _psp;
+
+#ifdef INCLUDE_CMD_DATE
+        cmd_date("", "");
+#endif
+#ifdef INCLUDE_CMD_TIME
+        cmd_time("", "");
+#endif
       }
       else
         parsecommandline("\\autoexec.bat");
@@ -710,11 +623,16 @@
         strcat(commandline, " ");
         strcat(commandline, argv[i]);
       }
+
       parsecommandline(commandline);
-      exit(1);
+
+ /* HBP_003 { Fix return value when /C used */
+      exit(process_input(1));
+    }
     }
 
-  ver("ver", "");
+  short_version();
+  showcmds();
 
   /* set up environment space and such */
   if (!EnvSeg)                  /* fix this to later make its own environment */
@@ -724,26 +642,18 @@
     exit(1);
   }
 
-  /* figure out if we're a permanent shell... and make it do this */
-  /* OwnerPSP = _psp; */
-
   /* JPP 07/08/1998 - Set COMSPEC environment variable */
   sprintf(temp, "COMSPEC=%s", argv[0]);
-  set("SET", temp);
-
-  return;
+  set_env(temp);
 }
 
-/*
- * main function
- *
- *
- */
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
-  /* check switches on command-line */
-  initialize(argc, argv);
+  /*
+   * * main function
+   */
+
+  initialize(argc, argv);       /* check switches on command-line */
 
-  return (process_input());     /* call prompt routine */
+  return process_input(0);      /* call prompt routine */
 }
Binary files com074d/command.com and com075/command.com differ
Binary files com074d/command.dsk and com075/command.dsk differ
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/command.h com075/command.h
--- com074d/command.h	Thu Jul 16 10:57:22 1998
+++ com075/command.h	Fri Aug  7 08:44:26 1998
@@ -7,10 +7,15 @@
  *      - Moved error messages in here
  *
  * 07/12/98 (Rob Lake)
- *  - Moved more error message here
+ *  - Moved more error messages here
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - Added compile date to version
  *
  */
 
+#define SHELLVER     "version 0.75 [" __DATE__"]"
+
 #define EnvSeg (*(unsigned far*)MK_FP(_psp, 0x2c))
 #define OwnerPSP (*(unsigned far *)MK_FP(_psp, 0x16))
 
@@ -20,41 +25,21 @@
 #define BREAK_IGNORE 4
 
 /* define some error messages */
-#define SYNTAXERR       "Syntax error"
 #define NOENVERR        "ERROR: no environment"
 #define INVALIDDRIVE    "ERROR: invalid drive"
 #define INVALIDFUNCTION "ERROR: invalid function"
-#define BADCOMMAND      "Bad command or filename"
 #define ACCESSDENIED    "ERROR: access denied"
-#define NOTENOUGHMEMORY "ERROR: not enough memory"
 #define BADENVIROMENT   "ERROR: bad enviroment"
 #define BADFORMAT       "ERROR: bad format"
 #define ERROR_E2BIG     "ERROR: Argument list too long"
 #define ERROR_EINVAL    "ERROR: Invalid argument"
 
-#define CANNOTPIPE      "Error!  Cannot pipe!  Cannot open temporary file!\n"
-
-#define TOO_MANY_PARAMETERS "Too many parameters - %s\n"
-#define INVALID_SWITCH "Invalid switch - /%c\n"
-#define PATH_NOT_FOUND "Path not found\n"
-#define FILE_NOT_FOUND "File not found"
-#define REQ_PARAM_MISSING "Required parameter missing\n"
-#define INVALID_DRIVE "Invalid drive specification\n"
-
 #define SHELLINFO    "FreeDOS Command Line Interface"
-#define SHELLVER     "version 0.74d"
-#define BADCMDLINE   "bad or incorrect command line"
 #define USAGE        "usage"
 #define CD_HELP      "change to directory   CD [d:][path]"
 #define MD_HELP      "make directory   MD [d:]path"
 #define RD_HELP      "remove directory   RD [d:]path"
-#define DIR_HELP     "display directory listing   DIR [d:][path][filespec]"
-#define VER_HELP     "display shell version info   VER [/C/R/W/?]"
-#define DEL_HELP     "delete file   DEL [d:][path]filespec"
-#define REN_HELP     "rename file   REN [d:][path]filespec1 [d:][path]filespec2"
 #define SET_HELP     "SET"
-#define PROMPTEQUAL  "PROMPT="
-#define PATHEQUAL    "PATH="
 
 enum
 {
@@ -73,30 +58,33 @@
 void execute(char *, char *);
 void command(char *);
 void parsecommandline(char *);
-int process_input(void);
 int c_brk(void);
 void initialize(int, char *[]);
+void short_version(void);
 
 /* prototypes for INTERNAL.C */
-int dir(char *, char *);
-int cd(char *, char *);
-int md(char *, char *);
-int rd(char *, char *);
-int set(char *, char *);
-int ver(char *, char *);
-int del(char *, char *);
-int ren(char *, char *);
+int cmd_dir(char *, char *);
+int cmd_chdir(char *, char *);
+int cmd_mkdir(char *, char *);
+int cmd_rmdir(char *, char *);
+int cmd_set(char *, char *);
+int cmd_ver(char *, char *);
+int cmd_del(char *, char *);
+int cmd_rename(char *, char *);
 int internal_exit(char *, char *);
-int rem(char *, char *);
-int doskey(char *, char *);
-int prompt(char *, char *);
-int path(char *, char *);
+int cmd_rem(char *, char *);
+int cmd_doskey(char *, char *);
+int cmd_prompt(char *, char *);
+int cmd_path(char *, char *);
 int cmd_date(char *, char *);   /*JPP 07/08/1998 */
 int cmd_time(char *, char *);   /*JPP 07/08/1998 */
 int cmd_type(char *, char *);   /*JPP 07/08/1998 */
+int cmd_truename(char *first, char *rest);  /*RL 07/14/1998 */
+int cmd_cls(char *, char *);   /*JPP 07/27/1998 */
+int set_env(char *s);
+int cmd_verify(char *cmd, char *param);/*JPP 31-Jul-1998 */
 
 /* prototypes for ENVIRON.C */
-void show_environment(void);
 
 /* prototypes from PROMPT.C */
 void printprompt(void);
@@ -105,28 +93,26 @@
 void readcommand(char *, int);
 
 /* prototypes for BATCH.C */
-int batch(char *, char *);
+/* int batch(char *, char *); - HBP */
 int _getch(void);
 
 /* prototypes for WHERE.C */
-void get_paths(char *[129]);
-int find_which(char *[129], char *, char *);
+char *find_which(const char *);
 
 /* prototypes for EXEC.C */
 int exec(const char *, char *, const unsigned);
 
 /* prototypes for REDIR.C */
-void get_redirection(char *, char *, char *, char *[128], int *);
 
 /* prototypes for LOADHIGH.C */
-int loadhigh(char *, char *);
-int loadfix(char *, char *);
+int cmd_loadhigh(char *, char *);
+int cmd_loadfix(char *, char *);
 
 /* prototypes for ALIAS.C */
 void aliasexpand(char *, int);
 int aliasswapout(void);
 int aliasswapin(void);
-int alias(char *, char *);
+int cmd_alias(char *, char *);
 
 /* Prototypes for ERR_HAND.C */
 void init_error_handler(void);
@@ -136,19 +122,72 @@
                           unsigned, unsigned, unsigned, unsigned, unsigned);
 
 /* Prototypes for MISC.C */
-int exist(char *);
+int exist(const char *);
 int chkCBreak(int);
 int cgetchar(void);
 int split(char *, char **);
 char *parse_firstarg(char *);
 
 /* Prototypes for ERROR.C */
-void no_pipe(void);
-void badcommand(void);
-void invalid_drive(void);
-void req_param_missing(void);
-void sfile_not_found(char *);
-void file_not_found(void);
-void path_not_found(void);
-void too_many_parameters(char *);
-void invalid_switch(char);
+void error_no_pipe(void);
+void error_bad_command(void);
+void error_invalid_drive(void);
+void error_req_param_missing(void);
+void error_sfile_not_found(char *);
+void error_file_not_found(void);
+void error_path_not_found(void);
+void error_too_many_parameters(char *);
+void error_invalid_switch(char);
+void error_out_of_memory(void);
+void error_syntax(char *);
+
+void msg_pause(void);
+
+/* [ HBP 16 Jul 1998   */
+
+/* use the first line for debugging messages.  2nd for none. */
+#ifdef DEBUG
+#define dprintf(p)  printf p
+#else
+#define dprintf(p)
+#endif
+
+#define D_ON         "on"
+#define D_OFF        "off"
+
+/* Flags used in CMDTABLE */
+
+#define CMD_SPECIAL     1
+#define CMD_BATCHONLY   2
+
+struct CMD
+{
+  char *name;
+  int flags;
+  int (*func) (char *, char *);
+};
+
+/* New procs in BATCH.C */
+
+char *readbatchline(int *);
+char *find_arg(int);
+
+/* The MSDOS Batch Commands [MS-DOS 5.0 User's Guide and Reference p359] */
+int cmd_call(char *, char *);
+int cmd_echo(char *, char *);
+int cmd_for(char *, char *);
+int cmd_goto(char *, char *);
+int cmd_if(char *, char *);
+int cmd_pause(char *, char *);
+int cmd_shift(char *, char *);
+
+int cmd_beep(char *, char *);
+
+/* The following are changes to old lines, originals commented out with
+ * -HBP tag */
+
+int get_redirection(char *, char *, char *, int *);
+
+int batch(char *, char *, char *);
+
+/*   HBP 16 Jul 1998 ] */
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/command.mak com075/command.mak
--- com074d/command.mak	Thu Jul 16 10:25:20 1998
+++ com075/command.mak	Thu Aug  6 11:00:36 1998
@@ -45,7 +45,23 @@
  del.obj \
  ren.obj \
  set.obj \
- ver.obj
+ ver.obj \
+ cmdtable.obj \
+ truename.obj \
+ call.obj \
+ echo.obj \
+ for.obj \
+ goto.obj \
+ if.obj \
+ beep.obj \
+ pause.obj \
+ shift.obj \
+ path.obj \
+ cls.obj \
+ verify.obj \
+ datefunc.obj \
+ timefunc.obj \
+ filecomp.obj
 
 #		*Explicit Rules*
 command.exe: command.cfg $(EXE_dependencies)
@@ -76,7 +92,23 @@
 del.obj+
 ren.obj+
 set.obj+
-ver.obj
+ver.obj+
+cmdtable.obj+
+truename.obj+
+call.obj+
+echo.obj+
+for.obj+
+goto.obj+
+if.obj+
+beep.obj+
+pause.obj+
+shift.obj+
+path.obj+
+cls.obj+
+verify.obj+
+datefunc.obj+
+timefunc.obj+
+filecomp.obj
 command
 		# no map file
 cs.lib
@@ -138,42 +170,54 @@
 
 ver.obj: command.cfg ver.c 
 
+cmdtable.obj: command.cfg cmdtable.c 
+
+truename.obj: command.cfg truename.c 
+
+call.obj: command.cfg call.c 
+
+echo.obj: command.cfg echo.c 
+
+for.obj: command.cfg for.c 
+
+goto.obj: command.cfg goto.c 
+
+if.obj: command.cfg if.c 
+
+beep.obj: command.cfg beep.c 
+
+pause.obj: command.cfg pause.c 
+
+shift.obj: command.cfg shift.c 
+
+path.obj: command.cfg path.c 
+
+cls.obj: command.cfg cls.c 
+
+verify.obj: command.cfg verify.c 
+
+datefunc.obj: command.cfg datefunc.c 
+
+timefunc.obj: command.cfg timefunc.c 
+
+filecomp.obj: command.cfg filecomp.c 
+
 #		*Compiler Configuration File*
 command.cfg: command.mak
   copy &&|
 -mt
+-a
 -f-
 -ff-
+-K
 -C
+-w+
 -O
 -Z
 -k-
+-d
 -vi-
--w-ret
--w-nci
--w-inl
--wpin
--wamb
--wamp
--w-par
--wasm
--wcln
--w-cpt
--wdef
--w-dup
--w-pia
--wsig
--wnod
--w-ill
--w-sus
--wstv
--wucp
--wuse
--w-ext
--w-ias
--w-ibc
--w-pre
--w-nst
+-H=COMMAND.SYM
 -I$(INCLUDEPATH)
 -L$(LIBPATH)
 | command.cfg
Binary files com074d/command.prj and com075/command.prj differ
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/config.h com075/config.h
--- com074d/config.h	Wed Dec 31 18:00:00 1969
+++ com075/config.h	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,59 @@
+/*
+ * config.h - Used to configure what will be compiled into the shell.
+ *
+ *
+ * Comments:
+ * 27 Jul 1998 - John P. Price
+ * - started.
+ *
+ */
+
+
+/* JPP 20 Jul 1998 - define DEBUG to add debugging code */
+/* #define DEBUG */
+
+/* Define to enable the alias command, and aliases.*/
+#define FEATURE_ALIASES
+
+/* Define to enable history (and the doskey command) */
+#define FEATURE_HISTORY
+
+/* Define to enable filename completion */
+#define FEATURE_FILENAME_COMPLETION
+
+
+#define INCLUDE_CMD_CHDIR
+#define INCLUDE_CMD_CLS
+#define INCLUDE_CMD_DATE
+#define INCLUDE_CMD_DEL
+#define INCLUDE_CMD_DIR
+#define INCLUDE_CMD_LOADHIGH
+#define INCLUDE_CMD_MKDIR
+#define INCLUDE_CMD_PATH
+#define INCLUDE_CMD_PROMPT
+#define INCLUDE_CMD_RMDIR
+#define INCLUDE_CMD_RENAME
+#define INCLUDE_CMD_SET
+#define INCLUDE_CMD_TIME
+#define INCLUDE_CMD_TYPE
+#define INCLUDE_CMD_VER
+#define INCLUDE_CMD_VERIFY
+#define INCLUDE_CMD_REM
+#define INCLUDE_CMD_PAUSE
+#define INCLUDE_CMD_BEEP
+#define INCLUDE_CMD_LOADFIX
+#define INCLUDE_CMD_TRUENAME
+
+/*
+command that do not have a define:
+
+exit
+call
+echo
+goto
+for
+if
+shift
+
+*/
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/date.c com075/date.c
--- com074d/date.c	Thu Jul 16 10:57:22 1998
+++ com075/date.c	Fri Aug  7 08:44:26 1998
@@ -3,46 +3,65 @@
  *
  *  Comments:
  *
- *  07/08/1998 (John P. Price)
+ *  08 Jul 1998 (John P. Price)
  *    started.
  *
+ *  20 Jul 1998 (John P. Price)
+ *  - corrected number of days for December from 30 to 31.
+ *    (Thanx to Steffen Kaiser for bug report)
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 29-Jul-1998 (Rob Lake)
+ * - fixed stand-alone mode.  Added Pacific C compatible dos_getdate functions
  *
  */
 
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DATE
+
 #include <stdio.h>
 #include <dos.h>
 #include <ctype.h>
 #include <string.h>
 
 #include "command.h"
+#include "datefunc.h"
 
 static unsigned char months[2][13] =
 {
-  {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 30},
-  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 30}
+  {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
 };
 
-static unsigned char *dowstring[7] =
-{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+#ifdef DEBUG_STANDALONE
+const char *day_strings[] = {
+        "Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"
+        };
+
+#else
+extern const char *day_strings[];
+#endif
 
-int
-parsedate(char *s)
+int parsedate(char *s)
 {
-  struct date d;
+  struct dosdate_t d;
   unsigned char leap;
 
   if (!*s)
     return 1;
 
-  d.da_year = 0;
-  d.da_day = 0;
-  d.da_mon = 0;
+  d.year = 0;
+  d.day = 0;
+  d.month = 0;
 
   // first get mon
   if (isdigit(*s))
   {
     while (isdigit(*s))
-      d.da_mon = d.da_mon * 10 + (*s++) - '0';
+      d.month = d.month * 10 + (*s++) - '0';
   }
   else
     return 0;
@@ -57,7 +76,7 @@
   if (isdigit(*s))
   {
     while (isdigit(*s))
-      d.da_day = d.da_day * 10 + (*s++) - '0';
+      d.day = d.day * 10 + (*s++) - '0';
   }
   else
     return 0;
@@ -72,28 +91,29 @@
   if (isdigit(*s))
   {
     while (isdigit(*s))
-      d.da_year = d.da_year * 10 + (*s++) - '0';
+      d.year = d.year * 10 + (*s++) - '0';
   }
   else
     return 0;
 
   //if only entered two digits, assume 1900's
-  if (d.da_year >= 0 && d.da_year <= 99)
-    d.da_year = 1900 + d.da_year;
+  if (d.year <= 99)
+    d.year = 1900 + d.year;
 
-  leap = (!(d.da_year % 4) && (d.da_year % 100)) || !(d.da_year % 400);
+  leap = (!(d.year % 4) && (d.year % 100)) || !(d.year % 400);
 
-  if ((d.da_mon >= 1 && d.da_mon <= 12) &&
-      (d.da_day >= 1 && d.da_day <= months[leap][d.da_mon]) &&
-      (d.da_year >= 1980 && d.da_year <= 2099))
+  if ((d.month >= 1 && d.month <= 12) &&
+      (d.day >= 1 && d.day <= months[leap][d.month]) &&
+      (d.year >= 1980 && d.year <= 2099))
   {
-    setdate(&d);
+    _dos_setdate(&d);
     return 1;
   }
 
   return 0;
 }
 
+#pragma argsused
 int
 cmd_date(char *first, char *rest)
 {
@@ -117,7 +137,7 @@
     _dos_getdate(&d);
 
     printf("Current date is %s %02d-%02d-%d\n",
-           dowstring[d.dayofweek], d.month, d.day, d.year);
+           day_strings[d.dayofweek], d.month, d.day, d.year);
   }
 
   while (1)                     //forever loop
@@ -139,6 +159,15 @@
       // force input the next time around.
       *rest = '\0';
     }
-    printf("Invalid date.\n");
+    puts("Invalid date.");
   }
 }
+#endif
+
+#ifdef DEBUG_STANDALONE
+int main(void)
+{
+        cmd_date("date", "");
+        return 1;
+}
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/datefunc.c com075/datefunc.c
--- com074d/datefunc.c	Wed Dec 31 18:00:00 1969
+++ com075/datefunc.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,102 @@
+/*
+
+DateFunc -- DOS Date Functions
+Copyright (C) 1998 Rob Lake
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+Rob Lake can be contacted at
+email: rlake@cs.mun.ca
+
+*/
+
+/*
+ * 07/29/1998 (Rob Lake)
+ *      started
+ *
+ * Works Under:
+ *      Borland C++ v.3.0
+ *      Pacific C (pacc v.7.51)
+ *
+ */
+
+#ifdef _NO__DOS_DATE
+
+#include <dos.h>
+#include <stdio.h>
+#include "datefunc.h"
+
+unsigned _dos_setdate(struct dosdate_t *d)
+{
+  union REGPACK r;
+  r.x.ax = 0x2B << 8;
+  r.x.cx = d->year;
+  r.x.dx = d->month << 8;
+  r.x.dx += d->day & 0xFF;
+
+  intr(0x21, &r);
+
+  if(r.x.ax & 0x00FF)
+    return 1;
+  return 0;
+}
+
+void _dos_getdate(struct dosdate_t *d)
+{
+  union REGPACK r;
+  r.x.ax = 0x2A << 8;
+
+  intr(0x21, &r);
+
+  d->year = r.x.cx;
+  d->month = r.x.dx >> 8;
+  d->day = r.x.dx & 0xFF;
+  d->dayofweek = r.x.ax & 0xFF;
+}
+
+#ifdef DEBUG_STANDALONE
+int main(void)
+{
+  struct dosdate_t d, orig_d, new_d;
+
+  _dos_getdate(&orig_d);
+  printf("The current year is: %d\n", orig_d.year);
+  printf("The current day is: %d\n", orig_d.day);
+  printf("The current month is: %d\n", orig_d.month);
+  printf("Day of week: %d\n", orig_d.dayofweek);
+
+  new_d = orig_d;
+  new_d.day++;
+  if(_dos_setdate(&new_d) != 0)
+        return 1;
+
+  _dos_getdate(&d);
+  printf("The current year is: %d\n", d.year);
+  printf("The current day is: %d\n", d.day);
+  printf("The current month is: %d\n", d.month);
+  printf("Day of week: %d\n", d.dayofweek);
+
+  _dos_setdate(&orig_d);
+  printf("The current year is: %d\n", orig_d.year);
+  printf("The current day is: %d\n", orig_d.day);
+  printf("The current month is: %d\n", orig_d.month);
+  printf("Day of week: %d\n", orig_d.dayofweek);
+
+  return 0;
+}
+#endif /* DEBUG_STANDALONE */
+
+#endif /* _NO_DATE */
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/datefunc.h com075/datefunc.h
--- com074d/datefunc.h	Wed Dec 31 18:00:00 1969
+++ com075/datefunc.h	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,42 @@
+/*
+
+DateFunc -- DOS Date Functions
+Copyright (C) 1998 Rob Lake
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+Rob Lake can be contacted at
+email: rlake@cs.mun.ca
+
+*/
+
+#if !defined(__DATEFUNC_H)
+#define __DATEFUNC_H
+
+#ifdef _NO__DOS_DATE
+
+struct dosdate_t {
+  unsigned char day;        /* 1--31 */
+  unsigned char month;      /* 1--12 */
+  unsigned int  year;       /* 1980--2099 */
+  unsigned char dayofweek;  /* 0--6; 0 = Sunday */
+};
+
+unsigned _dos_setdate(struct dosdate_t *);
+void _dos_getdate(struct dosdate_t *);
+
+#endif
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/del.c com075/del.c
--- com074d/del.c	Thu Jul 16 10:57:22 1998
+++ com075/del.c	Fri Aug  7 08:44:26 1998
@@ -1,9 +1,25 @@
-
 /*
- * DEL.C
+ *  DEL.C - del command.
+ *
+ *  Comments:
+ *
+ *  06/29/98 (Rob Lake rlake@cs.mun.ca)
+ *      rewrote del to support wildcards
+ *      added my name to the contributors
+ *
+ * 07/13/98 (Rob Lake)
+ *  - fixed bug that caused del not to delete file with out attribute.
+ *  - moved set, del, ren, and ver to there own files
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
-#include "command.h"
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DEL
+
 #include <dir.h>
 #include <sys/stat.h>
 #include <string.h>
@@ -14,16 +30,19 @@
 #include <ctype.h>
 #include <dos.h>
 
+#include "command.h"
+
 /*
- *
+
  *  simple file delete internal command.
  *  Rewritten by Rob Lake (06/29/98)
  *
  */
 
+#define DEL_HELP     "delete file   DEL [d:][path]filespec"
+
 #pragma argsused
-int
-del(char *first, char *rest)
+int cmd_del(char *first, char *rest)
 {
   int done,
     flags,
@@ -31,15 +50,19 @@
     args,
     inter,
     filespec;
+
   struct ffblk f;
   struct stat stbuf;
+
   static char drive[MAXDRIVE],
     dir[MAXDIR],
     file[MAXFILE],
     ext[MAXEXT];
+
   char fn[MAXFILE + MAXEXT + 1],
     orig_dir[MAXPATH];
-  char **arg;
+
+  static char **arg;
 
   drive[0] = '\0';
   dir[0] = '\0';
@@ -50,8 +73,7 @@
 
   if (args > 2)
   {
-    //fprintf(stderr, TOO_MANY_PARAMETERS, arg[args - 1]);
-    too_many_parameters(arg[args - 1]);
+    error_too_many_parameters(arg[args - 1]);
     return 1;
   }
   else if (args >= 1)
@@ -77,16 +99,14 @@
     /* only one argument and that's /P */
     if (args == 1 && inter)
     {
-      //fprintf(stderr, REQ_PARAM_MISSING);
-      req_param_missing();
+      error_req_param_missing();
       return 1;
     }
     /* check whether the file actually exists */
-    if (access(arg[filespec], 4) != 0 &&
+    if (access(arg[filespec], 2) != 0 &&
         strchr(arg[filespec], '*') == NULL)
     {
-      //fprintf(stderr, FILE_NOT_FOUND);
-      file_not_found();
+      error_file_not_found();
       return 1;
     }
     stat(arg[filespec], &stbuf);
@@ -123,8 +143,7 @@
       getcwd(orig_dir, MAXPATH);
       if (chdir(dir))
       {
-        //fprintf(stderr, PATH_NOT_FOUND);
-        path_not_found();
+        error_path_not_found();
         return 1;
       }
       if (dir[0] != '\0' && strlen(dir) > 1)
@@ -134,16 +153,14 @@
   else
   {
     /* only command given */
-    //fprintf(stderr, REQ_PARAM_MISSING);
-    req_param_missing();
+    error_req_param_missing();
     return 1;
   }
 
   /* needed? */
   if (inter && args == 1)
   {
-    //fprintf(stderr, REQ_PARAM_MISSING);
-    req_param_missing();
+    error_req_param_missing();
     return 1;
   }
 
@@ -183,8 +200,7 @@
   if (done)
   {
     chdir(orig_dir);
-    //fprintf(stderr, FILE_NOT_FOUND);
-    file_not_found();
+    error_file_not_found();
     return 0;
   }
 
@@ -247,3 +263,5 @@
   chdir(orig_dir);
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/dir-test.txt com075/dir-test.txt
--- com074d/dir-test.txt	Thu Jul 16 10:57:22 1998
+++ com075/dir-test.txt	Wed Dec 31 18:00:00 1969
@@ -1,25 +0,0 @@
-Regression tests for dir.c
---------------------------
-
-If you add tests, please email them to normat@rpi.edu
-
-The following directories must exist: C:\TEMP, D:\TIM, C:\WINDOWS D:\TIM\C
-
-Current working directories are: C:\TEMP, D:\TIM
-
-Current drive is: C
-
-Type the command in the "From" column and make sure the files listed are what
-are shown in the other columns.
-
-From                                    Drive   Dir             File
-----                                    -----   ---             ----
-DIR                                     C       \TEMP           *.*
-DIR \                                   C       \               *.*
-DIR \windows                            C       \windows        *.*
-DIR d:                                  D       \tim            *.*
-DIR d:\                                 D       \               *.*
-DIR d:.                                 D       \tim            *.*
-DIR file                                C       \TEMP           file.*
-DIR .ext                                C       \TEMP           *.ext
-DIR D:c                                 D       \tim\c          *.*
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/dir.c com075/dir.c
--- com074d/dir.c	Thu Jul 16 10:57:22 1998
+++ com075/dir.c	Fri Aug  7 08:44:26 1998
@@ -87,8 +87,14 @@
  * 07/12/98 (Rob Lake)
  * - Changed error messages
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
  */
 
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DIR
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -101,10 +107,13 @@
 #include <alloc.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
 #include "command.h"
 
 /* useful macros */
-#define MEM_ERR fprintf (stderr, "Memory error.\n"); return 1;
+#define MEM_ERR error_out_of_memory(); return 1;
+
+#define DIR_HELP  "display directory listing   DIR [d:][path][filespec]"
 
 /* flag definitions */
 /* Changed hex to decimal, hex wouldn't work
@@ -132,24 +141,23 @@
  * displays help screen for dir
  * Rob Lake
  */
-void
-help(void)
+void help(void)
 {
-  printf("Displays a list of files and directories in a give subdirectory\n" \
-         "\n" \
-       "DIR [drive:][directory][filename] [/S] [/P] [/W] [/A] [/B] [/L]\n" \
-         "\n" \
-         "    /S -- Displays files in specified directory and all subdirectories\n" \
-         "    /P -- Pauses after each screen full\n" \
-         "    /W -- Prints in wide format\n" \
-         "    /A -- Displays files with HIDDEN SYSTEM attributes\n" \
-         "         default is ARCHIVE and READ ONLY\n" \
-       "    /B -- Prints in bare format (no header or file information)\n" \
-         "    /L -- Prints files in lower case\n" \
-         "\n" \
-      "Switches may be present in the DIRCMD environment variable.  Use\n" \
-       "of the - (hyphen) can turn off defined swtiches.  Ex. /-W would\n" \
-         "turn off printing in wide format.\n\n" \
+  puts("Displays a list of files and directories in a give subdirectory\n"
+         "\n"
+       "DIR [drive:][directory][filename] [/S] [/P] [/W] [/A] [/B] [/L]\n"
+         "\n"
+         "    /S -- Displays files in specified directory and all subdirectories\n"
+         "    /P -- Pauses after each screen full\n"
+         "    /W -- Prints in wide format\n"
+         "    /A -- Displays files with HIDDEN SYSTEM attributes\n"
+         "         default is ARCHIVE and READ ONLY\n"
+       "    /B -- Prints in bare format (no header or file information)\n"
+         "    /L -- Prints files in lower case\n"
+         "\n"
+      "Switches may be present in the DIRCMD environment variable.  Use\n"
+       "of the - (hyphen) can turn off defined swtiches.  Ex. /-W would\n"
+         "turn off printing in wide format.\n"
       );
 }
 
@@ -158,8 +166,7 @@
  *
  * read the parameters from the command line
  */
-int
-dir_read_param(char *line, char **param, unsigned *flags)
+int dir_read_param(char *line, char **param, unsigned *flags)
 {
   int slash = 0;
 
@@ -193,7 +200,7 @@
         else
         {
           //fprintf(stderr, INVALID_SWITCH, toupper(*line));
-          invalid_switch(toupper(*line));
+          error_invalid_switch(toupper(*line));
           return 1;
         }
         line++;
@@ -224,7 +231,7 @@
         else
         {
           //fprintf(stderr, INVALID_SWITCH, toupper(*line));
-          invalid_switch(toupper(*line));
+          error_invalid_switch(toupper(*line));
           return 1;
         }
         line++;
@@ -237,8 +244,7 @@
     {
       if (*param)
       {
-        //fprintf(stderr, TOO_MANY_PARAMETERS, *param);
-        too_many_parameters(*param);
+        error_too_many_parameters(*param);
         return 1;
       }
 
@@ -265,8 +271,7 @@
 
   if (slash)
   {
-    //fprintf(stderr, INVALID_SWITCH, *line);
-    invalid_switch(toupper(*line));
+    error_invalid_switch(toupper(*line));
     return 1;
   }
 
@@ -278,8 +283,7 @@
  *
  * extend the filespec, possibly adding wildcards
  */
-void
-extend_file(char **file)
+void extend_file(char **file)
 {
   char *tmp;
 
@@ -328,12 +332,11 @@
  *
  * split the pathspec into drive, directory, and filespec
  */
-int
-dir_parse_pathspec(char *pathspec, int *drive, char **dir, char **file)
+int dir_parse_pathspec(char *pathspec, int *drive, char **dir, char **file)
 {
   char *start,
    *tmp,
-    orig_dir[128];
+    orig_dir[MAXDIR];
   int i,
     wildcards = 0;
 
@@ -433,8 +436,7 @@
   /* change to this directory and get its full name */
   if (chdir(start) < 0)
   {
-    //fprintf(stderr, PATH_NOT_FOUND);
-    path_not_found();
+    error_path_not_found();
     *tmp = '\\';
     free(*file);
     chdir(orig_dir);
@@ -466,25 +468,10 @@
  *
  * pause until a key is pressed
  */
-int
-pause(void)
+int pause(void)
 {
-  int c;
+  cmd_pause("", "");
 
-  if ((isatty(0)) && (isatty(1)))
-  {
-    printf("Press any key to continue . . .");
-    c = getch();
-    putchar('\n');
-    if (c == 27 || c == 3)
-    {
-      return 1;
-    }
-    if (c == 0)
-    {
-      getch();
-    }
-  }
   return 0;
 }
 
@@ -493,8 +480,7 @@
  *
  * increment our line if paginating, display message at end of screen
  */
-int
-incline(int *line, unsigned flags)
+int incline(int *line, unsigned flags)
 {
   if (!(flags & DIR_PAGE))
     return 0;
@@ -515,8 +501,7 @@
  *
  * print the header for the dir command
  */
-int
-dir_print_header(int drive, int *line, unsigned flags)
+int dir_print_header(int drive, int *line, unsigned flags)
 {
   struct media_id
   {
@@ -525,8 +510,7 @@
       serial2;
     char vol_id[11],
       file_sys[8];
-  }
-  media;
+  } media;
   struct ffblk f;
   struct SREGS s;
   union REGS r;
@@ -537,8 +521,7 @@
   setdisk(drive);
   if (getdisk() != drive)
   {
-    //fprintf(stderr, "Invalid drive specification\n");
-    invalid_drive();
+    error_invalid_drive();
     return 1;
   }
 
@@ -553,7 +536,7 @@
   media.vol_id[10] = NULL;
 
   /* print drive info */
-  printf(" Volume in drive %c", drive + 'A');
+  printf("\n Volume in drive %c", drive + 'A');
 
   if (findfirst("\\*.*", &f, FA_LABEL) == 0)
   {
@@ -582,8 +565,7 @@
  *
  * insert commas into a number
  */
-int
-convert(long num, char *des)
+int convert(long num, char *des)
 {
   char temp[32];
   int c = 0,
@@ -612,14 +594,13 @@
 }
 
 /*
- *
+
  * print_summary: prints dir summary
  * Added by Rob Lake 06/17/98 to compact code
  * Just copied Tim's Code and patched it a bit
  *
  */
-int
-print_summary(int drive, long files, long dirs, long bytes,
+int print_summary(int drive, long files, long dirs, long bytes,
               unsigned flags, int *line)
 {
   char buffer[32];
@@ -653,11 +634,10 @@
  *
  * list the files in the directory
  */
-int
-dir_list(int drive, char *directory, char *filespec, int *line,
+int dir_list(int drive, char *directory, char *filespec, int *line,
          unsigned flags)
 {
-  char pathspec[128],
+  char pathspec[MAXPATH],
    *ext,
     buffer[32];
   struct ffblk file;
@@ -684,8 +664,7 @@
      */
     if ((flags & DIR_RECURSE) == 0)
     {
-      //fprintf(stderr, "File not found.\n");
-      file_not_found();
+      error_file_not_found();
       incline(line, flags);
       return 1;
     }
@@ -828,25 +807,16 @@
   }
   else
   {
-    printf("File not found\n");
+    error_file_not_found();
     return 1;
   }
-/* JPP 07/08/1998 removed extra return; closer to MSDOS */
-//  if ((flags & DIR_BARE) == 0)
-  //  {
-  //    printf("\n");
-  //    if (incline(line, flags) != 0)
-  //      return 1;
-  //  }
-
   return 0;
 }
 
 /*
  * _Read_Dir: Actual function that does recursive listing
  */
-int
-_Read_Dir(int drive, char *parent, char *filespec, int *lines,
+int _Read_Dir(int drive, char *parent, char *filespec, int *lines,
           unsigned flags)
 {
   DIR *dir;
@@ -908,15 +878,14 @@
 /*
  * do_recurse: Sets up for recursive directory listing
  */
-int
-do_recurse(int drive, char *directory, char *filespec,
+int do_recurse(int drive, char *directory, char *filespec,
            int *line, unsigned flags)
 {
-  char cur_dir[128];
+  char cur_dir[MAXDIR];
 
   recurse_dir_cnt = recurse_file_cnt = recurse_bytes = 0L;
   setdisk(drive);
-  getcwd(cur_dir, 128);
+  getcwd(cur_dir, sizeof(cur_dir));
 
   if (chdir(directory) == -1)
     return 1;
@@ -944,9 +913,6 @@
     if (incline(line, flags) != 0)
       return 1;
   }
-//  printf("\n");
-  //  if (incline(line, flags) != 0)
-  //    return 1;
   chdir(cur_dir);
   return 0;
 }
@@ -957,8 +923,7 @@
  * internal dir command
  */
 #pragma argsused
-int
-dir(char *first, char *rest)
+int cmd_dir(char *first, char *rest)
 {
   unsigned flags = 0;
   char *param,
@@ -968,7 +933,7 @@
     orig_drive;
   char *directory,
    *filespec,
-    orig_dir[128];
+    orig_dir[MAXDIR];
 
   /* read the parameters from env */
   dircmd = getenv("DIRCMD");
@@ -987,7 +952,7 @@
 
   /* save the current directory info */
   orig_drive = getdisk();
-  getcwd(orig_dir, 128);
+  getcwd(orig_dir, sizeof(orig_dir));
 
   /* parse the directory info */
   if (dir_parse_pathspec(param, &drive, &directory, &filespec) != 0)
@@ -1016,3 +981,5 @@
     return 1;
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/echo.c com075/echo.c
--- com074d/echo.c	Wed Dec 31 18:00:00 1969
+++ com075/echo.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,52 @@
+/*
+ *  ECHO.C - echo command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_echo(char *cmd, char *param)
+{
+  /*
+   * Perform ECHO command.
+   *
+   */
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  if (stricmp(param, D_OFF) == 0)
+    echo = 0;
+  else if (stricmp(param, D_ON) == 0)
+    echo = 1;
+  else if (*param)
+    puts(param);
+  else
+    printf("ECHO is %s\n", echo ? D_ON : D_OFF);
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/environ.c com075/environ.c
--- com074d/environ.c	Thu Jul 16 10:57:22 1998
+++ com075/environ.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /* 
  *  ENVIRON.C - enviroment handling.
  *
@@ -15,7 +16,12 @@
  *  07/08/1998 (John P. Price)
  *  - commented out show_environment function.  Not used anymore.
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
+
+#include "config.h"
 
 #include <stdlib.h>
 #include <stdio.h>
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/err_hand.c com075/err_hand.c
--- com074d/err_hand.c	Thu Jul 16 10:57:22 1998
+++ com075/err_hand.c	Fri Aug  7 08:44:26 1998
@@ -3,22 +3,26 @@
  *
  * Comments:
  *
- * 07/03/98 (Rob Lake) ------------------------------------------------------
+ * 07/03/98 (Rob Lake)
  *      Started
  *
- * 07/13/98 (Rob Lake) ------------------------------------------------------
+ * 07/13/98 (Rob Lake)
  *  Added critical error handling counting.  Now only 5 calls to error
  *  handler can occur, unless user aborts or fails, without auto-failing.
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
 #include "err_hand.h"
 
 static unsigned calls = 0;
 
 /* Code courtesy of Pasquale J. Villani */
-void
-init_error_handler(void)
+void init_error_handler(void)
 {
   asm {
     xor ax, ax
@@ -37,8 +41,7 @@
  * string
  *
  */
-static void
-printstring(char *string)
+static void printstring(char *string)
 {
   asm {
     push ds
@@ -61,8 +64,7 @@
  * get_err -- returns the text to the actual error message
  *
  */
-static char *
-get_err(unsigned err_code)
+static char *get_err(unsigned err_code)
 {
   switch (err_code)
   {
@@ -102,8 +104,7 @@
  *
  */
 #pragma argsused
-void interrupt far
-dos_critical_error(unsigned reg_Bp, unsigned reg_Di,
+void interrupt far dos_critical_error(unsigned reg_Bp, unsigned reg_Di,
          unsigned reg_Si, unsigned reg_Ds, unsigned reg_Es, unsigned reg_Dx,
                    unsigned reg_Cx, unsigned reg_Bx, unsigned reg_Ax)
 {
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/err_hand.h com075/err_hand.h
--- com074d/err_hand.h	Thu Jul 16 10:57:22 1998
+++ com075/err_hand.h	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /*
  * ERR_HAND.H -- Header for Critical Error Handling
  * Rob Lake
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/error.c com075/error.c
--- com074d/error.c	Thu Jul 16 10:57:22 1998
+++ com075/error.c	Fri Aug  7 08:44:26 1998
@@ -1,66 +1,92 @@
 /*
  * ERROR.C -- Error reporting functions
  *
- * 07/12/98 (Rob Lake) ------------------------------------------------------
+ * 07/12/98 (Rob Lake)
  *      started
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
-#include "command.h"
+#include "config.h"
+
 #include <stdio.h>
+#include "command.h"
+
+#define INVALID_SWITCH      "Invalid switch - /%c\n"
+#define TOO_MANY_PARAMETERS "Too many parameters - %s\n"
+#define PATH_NOT_FOUND      "Path not found\n"
+#define FILE_NOT_FOUND      "File not found"
+#define REQ_PARAM_MISSING   "Required parameter missing\n"
+#define INVALID_DRIVE       "Invalid drive specification\n"
+#define BADCOMMAND          "Bad command or filename\n"
+#define OUT_OF_MEMORY       "Out of memory error.\n"
+#define CANNOTPIPE      "Error!  Cannot pipe!  Cannot open temporary file!\n"
 
-void
-invalid_switch(char c)
+#define D_PAUSEMSG   "Press any key to continue . . ."
+
+
+void error_invalid_switch(char c)
 {
   fprintf(stderr, INVALID_SWITCH, c);
 }
 
-void
-too_many_parameters(char *s)
+void error_too_many_parameters(char *s)
 {
   fprintf(stderr, TOO_MANY_PARAMETERS, s);
 }
 
-void
-path_not_found(void)
+void error_path_not_found(void)
 {
   fprintf(stderr, PATH_NOT_FOUND);
 }
 
-void
-file_not_found(void)
+void error_file_not_found(void)
 {
   fprintf(stderr, FILE_NOT_FOUND);
-  //fprintf(stderr, "\n");
 }
 
-void
-sfile_not_found(char *f)
+void error_sfile_not_found(char *f)
 {
-  file_not_found();
-  fprintf(stderr, " - %s\n", f);
+  fprintf(stderr, FILE_NOT_FOUND " - %s\n", f);
 }
 
-void
-req_param_missing(void)
+void error_req_param_missing(void)
 {
   fprintf(stderr, REQ_PARAM_MISSING);
 }
 
-void
-invalid_drive(void)
+void error_invalid_drive(void)
 {
   fprintf(stderr, INVALID_DRIVE);
 }
 
-void
-badcommand(void)
+void error_bad_command(void)
 {
   fprintf(stderr, BADCOMMAND);
 }
 
-void
-no_pipe(void)
+void error_no_pipe(void)
 {
   fprintf(stderr, CANNOTPIPE);
 }
+
+void error_out_of_memory(void)
+{
+  fprintf(stderr, OUT_OF_MEMORY);
+}
+
+void error_syntax(char *s)
+{
+  if (s)
+    fprintf(stderr, "Syntax error - %s\n", s);
+  else
+    fprintf(stderr, "Syntax error.\n");
+}
+
+void msg_pause(void)
+{
+  puts(D_PAUSEMSG);
+}
+
Files com074d/exe2bin.com and com075/exe2bin.com are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/exec.c com075/exec.c
--- com074d/exec.c	Thu Jul 16 10:57:22 1998
+++ com075/exec.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /*
  *  EXEC.C - external program execution
  *
@@ -17,11 +18,17 @@
  *  06/14/97 (Steffen Kaiser) ---------------------------------------------
  *    added errorlevel
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <dos.h>
 #include <string.h>
+
 #include "command.h"
 
 #define CBREAK_ERRORLEVEL 3
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/filecomp.c com075/filecomp.c
--- com074d/filecomp.c	Wed Dec 31 18:00:00 1969
+++ com075/filecomp.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,226 @@
+/*
+ *  FILECOMP.C - handles filename completion
+ *
+ *
+ *  Comments:
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - moved from command.c file
+ * - made second TAB display list of filename matches
+ * - made filename be lower case if last character typed is lower case
+ *
+ */
+
+#include "config.h"
+
+#ifdef FEATURE_FILENAME_COMPLETION
+
+#include <stdio.h>
+#include <string.h>
+#include <dir.h>
+#include <dos.h>
+
+#define D_BEEP    putchar('\a')
+
+
+void goxy(unsigned char x, unsigned char y);
+
+
+void complete_filename(char *str, unsigned charcount)
+{
+  // varibles found within code
+  struct ffblk file;
+
+  int found_dot = 0;
+  int curplace = 0;
+  int start;
+  int count;
+  char perfectmatch = 1;
+  char makelower;
+  char path[128];
+  char fname[14];
+  char maxmatch[13] = "";
+  char directory[128];
+
+  // expand current file name
+  count = charcount - 1;
+  if (count < 0)
+    count = 0;
+  else
+  {
+    // if last character is lower case, then make lookup lower case.
+    if (str[count] >= 'A' && str[count] <= 'Z')
+      makelower = 0;
+    else
+      makelower = 1;
+  }
+
+  while (count > 0 && str[count] != ' ')  // find front of word
+
+    count--;
+
+  if (str[count] == ' ')  // if not at beginning, go forward 1
+
+    count++;
+
+  start = count;
+
+  // extract directory from word
+  strcpy(directory, &str[start]);
+  curplace = strlen(directory) - 1;
+  while (curplace >= 0 && directory[curplace] != '\\' &&
+          directory[curplace] != ':')
+  {
+    directory[curplace] = 0;
+    curplace--;
+  }
+
+  strcpy(path, &str[start]);
+
+  // look for a . in the filename
+  for (count = strlen(directory); path[count] != 0; count++)
+    if (path[count] == '.')
+    {
+      found_dot = 1;
+      break;
+    }
+  if (found_dot)
+    strcat(path, "*");
+  else
+    strcat(path, "*.*");
+
+  curplace = 0;         // current fname
+
+  if (findfirst(path, &file, 0x3F) == 0)
+  {                     // find anything
+    do
+    {
+      if (file.ff_name[0] == '.') // ignore . and ..
+        continue;
+
+      strcpy(fname, file.ff_name);
+      if (makelower)
+        strlwr(fname);
+
+      if (file.ff_attrib == FA_DIREC)
+        strcat(fname, "\\");
+      else
+        strcat(fname, " ");
+
+      if (!maxmatch[0] && perfectmatch)
+        strcpy(maxmatch, fname);
+
+      else
+      {
+        for (count = 0; maxmatch[count] && fname[count]; count++)
+          if (maxmatch[count] != fname[count])
+          {
+            perfectmatch = 0;
+            maxmatch[count] = 0;
+            break;
+          }
+      }
+    }
+    while (findnext(&file) == 0);
+
+    strcpy(&str[start], directory);
+    strcat(&str[start], maxmatch);
+
+    if (!perfectmatch)
+      D_BEEP;
+  }
+  else /* no match found */
+    D_BEEP;
+}
+
+int show_completion_matches(char *str, unsigned charcount)
+// returns 1 if at least one match, else returns 0
+{
+  // varibles found within code
+  struct ffblk file;
+
+  int found_dot = 0;
+  int curplace = 0;
+  int start;
+  int count;
+  char path[128];
+  char fname[14];
+  char directory[128];
+
+  // expand current file name
+  count = charcount - 1;
+  if (count < 0)
+    count = 0;
+
+  while (count > 0 && str[count] != ' ')  // find front of word
+
+    count--;
+
+  if (str[count] == ' ')  // if not at beginning, go forward 1
+
+    count++;
+
+  start = count;
+
+  // extract directory from word
+  strcpy(directory, &str[start]);
+  curplace = strlen(directory) - 1;
+  while (curplace >= 0 && directory[curplace] != '\\' &&
+          directory[curplace] != ':')
+  {
+    directory[curplace] = 0;
+    curplace--;
+  }
+
+  strcpy(path, &str[start]);
+
+  // look for a . in the filename
+  for (count = strlen(directory); path[count] != 0; count++)
+    if (path[count] == '.')
+    {
+      found_dot = 1;
+      break;
+    }
+  if (found_dot)
+    strcat(path, "*");
+  else
+    strcat(path, "*.*");
+
+  curplace = 0;         // current fname
+
+  if (findfirst(path, &file, 0x3F) == 0)
+  {                     // find anything
+    putchar('\n');
+    count = 0;
+    do
+    {
+      if (file.ff_name[0] == '.') // ignore . and ..
+        continue;
+
+
+      if (file.ff_attrib == FA_DIREC)
+        sprintf(fname,"[%s]",file.ff_name);
+      else
+        strcpy(fname, file.ff_name);
+
+      printf("%-14s",fname);
+      if (++count == 5)
+      {
+        putchar('\n');
+        count = 0;
+      }
+    }
+    while (findnext(&file) == 0);
+
+    if (count)
+      putchar('\n');
+
+  }
+  else /* no match found */
+  {
+    D_BEEP;
+    return 0;
+  }
+  return 1;
+}
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/files.txt com075/files.txt
--- com074d/files.txt	Thu Jul 16 10:57:22 1998
+++ com075/files.txt	Fri Aug  7 08:44:26 1998
@@ -6,7 +6,6 @@
 license.txt     GNU license - applies to all files named here
 readme.txt      General shell info
 todo.txt        What I have to do
-dir-test.txt    Regression tests for dir.c
 
 command.dsk     Borland C desktop file
 command.prj     Borland C project file
@@ -16,17 +15,28 @@
 alias.c         Alias code
 alias.h         Alias header file
 batch.c         Batch file interpreter
+beep.c          Implements beep command
+call.c          Implements call command
+cls.c           Implements cls command
 cmdinput.c      Command-line input functions
+cmdtable.c      Table of available internal commands
 command.c       Main code for command-line interpreter
 command.h       Command header file
 date.c          Date command code
+datefunc.c      Get and set date functions for Pacific C compatibility
+del.c           Implements del command
 dir.c           Directory listing code
+echo.c          Implements echo command
 environ.c       Environment handling
 err_hand.c      Critical Error Handling code
 err_hand.h      Critical Error Handling header
 error.c         Error Message Routines
 exec.c          Exec C interface code
+filecomp.c      Filename completion functions
+for.c           Implements for command
+goto.c          Implements goto command
 history.c       Command-line history handling
+if.c            Implements if command
 internal.c      Internal commands (DIR, RD, etc)
 lh.asm          Loadhigh assembler functions
 loadhigh.c      Loadhigh C source
@@ -34,20 +44,28 @@
 lowexec.asm     Low-level exec functions
 model.def       memory model for exec stuff
 misc.c          Misc. Functions
+path.c          Implements path command
+pause.c         Implements pause command
 prompt.c        Prompt handling functions
 redir.c         Redirection and piping parsing functions
+ren.c           Implements rename command
+set.c           Implements set command
+shift.c         Implements shift command
 tempfile.c      Re-implementation of tmpfile library function
 tempfile.h      tempfile.c header file
 testenv.c       Code to test environment passing
 time.c          Time command code
+timefunc.c      Get and set time functions for Pacific C compatibility
+truename.c      Implements truename command
 type.c          Type command code
+ver.c           Implements ver command
 where.c         Code to search path for executables
+verify.c        Implements verify command
 
-28.com          program to switch to 28-line mode (lost?)
+28.com          program to switch to 28-line mode
 command.com     COMMAND.COM executable
 
-test.bat        Test batch file
-
 makecom.bat     Make com file from exe
-makedist.bat    Make distribution zip files from source code
 clean.bat       Deletes the .bak and .obj files (cleans up)
+
+TESTS/          Test files and documents
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/for.c com075/for.c
--- com074d/for.c	Wed Dec 31 18:00:00 1969
+++ com075/for.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,134 @@
+/*
+ *  FOR.C - for command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *   Implementation of FOR
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_for(char *cmd, char *param)
+{
+  /*
+   * Perform FOR command.
+   *
+   * First check syntax is correct : FOR %v IN ( <list> ) DO <command>
+   *   v must be alphabetic, <command> must not be empty.
+   *
+   * If all is correct build a new bcontext structure which preserves
+   *   the necessary information so that readbatchline can expand
+   *   each the command prototype for each list element.
+   *
+   * You might look on a FOR as being a called batch file with one line
+   *   per list element.
+   */
+
+  char *pp, var;
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  /* Check that first element is % then an alpha char followed by space */
+
+  if ((*param != '%') || !isalpha(*(param + 1)) || !isspace(*(param + 2)))
+  {
+    error_syntax("bad varable specification.");
+    return 1;
+  }
+
+  param++;
+  var = *param++;               /* Save FOR var name */
+
+  while (isspace(*param))
+    param++;
+
+  /* Check next element is 'IN' */
+
+  if ((strncmpi(param, "in", 2) != 0) || !isspace(*(param + 2)))
+  {
+    error_syntax("'in' missing in for statement.");
+    return 1;
+  }
+
+  param += 2;
+  while (isspace(*param))
+    param++;
+
+  /* Folowed by a '(', find also matching ')' */
+
+  if ((*param != '(') || (NULL == (pp = strchr(param, ')'))))
+  {
+    error_syntax("no brackets found.");
+    return 1;
+  }
+
+  *pp++ = '\0';
+  param++;                      /* param now points at null terminated list */
+
+  while (isspace(*pp))
+    pp++;
+
+  /* Check DO follows */
+
+  if ((strncmpi(pp, "do", 2) != 0) || !isspace(*(pp + 2)))
+  {
+    error_syntax("'do' missing.");
+    return 1;
+  }
+
+  pp += 2;
+  while (isspace(*pp))
+    pp++;
+
+  /* Check that command tail is not empty */
+
+  if (*pp == '\0')
+  {
+    error_syntax("no command after 'do'.");
+    return 1;
+  }
+
+  /* OK all is correct, build a bcontext.... */
+
+  {
+    struct bcontext
+     *new = (struct bcontext *)malloc(sizeof(struct bcontext));
+
+    new->prev = bc;
+    bc = new;
+
+    bc->bfile = NULL;
+    bc->ffind = NULL;
+    bc->params = batch_params("", param); /* Split out list */
+    bc->shiftlevel = 0;
+    bc->forvar = var;
+    bc->forproto = strdup(pp);
+  }
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/goto.c com075/goto.c
--- com074d/goto.c	Wed Dec 31 18:00:00 1969
+++ com075/goto.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,100 @@
+/*
+ *  GOTO.C - goto command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 28 Jul 1998 (Hans B Pufal) [HBP_003]
+ *   Terminate label on first space character, use only first 8 chars of
+ *   label string
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_goto(char *cmd, char *param)
+{
+/*
+ * Perform GOTO command.
+ *
+ * Only valid if batch file current.
+ *
+ */
+
+  char *tmp;
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  if (bc == NULL)
+  {
+    /*!! not in batch error */
+
+    return 1;
+  }
+
+  if (*param == '\0')
+  {
+    exit_batch("No label specified for GOTO\n");
+    return 1;
+  }
+
+/* { HBP_003 : terminate label at first space char */
+
+  tmp = param;
+  while (*tmp && !isspace (*tmp))
+    tmp++;
+  *tmp = '\0';
+
+/* HBP_003 ) */
+
+  rewind(bc->bfile);
+
+  while (fgets(textline, sizeof(textline), bc->bfile) != NULL)
+  {
+    /* Strip out any trailing spaces or control chars */
+
+    tmp = textline + strlen(textline) - 1;
+    while (iscntrl(*tmp) || isspace(*tmp))
+      tmp--;
+    *(tmp + 1) = '\0';
+
+    /* Then leading spaces... */
+
+    tmp = textline;
+    while (isspace(*tmp))
+      tmp++;
+
+/* { HBP_003 : use only 1st 8 chars of label */
+
+    if ((*tmp == ':') && (strncmp(++tmp, param, 8) == 0))
+      return 0;
+
+/* HBP_003 }  */
+  }
+
+  printf("Label '%s' not found\n", param);
+  exit_batch(NULL);
+  return 1;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/history.c com075/history.c
--- com074d/history.c	Thu Jul 16 10:57:22 1998
+++ com075/history.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /* 
  *  HISTORY.C - command line history.
  *
@@ -5,24 +6,31 @@
  *
  *  Comments:
  *
- *  14/01/95 (Tim Norman) ---------------------------------------------------
+ *  14/01/95 (Tim Norman)
  *    started.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
+ *  08/08/95 (Matt Rains)
  *    i have cleaned up the source code. changes now bring this source into
  *    guidelines for recommended programming practice.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
+#ifdef FEATURE_HISTORY
+
 #include <string.h>
 #include <stdio.h>
-#include <alloc.h>
+#include <stdlib.h>
 
 #define MAXLINES 128
 
 unsigned history_size = 256;    /* make this configurable later */
 
-void
-history(int dir, char *commandline)
+void history(int dir, char *commandline)
 {
   static char *history = NULL;
   static char *lines[MAXLINES];
@@ -105,3 +113,5 @@
 
   return;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/history.txt com075/history.txt
--- com074d/history.txt	Thu Jul 16 10:57:22 1998
+++ com075/history.txt	Fri Aug  7 08:44:26 1998
@@ -7,7 +7,7 @@
 
 01/01/95 version 0.10
 ~~~~~~~~~~~~~~~~~~~~~
-o  removed some scafolding.
+o  removed some scaffolding.
 o  modified CD.
 o  added tab file completion.
 o  added command line history.
@@ -205,3 +205,99 @@
 o fixed bug that caused del not to delete files with no attributes
 o the critical error handler count number of times called, autofails
   at 5 calls
+
+
+16 Jul 1998 (Hans B Pufal <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+batch.c
+  A new version, implements CALL, ECHO, GOT, IF, PAUSE, SHIFT and
+  BEEP. There is a stub for FOR but that's all.
+
+cmdtable.c
+  New file to keep the internal command table. I plan on getting rid
+  of the table real soon now and replacing it with a dynamic
+  mechanism.
+
+command.c
+  A new (improved ;) version. Conforms closely to MS-DOS specs.
+  Cleaned up (and fixed) the redirection handler.
+
+command.h
+  Version D with changes. Look for the HBP tag.
+
+redir.c
+  Modified file, now supports append redirects.
+
+
+16 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+Added TRUENAME command.
+
+
+19 Jul 1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Preserve state of echo flag across batch calls.
+o Implementation of FOR command
+
+
+20 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in DATE.C.
+o Fixed bug in LH.ASM.
+o Separated commands into individual files.
+
+
+28 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Added CLS command.
+o Put ifdef's around all commands and added include file config.h
+  Now you can define exact what commands you want to include in
+  command.com.
+o Also added ifdefs for optional features: aliases, command history
+  and filename completion.
+o Added display of available internal commands and options at startup.
+
+
+29 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+o changed date.c and time.c, and wrote datefunc.c and timefunc.c to
+  impliment _dos_getdate, _dos_setdate, _dos_gettime and _dos_settime.
+  This is the first of many steps to make the shell compatible under
+  Pacific C.
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Changed filename completion so that a second TAB displays a list of
+  matching filenames!
+o made filename be lower case if last character typed is lower case.
+o Moved filename completion code to filecomp.c.
+o Change ver command to display email address to report bugs, and the
+  web page address for updates.
+o fixed so that it find_which returns NULL if filename is not
+  executable (does not have .bat, .com, or .exe extension).  Before
+  command would to execute any file with any extension. (opps!)
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug where if you typed something, then hit HOME, then tried to
+  type something else in insert mode, it locked up.
+o Changed default insert mode to on.  There should be a way to change
+  this.  Maybe options to doskey command.
+o Added VERIFY command
+
+02-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o batch.c: Fixed bug in ECHO flag restoration at exit from batch file
+o command.c: Fixed return value when called with /C option
+o Terminate label on first space character, use only first 8 chars of
+  label string
+
+04-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o call.c: added lines to initialize for pointers.  This fixed the
+  lock-up that happened sometimes when calling a batch file from
+  another batch file.
+
+07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed carrage return output to better match MSDOS with echo on or off.
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/if.c com075/if.c
--- com074d/if.c	Wed Dec 31 18:00:00 1969
+++ com075/if.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,162 @@
+/*
+ *  IF.C - if command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <dir.h>
+#include <dos.h>
+
+#include "command.h"
+#include "batch.h"
+
+int
+cmd_if(char *cmd, char *param)
+{
+/*
+ * Perform IF command.
+ *
+ */
+
+#define X_EXEC 1
+#define X_EMPTY 0x80
+
+  int
+    x_flag = 0;                 /* when set cuase 'then' clause to be executed */
+
+  char
+   *pp;
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  /* First check if param string begins with word 'not' */
+
+  if ((strncmpi(param, "not", 3) == 0) && isspace(*(param + 3)))
+  {
+    x_flag = X_EXEC;            /* Remember 'NOT' */
+    param += 3;                 /* Step over 'NOT' */
+    while (isspace(*param))     /* And subsequent spaces */
+      param++;
+  }
+
+  /* Check for 'exist' form */
+
+  if ((strncmpi(param, "exist", 5) == 0) && isspace(*(param + 5)))
+  {
+    param += 5;
+    while (isspace(*param))
+      param++;
+
+    pp = param;
+    while (*pp && !isspace(*pp))
+      pp++;
+
+    if (*pp)
+    {
+      struct ffblk f;
+
+      *pp++ = '\0';
+
+      x_flag ^= findfirst(param, &f, FA_NORMAL) ? 0 : X_EXEC;
+    }
+    else
+      return 0;
+  }
+
+  /* Check for 'errorlevel' form */
+
+  else if ((strncmpi(param, "errorlevel", 10) == 0) && isspace(*(param + 10)))
+  {
+    int
+      n = 0;
+
+    pp = param + 10;
+    while (isspace(*pp))
+      pp++;
+
+    while (isdigit(*pp))
+      n = n * 10 + (*pp++ - '0');
+
+    x_flag ^= (errorlevel < n) ? 0 : X_EXEC;
+
+    x_flag |= X_EMPTY;          /* Syntax error if comd empty */
+  }
+
+  /* Check that '==' is present, syntax error if not */
+
+  else if (NULL == (pp = strstr(param, "==")))
+  {
+    error_syntax(NULL);
+    return 1;
+  }
+
+  else
+  {
+    /* Change first '='to space to terminate comparison loop */
+
+    *pp = ' ';                  /* Need a space to terminate comparison loop */
+
+    pp += 2;                    /* over '==' */
+
+    while (isspace(*pp))        /* Skip subsequent spaces */
+      pp++;
+
+    strcat(pp, " ");            /* Add one space to ensure comparison ends */
+
+    while (*param == *pp)       /* Comparison loop */
+    {
+      if (isspace(*param))      /* Terminates on space */
+        break;
+
+      param++, pp++;
+    }
+
+    if (x_flag ^= (*param != *pp) ? 0 : X_EXEC)
+    {
+      while (*pp && !isspace(*pp))  /* Find first space, */
+        pp++;
+
+      x_flag |= X_EMPTY;
+    }
+  }
+
+  if (x_flag & X_EMPTY)
+  {
+    while (isspace(*pp))        /* Then skip spaces */
+      pp++;
+
+    if (*pp == '\0')            /* If nothing left then syntax err */
+    {
+      error_syntax(NULL);
+      return 1;
+    }
+  }
+
+  if (x_flag & X_EXEC)
+    parsecommandline(pp);
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/internal.c com075/internal.c
--- com074d/internal.c	Thu Jul 16 10:57:22 1998
+++ com075/internal.c	Fri Aug  7 08:44:26 1998
@@ -1,12 +1,13 @@
+
 /*
  *  INTERNAL.C - command.com internal commands.
  *
  *  Comments:
  *
- *  17/08/94 (Tim Norman) ---------------------------------------------------
+ *  17/08/94 (Tim Norman)
  *    started.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
+ *  08/08/95 (Matt Rains)
  *    i have cleaned up the source code. changes now bring this source into
  *    guidelines for recommended programming practice.
  *
@@ -50,12 +51,12 @@
  *  will be better in the long run. it is too hard to maintain such diverse
  *  functions when you are involved in a group project like this.
  *
- *  12/14/95 (Tim Norman) -----------------------------------------------------
+ *  12/14/95 (Tim Norman)
  *    fixed DIR so that it will stick \*.* if a directory is specified and
  *    that it will stick on .* if a file with no extension is specified or
  *    *.* if it ends in a \
  *
- *  1/6/96 (Tim Norman) -----------------------------------------------------
+ *  1/6/96 (Tim Norman)
  *    added an isatty call to DIR so it won't prompt for keypresses unless
  *    stdin and stdout are the console.
  *
@@ -68,54 +69,39 @@
  *  doskey()
  *    started.
  *
- *  1/22/96 (Oliver Mueller) -------------------------------------------------
+ *  1/22/96 (Oliver Mueller)
  *    error messages are now handled by perror.
  *
- *  02/05/96 (Tim Norman) ----------------------------------------------------
+ *  02/05/96 (Tim Norman)
  *    converted all functions to accept first/rest parameters
  *
- *  07/26/96 (Tim Norman) ----------------------------------------------------
+ *  07/26/96 (Tim Norman)
  *     changed return values to int instead of void
  *
  *  path()
  *     started.
  *
- *  12/23/96 (Aaron Kaufman) -------------------------------------------------
+ *  12/23/96 (Aaron Kaufman)
  *     rewrote dir() to mimic MS-DOS's dir
  *
- *  01/28/97 (Tim Norman) ----------------------------------------------------
+ *  01/28/97 (Tim Norman)
  *     cleaned up Aaron's DIR code
  *
- *  06/13/97 (Tim Norman) ----------------------------------------------------
+ *  06/13/97 (Tim Norman)
  *     moved DIR code to dir.c
  *     re-implemented Aaron's DIR code
  *
- *  06/14/97 (Steffan Kaiser) ------------------------------------------------
+ *  06/14/97 (Steffan Kaiser)
  *     ctrl-break handling
  *     bug fixes
  *
- *  06/14/97 (Tim Norman) ----------------------------------------------------
- *     changed static var in set() to a malloc'd space to pass to putenv.
- *     need to find a better way to do this, since it seems it is wasting
- *     memory when variables are redefined.
- *
- *  06/29/98 (Rob Lake) ------------------------------------------------------
- *      rewrote del to support wildcards
- *      added my name to the contributors
- *
- *  06/30/98 (Rob Lake) ------------------------------------------------------
- *      rewrote ver command to accept switches, now ver alone prints
- *      copyright notice only.
- *  07/08/1998 (John P. Price)
- *  - removed call to show_environment in set command.
- *  - moved test for syntax before allocating memory in set command.
- *  - misc clean up and optimization.
- * 07/13/98 (Rob Lake)
- *  - fixed bug that caused del not to delete file with out attribute.
- *      - moved set, del, ren, and ver to there own files
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
  *
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <dos.h>
 #include <direct.h>
@@ -126,19 +112,28 @@
 #include <conio.h>
 #include <io.h>
 #include <sys/stat.h>
-#include "command.h"
 
-#define SET "set"
+#include "command.h"
 
 /*
  *  generic function to handle cd, md, and rd (and their verbose names)
  *
  *
  */
-int
-directory_handler(char *first, char *rest,
-                  int (*func) (const char *),
-                  char *func_name, char *usage)
+
+
+#if defined(INCLUDE_CMD_CHDIR)
+ #define INCLUDE_DIRECTORY_HANDLER
+#elif defined(INCLUDE_CMD_MDDIR)
+ #define INCLUDE_DIRECTORY_HANDLER
+#elif defined(INCLUDE_CMD_RMDIR)
+ #define INCLUDE_DIRECTORY_HANDLER
+#endif
+
+
+#ifdef INCLUDE_DIRECTORY_HANDLER
+int directory_handler(char *first, char *rest,
+                  int (*func) (const char *))
 {
   char *dir;                    /* pointer to the directory to change to          */
   char *place;                  /* used to search for the \ when no space is used */
@@ -161,8 +156,8 @@
     /* if there is more than 1 parameter */
     if (parse_firstarg(rest) != NULL)
     {
-      puts(BADCMDLINE);         /* JPP 07/08/1998 clean up */
-      printf(USAGE ": %s\n", usage);  /*JPP 07/08/1998 clean up */
+      /*JPP 20-Jul-1998 use standard error message */
+      error_too_many_parameters(rest);
       return 1;
     }
     else
@@ -200,142 +195,86 @@
 
   if (func(dir) != 0)
   {
-    perror(func_name);
+    perror("");
     return 1;
   }
 
   return 0;
 }
+#endif
 
+#ifdef INCLUDE_CMD_CHDIR
 /*
  * CD / CHDIR - makes a call to directory_handler to do its work
  *
  *
  */
-int
-cd(char *first, char *rest)
+int cmd_chdir(char *first, char *rest)
 {
-  return directory_handler(first, rest, chdir, "cd()", CD_HELP);
+  return directory_handler(first, rest, chdir);
 }
+#endif
 
+#ifdef INCLUDE_CMD_MKDIR
 /*
  * MD / MKDIR - makes a call to directory_handler to do its work
  *
  *
  */
-int
-md(char *first, char *rest)
+int cmd_mkdir(char *first, char *rest)
 {
-  return directory_handler(first, rest, mkdir, "md()", MD_HELP);
+  return directory_handler(first, rest, mkdir);
 }
+#endif
 
+#ifdef INCLUDE_CMD_RMDIR
 /*
  * RD / RMDIR - makes a call to directory_handler to do its work
  *
  *
  */
 int
-rd(char *first, char *rest)
+cmd_rmdir(char *first, char *rest)
 {
-  return directory_handler(first, rest, rmdir, "rd()", RD_HELP);
+  return directory_handler(first, rest, rmdir);
 }
+#endif
 
 /*
- *
  * set the exitflag to true
  *
  */
 #pragma argsused
-int
-internal_exit(char *first, char *rest)
+int internal_exit(char *first, char *rest)
 {
   exitflag = 1;
 
   return 0;
 }
 
+#ifdef INCLUDE_CMD_REM
 /*
- *
  * does nothing
  *
  */
 #pragma argsused
-int
-rem(char *first, char *rest)
+int cmd_rem(char *first, char *rest)
 {
   return 0;
 }
+#endif
 
+#ifdef FEATURE_HISTORY
 /*
- *
  * prints DOSKEY message...  will soon emulate DOSKEY macros
  *
  */
 #pragma argsused
-int
-doskey(char *first, char *rest)
+int cmd_doskey(char *first, char *rest)
 {
   printf("DOSKEY features are already enabled in the shell.\n");
 
   return 0;
 }
+#endif
 
-/*
- *
- * changes the PROMPT env. var.
- *
- */
-#pragma argsused
-int
-prompt(char *first, char *rest)
-{
-  char *from,
-    tempcommand[256];
-
-  /* create a fake command to pass to set() */
-  strcpy(tempcommand, PROMPTEQUAL);
-  if (*rest == '=')
-  {
-    from = &rest[1];
-    while (isspace(*from))
-      from++;
-    strcat(tempcommand, from);
-  }
-  else
-    strcat(tempcommand, rest);
-
-  return set(SET, tempcommand);
-}
-
-/*
- *
- * changes the PATH env. var.
- *
- */
-#pragma argsused
-int
-path(char *first, char *rest)
-{
-  char *from,
-    tempcommand[256];
-
-  if (!rest || !*rest)
-  {
-    printf("PATH=%s\n", getenv("PATH"));
-    return 0;
-  }
-
-  /* create a fake command to pass to set() */
-  strcpy(tempcommand, PATHEQUAL);
-  if (*rest == '=')
-  {
-    from = &rest[1];
-    while (isspace(*from))
-      from++;
-    strcat(tempcommand, from);
-  }
-  else
-    strcat(tempcommand, rest);
-
-  return set(SET, tempcommand);
-}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/lh.asm com075/lh.asm
--- com074d/lh.asm	Thu Jul  9 08:28:12 1998
+++ com075/lh.asm	Fri Jul 31 21:57:32 1998
@@ -6,7 +6,7 @@
         ASSUME  CS:_TEXT, DS:DGROUP
 
 _DATA   SEGMENT WORD PUBLIC 'DATA'
-        extrn   _UMBLink:WORD           ; Holds the current state of the UMB link
+        extrn   _umbLink:WORD           ; Holds the current state of the UMB link
 _DATA   ENDS
 
 _TEXT   SEGMENT WORD PUBLIC 'CODE'
Files com074d/license.txt and com075/license.txt are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/loadhigh.c com075/loadhigh.c
--- com074d/loadhigh.c	Thu Jul 16 10:57:22 1998
+++ com075/loadhigh.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /*
  * LOADHIGH.C - command that loads a DOS executable into upper memory.
  * 
@@ -23,26 +24,34 @@
  *
  *   Comments
  *
- * ??/??/96 (Svante Frey) -------------------------------------------------
+ * ??/??/96 (Svante Frey)
  *   began.
  *
- * 01/17/96 (Tim Norman) --------------------------------------------------
+ * 01/17/96 (Tim Norman)
  *   plugged into COMMAND.COM
  *
- * 02/05/96 (Tim Norman) --------------------------------------------------
+ * 02/05/96 (Tim Norman)
  *   converted to new first/rest calling scheme
  *
- * 08/27/96 (Tim Norman) --------------------------------------------------
+ * 08/27/96 (Tim Norman)
  *   removed support for - as a switch character
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
+
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <fcntl.h>
 #include <dos.h>                /* must have those MK_FP() macros */
+#include <dir.h>                /* for searchpath() */
+
 #include "command.h"            /* command shell interface functions */
 #include "loadhigh.h"           /* contains macros, global variables, etc */
 
@@ -54,46 +63,55 @@
  * LOADFIX, otherwise LOADHIGH.
  */
 
+#ifdef INCLUDE_CMD_LOADHIGH
 /* This is the loadhigh handler */
 #pragma argsused
-int
-loadhigh(char *first, char *rest)
+int cmd_loadhigh(char *first, char *rest)
 {
   loadfix_flag = 0;
   return lh_lf(rest);
 }
+#endif
 
+#ifdef INCLUDE_CMD_LOADFIX
 /* This is the loadfix handler */
 #pragma argsused
-int
-loadfix(char *first, char *rest)
+int cmd_loadfix(char *first, char *rest)
 {
   loadfix_flag = 1;
   return lh_lf(rest);
 }
+#endif
+
+#if defined(INCLUDE_CMD_LOADHIGH)
+ #define INCLUDE_LOADHIGH_HANDLER
+#elif defined(INCLUDE_CMD_LOADFIX)
+ #define INCLUDE_LOADHIGH_HANDLER
+#endif
+
+#ifdef INCLUDE_LOADHIGH_HANDLER
 
 /* This is the "real" handler of the two commands. The argument is
  * the original command line.
  */
 
-int
-lh_lf(char *args)
+int lh_lf(char *args)
 {
   int rc = err_out_of_memory;
-  char *fullname = malloc(128);
-  char **paths = malloc(128 * sizeof(*paths));
+  char *fullname;
   filename = malloc(128);
 
-  if (paths && fullname && filename)
+  if (filename)
   {
     if (initialise() == OK)
     {
       if ((rc = parseArgs(args)) == OK)
       {
         /* command line was OK - try to find the file */
-        get_paths(paths);
 
-        if (find_which(paths, filename, fullname) == 1)
+        fullname = find_which(filename);
+
+        if (fullname)
         {
           /* a file was found - allocate the memory */
           if (loadfix_flag)
@@ -110,8 +128,6 @@
       }
     }
     cleanup();
-    free(paths);
-    free(fullname);
     free(filename);
   }
 
@@ -122,8 +138,7 @@
   return rc;
 }
 
-int
-initialise(void)
+int initialise(void)
 {
   int rc;
 
@@ -150,8 +165,7 @@
   return OK;
 }
 
-void
-cleanup(void)
+void cleanup(void)
 {
   int i;
 
@@ -172,8 +186,7 @@
 
 /* lh_error(): print error messages to stderr */
 
-void
-lh_error(int errcode)
+void lh_error(int errcode)
 {
   if (errcode > err_help)
     fprintf(stderr, "ERROR: ");
@@ -201,7 +214,6 @@
 }
 
 /* findUMBRegions():
- *
  * This routine scans the MCB chain to find all active memory regions.
  * Info about the regions is written to the array "umbRegions".
  *
@@ -209,8 +221,7 @@
  * memory.
  */
 
-int
-findUMBRegions(void)
+int findUMBRegions(void)
 {
   struct UMBREGION *region = umbRegion;
   struct MCB far *mcb = MK_FP(GetFirstMCB(), 0);  /* get start of MCB chain */
@@ -327,14 +338,13 @@
 }
 
 /* loadhigh_prepare():
- *
+
  * This routine allocates memory as necessary. All memory that the 
  * program is not allowed to access must be temporarily allocated
  * while the program is running.
  */
 
-int
-loadhigh_prepare(void)
+int loadhigh_prepare(void)
 {
   int i;
   struct UMBREGION far *region = umbRegion;
@@ -430,8 +440,7 @@
 
 /* loadfix_prepare(): Allocates all memory up to 1000:0000. */
 
-int
-loadfix_prepare(void)
+int loadfix_prepare(void)
 {
   struct MCB far *mcb = MK_FP(umbRegion[0].start, 0);
 
@@ -460,7 +469,7 @@
 }
 
 /*  parseArgs(): parse the command line
- *
+
  *  Only '/' is recognized as switch characters.
  *  The first argument not starting with '/' will be
  *  considered to be the filename.
@@ -468,8 +477,7 @@
  *  The LOADFIX command only accepts the '?' switch.
  */
 
-int
-parseArgs(char *cmdline)
+int parseArgs(char *cmdline)
 {
   char *c = cmdline;
   int i,
@@ -509,7 +517,7 @@
           {
             DWORD region_minSize = 0xffff;  /* flag value, indicating no minsize was specified */
 
-            int region_number = strtol(c + 1, &c, 10);
+            int region_number = (int)strtol(c + 1, &c, 10);
 
             if (*c == ',')
             {
@@ -561,3 +569,5 @@
 
   return OK;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/loadhigh.h com075/loadhigh.h
--- com074d/loadhigh.h	Thu Jul 16 10:57:22 1998
+++ com075/loadhigh.h	Fri Aug  7 08:44:26 1998
@@ -68,12 +68,11 @@
   WORD end;                     /* end of the region */
   WORD minSize;                 /* minimum free size, given by the L switch */
   int access;                   /* does the program have access to this region? */
-}
- *umbRegion;
+} *umbRegion;
 
 /* functions... */
 int loadhigh(char *first, char *rest);
-int loadfix(char *first, char *rest);
+int cmd_loadfix(char *first, char *rest);
 int findUMBRegions(void);
 int parseArgs(char *cmdline);
 void lh_error(int errcode);
Files com074d/lowexec.asm and com075/lowexec.asm are identical
Files com074d/makecom.bat and com075/makecom.bat are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/misc.c com075/misc.c
--- com074d/misc.c	Thu Jul 16 10:57:22 1998
+++ com075/misc.c	Fri Aug  7 08:44:26 1998
@@ -1,14 +1,19 @@
 /*
  * MISC.C -- Misc. Functions
  *
- * 07/12/98 (Rob Lake) -----------------------------------------------------
+ * 07/12/98 (Rob Lake)
  *  started
  *
- * 07/13/98 (Rob Lake) -----------------------------------------------------
+ * 07/13/98 (Rob Lake)
  *      moved functions in here
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
 #include <dos.h>
 #include <io.h>
 #include <fcntl.h>
@@ -26,16 +31,14 @@
  * exist -- Checks if a file exists
  *
  */
-int
-exist(char *fn)
+int exist(const char *fn)
 {
   return (access(fn, 0) == 0);
 }
 /*
  * get a character out-of-band and honor Ctrl-Break characters
  */
-int
-cgetchar(void)
+int cgetchar(void)
 {
   int c;
 
@@ -51,8 +54,7 @@
 /*
  * Check if Ctrl-Break was pressed during the last calls
  */
-int
-chkCBreak(int mode)
+int chkCBreak(int mode)
 {
   static int leaveAll = 0;      /* leave all batch files */
   int c;
@@ -98,8 +100,7 @@
  *   -- Rob Lake (06/29/98)
  *
  */
-int
-split(char *s, char **p)
+int split(char *s, char **p)
 {
   int sc = 0,
     pc = 0;                     /* string and parameter counters */
@@ -126,8 +127,7 @@
  * there are no more arguments
  *
  */
-char *
-parse_firstarg(char *s)
+char *parse_firstarg(char *s)
 {
   char *place;
 
Files com074d/model.def and com075/model.def are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/notes.txt com075/notes.txt
--- com074d/notes.txt	Wed Dec 31 18:00:00 1969
+++ com075/notes.txt	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,56 @@
+Notes from contributors....
+
+Notes from Hans B Pufal <hansp@digiweb.com>:
+
+Here is my package of changes to COMMAND, my coding was based on version
+74B, but I downloaded version 74D and modified my files accordingly.
+
+I use BC 4.5 and had some problems with the makefile, it was generating
+a .COM file of 102Kb!. I have included my modified makefile for your
+reference.
+
+For the files I have modified, I have reformatted them to my style (sorry).
+Take a look and see if you can live with it. I find that procedure headers
+are easier to find and that putting the history in reverse order helps
+quickly find the latest changes.
+
+
+
+   File   Description
+
+   batch.c  A new version, implements CALL, ECHO, GOT, IF, PAUSE, SHIFT
+    and BEEP. There is a stub for FOR but that's all.
+
+   cmdtable.c New file to keep the internal command table. I plan on
+    getting rid of the table real soon now and replacing it
+    with a dynamic mechanism.
+
+   command.c  A new (improved ;) version. Conforms closely to MS-DOS
+    specs. Cleaned up (and fixed) the redirection handler.
+
+   command.h  Your version D with changes. Look for the HBP tag.
+
+   makefile My version of the makefile, for BC 4.5. Sorry don't use
+    the IDE so could not make a .prj file.
+
+   notes.txt  This file...
+
+   redir.c  Modified file, now supports append redirects.
+
+   where.c  Modified, made it a little safer and quicker...
+
+
+The test subdirectory has some batch file tests. I run T.BAT which uses
+runs the test and sends output to a file. The tests are run twice once
+for a COMMAND.COM on the patch (presumably ours) and once with
+C:\COMMAND.COM, presumed to be the MSDOS version. Compare the outputs in
+MSDOS.OUT and FDOS.OUT to look for any problems.
+
+That's about it, ask if you have any questions.
+
+Regards,
+
+Hans <mailto:hansp@digiweb.com>
+
+-----------------------------------------------------------------------------
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/path.c com075/path.c
--- com074d/path.c	Wed Dec 31 18:00:00 1969
+++ com075/path.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,70 @@
+/*
+ *  PATH.C - path command.
+ *
+ *  Comments:
+ *
+ * 17 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PATH
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "command.h"
+
+#define PATHEQUAL    "PATH="
+
+/*
+ * changes the PATH env. var.
+ *
+ * JPP 17-Jul-1998 - changed to use dynamic memory instead of static.
+ *
+ */
+#pragma argsused
+int cmd_path(char *first, char *rest)
+{
+  char *from,
+   *tempcommand;
+  int returnvalue;
+
+  if (!rest || !*rest)
+  {
+    printf("PATH=%s\n", getenv("PATH"));
+    return 0;
+  }
+
+  /* create a fake command to pass to set() */
+  if (*rest == '=')
+  {
+    from = &rest[1];
+    while (isspace(*from))
+      from++;
+    tempcommand = (char *)malloc(strlen(PATHEQUAL) + strlen(from) + 1);
+    strcpy(tempcommand, PATHEQUAL);
+    strcat(tempcommand, from);
+  }
+  else
+  {
+    tempcommand = (char *)malloc(strlen(PATHEQUAL) + strlen(rest) + 1);
+    strcpy(tempcommand, PATHEQUAL);
+    strcat(tempcommand, rest);
+  }
+
+  returnvalue = set_env(tempcommand);
+  free(tempcommand);
+  return returnvalue;
+
+}
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/pause.c com075/pause.c
--- com074d/pause.c	Wed Dec 31 18:00:00 1969
+++ com075/pause.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,59 @@
+/*
+ *  PAUSE.C - pause command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PAUSE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_pause(char *cmd, char *param)
+{
+/*
+ * Perform PAUSE command.
+ *
+ * FREEDOS extension : If parameter is specified use that as the pause
+ *   message.
+ *
+ * ?? Extend to include functionality of CHOICE if switch chars
+ *     specified.
+ */
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  if (*param)
+    puts(param);
+  else
+    msg_pause();
+
+  cgetchar();
+
+  return 0;
+}
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/prompt.c com075/prompt.c
--- com074d/prompt.c	Thu Jul 16 10:57:22 1998
+++ com075/prompt.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /*
  *  PROMPT.C - prompt handling.
  *
@@ -5,21 +6,32 @@
  *
  *  Comments:
  *
- *  14/01/95 (Tim Normal) ---------------------------------------------------
+ *  14/01/95 (Tim Normal)
  *    started.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
+ *  08/08/95 (Matt Rains)
  *    i have cleaned up the source code. changes now bring this source into
  *    guidelines for recommended programming practice.
  *
- *  01/06/96 (Tim Norman) ---------------------------------------------------
+ *  01/06/96 (Tim Norman)
  *    added day of the week printing (oops, forgot about that!)
  *
- *  08/07/96 (Steffan Kaiser) -----------------------------------------------
+ *  08/07/96 (Steffan Kaiser)
  *    small changes for speed
  *
+ *  20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *   removed redundant day strings. Use ones defined in date.c.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - moved cmd_prompt from internal.c to here
+ *
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
@@ -28,16 +40,18 @@
 #include <dir.h>
 #include <string.h>
 
-static char days[7][4] =
+#include "command.h"
+
+/* JPP 20-Jul-1998 - removed redundant day strings. Use ones defined in date */
+
+const char *day_strings[] =
 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
 
 /*
- *
  * print the command-line prompt
  *
  */
-void
-printprompt(void)
+void printprompt(void)
 {
   struct time t;
   struct dosdate_t d;
@@ -85,7 +99,7 @@
         case 'D':
           {
             _dos_getdate(&d);
-            printf("%s %02d-%02d-%04d", days[d.dayofweek], d.month,
+            printf("%s %02d-%02d-%04d", day_strings[d.dayofweek], d.month,
                    d.day, d.year);
             break;
           }
@@ -152,6 +166,45 @@
     }
     pr++;
   }
+}
+
+
+#ifdef INCLUDE_CMD_PROMPT
+
+#define PROMPTEQUAL  "PROMPT="
+
+/*
+ * changes the PROMPT env. var.
+ *
+ * JPP 17-Jul-1998 - changed to use dynamic memory instead of static.
+ *
+ */
+#pragma argsused
+int cmd_prompt(char *first, char *rest)
+{
+  char *from,
+   *tempcommand;
+  int returnvalue;
+
+  /* create a fake command to pass to set() */
+  if (*rest == '=')
+  {
+    from = &rest[1];
+    while (isspace(*from))
+      from++;
+    tempcommand = (char *)malloc(strlen(PROMPTEQUAL) + strlen(from) + 1);
+    strcpy(tempcommand, PROMPTEQUAL);
+    strcat(tempcommand, from);
+  }
+  else
+  {
+    tempcommand = (char *)malloc(strlen(PROMPTEQUAL) + strlen(rest) + 1);
+    strcpy(tempcommand, PROMPTEQUAL);
+    strcat(tempcommand, rest);
+  }
 
-  return;
+  returnvalue = set_env(tempcommand);
+  free(tempcommand);
+  return returnvalue;
 }
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/readme.txt com075/readme.txt
--- com074d/readme.txt	Thu Jul 16 10:57:22 1998
+++ com075/readme.txt	Fri Aug  7 08:44:26 1998
@@ -1,6 +1,5 @@
 FreeDOS Command Line Interface
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
 About
 ~~~~~
 This software is part of the FreeDOS project. Please email
@@ -8,9 +7,13 @@
 archive at "ftp://sunsite.unc.edu/pub/micro/pc-stuff/freedos".  Also,
 visit our web page at http://www.freedos.org/.
 
+The command.com web site is at
+
+   http://www.gcfl.net/FreeDOS/command.com/
+
 Please send any bug reports, comments or other info to:
 
-   normat@rpi.edu (Tim Norman)
+   command@gcfl.net  (command.com development mailing list)
 
 This software has been developed by the following people:
 (listed in approximate chronological order of contributions)
@@ -24,7 +27,8 @@
    Aaron Kaufman (morgan@remarque.berkeley.edu)
    Marc Desrochers (bitzero@hotmail.com)
    Rob Lake (rlake@cs.mun.ca)
-   John P. Price (linux-guru@gcfl.net)
+   John P. Price <linux-guru@gcfl.net>
+   Hans B Pufal <hansp@digiweb.com>
 
 Please note that this software is separate from the DOS-C kernel and
 may or may not work properly under it.  Of course I am making every
@@ -49,17 +53,11 @@
 
 Current Features
 ~~~~~~~~~~~~~~~~
-enviroment handling with prompt and path support.
+environment handling with prompt and path support.
 directory utilities.
 command-line history with doskey-like features.
 batch file processing
 input/output redirection and piping
 loadhigh support
 alias support
-
-Caution
-~~~~~~~
-Be careful with the DEL.  If there are any problems with it, please
-send a bug report to Rob Lake (rlake@cs.mun.ca).  When I was testing
-the del command and exited the shell it rebooted my computer.  It
-seems to work fine now that it calls unlink instead of remove.
+filename completion (use TAB)
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/redir.c com075/redir.c
--- com074d/redir.c	Thu Jul 16 10:57:22 1998
+++ com075/redir.c	Fri Aug  7 08:44:26 1998
@@ -1,88 +1,129 @@
 /*
  *  REDIR.C
  *
- *
- *
  *  Comments:
  *
- *  12/15/95 (Tim Norman) ---------------------------------------------------
+ * 12/15/95 (Tim Norman)
  *    started.
  *
+ * 12 Jul 98 (Hans B Pufal)
+ * - Rewrote to make more efficient and to conform to new command.c and
+ *   batch.c processing.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
+#include <fcntl.h>
 
-int
-is_redir(char c)
-{
-  return c == '<' || c == '>' || c == '|';
+static int is_redir(char c)
+ {
+  return (c == '<') || (c == '>') || (c == '|');
 }
 
-/* gets the redirection from the command line and chops it out of the */
-/* command line                                                       */
-void
-get_redirection(char *s, char *in, char *out, char *pipe[128], int *num)
-{
-  int count,
-    start,
-    inquote = 0,
-    numpipes = 0;
-
-  /* find and remove all the redirections first */
-  for (count = 0; s[count]; count++)
-    if (s[count] == '"')
-      inquote = !inquote;
-    else if (!inquote && (s[count] == '<' || s[count] == '>'))
+int get_redirection(char *s, char *ifn, char *ofn, int *ofatt)
     {
-      /* MS-DOS ignores multiple redirection symbols and uses the last */
-      /* redirection, so we'll emulate that and not check */
+  /*
+   * Gets the redirection infor from the command line and copies the
+   * file names into ifn and ofn removing them form the command line.
+   *
+   * Converts remainin command line into a series of null terminated
+   * strings defined by the pipe char '|'. Each string corresponds
+   * to a single executable command. A double null terminates the
+   * command strings.
+   *
+   * Check for, but do not implement, output append redirect.
+   *
+   * Return number of command strings found.
+   *
+   */
 
-      /* find the next word */
-      start = count;
-      count++;
+  int
+    num = 1;
 
-      /* skip over whitespace */
-      while (isspace(s[count]))
-        count++;
+  char
+   *dp = s,
+   *sp = s;
 
-      /* skip until we hit whitespace or a delimiter of some sort */
-      while (!is_redir(s[count]) && s[count] && !isspace(s[count]))
-        count++;
+  /* find and remove all the redirections first */
 
-      if (s[start] == '<')
+  while (*sp)
       {
-        memcpy(in, &s[start + 1], count - start - 1);
-        in[count - start - 1] = 0;
+    if ((*sp == '"') || (*sp == '\''))  /* No redirects inside quotes */
+    {
+      char
+        qc = *sp;
+
+      do
+        *dp++ = *sp++;
+      while (*sp != qc);
+
+      *dp++ = *sp++;
       }
-      else if (s[start] == '>')
+
+    else if ((*sp == '<') || (*sp == '>'))
       {
-        memcpy(out, &s[start + 1], count - start - 1);
-        out[count - start - 1] = 0;
+      /* MS-DOS ignores multiple redirection symbols and uses the last */
+      /* redirection, so we'll emulate that and not check */
+
+      char
+       *op = (*sp == '<') ? ifn : ofn;
+
+      if ((*sp++ == '>') && (*sp == '>')) /* Append request ? */
+      {
+        *ofatt = O_CREAT | O_APPEND | O_TEXT | O_WRONLY;
+        sp++;
       }
 
-      memmove(&s[start], &s[count], strlen(&s[count]) + 1);
+      while (isspace(*sp))
+        sp++;
 
-      /* move back one so we can check this character */
-      count = start - 1;
+      while (*sp && !is_redir(*sp) && !isspace(*sp))
+        *op++ = *sp++;
+
+      *op = '\0';
     }
 
+    else
+      *dp++ = *sp++;
+  }
+
+  *dp++ = '\0';
+  *dp = '\0';
+
   /* now go after the pipes */
 
-  pipe[numpipes++] = s;
+  sp = s;
 
-  for (count = 0; s[count]; count++)
-    if (s[count] == '"')
-      inquote = !inquote;
-    else if (!inquote && s[count] == '|')
+  while (*sp)
     {
-      s[count] = 0;
+    if ((*sp == '"') || (*sp == '\''))
+    {
+      char
+        qc = *sp;
+
+      do
+        sp++;
+      while (*sp != qc);
 
-      pipe[numpipes++] = &s[count + 1];
+      sp++;
     }
 
-  pipe[numpipes] = NULL;
+    else if (*sp == '|')
+    {
+      *sp++ = '\0';
+      num++;
+    }
+
+    else
+      sp++;
+  }
 
-  *num = numpipes;
+  return num;
 }
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/ren.c com075/ren.c
--- com074d/ren.c	Thu Jul 16 10:57:22 1998
+++ com075/ren.c	Fri Aug  7 08:44:26 1998
@@ -1,18 +1,25 @@
 /*
- * REN.C
+ * REN.C - rename command
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
-#include "command.h"
+#include "config.h"
+
+#ifdef INCLUDE_CMD_RENAME
+
+
 #include <stdio.h>
+#include "command.h"
 
 /*
- *
  *  simple file rename internal command.
  *
  */
 #pragma argsused
-int
-ren(char *first, char *rest)
+int cmd_rename(char *first, char *rest)
 {
   char *arg[2];
 
@@ -25,15 +32,16 @@
   /* check if there are the wrong number of arguments */
   if (!arg[0][0] || !arg[1] || parse_firstarg(arg[1]) != NULL)
   {
-    printf("%s\n", BADCMDLINE);
-    printf("%s: %s\n", USAGE, REN_HELP);
+    error_too_many_parameters(rest);
     return 1;
   }
   else if (rename(arg[0], arg[1]) != 0)
   {
-    perror("ren()");
+    perror("rename");
     return 1;
   }
 
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/set.c com075/set.c
--- com074d/set.c	Thu Jul 16 10:57:22 1998
+++ com075/set.c	Fri Aug  7 08:44:26 1998
@@ -1,25 +1,68 @@
 /*
  * SET.C
  *
+ *  06/14/97 (Tim Norman)
+ *     changed static var in set() to a malloc'd space to pass to putenv.
+ *     need to find a better way to do this, since it seems it is wasting
+ *     memory when variables are redefined.
+ *
+ *  07/08/1998 (John P. Price)
+ *  - removed call to show_environment in set command.
+ *  - moved test for syntax before allocating memory in set command.
+ *  - misc clean up and optimization.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added set_env function to set env. variable without needing set command
+ *
  */
 
-#include "command.h"
+#include "config.h"
+
+#ifdef INCLUDE_CMD_SET
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 
+#include "command.h"
+
+
+int set_env(char *s)
+{
+  char *env_temp;               /* temporary copy for putenv */
+  unsigned char count;          /* counter */
+
+  if ((env_temp = strdup(s)) == NULL)
+  {
+    error_out_of_memory();
+    return 1;
+  }
+
+  /* capitalize name of env. var. */
+  for (count = 0; env_temp[count] && env_temp[count] != '='; count++)
+  {
+    env_temp[count] = toupper(env_temp[count]);
+  }
+
+  dprintf(("[SET:putenv: %s]\n", env_temp));
+
+  return putenv(env_temp);
+}
+
+
 /*
  * set environment variables
  *
  *
  */
 #pragma argsused
-int
-set(char *first, char *rest)
+int cmd_set(char *first, char *rest)
 {
   unsigned char count;          /* counter */
-  char *env_temp;               /* temporary copy for putenv */
 
   /* if no parameters, show the environment */
   if (rest[0] == 0)
@@ -36,26 +79,16 @@
   /* JPP 07/08/1998 moved test for syntax before allocating memory */
   if (strchr(rest, '=') == NULL)
   {
-    puts("Syntax error");
-    return 1;
-  }
-
-  if ((env_temp = strdup(rest)) == NULL)
-  {
-    puts("Memory error");
+    error_syntax(NULL);
     return 1;
   }
 
-  /* capitalize name of env. var. */
-  for (count = 0; env_temp[count] && env_temp[count] != '='; count++)
-  {
-    env_temp[count] = toupper(env_temp[count]);
-  }
-
-  if (putenv(env_temp) < 0)
+  if (set_env(rest) < 0)
   {
-    puts("Environment error");
+    puts("SET: Environment error");
   }
 
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/shift.c com075/shift.c
--- com074d/shift.c	Wed Dec 31 18:00:00 1969
+++ com075/shift.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,62 @@
+/*
+ *  SHIFT.C - shift command.
+ *
+ *  Comments:
+ *
+ * 16 Jul 1998 (Hans B Pufal)
+ *   started.
+ *
+ * 16 Jul 1998 (John P Price)
+ *   Seperated commands into individual files.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command.h"
+#include "batch.h"
+
+int cmd_shift(char *cmd, char *param)
+{
+/*
+ *  Perform the SHIFT command.
+ *
+ * Only valid inside batch files.
+ *
+ * FREEDOS extension : optional parameter DOWN to allow shifting
+ *   parameters backwards.
+ */
+
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    printf("%s :\n", cmd);
+    return 0;
+  }
+
+  if (bc == NULL)
+  {
+    /*!! not in batch - error */
+
+    return 1;
+  }
+
+  if (stricmp(param, "down") == 0)
+  {
+    if (bc->shiftlevel)
+      bc->shiftlevel--;
+  }
+  else                          /* shift up */
+    bc->shiftlevel++;
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tempfile.c com075/tempfile.c
--- com074d/tempfile.c	Thu Jul 16 10:57:22 1998
+++ com075/tempfile.c	Fri Aug  7 08:44:26 1998
@@ -1,3 +1,4 @@
+
 /*
  *  TEMPFILE.C - tempfile() creates a unique temporary file
  *
@@ -9,8 +10,13 @@
  *    started. There is a problem with the tmpfile() routine of Borland so
  *    I have implemented it new.
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
 #include <dir.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -20,14 +26,12 @@
 
 static char tb[MAXPATH];
 
-void
-rmtmpfile(void)
+void rmtmpfile(void)
 {
   remove(tb);
 }
 
-FILE *
-tempfile()
+FILE *tempfile()
 {
   char *tmp;
 
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tempfile.h com075/tempfile.h
--- com074d/tempfile.h	Thu Jul 16 10:57:22 1998
+++ com075/tempfile.h	Fri Aug  7 08:44:26 1998
@@ -1,4 +1,3 @@
-
 /*
  *  TEMPFILE.H - header file with tempfile() prototype
  *  Oliver Mueller
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/test.bat com075/test.bat
--- com074d/test.bat	Sat Jun 14 16:19:32 1997
+++ com075/test.bat	Wed Dec 31 18:00:00 1969
@@ -1,15 +0,0 @@
-echo hi, this is a test
-rem a comment
-pause
-echo the path is %PATH%
-echo the path is %path%
-echo these are the parameters: %1 %2 %3 %4
-pause
-echo this is bogus: %bogus%
-echo this is a test: %test
-goto next
-
-echo this line will never be reached
-
-:next
-echo if is not implemented yet
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/testenv.c com075/testenv.c
--- com074d/testenv.c	Thu Jul 16 10:57:22 1998
+++ com075/testenv.c	Wed Dec 31 18:00:00 1969
@@ -1,24 +0,0 @@
-int
-main(int argc, char *argv[], char *env[])
-{
-  int count;
-
-  puts("Commandline:");
-
-  for (count = 0; count < argc; count++)
-    printf("%d: %s\n", count, argv[count]);
-
-  puts("\nEnvironment:");
-
-  for (count = 0; env[count]; count++)
-    printf("%d: %s\n", count, env[count]);
-
-  putenv("PATH=");
-
-  puts("\nEnvironment after a setenv (\"PATH=\");:");
-
-  for (count = 0; env[count]; count++)
-    printf("%d: %s\n", count, env[count]);
-
-  return 0;
-}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/bat1.bat com075/tests/bat1.bat
--- com074d/tests/bat1.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/bat1.bat	Tue Aug  4 12:19:42 1998
@@ -0,0 +1,3 @@
+echo in bat 1
+call bat2.bat
+echo back in bat 1
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/bat2.bat com075/tests/bat2.bat
--- com074d/tests/bat2.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/bat2.bat	Tue Aug  4 12:19:50 1998
@@ -0,0 +1,3 @@
+echo in bat 2
+call bat3.bat
+echo back in bat 2
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/bat3.bat com075/tests/bat3.bat
--- com074d/tests/bat3.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/bat3.bat	Tue Aug  4 12:19:32 1998
@@ -0,0 +1 @@
+echo in bat 3
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/dir-test.txt com075/tests/dir-test.txt
--- com074d/tests/dir-test.txt	Wed Dec 31 18:00:00 1969
+++ com075/tests/dir-test.txt	Thu Jul 16 09:53:04 1998
@@ -0,0 +1,25 @@
+Regression tests for dir.c
+--------------------------
+
+If you add tests, please email them to normat@rpi.edu
+
+The following directories must exist: C:\TEMP, D:\TIM, C:\WINDOWS D:\TIM\C
+
+Current working directories are: C:\TEMP, D:\TIM
+
+Current drive is: C
+
+Type the command in the "From" column and make sure the files listed are what
+are shown in the other columns.
+
+From                                    Drive   Dir             File
+----                                    -----   ---             ----
+DIR                                     C       \TEMP           *.*
+DIR \                                   C       \               *.*
+DIR \windows                            C       \windows        *.*
+DIR d:                                  D       \tim            *.*
+DIR d:\                                 D       \               *.*
+DIR d:.                                 D       \tim            *.*
+DIR file                                C       \TEMP           file.*
+DIR .ext                                C       \TEMP           *.ext
+DIR D:c                                 D       \tim\c          *.*
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/fdos.out com075/tests/fdos.out
--- com074d/tests/fdos.out	Wed Dec 31 18:00:00 1969
+++ com075/tests/fdos.out	Thu Jul 16 04:49:00 1998
@@ -0,0 +1,33 @@
+
+D:\FREEDOS\COM074BS\SOURCE\PACK\TEST>echo This is a test batch file
+This is a test batch file
+
+D:\FREEDOS\COM074BS\SOURCE\PACK\TEST>echo
+ECHO is on
+Testing with echo off
+
+D:\FREEDOS\COM074BS\SOURCE\PACK\TEST>echo Testing wih echo on
+Testing wih echo on
+
+D:\FREEDOS\COM074BS\SOURCE\PACK\TEST>echo off
+Testing : test2 p1 p2 p3 p4
+Testing : p1 p2 p3 p4
+Testing : p2 p3 p4
+now test the environment substitution
+path is D:\AMI\TOOLS\MASM611\BIN;D:\AMI\TOOLS\BIN;C:\BIN;C:\WINDOWS;C:\WINDOWS\COMMAND;C:\BC45\BIN;C:\BRIEF;
+PATH is D:\AMI\TOOLS\MASM611\BIN;D:\AMI\TOOLS\BIN;C:\BIN;C:\WINDOWS;C:\WINDOWS\COMMAND;C:\BC45\BIN;C:\BRIEF;
+Absent variable is
+Bad format : bad format
+Testing double %comspec%
+Call another batch file...
+Testing : test3.bat t3p1 t3p2 t3p3
+Testing : t3p1 t3p2 t3p3
+Testing : t3p2 t3p3
+Press any key to continue . . .
+
+.
+Returned to TEST2
+.
+Testing : p2 p3 p4
+Testing : p3 p4
+Testing : p4
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/hbp001a.bat com075/tests/hbp001a.bat
--- com074d/tests/hbp001a.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/hbp001a.bat	Mon Jul 20 09:52:54 1998
@@ -0,0 +1,12 @@
+echo on
+echo Root batch, echo on
+echo starting hbp001b
+call hbp001b
+echo root batch: I'm back, this should be echo'd
+
+echo off
+echo Root batch, echo off
+echo starting hbp001b
+call hbp001b
+echo root batch: I'm back, this should NOT be echo'd
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/hbp001b.bat com075/tests/hbp001b.bat
--- com074d/tests/hbp001b.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/hbp001b.bat	Sun Jul 19 02:53:32 1998
@@ -0,0 +1,6 @@
+echo This is the start of called batch echo state form caller
+
+echo on
+echo This should always be echoed
+
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/hbp002.txt com075/tests/hbp002.txt
--- com074d/tests/hbp002.txt	Wed Dec 31 18:00:00 1969
+++ com075/tests/hbp002.txt	Sun Jul 19 04:21:32 1998
@@ -0,0 +1,23 @@
+OK, here is my implementation of the FOR command, files changed :
+
+   BATCH.C
+   BATCH.H
+   FOR.C
+
+
+There is a problem running form BATCH files. Formthe command line
+type in something like:
+
+	for %%a in (a bb ccc) do echo %%a
+  or
+        for %%a in (*.c) do echo %%a
+
+
+Put it in the next release and I'll work on fixing the batch issue.
+
+Hans
+19 Jul 1998
+
+
+
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/hbp_001.txt com075/tests/hbp_001.txt
--- com074d/tests/hbp_001.txt	Wed Dec 31 18:00:00 1969
+++ com075/tests/hbp_001.txt	Sun Jul 19 02:47:06 1998
@@ -0,0 +1,9 @@
+Minor changes to BATCH.C and BATCH.H to preserve the staets of the echo
+flag across batch calls.
+
+Please add HBP_001a.bat and hbp_001b.bat to test directory.
+
+
+19 July 1998
+Hans B Pufal
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/msdos.out com075/tests/msdos.out
--- com074d/tests/msdos.out	Wed Dec 31 18:00:00 1969
+++ com075/tests/msdos.out	Thu Jul 16 04:49:00 1998
@@ -0,0 +1,33 @@
+
+D:\freedos\com074bs\source\PACK\test>echo This is a test batch file
+This is a test batch file
+
+D:\freedos\com074bs\source\PACK\test>echo
+ECHO is on
+Testing with echo off
+
+D:\freedos\com074bs\source\PACK\test>echo Testing wih echo on
+Testing wih echo on
+
+D:\freedos\com074bs\source\PACK\test>echo off
+Testing : test2 p1 p2 p3 p4    
+Testing : p1 p2 p3 p4     
+Testing : p2 p3 p4      
+now test the environment substitution
+path is D:\AMI\TOOLS\MASM611\BIN;D:\AMI\TOOLS\BIN;C:\BIN;C:\WINDOWS;C:\WINDOWS\COMMAND;C:\BC45\BIN;C:\BRIEF;
+PATH is D:\AMI\TOOLS\MASM611\BIN;D:\AMI\TOOLS\BIN;C:\BIN;C:\WINDOWS;C:\WINDOWS\COMMAND;C:\BC45\BIN;C:\BRIEF;
+Absent variable is 
+Bad format : bad format
+Testing double %comspec% 
+Call another batch file...
+Testing : test3.bat t3p1 t3p2 t3p3     
+Testing : t3p1 t3p2 t3p3      
+Testing : t3p2 t3p3       
+Press any key to continue . . .
+
+.
+Returned to TEST2
+.
+Testing : p2 p3 p4      
+Testing : p3 p4       
+Testing : p4        
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/t.bat com075/tests/t.bat
--- com074d/tests/t.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/t.bat	Tue Jul 14 05:53:54 1998
@@ -0,0 +1,2 @@
+c:\command /c test1 >msdos.out
+command /c test1 >fdos.out
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/test.bat com075/tests/test.bat
--- com074d/tests/test.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/test.bat	Sun Jul 12 19:31:06 1998
@@ -0,0 +1,24 @@
+echo
+echo hi, this is a test
+freda
+rem a comment
+pause
+@echo the path is %PATH%
+echo the path is %path%
+echo Batch file called as : %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
+@shift
+echo shifted : %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
+@shift down
+echo shifted  down: %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
+pause
+echo this is bogus: %bogus%
+echo this is a test: %test
+echo
+echo off
+echo
+goto next
+
+echo this line will never be reached
+
+:next
+echo continue form here...
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/test1.bat com075/tests/test1.bat
--- com074d/tests/test1.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/test1.bat	Tue Jul 14 05:44:16 1998
@@ -0,0 +1,9 @@
+echo This is a test batch file
+echo
+@echo off
+echo Testing with echo off
+echo on
+echo Testing wih echo on
+echo off
+test2 p1 p2 p3 p4
+echo This should not appear!!
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/test2.bat com075/tests/test2.bat
--- com074d/tests/test2.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/test2.bat	Tue Jul 14 17:18:04 1998
@@ -0,0 +1,25 @@
+@echo off
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+
+echo now test the environment substitution
+echo path is %path%
+echo PATH is %PATH%
+echo Absent variable is %Absent%
+echo Bad format : %bad format
+echo Testing double %%comspec%% 
+
+echo Call another batch file...
+call test3.bat t3p1 t3p2 t3p3
+
+echo .
+echo Returned to TEST2
+echo .
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/test3.bat com075/tests/test3.bat
--- com074d/tests/test3.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/test3.bat	Tue Jul 14 17:16:50 1998
@@ -0,0 +1,7 @@
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+shift
+echo Testing : %0 %1 %2 %3 %4 %5 %6 %7 %8
+pause
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/test4.bat com075/tests/test4.bat
--- com074d/tests/test4.bat	Wed Dec 31 18:00:00 1969
+++ com075/tests/test4.bat	Tue Jul 14 17:17:58 1998
@@ -0,0 +1,5 @@
+dir > q1
+dir >> q1
+sort <q1 >q1s
+dir | sort >>q1s
+
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/tests/testenv.c com075/tests/testenv.c
--- com074d/tests/testenv.c	Wed Dec 31 18:00:00 1969
+++ com075/tests/testenv.c	Thu Jul 16 09:57:56 1998
@@ -0,0 +1,24 @@
+int
+main(int argc, char *argv[], char *env[])
+{
+  int count;
+
+  puts("Commandline:");
+
+  for (count = 0; count < argc; count++)
+    printf("%d: %s\n", count, argv[count]);
+
+  puts("\nEnvironment:");
+
+  for (count = 0; env[count]; count++)
+    printf("%d: %s\n", count, env[count]);
+
+  putenv("PATH=");
+
+  puts("\nEnvironment after a setenv (\"PATH=\");:");
+
+  for (count = 0; env[count]; count++)
+    printf("%d: %s\n", count, env[count]);
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/time.c com075/time.c
--- com074d/time.c	Thu Jul 16 10:57:22 1998
+++ com075/time.c	Fri Aug  7 08:44:26 1998
@@ -6,18 +6,24 @@
  *  07/08/1998 (John P. Price)
  *    started.
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
  *
  */
 
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TIME
+
 #include <stdio.h>
 #include <dos.h>
 #include <ctype.h>
 #include <string.h>
 
 #include "command.h"
+#include "timefunc.h"
 
-int
-parsetime(char *s)
+int parsetime(char *s)
 {
   struct dostime_t t;
 
@@ -94,8 +100,8 @@
   return 1;
 }
 
-int
-cmd_time(char *first, char *rest)
+#pragma argsused
+int cmd_time(char *first, char *rest)
 {
   struct dostime_t t;
   char ampm;
@@ -151,6 +157,14 @@
     }
     printf("Invalid time.\n");
   }
+}
 
-  return 0;
+#endif
+
+#ifdef DEBUG_STANDALONE
+int main(void)
+{
+  cmd_time("time", "");
+  return 1;
 }
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/timefunc.c com075/timefunc.c
--- com074d/timefunc.c	Wed Dec 31 18:00:00 1969
+++ com075/timefunc.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,101 @@
+/*
+
+TimeFunc -- DOS Time Functions
+Copyright (C) 1998 Rob Lake
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+Rob Lake can be contacted at
+email: rlake@cs.mun.ca
+
+*/
+
+/*
+ * 07/29/98 (Rob Lake)
+ *  started
+ *
+ * Works Under:
+ *    Borland C++ 3.0
+ *  Pacific C (pacc 7.51)
+ *
+ */
+
+#ifdef _NO__DOS_TIME
+
+#include <dos.h>
+#include <stdio.h>
+#include "timefunc.h"
+
+unsigned _dos_settime(struct dostime_t *t)
+{
+  union REGS r;
+
+  r.h.ah = 0x2D;
+  r.h.ch = t->hour;
+  r.h.cl = t->minute;
+  r.h.dh = t->second;
+  r.h.dl = t->hsecond;
+
+  int86(0x21, &r, &r);
+
+  if(r.h.al == 0xFF) /* Error occured setting time */
+    return -1;
+
+  return 0;
+}
+
+void _dos_gettime(struct dostime_t *t)
+{
+  union REGS r;
+
+  r.h.ah = 0x2C;
+  int86(0x21, &r, &r);
+
+  t->hour = r.h.ch;
+  t->minute = r.h.cl;
+        t->second = r.h.dh;
+  t->hsecond = r.h.dl;
+}
+
+#ifdef DEBUG_STANDALONE
+int main(void)
+{
+        struct dostime_t new_ct, t, orig_t;
+
+        _dos_gettime(&orig_t);
+  printf("The current time is: %2d:%02d:%02d.%02d\n",
+               orig_t.hour, orig_t.minute, orig_t.second, orig_t.hsecond);
+
+  new_ct.hour = 12;
+        new_ct.minute = 12;
+        new_ct.second = 12;
+        new_ct.hsecond = 12;
+
+        _dos_settime(&new_ct);
+
+        _dos_gettime(&t);
+  printf("The current time is: %2d:%02d:%02d.%02d\n",
+               t.hour, t.minute, t.second, t.hsecond);
+
+        _dos_settime(&orig_t);
+  printf("The current time is: %2d:%02d:%02d.%02d\n",
+               orig_t.hour, orig_t.minute, orig_t.second, orig_t.hsecond);
+
+  return 1;
+}
+#endif
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/timefunc.h com075/timefunc.h
--- com074d/timefunc.h	Wed Dec 31 18:00:00 1969
+++ com075/timefunc.h	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,44 @@
+/*
+
+TimeFunc -- DOS Time Functions
+Copyright (C) 1998 Rob Lake
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+Rob Lake can be contacted at
+email: rlake@cs.mun.ca
+
+*/
+
+#if !defined(__TIMEFUNC_H)
+#define __TIMEFUNC_H
+
+#ifdef _NO__DOS_TIME
+
+/* The time structure, compatible with dostime_t */
+struct dostime_t {
+  unsigned char hour;         /* Hours */
+  unsigned char minute;       /* Minutes */
+  unsigned char second;       /* Seconds */
+  unsigned char hsecond;      /* Hundredths of seconds */
+};
+
+unsigned _dos_settime(struct dostime_t *);
+void _dos_gettime(struct dostime_t *);
+
+#endif
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/todo.txt com075/todo.txt
--- com074d/todo.txt	Thu Jul 16 10:57:22 1998
+++ com075/todo.txt	Fri Aug  7 08:44:26 1998
@@ -4,28 +4,22 @@
 
 Support the DOS=HIGH directive in CONFIG.SYS
 
-Optimize the code!  For size and speed.  There are numerous places where the
-code is hardly optimal for either.
+Optimize the code!  For size and speed.  There are numerous places
+where the code is hardly optimal for either.
 
 Swap out when exec'ing? YES! Unless running from a floppy?
 
 ^S and ^Q to pause/resume displays.
 
-ECHO, COPY, BREAK commands on command-line.
+COPY, BREAK commands on command-line.
 
 Fix environment handling, probably using Steffan Kaiser's library.
 
-Find and fix NULL pointer assignment (shows up when compiling in
-small model).
-
 Add wildcard support to REN.
 
-Allow customization at compile time to take out history, aliasing,
-etc.
-
-Support '>>' redirection.  Currently this overwrites files instead of
-adding to them.
+Make every command respond to "/?".
 
-Add INT23 Handler.
+Move all text to another file or end of COM file, and only load it
+into memory when it is necessary.  This would help to support
+multiple languages.
 
-Find out why command crashes when trying to exit.
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/truename.c com075/truename.c
--- com074d/truename.c	Wed Dec 31 18:00:00 1969
+++ com075/truename.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,85 @@
+/*
+ * TRUENAME.C -- Truename Command (undocumented DOS?)
+ *
+ * 07/14/98 (Rob Lake)
+ *  - started and tested fine
+ *  - added stand alone debugging
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - changed _truename function so it does not return a pointer to a local
+ *   variable.
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TRUENAME
+
+#include <stdio.h>
+#include <string.h>
+#include <dos.h>
+
+#include "command.h"
+
+static char *_truename(char *fn)
+{
+  char fn1[128];
+  struct REGPACK rp;
+
+  strcpy(fn1,fn);
+  rp.r_ds = FP_SEG(fn1);
+  rp.r_si = FP_OFF(fn1);
+  rp.r_es = FP_SEG(fn);
+  rp.r_di = FP_OFF(fn);
+  rp.r_ax = 0x60 << 8;          // AH = 0x60
+
+  intr(0x21, &rp);
+
+  if (rp.r_flags & 1)
+  {
+    *fn = '\0';
+  }
+  return fn;
+}
+
+#pragma argsused
+int cmd_truename(char *first, char *rest)
+{
+  char p[128];
+
+  if (*rest)
+  {
+    strcpy(p,rest);
+    _truename(p);
+  }
+  else
+  {
+    strcpy(p,".");
+    _truename(p);
+  }
+
+  if (*p == '\0')
+  {
+    error_path_not_found();
+    fprintf(stderr, "\n\r");
+    return 0;
+  }
+
+  printf("\n%s\n", p);
+
+  return 1;
+}
+
+#ifdef DEBUG_STANDALONE
+int main(int argc, char **argv)
+{
+  cmd_truename("", argv[1]);
+
+  return 0;
+}
+#endif
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/type.c com075/type.c
--- com074d/type.c	Thu Jul 16 10:57:22 1998
+++ com075/type.c	Fri Aug  7 08:44:26 1998
@@ -9,15 +9,22 @@
  * 07/12/98 (Rob Lake)
  *    - Changed error messages
  *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
  */
 
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TYPE
+
 #include <stdio.h>
 #include <string.h>
 
 #include "command.h"
 
-int
-cmd_type(char *first, char *rest)
+#pragma argsused
+int cmd_type(char *first, char *rest)
 {
   char buf[128];
   FILE *f;
@@ -33,22 +40,19 @@
 
   if (!*rest)
   {
-    //printf("Required parameter missing.\n");
-    req_param_missing();
+    error_req_param_missing();
     return 1;
   }
 
   if (strchr(rest, ' '))
   {
-    //printf("Too many parameters.\n");
-    too_many_parameters("\b \b");
+    error_too_many_parameters("\b \b");
     return 1;
   }
 
   if ((f = fopen(rest, "r")) == NULL)
   {
-    //printf("File not found - %s\n",rest);
-    sfile_not_found(rest);
+    error_sfile_not_found(rest);
     return 1;
   }
 
@@ -60,3 +64,5 @@
 
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/ver.c com075/ver.c
--- com074d/ver.c	Thu Jul 16 10:57:22 1998
+++ com075/ver.c	Fri Aug  7 08:44:26 1998
@@ -1,42 +1,66 @@
 /*
  * VER.C
+ *
+ *  06/30/98 (Rob Lake)
+ *      rewrote ver command to accept switches, now ver alone prints
+ *      copyright notice only.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added text about where to send bug reports and get updates.
+ *
+ *
  */
 
-#include "command.h"
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
+#include "command.h"
+
+#define VER_HELP     "display shell version info   VER [/C/R/W/?]"
+
+
+void short_version(void)
+{
+  printf("\n" SHELLINFO " " SHELLVER "\n");
+}
+
+
+#ifdef INCLUDE_CMD_VER
+
 /*
  *  display shell version info internal command.
  *
  *
  */
 #pragma argsused
-int
-ver(char *first, char *rest)
+int cmd_ver(char *first, char *rest)
 {
   int i;
 
   /* JPP 07/08/1998 clean up and shortened info. */
 
-  printf("\n" SHELLINFO " " SHELLVER ", (C) 1994-1998 Tim Norman\n");
+  puts("\n" SHELLINFO " " SHELLVER "\nCopyright (C) 1994-1998 Tim Norman and others.");
   /* Basic copyright notice */
   if (rest[0] == 0)
   {
-    printf("\n"
-           "%s comes with ABSOLUTELY NO WARRANTY; for details\n"
+    puts("\n"SHELLINFO
+           " comes with ABSOLUTELY NO WARRANTY; for details\n"
            "type: `ver /w'. This is free software, and you are welcome to redistribute\n"
            "it under certain conditions; type `ver /r' for details. Type `ver /c' for a\n"
-           "listing of credits.\n"
-           "\n", SHELLINFO);
-    return 0;
+           "listing of credits.");
   }
-
+  else
+  {
   /* MS-DOS ver prints just help if /? is alone or not */
   if (strstr(rest, "/?") != NULL)
   {
-    printf("%s: %s\n", USAGE, VER_HELP);
+      puts(USAGE ": " VER_HELP);
     return 0;
   }
 
@@ -50,8 +74,7 @@
       /* is this a lone '/' ? */
       if (rest[i + 1] == 0)
       {
-        //fprintf(stderr, INVALID_SWITCH, ' ');
-        invalid_switch(' ');
+          error_invalid_switch(' ');
         return 1;
       }
       continue;
@@ -80,14 +103,20 @@
            "    Evan Jeffrey    Steffen Kaiser\n"
            "    Svante Frey     Oliver Mueller\n"
            "    Aaron Kaufman   Marc Desrochers\n"
-           "    Rob Lake        John P. Price");
+             "    Rob Lake        John P Price\n"
+             "    Hans B Pufal");
     }
     else
     {
-      //fprintf(stderr, INVALID_SWITCH, toupper(rest[i]));
-      invalid_switch(toupper(rest[i]));
+        error_invalid_switch(toupper(rest[i]));
       return 1;
     }
+
   }
+  }
+  puts("\nSend bug reports to command@gcfl.net.\n"
+     "Updates are available from http://www.gcfl.net/FreeDOS/command.com.");
   return 0;
 }
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/verify.c com075/verify.c
--- com074d/verify.c	Wed Dec 31 18:00:00 1969
+++ com075/verify.c	Fri Aug  7 08:44:26 1998
@@ -0,0 +1,52 @@
+/*
+ *  VERIFY.C - verify command.
+ *
+ *  Comments:
+ *
+ * 31 Jul 1998 (John P Price)
+ *   started.
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VERIFY
+
+#include <stdio.h>
+#include <string.h>
+#include <dos.h>
+
+#include "command.h"
+
+#pragma argsused
+int cmd_verify(char *cmd, char *param)
+{
+  dprintf(("CMD '%s' : '%s'\n", cmd, param));
+
+  if (strcmp(param, "/?") == 0)
+  {
+    puts(
+"Sets whether to verify that your files are written correctly to a\n"
+"disk.\n"
+"\n"
+"VERIFY [ON | OFF]\n"
+"\n"
+"Type VERIFY without a parameter to display the current VERIFY setting."
+    );
+    return 0;
+  }
+
+  if (!*param)
+    printf("VERIFY is %s\n", getverify() ? D_ON : D_OFF);
+  else if (stricmp(param, D_OFF) == 0)
+    setverify(0);
+  else if (stricmp(param, D_ON) == 0)
+    setverify(1);
+  else
+    puts("Must specify ON or OFF.");
+
+  return 0;
+}
+
+#endif
diff --new-file --recursive --ignore-space-change --unified --report-identical-files com074d/where.c com075/where.c
--- com074d/where.c	Thu Jul 16 10:57:22 1998
+++ com075/where.c	Fri Aug  7 08:44:26 1998
@@ -5,181 +5,153 @@
  *
  *  Comments:
  *
- *  07/15/95 (Tim Norman) ---------------------------------------------------
+ *  07/15/95 (Tim Norman)
  *    started.
  *
- *  08/08/95 (Matt Rains) ---------------------------------------------------
+ *  08/08/95 (Matt Rains)
  *    i have cleaned up the source code. changes now bring this source into
  *    guidelines for recommended programming practice.
  *
- *  12/12/95 (Steffan Kaiser & Tim Norman) ----------------------------------
+ *  12/12/95 (Steffan Kaiser & Tim Norman)
  *    added some patches to fix some things and make more efficient
  *
- *  1/6/96 (Tim Norman) -----------------------------------------------------
+ *  1/6/96 (Tim Norman)
  *    fixed a stupid pointer mistake...  Thanks to everyone who noticed it!
  *
- *  8/1/96 (Tim Norman) -----------------------------------------------------
+ *  8/1/96 (Tim Norman)
  *    fixed a bug when getenv returns NULL
  *
- *  8/7/96 (Steffan Kaiser and Tim Norman) ----------------------------------
+ *  8/7/96 (Steffan Kaiser and Tim Norman)
  *    speed improvements and bug fixes
  *
- *  8/27/96 (Tim Norman) ----------------------------------------------------
+ *  8/27/96 (Tim Norman)
  *    changed code to use pointers directly into PATH environment variable
  *    rather than making our own copy.  This saves some memory, but requires
  *    we write our own function to copy pathnames out of the variable.
  *
- *  12/23/96 (Aaron Kaufman) ------------------------------------------------
+ *  12/23/96 (Aaron Kaufman)
  *    Fixed a bug in get_paths() that did not point to the first PATH in the
  *    environment variable.
  *
- *  7/12/97 (Tim Norman) ----------------------------------------------------
+ *  7/12/97 (Tim Norman)
  *    Apparently, Aaron's bugfix got lost, so I fixed it again.
  *
+ *  16 July 1998 (John P. Price)
+ *    Added stand alone code.
+ *
+ *  17 July 1998 (John P. Price)
+ *    Rewrote find_which to use searchpath function
+ *
+ * 24-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed bug where didn't check all extensions when path was specified
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed so that it find_which returns NULL if filename is not executable
+ *   (does not have .bat, .com, or .exe extention). Before command would
+ *   to execute any file with any extension (opps!)
+ *
  */
 
+#include "config.h"
+
+#include <stdio.h>
 #include <dos.h>
 #include <dir.h>
 #include <stdlib.h>
 #include <string.h>
 
-/*
- * 
- *  copy a string, stopping at ';' or '\0'
- * 
- *  Return value:  position in dest where NUL is placed
- * 
- */
-char *
-pathcpy(char *dest, char *src)
-{
-  char *ret,
-   *tmp = dest;
+#include "command.h"
 
-  /* copy data */
-  while (*src != ';' && *src != 0)
-    *dest++ = *src++;
-
-  /* strip final backslash if there is one */
-  ret = dest > tmp && dest[-1] == '\\' ? dest - 1 : dest;
-  *ret = 0;
-  return ret;
-}
+//#define DEBUG_STANDALONE
 
 /*
- *
- *  get paths from environment variable and assigns an array of pointers
- *  to point to each individual path entry
+ *  searches for file using path info.
  *
  */
-void
-get_paths(char *paths[129])
+char *find_which(const char *fname)
 {
-  char *p;                      /* pointer to path */
-  int count,
-    pos;                        /* counters */
+  char *fullname;
+  static char temp[MAXPATH];
+  int x;
+  static char *ext[3] =
+  {".COM", ".EXE", ".BAT"};
 
-  p = getenv("PATH");
-  if (!p)
+  /* if there an extension and it is in the last path component, then
+   * don't test all the extensions. */
+  if (!(fullname = strrchr(fname, '.')) || strchr(fullname + 1, '\\'))
   {
-    paths[0] = ".";
-    paths[1] = NULL;
-    return;
-  }
-
-  /* set up paths array */
-  paths[0] = ".";
-  paths[1] = p;
-  pos = 0;
-  count = 2;
-
-  /* set the pointers in paths */
-  while (p[pos] != 0)
+    for (x = 0; x < 3; x++)
   {
-    if (p[pos] == ';')
+      strcpy(temp, fname);
+      strcat(temp, ext[x]);
+      dprintf(("Checking for %s\n", temp));
+      if (strchr(fname,'\\'))
     {
-      if (p[pos + 1] != 0)
+        if (exist(temp))
       {
-        paths[count] = &p[pos + 1];
-        count++;
+          return temp;
       }
     }
-    pos++;
-  }
-
-  paths[count] = NULL;          /* last path points to NULL */
-
-  /* paths is now an array of pointers to all the search paths */
-  /* we need to use pathcpy to copy stuff out of it */
-
-  return;
-}
-
-/*
- *
- *  searches for file using path info.
- *
- */
-int
-find_which(char *paths[129], char *fname, char *fullname)
-{
-  struct ffblk f;               /* directory search structure */
-
-  int count;
-  int tryall;                   /* whether to try all extensions */
-  int extcount;
-  char *extp;
-  static char ext[3][5] =
-  {".COM", ".EXE", ".BAT"};
-
-  count = 0;
-
-  /* is there an extension and is it in the last path component? */
-  tryall = !(extp = strrchr(fname, '.')) || strchr(extp + 1, '\\');
-
-  /* if a path is already specified, then just try tacking on .com, .exe */
-  if (strchr(fname, '\\') || fname[1] == ':')
+      else
   {
-    if (tryall == 0)
+        if ((fullname = searchpath(temp)) != NULL)
     {
-      strcpy(fullname, fname);
-      return 1;
+          return fullname;
     }
-
-    extp = stpcpy(fullname, fname);
-
-    for (extcount = 0; extcount < 3; extcount++)
-    {
-      strcpy(extp, ext[extcount]);
-
-      if (findfirst(fullname, &f, 7) == 0)
-        return 1;
     }
   }
-  else
-    while (paths[count])        /* cycle through paths */
+  }
+  else  /* there is an extension... don't test other extensions */
     {
-      /* create base filename */
-      extp = stpcpy(stpcpy(pathcpy(fullname, paths[count]), "\\"), fname);
-
-      if (tryall)
+    /* make sure that the extention is one of the three */
+    for (x = 0; x < 3; x++)
       {
-        /* try all extensions */
-        for (extcount = 0; extcount < 3; extcount++)
+      if (stricmp(strrchr(fname, '.'), ext[x]) == 0)
         {
-          strcpy(extp, ext[extcount]);
-
-          if (findfirst(fullname, &f, 7) == 0)
-            return 1;
+        if (strchr(fname,'\\'))
+        {
+          if (exist(fname))
+          {
+            strcpy(temp,fname);
+            return temp;
         }
       }
       else
       {
-        if (findfirst(fullname, &f, 7) == 0)
-          return 1;
+          dprintf(("Checking for %s\n", fname));
+          if ((fullname = searchpath(fname)) != NULL)
+            return fullname;
       }
-      count++;
     }
+    }
+  }
+
+  return NULL;
+}
+
+#ifdef DEBUG_STANDALONE
+int main(int argc, char **argv)
+{
+  char *fullname;
+
+  if ((fullname = find_which("deltree.exe")) != NULL)
+  {
+    printf("deltree.exe found at %s\n", fullname);
+  }
+  else
+    printf("deltree.exe not found.\n");
+
+  if ((fullname = find_which("deltree")) != NULL)
+  {
+    printf("deltree found at %s\n", fullname);
+  }
+  else
+    printf("deltree not found.\n");
 
   return 0;
 }
+
+#endif
