Files com074c/28.com and com074d/28.com are identical
Files com074c/alias.c and com074d/alias.c are identical
Files com074c/alias.h and com074d/alias.h are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/batch.c com074d/batch.c
--- com074c/batch.c	Thu Jul 16 11:29:11 1998
+++ com074d/batch.c	Thu Jul 16 11:29:11 1998
@@ -55,7 +55,7 @@
 #define D_SHIFT      "shift"
 
 /* function decls */
-void split(char *, char **);
+int split(char *, char **);
 char *parse_firstarg(char *);
 void printprompt(void);
 
Files com074c/bugs.txt and com074d/bugs.txt are identical
Files com074c/clean.bat and com074d/clean.bat are identical
Files com074c/cmdinput.c and com074d/cmdinput.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/command.c com074d/command.c
--- com074c/command.c	Thu Jul 16 11:29:11 1998
+++ com074d/command.c	Thu Jul 16 11:29:11 1998
@@ -224,8 +224,8 @@
     }
   }
 /*
- *else if ((r = exec(fullname, rest, EnvSeg)) != 0)
- *{
+ * else if ((r = exec(fullname, rest, EnvSeg)) != 0)
+ * {
  *  switch (r)
  *  {
  *    case 1:
Binary files com074c/command.com and com074d/command.com differ
Binary files com074c/command.dsk and com074d/command.dsk differ
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/command.h com074d/command.h
--- com074c/command.h	Thu Jul 16 11:29:11 1998
+++ com074d/command.h	Thu Jul 16 11:29:12 1998
@@ -41,6 +41,26 @@
 #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
+{
+  FALSE, TRUE
+};
+
 /* prototypes for COMMAND.C */
 extern int ctrlBreak;
 extern int exitflag;
@@ -75,9 +95,6 @@
 int cmd_time(char *, char *);   /*JPP 07/08/1998 */
 int cmd_type(char *, char *);   /*JPP 07/08/1998 */
 
-int chkCBreak(int);
-int cgetchar(void);
-
 /* prototypes for ENVIRON.C */
 void show_environment(void);
 
@@ -120,6 +137,10 @@
 
 /* Prototypes for MISC.C */
 int exist(char *);
+int chkCBreak(int);
+int cgetchar(void);
+int split(char *, char **);
+char *parse_firstarg(char *);
 
 /* Prototypes for ERROR.C */
 void no_pipe(void);
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/command.mak com074d/command.mak
--- com074c/command.mak	Thu Jul 16 10:25:16 1998
+++ com074d/command.mak	Thu Jul 16 10:25:20 1998
@@ -25,22 +25,27 @@
  cmdinput.obj \
  command.obj \
  dir.obj \
+ environ.obj \
+ exec.obj \
  history.obj \
  internal.obj \
  loadhigh.obj \
  prompt.obj \
  redir.obj \
  where.obj \
+ lowexec.obj \
  lh.obj \
  tempfile.obj \
  date.obj \
- time.obj \
- exec.obj \
- lowexec.obj \
+ err_hand.obj \
  type.obj \
+ time.obj \
+ misc.obj \
  error.obj \
- err_hand.obj \
- misc.obj
+ del.obj \
+ ren.obj \
+ set.obj \
+ ver.obj
 
 #		*Explicit Rules*
 command.exe: command.cfg $(EXE_dependencies)
@@ -51,22 +56,27 @@
 cmdinput.obj+
 command.obj+
 dir.obj+
+environ.obj+
+exec.obj+
 history.obj+
 internal.obj+
 loadhigh.obj+
 prompt.obj+
 redir.obj+
 where.obj+
+lowexec.obj+
 lh.obj+
 tempfile.obj+
 date.obj+
-time.obj+
-exec.obj+
-lowexec.obj+
+err_hand.obj+
 type.obj+
+time.obj+
+misc.obj+
 error.obj+
-err_hand.obj+
-misc.obj
+del.obj+
+ren.obj+
+set.obj+
+ver.obj
 command
 		# no map file
 cs.lib
@@ -84,6 +94,10 @@
 
 dir.obj: command.cfg dir.c 
 
+environ.obj: command.cfg environ.c 
+
+exec.obj: command.cfg exec.c 
+
 history.obj: command.cfg history.c 
 
 internal.obj: command.cfg internal.c 
@@ -96,6 +110,9 @@
 
 where.obj: command.cfg where.c 
 
+lowexec.obj: command.cfg lowexec.asm 
+	$(TASM) /MX /ZI /O LOWEXEC.ASM,LOWEXEC.OBJ
+
 lh.obj: command.cfg lh.asm 
 	$(TASM) /MX /ZI /O LH.ASM,LH.OBJ
 
@@ -103,20 +120,23 @@
 
 date.obj: command.cfg date.c 
 
-time.obj: command.cfg time.c 
+err_hand.obj: command.cfg err_hand.c 
 
-exec.obj: command.cfg exec.c 
+type.obj: command.cfg type.c 
 
-lowexec.obj: command.cfg lowexec.asm 
-	$(TASM) /MX /ZI /O LOWEXEC.ASM,LOWEXEC.OBJ
+time.obj: command.cfg time.c 
 
-type.obj: command.cfg type.c 
+misc.obj: command.cfg misc.c 
 
 error.obj: command.cfg error.c 
 
-err_hand.obj: command.cfg err_hand.c 
+del.obj: command.cfg del.c 
 
-misc.obj: command.cfg misc.c 
+ren.obj: command.cfg ren.c 
+
+set.obj: command.cfg set.c 
+
+ver.obj: command.cfg ver.c 
 
 #		*Compiler Configuration File*
 command.cfg: command.mak
Binary files com074c/command.prj and com074d/command.prj differ
Files com074c/date.c and com074d/date.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/del.c com074d/del.c
--- com074c/del.c	Wed Dec 31 18:00:00 1969
+++ com074d/del.c	Thu Jul 16 11:29:11 1998
@@ -0,0 +1,249 @@
+
+/*
+ * DEL.C
+ */
+
+#include "command.h"
+#include <dir.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <io.h>
+#include <direct.h>
+#include <conio.h>
+#include <ctype.h>
+#include <dos.h>
+
+/*
+ *
+ *  simple file delete internal command.
+ *  Rewritten by Rob Lake (06/29/98)
+ *
+ */
+
+#pragma argsused
+int
+del(char *first, char *rest)
+{
+  int done,
+    flags,
+    orig_disk,
+    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;
+
+  drive[0] = '\0';
+  dir[0] = '\0';
+
+  args = split(rest, arg);
+  inter = 0;
+  filespec = 0;
+
+  if (args > 2)
+  {
+    //fprintf(stderr, TOO_MANY_PARAMETERS, arg[args - 1]);
+    too_many_parameters(arg[args - 1]);
+    return 1;
+  }
+  else if (args >= 1)
+  {
+    /* check for /? anywhere in command line */
+    if (stricmp(arg[2], "/?") == 0 ||
+        stricmp(arg[1], "/?") == 0 ||
+        stricmp(arg[0], "/?") == 0)
+    {
+      printf("%s: %s\n", USAGE, DEL_HELP);
+      return 0;
+    }
+    if (stricmp(arg[1], "/p") == 0)
+    {
+      inter = 1;
+      filespec = 0;
+    }
+    else if (stricmp(arg[0], "/p") == 0)
+    {
+      filespec = 1;
+      inter = 1;
+    }
+    /* only one argument and that's /P */
+    if (args == 1 && inter)
+    {
+      //fprintf(stderr, REQ_PARAM_MISSING);
+      req_param_missing();
+      return 1;
+    }
+    /* check whether the file actually exists */
+    if (access(arg[filespec], 4) != 0 &&
+        strchr(arg[filespec], '*') == NULL)
+    {
+      //fprintf(stderr, FILE_NOT_FOUND);
+      file_not_found();
+      return 1;
+    }
+    stat(arg[filespec], &stbuf);
+    /* check if it is a directory */
+    if ((stbuf.st_mode & S_IFMT) == S_IFDIR
+        && strchr(arg[filespec], '*') == NULL)
+      strcat(arg[filespec], "\\");
+
+    flags = fnsplit(arg[filespec], drive, dir, file, ext);
+    /* build the filename, wildcards allowed */
+    if (flags & FILENAME && flags && EXTENSION)
+      sprintf(fn, "%s%s", file, ext);
+    else if (flags & FILENAME && (flags && EXTENSION) == 0)
+      sprintf(fn, "%s", file);
+    else
+      sprintf(fn, "*.*");
+
+    /* uppercase the strings, for prettier output */
+    strupr(drive);
+    strupr(dir);
+    strupr(file);
+    strupr(ext);
+
+    if (flags & DRIVE)
+    {
+      orig_disk = getdisk();
+      _chdrive(drive[0] - 'A' + 1);
+    }
+
+    if (flags & DIRECTORY)
+    {
+      if (strlen(dir) > 1)
+        dir[strlen(dir) - 1] = '\0';
+      getcwd(orig_dir, MAXPATH);
+      if (chdir(dir))
+      {
+        //fprintf(stderr, PATH_NOT_FOUND);
+        path_not_found();
+        return 1;
+      }
+      if (dir[0] != '\0' && strlen(dir) > 1)
+        strcat(dir, "\\");
+    }
+  }
+  else
+  {
+    /* only command given */
+    //fprintf(stderr, REQ_PARAM_MISSING);
+    req_param_missing();
+    return 1;
+  }
+
+  /* needed? */
+  if (inter && args == 1)
+  {
+    //fprintf(stderr, REQ_PARAM_MISSING);
+    req_param_missing();
+    return 1;
+  }
+
+  /* make sure user is sure if all files are to be
+   * deleted */
+  if (strcmp(fn, "*.*") == 0 && !inter)
+  {
+    int yes;
+    char c;
+    c = 0;
+    yes = 0;
+    puts("All files in directory will be deleted!\n");
+    puts("Are you sure (Y/N)?");
+    while (c != 13)
+    {
+      c = getch();
+      while (toupper(c) != 'N' && toupper(c) != 'Y')
+        c = getch();
+      putchar(toupper(c));
+      if (toupper(c) == 'Y')
+        yes = 1;
+      else
+        yes = 0;
+      c = getch();
+      if (c == 8)
+        printf("\b \b");
+    }
+    printf("\n");
+    if (yes == 0)
+    {
+      chdir(orig_dir);
+      return 1;
+    }
+  }
+
+  done = findfirst(fn, &f, FA_ARCH);
+  if (done)
+  {
+    chdir(orig_dir);
+    //fprintf(stderr, FILE_NOT_FOUND);
+    file_not_found();
+    return 0;
+  }
+
+  while (!done)
+  {
+    int okay = 1;
+    if (inter)
+    {
+      char c;
+      okay = -1;
+      printf(drive);
+      printf(dir);
+      printf(f.ff_name);
+      while (okay == -1)
+      {
+        printf(", Delete(Y/N)?");
+        c = toupper(getche());
+        if (c == 'Y')
+          okay = 1;
+        else if (c == 'N')
+          okay = 0;
+        else if (c == 3)
+        {                       /* ^C pressed */
+          if (flags & DRIVE)
+            _chdrive(orig_disk + 1);
+          chdir(orig_dir);
+          printf("\n");
+          return 1;
+        }
+        else
+        {
+          printf(drive);
+          printf(dir);
+          printf(f.ff_name);
+        }
+      }
+      printf("\n");
+    }
+    if (okay)
+    {
+#ifdef NODEL
+/* define NODEL if you want to debug */
+      printf(drive);
+      printf(dir);
+      printf(f.ff_name);
+      printf("\n");
+#else
+      if (unlink(f.ff_name) != 0)
+      {
+        perror("del()");
+        return 1;
+      }
+#endif
+    }
+    done = findnext(&f);
+  }
+
+  if (flags & DRIVE)
+    _chdrive(orig_disk + 1);
+  chdir(orig_dir);
+  return 0;
+}
Files com074c/dir-test.txt and com074d/dir-test.txt are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/dir.c com074d/dir.c
--- com074c/dir.c	Thu Jul 16 11:29:11 1998
+++ com074d/dir.c	Thu Jul 16 11:29:11 1998
@@ -1,4 +1,3 @@
-
 /*
  *  DIR.C - dir internal command
  *
Files com074c/environ.c and com074d/environ.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/err_hand.c com074d/err_hand.c
--- com074c/err_hand.c	Thu Jul 16 11:29:11 1998
+++ com074d/err_hand.c	Thu Jul 16 11:29:11 1998
@@ -6,10 +6,16 @@
  * 07/03/98 (Rob Lake) ------------------------------------------------------
  *      Started
  *
+ * 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.
+ *
  */
 
 #include "err_hand.h"
 
+static unsigned calls = 0;
+
 /* Code courtesy of Pasquale J. Villani */
 void
 init_error_handler(void)
@@ -21,7 +27,7 @@
     mov ax, offset dos_critical_error
     mov es:[si], ax
     mov ax, cs
-    mov es:[si + 2], ax
+    mov es:[si + 2],ax
   }
 }
 
@@ -110,6 +116,14 @@
     buf[BUFSIZE],
     action;
 
+  if (++calls == 5)
+  {
+    calls = 0;
+    printstring("Fail on INT24\n\r$");
+    reg_Ax = (0xFF00 | FAIL);
+    return;
+  }
+
   asm {
     push cs
     pop ds
@@ -172,14 +186,21 @@
   {
     case 'A':
       reg_Ax |= ABORT;
+      calls = 0;
       return;
     case 'R':
       if ((err_flags & RETRY_FLG) == 0)
       {
         if ((err_flags & FAIL_FLG) == 0)
+        {
           reg_Ax |= ABORT;
+          calls = 0;
+        }
         else
+        {
           reg_Ax |= FAIL;
+          calls = 0;
+        }
       }
       else
         reg_Ax = RETRY;
@@ -189,14 +210,21 @@
         reg_Ax |= ABORT;
       else
         reg_Ax |= FAIL;
+      calls = 0;
       return;
     case 'I':
       if ((err_flags & IGNORE_FLG) == 0)
       {
         if ((err_flags & FAIL_FLG) == 0)
+        {
           reg_Ax |= ABORT;
+          calls = 0;
+        }
         else
+        {
           reg_Ax |= FAIL;
+          calls = 0;
+        }
       }
       else
         reg_Ax |= IGNORE;
Files com074c/err_hand.h and com074d/err_hand.h are identical
Files com074c/error.c and com074d/error.c are identical
Files com074c/exe2bin.com and com074d/exe2bin.com are identical
Files com074c/exec.c and com074d/exec.c are identical
Files com074c/files.txt and com074d/files.txt are identical
Files com074c/history.c and com074d/history.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/history.txt com074d/history.txt
--- com074c/history.txt	Thu Jul 16 11:29:11 1998
+++ com074d/history.txt	Thu Jul 16 11:29:12 1998
@@ -195,3 +195,13 @@
 o created MISC.C
 o created ERR_HAND.C/H
 o created ERROR.C
+
+07/13/98 version 0.74d (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+INTERNAL.C
+o removed most of the commands and placed them in there own file
+  -- del, ren, set and ver
+o created DEL.C, REN.C SET.C and VER.C
+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
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/internal.c com074d/internal.c
--- com074c/internal.c	Thu Jul 16 11:29:11 1998
+++ com074d/internal.c	Thu Jul 16 11:29:12 1998
@@ -110,6 +110,10 @@
  *  - 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
+ *
  */
 
 #include <stdlib.h>
@@ -124,200 +128,7 @@
 #include <sys/stat.h>
 #include "command.h"
 
-#define SHELLINFO    "FreeDOS Command Line Interface"
-#define SHELLVER     "version 0.74c"
-#define BADCMDLINE   "bad or incorrect command line"
-#define USAGE        "usage"
-#define CD           "change to directory   CD [d:][path]"
-#define MD           "make directory   MD [d:]path"
-#define RD           "remove directory   RD [d:]path"
-#define DIR          "display directory listing   DIR [d:][path][filespec]"
-#define VER          "display shell version info   VER [/C/R/W/?]"
-#define DEL          "delete file   DEL [d:][path]filespec"
-#define REN          "rename file   REN [d:][path]filespec1 [d:][path]filespec2"
-#define SET          "SET"
-#define PROMPTEQUAL  "PROMPT="
-#define PATHEQUAL    "PATH="
-
-enum
-{
-  FALSE, TRUE
-};
-
-/*
- * get a character out-of-band and honor Ctrl-Break characters
- */
-int
-cgetchar(void)
-{
-  int c;
-
-  if ((c = getch()) == 0)
-    c = getch() << 8;
-
-  if (c == 3)
-    ctrlBreak = 1;
-
-  return c;
-}
-
-/*
- * Check if Ctrl-Break was pressed during the last calls
- */
-int
-chkCBreak(int mode)
-{
-  static int leaveAll = 0;      /* leave all batch files */
-  int c;
-
-  switch (mode)
-  {
-    case BREAK_OUTOFBATCH:
-      leaveAll = 0;
-      return 0;
-    case BREAK_BATCHFILE:
-      if (leaveAll)
-        return 1;
-      if (!ctrlBreak)
-        return 0;
-
-      /* we need to be sure the string arrives on the screen! */
-      do
-        cputs("\r\nCtrl-Break pressed.  Cancel batch file? (Yes/No/All) ");
-      while (!strchr("YNA\3", c = toupper(cgetchar())) || !c);
-
-      cputs("\r\n");
-
-      if (c == 'N')
-        return ctrlBreak = 0;   /* ignore */
-
-      leaveAll = c == 'A' || c == '\3'; /* leave all batch files */
-
-      break;
-    case BREAK_INPUT:
-      if (!ctrlBreak)
-        return 0;
-      break;
-  }
-
-  ctrlBreak = 0;                /* state processed */
-  return 1;
-}
-
-/*
- * function to destructively split a string into an array of strings
- *
- * Changed return value to int to determine number of args
- *   -- Rob Lake (06/29/98)
- *
- */
-int
-split(char *s, char **p)
-{
-  int sc = 0,
-    pc = 0;                     /* string and parameter counters */
-
-  while (s[sc])
-  {
-    if (sc && isspace(s[sc]) && !isspace(s[sc - 1]))
-      s[sc] = 0;
-
-    else if (!isspace(s[sc]) && (sc == 0 || isspace(s[sc - 1]) ||
-                                 s[sc - 1] == 0))
-      p[pc++] = &s[sc];
-
-    sc++;
-  }
-
-  p[pc] = NULL;
-  return pc;
-}
-
-/*
- * set environment variables
- *
- *
- */
-#pragma argsused
-int
-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)
-  {
-    /* JPP 07/08/1998 removed call to show_environment */
-    for (count = 0; environ[count]; count++)
-    {
-      puts(environ[count]);
-    }
-    return 0;
-  }
-
-  /* make sure there is an = in the command */
-  /* 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");
-    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)
-  {
-    puts("Environment error");
-  }
-
-  return 0;
-}
-
-/*
- * internal function to get the first argument from the parameter list
- * and return a pointer to the beginning of the next argument, or NULL if
- * there are no more arguments
- *
- */
-char *
-parse_firstarg(char *s)
-{
-  char *place;
-
-  /* skip over first argument */
-  place = s;
-  while (*place && !isspace(*place))
-    place++;
-
-  if (*place)
-  {
-    /* mark the end of the first parameter */
-    *place++ = 0;
-
-    /* skip over whitespace before next argument */
-    while (isspace(*place))
-      place++;
-
-    /* if there is something here, return a pointer to it, else NULL */
-    if (*place)
-      return place;
-    else
-      return NULL;
-  }
-  else
-    return NULL;
-}
+#define SET "set"
 
 /*
  *  generic function to handle cd, md, and rd (and their verbose names)
@@ -404,7 +215,7 @@
 int
 cd(char *first, char *rest)
 {
-  return directory_handler(first, rest, chdir, "cd()", CD);
+  return directory_handler(first, rest, chdir, "cd()", CD_HELP);
 }
 
 /*
@@ -415,7 +226,7 @@
 int
 md(char *first, char *rest)
 {
-  return directory_handler(first, rest, mkdir, "md()", MD);
+  return directory_handler(first, rest, mkdir, "md()", MD_HELP);
 }
 
 /*
@@ -426,358 +237,7 @@
 int
 rd(char *first, char *rest)
 {
-  return directory_handler(first, rest, rmdir, "rd()", RD);
-}
-
-/*
- *  display shell version info internal command.
- *
- *
- */
-#pragma argsused
-int
-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");
-  /* Basic copyright notice */
-  if (rest[0] == 0)
-  {
-    printf("\n"
-           "%s 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;
-  }
-
-  /* MS-DOS ver prints just help if /? is alone or not */
-  if (strstr(rest, "/?") != NULL)
-  {
-    printf("%s: %s\n", USAGE, VER);
-    return 0;
-  }
-
-  for (i = 0; rest[i]; i++)
-  {
-    /* skip spaces */
-    if (rest[i] == ' ')
-      continue;
-    if (rest[i] == '/')
-    {
-      /* is this a lone '/' ? */
-      if (rest[i + 1] == 0)
-      {
-        //fprintf(stderr, INVALID_SWITCH, ' ');
-        invalid_switch(' ');
-        return 1;
-      }
-      continue;
-    }
-    if (toupper(rest[i]) == 'W')
-    {                           /* Warranty notice */
-      /* JPP 07/08/1998 removed extra printf calls */
-      puts("\n This program is distributed in the hope that it will be useful,\n"
-         " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-           " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
-           " GNU General Public License for more details.");
-    }
-    else if (toupper(rest[i]) == 'R')
-    {                           /* Redistribution notice */
-      /* JPP 07/08/1998 removed extra printf calls */
-      puts("\n This program is free software; you can redistribute it and/or modify\n"
-           " it under the terms of the GNU General Public License as published by\n"
-      " the Free Software Foundation; either version 2 of the License, or\n"
-           " (at your option) any later version.");
-    }
-    else if (toupper(rest[i]) == 'C')
-    {                           /* Developer listing */
-      /* JPP 07/08/1998 removed extra printf calls; rearranged names */
-      puts("\ndeveloped by:\n"
-           "    Tim Norman      Matt Rains\n"
-           "    Evan Jeffrey    Steffen Kaiser\n"
-           "    Svante Frey     Oliver Mueller\n"
-           "    Aaron Kaufman   Marc Desrochers\n"
-           "    Rob Lake        John P. Price");
-    }
-    else
-    {
-      //fprintf(stderr, INVALID_SWITCH, toupper(rest[i]));
-      invalid_switch(toupper(rest[i]));
-      return 1;
-    }
-  }
-  return 0;
-}
-
-/*
- *
- *  simple file delete internal command.
- *  Rewritten by Rob Lake (06/29/98)
- *
- */
-
-#pragma argsused
-int
-del(char *first, char *rest)
-{
-  int done,
-    flags,
-    orig_disk,
-    args,
-    inter,
-    filespec;
-  struct ffblk f;
-  static char drive[MAXDRIVE],
-    dir[MAXDIR],
-    file[MAXFILE],
-    ext[MAXEXT];
-  char fn[MAXFILE + MAXEXT + 1],
-    orig_dir[MAXPATH];
-  char **arg;
-
-  drive[0] = '\0';
-  dir[0] = '\0';
-
-  args = split(rest, arg);
-  inter = 0;
-
-  if (args > 2)
-  {
-    //fprintf(stderr, TOO_MANY_PARAMETERS, arg[args - 1]);
-    too_many_parameters(arg[args - 1]);
-    return 1;
-  }
-  else if (args >= 1)
-  {
-    struct stat stbuf;
-    /* check for /? anywhere in command line */
-    if (stricmp(arg[2], "/?") == 0 ||
-        stricmp(arg[1], "/?") == 0 ||
-        stricmp(arg[0], "/?") == 0)
-    {
-      printf("%s: %s\n", USAGE, DEL);
-      return 0;
-    }
-    /* check for /p as the first or second, MS-DOS
-     * only allows for it as the second arg, so do we :) */
-    if (stricmp(arg[1], "/p") == 0)
-    {
-      inter = 1;
-      filespec = 0;
-    }
-    else if (stricmp(arg[0], "/p") == 0)
-    {
-      filespec = 1;
-      inter = 1;
-    }
-    /* only one argument and that's /P */
-    if (args == 1 && inter)
-    {
-      //fprintf(stderr, REQ_PARAM_MISSING);
-      req_param_missing();
-      return 1;
-    }
-    /* check whether the file actually exists */
-    if (stat(arg[filespec], &stbuf) == -1)
-    {
-      //fprintf(stderr, FILE_NOT_FOUND);
-      file_not_found();
-      return 1;
-    }
-    /* check if it is a directory */
-    if ((stbuf.st_mode & S_IFMT) == S_IFDIR
-        && strchr(arg[filespec], '*') == NULL)
-      strcat(arg[filespec], "\\");
-
-    flags = fnsplit(arg[filespec], drive, dir, file, ext);
-    /* build the filename, wildcards allowed */
-    if (flags & FILENAME && flags && EXTENSION)
-      sprintf(fn, "%s%s", file, ext);
-    else if (flags & FILENAME && (flags && EXTENSION) == 0)
-      sprintf(fn, "%s", file);
-    else
-      sprintf(fn, "*.*");
-
-    /* uppercase the strings, for prettier output */
-    strupr(drive);
-    strupr(dir);
-    strupr(file);
-    strupr(ext);
-
-    if (flags & DRIVE)
-    {
-      orig_disk = getdisk();
-      _chdrive(drive[0] - 'A' + 1);
-    }
-
-    if (flags & DIRECTORY)
-    {
-      if (strlen(dir) > 1)
-        dir[strlen(dir) - 1] = '\0';
-      getcwd(orig_dir, MAXPATH);
-      if (chdir(dir))
-      {
-        //fprintf(stderr, PATH_NOT_FOUND);
-        path_not_found();
-        return 1;
-      }
-      if (dir[0] != '\0' && strlen(dir) > 1)
-        strcat(dir, "\\");
-    }
-  }
-  else
-  {
-    /* only command given */
-    //fprintf(stderr, REQ_PARAM_MISSING);
-    req_param_missing();
-    return 1;
-  }
-
-  /* needed? */
-  if (inter && args == 1)
-  {
-    //fprintf(stderr, REQ_PARAM_MISSING);
-    req_param_missing();
-    return 1;
-  }
-
-  /* make sure user is sure if all files are to be
-   * deleted */
-  if (strcmp(fn, "*.*") == 0 && !inter)
-  {
-    int yes;
-    char c;
-    c = 0;
-    yes = 0;
-    puts("All files in directory will be deleted!\n");
-    puts("Are you sure (Y/N)?");
-    while (c != 13)
-    {
-      c = getch();
-      while (toupper(c) != 'N' && toupper(c) != 'Y')
-        c = getch();
-      putchar(toupper(c));
-      if (toupper(c) == 'Y')
-        yes = 1;
-      else
-        yes = 0;
-      c = getch();
-      if (c == 8)
-        printf("\b \b");
-    }
-    printf("\n");
-    if (yes == 0)
-    {
-      chdir(orig_dir);
-      return 1;
-    }
-  }
-
-  done = findfirst(fn, &f, FA_NORMAL | FA_ARCH);
-  if (done)
-  {
-    chdir(orig_dir);
-    //fprintf(stderr, FILE_NOT_FOUND);
-    file_not_found();
-    return 0;
-  }
-
-  while (!done)
-  {
-    int okay = 1;
-    if (inter)
-    {
-      char c;
-      okay = -1;
-      printf(drive);
-      printf(dir);
-      printf(f.ff_name);
-      while (okay == -1)
-      {
-        printf(", Delete(Y/N)?");
-        c = toupper(getche());
-        if (c == 'Y')
-          okay = 1;
-        else if (c == 'N')
-          okay = 0;
-        else if (c == 3)
-        {                       /* ^C pressed */
-          if (flags & DRIVE)
-            _chdrive(orig_disk + 1);
-          chdir(orig_dir);
-          printf("\n");
-          return 1;
-        }
-        else
-        {
-          printf(drive);
-          printf(dir);
-          printf(f.ff_name);
-        }
-      }
-      printf("\n");
-    }
-    if (okay)
-    {
-#ifdef NODEL
-/* define NODEL if you want to debug */
-      printf(drive);
-      printf(dir);
-      printf(f.ff_name);
-      printf("\n");
-#else
-      if (unlink(f.ff_name) != 0)
-      {
-        perror("del()");
-        return 1;
-      }
-#endif
-    }
-    done = findnext(&f);
-  }
-
-  if (flags & DRIVE)
-    _chdrive(orig_disk + 1);
-  chdir(orig_dir);
-  return 0;
-}
-
-/*
- *
- *  simple file rename internal command.
- *
- */
-#pragma argsused
-int
-ren(char *first, char *rest)
-{
-  char *arg[2];
-
-  /* set the first argument */
-  arg[0] = rest;
-
-  /* split off the first argument and get the second argument start */
-  arg[1] = parse_firstarg(rest);
-
-  /* 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);
-    return 1;
-  }
-  else if (rename(arg[0], arg[1]) != 0)
-  {
-    perror("ren()");
-    return 1;
-  }
-
-  return 0;
+  return directory_handler(first, rest, rmdir, "rd()", RD_HELP);
 }
 
 /*
Files com074c/lh.asm and com074d/lh.asm are identical
Files com074c/license.txt and com074d/license.txt are identical
Files com074c/loadhigh.c and com074d/loadhigh.c are identical
Files com074c/loadhigh.h and com074d/loadhigh.h are identical
Files com074c/lowexec.asm and com074d/lowexec.asm are identical
Files com074c/makecom.bat and com074d/makecom.bat are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/misc.c com074d/misc.c
--- com074c/misc.c	Thu Jul 16 11:29:11 1998
+++ com074d/misc.c	Thu Jul 16 11:29:12 1998
@@ -4,17 +4,23 @@
  * 07/12/98 (Rob Lake) -----------------------------------------------------
  *  started
  *
+ * 07/13/98 (Rob Lake) -----------------------------------------------------
+ *      moved functions in here
+ *
  */
 
 #include <dos.h>
-
-/*
- * exist -- Check to see if fn exists
- *
- */
 #include <io.h>
-#include <sys/stat.h>
 #include <fcntl.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <dir.h>
+#include <conio.h>
+#include <sys/stat.h>
+#include "command.h"
 
 /*
  * exist -- Checks if a file exists
@@ -23,10 +29,128 @@
 int
 exist(char *fn)
 {
-  int f;
-  f = open(fn, O_BINARY);
-  if (f == -1)
+  return (access(fn, 0) == 0);
+}
+/*
+ * get a character out-of-band and honor Ctrl-Break characters
+ */
+int
+cgetchar(void)
+{
+  int c;
+
+  if ((c = getch()) == 0)
+    c = getch() << 8;
+
+  if (c == 3)
+    ctrlBreak = 1;
+
+  return c;
+}
+
+/*
+ * Check if Ctrl-Break was pressed during the last calls
+ */
+int
+chkCBreak(int mode)
+{
+  static int leaveAll = 0;      /* leave all batch files */
+  int c;
+
+  switch (mode)
+  {
+    case BREAK_OUTOFBATCH:
+      leaveAll = 0;
     return 0;
-  close(f);
+    case BREAK_BATCHFILE:
+      if (leaveAll)
+        return 1;
+      if (!ctrlBreak)
+        return 0;
+
+      /* we need to be sure the string arrives on the screen! */
+      do
+        cputs("\r\nCtrl-Break pressed.  Cancel batch file? (Yes/No/All) ");
+      while (!strchr("YNA\3", c = toupper(cgetchar())) || !c);
+
+      cputs("\r\n");
+
+      if (c == 'N')
+        return ctrlBreak = 0;   /* ignore */
+
+      leaveAll = c == 'A' || c == '\3'; /* leave all batch files */
+
+      break;
+    case BREAK_INPUT:
+      if (!ctrlBreak)
+        return 0;
+      break;
+  }
+
+  ctrlBreak = 0;                /* state processed */
   return 1;
+}
+
+/*
+ * function to destructively split a string into an array of strings
+ *
+ * Changed return value to int to determine number of args
+ *   -- Rob Lake (06/29/98)
+ *
+ */
+int
+split(char *s, char **p)
+{
+  int sc = 0,
+    pc = 0;                     /* string and parameter counters */
+
+  while (s[sc])
+  {
+    if (sc && isspace(s[sc]) && !isspace(s[sc - 1]))
+      s[sc] = 0;
+
+    else if (!isspace(s[sc]) && (sc == 0 || isspace(s[sc - 1]) ||
+                                 s[sc - 1] == 0))
+      p[pc++] = &s[sc];
+
+    sc++;
+  }
+
+  p[pc] = NULL;
+  return pc;
+}
+
+/*
+ * internal function to get the first argument from the parameter list
+ * and return a pointer to the beginning of the next argument, or NULL if
+ * there are no more arguments
+ *
+ */
+char *
+parse_firstarg(char *s)
+{
+  char *place;
+
+  /* skip over first argument */
+  place = s;
+  while (*place && !isspace(*place))
+    place++;
+
+  if (*place)
+  {
+    /* mark the end of the first parameter */
+    *place++ = 0;
+
+    /* skip over whitespace before next argument */
+    while (isspace(*place))
+      place++;
+
+    /* if there is something here, return a pointer to it, else NULL */
+    if (*place)
+      return place;
+    else
+      return NULL;
+  }
+  else
+    return NULL;
 }
Files com074c/model.def and com074d/model.def are identical
Files com074c/prompt.c and com074d/prompt.c are identical
Files com074c/readme.txt and com074d/readme.txt are identical
Files com074c/redir.c and com074d/redir.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/ren.c com074d/ren.c
--- com074c/ren.c	Wed Dec 31 18:00:00 1969
+++ com074d/ren.c	Thu Jul 16 11:29:12 1998
@@ -0,0 +1,39 @@
+/*
+ * REN.C
+ */
+
+#include "command.h"
+#include <stdio.h>
+
+/*
+ *
+ *  simple file rename internal command.
+ *
+ */
+#pragma argsused
+int
+ren(char *first, char *rest)
+{
+  char *arg[2];
+
+  /* set the first argument */
+  arg[0] = rest;
+
+  /* split off the first argument and get the second argument start */
+  arg[1] = parse_firstarg(rest);
+
+  /* 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);
+    return 1;
+  }
+  else if (rename(arg[0], arg[1]) != 0)
+  {
+    perror("ren()");
+    return 1;
+  }
+
+  return 0;
+}
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/set.c com074d/set.c
--- com074c/set.c	Wed Dec 31 18:00:00 1969
+++ com074d/set.c	Thu Jul 16 11:29:12 1998
@@ -0,0 +1,61 @@
+/*
+ * SET.C
+ *
+ */
+
+#include "command.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+ * set environment variables
+ *
+ *
+ */
+#pragma argsused
+int
+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)
+  {
+    /* JPP 07/08/1998 removed call to show_environment */
+    for (count = 0; environ[count]; count++)
+    {
+      puts(environ[count]);
+    }
+    return 0;
+  }
+
+  /* make sure there is an = in the command */
+  /* 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");
+    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)
+  {
+    puts("Environment error");
+  }
+
+  return 0;
+}
Files com074c/tempfile.c and com074d/tempfile.c are identical
Files com074c/tempfile.h and com074d/tempfile.h are identical
Files com074c/test.bat and com074d/test.bat are identical
Files com074c/testenv.c and com074d/testenv.c are identical
Files com074c/time.c and com074d/time.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/todo.txt com074d/todo.txt
--- com074c/todo.txt	Thu Jul 16 11:29:11 1998
+++ com074d/todo.txt	Thu Jul 16 11:29:12 1998
@@ -27,3 +27,5 @@
 adding to them.
 
 Add INT23 Handler.
+
+Find out why command crashes when trying to exit.
Files com074c/type.c and com074d/type.c are identical
diff --new-file --recursive --ignore-space-change --unified --report-identical-files --minimal com074c/ver.c com074d/ver.c
--- com074c/ver.c	Wed Dec 31 18:00:00 1969
+++ com074d/ver.c	Thu Jul 16 11:29:12 1998
@@ -0,0 +1,93 @@
+/*
+ * VER.C
+ */
+
+#include "command.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/*
+ *  display shell version info internal command.
+ *
+ *
+ */
+#pragma argsused
+int
+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");
+  /* Basic copyright notice */
+  if (rest[0] == 0)
+  {
+    printf("\n"
+           "%s 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;
+  }
+
+  /* MS-DOS ver prints just help if /? is alone or not */
+  if (strstr(rest, "/?") != NULL)
+  {
+    printf("%s: %s\n", USAGE, VER_HELP);
+    return 0;
+  }
+
+  for (i = 0; rest[i]; i++)
+  {
+    /* skip spaces */
+    if (rest[i] == ' ')
+      continue;
+    if (rest[i] == '/')
+    {
+      /* is this a lone '/' ? */
+      if (rest[i + 1] == 0)
+      {
+        //fprintf(stderr, INVALID_SWITCH, ' ');
+        invalid_switch(' ');
+        return 1;
+      }
+      continue;
+    }
+    if (toupper(rest[i]) == 'W')
+    {                           /* Warranty notice */
+      /* JPP 07/08/1998 removed extra printf calls */
+      puts("\n This program is distributed in the hope that it will be useful,\n"
+         " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+           " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+           " GNU General Public License for more details.");
+    }
+    else if (toupper(rest[i]) == 'R')
+    {                           /* Redistribution notice */
+      /* JPP 07/08/1998 removed extra printf calls */
+      puts("\n This program is free software; you can redistribute it and/or modify\n"
+           " it under the terms of the GNU General Public License as published by\n"
+      " the Free Software Foundation; either version 2 of the License, or\n"
+           " (at your option) any later version.");
+    }
+    else if (toupper(rest[i]) == 'C')
+    {                           /* Developer listing */
+      /* JPP 07/08/1998 removed extra printf calls; rearranged names */
+      puts("\ndeveloped by:\n"
+           "    Tim Norman      Matt Rains\n"
+           "    Evan Jeffrey    Steffen Kaiser\n"
+           "    Svante Frey     Oliver Mueller\n"
+           "    Aaron Kaufman   Marc Desrochers\n"
+           "    Rob Lake        John P. Price");
+    }
+    else
+    {
+      //fprintf(stderr, INVALID_SWITCH, toupper(rest[i]));
+      invalid_switch(toupper(rest[i]));
+      return 1;
+    }
+  }
+  return 0;
+}
Files com074c/where.c and com074d/where.c are identical
