diff -aprNU5 bash-4.1.orig/bashline.c bash-4.1/bashline.c
--- bash-4.1.orig/bashline.c	2019-02-01 23:36:36 +0000
+++ bash-4.1/bashline.c	2019-02-01 23:37:12 +0000
@@ -76,10 +76,24 @@
 #  define VI_EDITING_MODE	 0
 #endif
 
 #define RL_BOOLEAN_VARIABLE_VALUE(s)	((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
 
+#if defined (__DJGPP__)
+#  include "dospath.h"
+#endif /* __DJGPP__ */
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+#  define BASH_COMPLETER_WORD_BREAK_CHARACTERS  " \t\n\"'@><=;|&("
+#  define BASH_NOHOSTNAME_WORD_BREAK_CHARACTERS " \t\n\"'><=;|&("
+#  define RL_FILENAME_QUOTE_CHARACTERS          " \t\n\\\"'@<>=;|&()#$`?*[!{~"
+#else  /* !HAVE_DOS_BASED_FILE_SYSTEM */
+#  define BASH_COMPLETER_WORD_BREAK_CHARACTERS  " \t\n\"'@><=;|&(:"
+#  define BASH_NOHOSTNAME_WORD_BREAK_CHARACTERS " \t\n\"'><=;|&(:"
+#  define RL_FILENAME_QUOTE_CHARACTERS          " \t\n\\\"'@<>=;|&()#$`?*[!:{~"
+#endif /* !HAVE_DOS_BASED_FILE_SYSTEM */
+
 #if defined (BRACE_COMPLETION)
 extern int bash_brace_completion __P((int, int));
 #endif /* BRACE_COMPLETION */
 
 /* To avoid including curses.h/term.h/termcap.h and that whole mess. */
@@ -240,12 +254,12 @@ int no_empty_command_completion;
 int force_fignore = 1;
 
 /* Perform spelling correction on directory names during word completion */
 int dircomplete_spelling = 0;
 
-static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
-static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
+static char *bash_completer_word_break_characters = BASH_COMPLETER_WORD_BREAK_CHARACTERS;
+static char *bash_nohostname_word_break_characters = BASH_NOHOSTNAME_WORD_BREAK_CHARACTERS;
 /* )) */
 
 static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
 
 static int dot_in_path = 0;
@@ -529,11 +543,11 @@ initialize_readline ()
 
   /* characters that need to be quoted when appearing in filenames. */
 #if 0
   rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{";	/*}*/
 #else
-  rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~";	/*}*/
+  rl_filename_quote_characters = RL_FILENAME_QUOTE_CHARACTERS;	/*}*/
 #endif
   rl_filename_quoting_function = bash_quote_filename;
   rl_filename_dequoting_function = bash_dequote_filename;
   rl_char_is_quoted_p = char_is_quoted;
 
@@ -1524,10 +1538,27 @@ command_word_completion_function (hint_t
 
       /* If this is an absolute program name, do not check it against
 	 aliases, reserved words, functions or builtins.  We must check
 	 whether or not it is unique, and, if so, whether that filename
 	 is executable. */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+     if (hint_text && hint_text[1] == ':'
+         && hint_text[2] != '/')
+       {
+         char *buffer = get_real_path (hint_text);
+         hint = strdup (buffer);
+         hint_len = strlen (hint);
+         if (filename_hint)
+           free (filename_hint);
+
+         filename_hint = savestring (hint);
+
+         mapping_over = 4;
+         istate = 0;
+         goto inner;
+       }
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
       if (globpat || absolute_program (hint_text))
 	{
 	  /* Perform tilde expansion on what's passed, so we don't end up
 	     passing filenames with tildes directly to stat(). */
 	  if (*hint_text == '~')
diff -aprNU5 bash-4.1.orig/bshspawn.c bash-4.1/bshspawn.c
--- bash-4.1.orig/bshspawn.c	1970-01-01 00:00:00 +0000
+++ bash-4.1/bshspawn.c	2019-02-01 23:37:12 +0000
@@ -0,0 +1,239 @@
+#include <config.h>
+
+#if defined (__DJGPP__)
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <process.h>
+#include <sys/system.h>
+#include <sys/exceptn.h>
+
+#include "command.h"
+#include "general.h"
+#include "externs.h"
+#include "dospath.h"
+
+static char *spawn_make_response_file(char **argv);
+#if 0
+static void reset_console(void);
+#endif
+
+static const char * dos_ext_names[] =
+{ "exe", "bat", "com", "btm" };
+
+int bash_spawnve(const char *path, char **args, char **envp)
+{
+  int status;
+  char oldcwd[PATH_MAX];
+  int errno_save;
+  int i, is_dos_ext;
+  int old_ctrl_c;
+  char *base, *dot;
+
+  /* Force scripts not starting with #! to be invoked with Bash.  */
+  is_dos_ext = 0;
+  base = basename(path);
+  dot = strchr(base, '.');
+
+  if (dot && dot[1] != '\0')
+  {
+    ++dot;
+    for (i = 0; i < sizeof (dos_ext_names) / sizeof (dos_ext_names[0]); ++i)
+    {
+      if (strcmp(dot, dos_ext_names[i]) == 0)
+      {
+        is_dos_ext = 1;
+        break;
+      }
+    }
+  }
+
+  if (!is_dos_ext)
+  {
+    char sample[2];
+    int fd = open(path, O_RDONLY | O_BINARY);
+    if (fd > -1)
+    {
+      int sample_len = read(fd, sample, 2);
+      close(fd);
+      if (sample_len == 2)
+      {
+        if (sample[0] == 0x4c || sample[1] == 0x01)
+        {
+          /* Unstubbed COFF. Check for a file with .exe and
+             use it if it exists.  */
+          const char *exe_path = find_one_extension(path, "exe");
+          if (exe_path)
+            path = exe_path;
+        }
+        else if (!(sample[0] == 'M' || sample[1] == 'Z')
+                 && !(sample[0] == '#' || sample[1] == '!'))
+        {
+          /* Let Bash insert the shell name into argv[0] so
+             scripts without #! will run.  */
+          errno = ENOEXEC;
+          return -1;
+        }
+      }
+    }
+  }
+
+  /* keep cwd on exec */
+  getcwd(oldcwd, sizeof oldcwd);
+
+  /* Expand 'path'.  */
+  if (strncmp(path, "/dev/", sizeof("/dev/") - 1) == 0)
+    path = get_real_path(path);
+
+  /* disable interrupt */
+  old_ctrl_c = __djgpp_set_ctrl_c(0);
+
+  errno = 0;
+
+  /* Run child process.  */
+  status = __djgpp_spawn(P_WAIT, path, args, envp, SPAWN_NO_EXTENSION_SRCH);
+
+  /* make response file if E2BIG */
+  if (errno == E2BIG && args != NULL && args[1] != NULL && args[1][0] != '@')
+  {
+    char *tname;
+
+    tname = spawn_make_response_file(args);
+    if (tname != NULL)
+    {
+      char *xargs[3];
+
+      xargs[0] = args[0];
+      xargs[1] = xmalloc(1 + strlen(tname) + 2);
+      if (xargs[1])
+      {
+        char *resp = xargs[1];
+        resp[0] = '@';
+        strcpy(resp + 1, tname);
+
+        xargs[2] = NULL;
+
+        errno = 0;
+
+        /* try again */
+        status = __djgpp_spawn(P_WAIT, path, xargs, envp,
+                               SPAWN_NO_EXTENSION_SRCH);
+
+        /* cleanup */
+        free(xargs[1]);
+        remove(tname);
+        free(tname);
+      }
+    }
+  }
+
+  /* Reset standard input */
+#if 0
+  reset_console();
+#endif
+
+  /* enable interrupt */
+  __djgpp_set_ctrl_c(old_ctrl_c);
+
+  errno_save = errno;
+  if (status > -1)
+    chdir(oldcwd);
+  errno = errno_save;
+
+  return status;
+}
+
+static char *
+spawn_make_response_file(char **argv)
+{
+  char *tname;
+
+  tname = sh_mktmpname("rs", MT_USERANDOM | MT_USETMPDIR);
+
+  if (tname != NULL)
+  {
+    FILE *fp;
+    char *p;
+    int i;
+
+    fp = fopen(tname, "wt");
+    if (fp == NULL)
+    {
+      free(tname);
+      return NULL;
+    }
+
+    for (i = 1; (p = argv[i]) != NULL; i++)
+    {
+      if (i != 1)
+        fputc(' ', fp);
+      if (strchr(p, '"') == NULL)
+      {
+        fputc('"', fp);
+        fputs(p, fp);
+        fputc('"', fp);
+      }
+      else
+      {
+        fputc('"', fp);
+        for (; *p; p++)
+        {
+          if (*p == '"')
+            fputc('\\', fp);
+          fputc(*p, fp);
+        }
+        fputc('"', fp);
+      }
+    }
+    fclose(fp);
+  }
+
+  return tname;
+}
+
+#if 0
+#include <libc/getdinfo.h>
+
+#define _DEV_EOF    0x0040
+
+#define _REG_STATUS_CF 0x01
+#define _REG_STATUS_ZF 0x40
+
+/* XXX: Is this needed? */
+void
+reset_console (void)
+{
+  unsigned short devinfo;
+  int handle;
+  __dpmi_regs r;
+
+  handle = 0; /* STDIN (CON) */
+
+  r.x.ax = 0x4400;
+  r.x.bx = handle;
+  __dpmi_int(0x21, &r);
+  if (r.x.flags & _REG_STATUS_CF)
+    return;
+  devinfo = r.x.dx;
+
+  if ((devinfo & _DEV_CDEV) && (devinfo & _DEV_STDIN) && (devinfo & _DEV_EOF) == 0)
+  {
+    r.x.ax = 0x4000; /* WRITE */
+    r.x.bx = handle; /* STDIN (CON) */
+    r.x.cx = 0; /* zero byte */
+    r.x.dx = 0; /* dummy offset */
+    r.x.ds = 0; /* dummy segment */
+    __dpmi_int(0x21, &r);
+    if (r.x.flags & _REG_STATUS_CF)
+      return;
+  }
+}
+#endif
+
+#endif /* __DJGPP__ */
diff -aprNU5 bash-4.1.orig/builtins/cd.def bash-4.1/builtins/cd.def
--- bash-4.1.orig/builtins/cd.def	2009-01-04 19:32:22 +0000
+++ bash-4.1/builtins/cd.def	2019-02-01 23:37:12 +0000
@@ -47,10 +47,14 @@ $PRODUCES cd.c
 #include "../flags.h"
 #include "maxpath.h"
 #include "common.h"
 #include "bashgetopt.h"
 
+#if defined (__DJGPP__)
+#  include "dospath.h"
+#endif /* __DJGPP__ */
+
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
 
 extern int posixly_correct;
@@ -235,14 +239,21 @@ cd_builtin (list)
     }
   else if (absolute_pathname (list->word->word))
     dirname = list->word->word;
   else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
     {
+#if defined (__DJGPP__)
+      char cur_path_separator = path_separator;
+#endif /* __DJGPP__ */
       dirname = list->word->word;
 
       /* Find directory in $CDPATH. */
       path_index = 0;
+#if defined (__DJGPP__)
+      /* CDPATH is not affected by PATH_SEPARATOR.  */
+      path_separator=':';
+#endif /* __DJGPP__ */
       while (path = extract_colon_unit (cdpath, &path_index))
 	{
 	  /* OPT is 1 if the path element is non-empty */
 	  opt = path[0] != '\0';
 	  temp = sh_makepath (path, dirname, MP_DOTILDE);
@@ -261,17 +272,23 @@ cd_builtin (list)
 #if 0
 	      /* Posix.2 says that after using CDPATH, the resultant
 		 value of $PWD will not contain `.' or `..'. */
 	      return (bindpwd (posixly_correct || no_symlinks));
 #else
+#if defined (__DJGPP__)
+	      path_separator = cur_path_separator;
+#endif /* __DJGPP__ */
 	      return (bindpwd (no_symlinks));
 #endif
 	    }
 	  else
 	    free (temp);
 	}
 
+#if defined (__DJGPP__)
+        path_separator = cur_path_separator;
+#endif /* __DJGPP__ */
       /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
 	 try the current directory, so we just punt now with an error
 	 message if POSIXLY_CORRECT is non-zero.  The check for cdpath[0]
 	 is so we don't mistakenly treat a CDPATH value of "" as not
 	 specifying the current directory. */
@@ -459,10 +476,26 @@ change_to_directory (newdir, nolinks)
 	errno = ENOTDIR;
       free (tdir);
       return (0);
     }
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (tdir && tdir[1] == ':' && !ISDIRSEP(tdir[2]))
+    {
+      /* Relative path on another drive. Attempt to chdir to it and
+         retrieve its current directory.  */
+      if (chdir (nolinks ? newdir : tdir) == 0)
+        {
+          FREE (the_current_working_directory);
+          the_current_working_directory = (char *)NULL;
+          tdir = get_working_directory ("cd");
+          FREE (tdir);
+          return (1);
+        }
+    }
+  else
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
   /* If the chdir succeeds, update the_current_working_directory. */
   if (chdir (nolinks ? newdir : tdir) == 0)
     {
       /* If canonicalization failed, but the chdir succeeded, reset the
 	 shell's idea of the_current_working_directory. */
diff -aprNU5 bash-4.1.orig/builtins/common.c bash-4.1/builtins/common.c
--- bash-4.1.orig/builtins/common.c	2009-04-24 17:52:22 +0000
+++ bash-4.1/builtins/common.c	2019-02-01 23:37:12 +0000
@@ -61,10 +61,17 @@
 
 #if defined (HISTORY)
 #  include "../bashhist.h"
 #endif
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+/* Must be redefined after externs.h have been included!  */
+#undef getcwd
+#define getcwd dospath_getcwd
+#endif
+
 #if !defined (errno)
 extern int errno;   
 #endif /* !errno */
 
 extern int indirection_level, subshell_environment;
diff -aprNU5 bash-4.1.orig/builtins/exec.def bash-4.1/builtins/exec.def
--- bash-4.1.orig/builtins/exec.def	2009-02-19 21:40:36 +0000
+++ bash-4.1/builtins/exec.def	2019-02-01 23:37:12 +0000
@@ -75,10 +75,15 @@ extern int errno;
 #endif /* !errno */
 
 extern int subshell_environment;
 extern REDIRECT *redirection_undo_list;
 
+#if !defined (HAVE_WORKING_FORK)
+extern int subshell_exit_builtin;
+#endif /* !HAVE_WORKING_FORK */
+
+
 int no_exit_on_failed_exec;
 
 /* If the user wants this to look like a login shell, then
    prepend a `-' onto NAME and return the new name. */
 static char *
@@ -140,12 +145,21 @@ exec_builtin (list)
     }
 #endif /* RESTRICTED_SHELL */
 
   args = strvec_from_word_list (list, 1, 0, (int *)NULL);
 
+#if !defined (__DJGPP__)
   /* A command with a slash anywhere in its name is not looked up in $PATH. */
   command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
+#else  /* __DJGPP__ */
+  command = search_for_command (args[0]);
+  if (command)
+    {
+      free (args[0]);
+      args[0] = strdup (command);
+    }
+#endif /* __DJGPP__ */
 
   if (command == 0)
     {
       sh_notfound (args[0]);
       exit_value = EX_NOTFOUND;	/* As per Posix.2, 3.14.6 */
@@ -196,11 +210,28 @@ exec_builtin (list)
 #if defined (JOB_CONTROL)
   if (subshell_environment == 0)
     end_job_control ();
 #endif /* JOB_CONTROL */
 
+#if defined (HAVE_WORKING_FORK)
   shell_execve (command, args, env);
+#else  /* !HAVE_WORKING_FORK */
+  if (!subshell_exit_builtin)
+    {
+      exit_value = shell_execve (command, args, env);
+      if (exit_value >= 0)
+	  exit (exit_value);
+      exit_value = EXECUTION_FAILURE;
+    }
+  else
+    {
+      exit_value = shell_execve (command, args, env);
+      if (cleanenv == 0)
+	  adjust_shell_level (1);
+      goto failed_exec;
+    }
+#endif /* !HAVE_WORKING_FORK */
 
   /* We have to set this to NULL because shell_execve has called realloc()
      to stuff more items at the front of the array, which may have caused
      the memory to be freed by realloc().  We don't want to free it twice. */
   args = (char **)NULL;
@@ -216,16 +247,23 @@ exec_builtin (list)
     file_error (command);
 
 failed_exec:
   FREE (command);
 
+#if defined (HAVE_WORKING_FORK)
   if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
     exit_shell (exit_value);
+#endif /* HAVE_WORKING_FORK */
 
   if (args)
     strvec_dispose (args);
 
+#if !defined (HAVE_WORKING_FORK)
+  if (!subshell_environment && (interactive == 0 && no_exit_on_failed_exec == 0))
+    exit_shell (exit_value);
+#endif /* !HAVE_WORKING_FORK */
+
   initialize_traps ();
   initialize_signals (1);
 
 #if defined (JOB_CONTROL)
   if (interactive_shell || job_control)
diff -aprNU5 bash-4.1.orig/builtins/exit.def bash-4.1/builtins/exit.def
--- bash-4.1.orig/builtins/exit.def	2009-02-24 03:56:58 +0000
+++ bash-4.1/builtins/exit.def	2019-02-01 23:37:12 +0000
@@ -51,10 +51,16 @@ extern int last_command_exit_value;
 extern int running_trap, trap_saved_exit_value;
 extern int subshell_environment;
 extern sh_builtin_func_t *this_shell_builtin;
 extern sh_builtin_func_t *last_shell_builtin;
 
+#if !defined (HAVE_WORKING_FORK)
+int subshell_exit_value = 0;
+int subshell_exit_builtin = 0;
+int subshell_skip_commands = 0;
+#endif /* !HAVE_WORKING_FORK */
+
 static int exit_or_logout __P((WORD_LIST *));
 static int sourced_logout;
 
 int
 exit_builtin (list)
@@ -148,20 +154,33 @@ exit_or_logout (list)
   bash_logout ();
 
   last_command_exit_value = exit_value;
 
   /* Exit the program. */
+#if !defined (HAVE_WORKING_FORK)
+  if (subshell_exit_builtin)
+    {
+      subshell_exit_value = exit_value;
+      subshell_exit_builtin = 0;
+      subshell_skip_commands = 1;
+      return (EXECUTION_SUCCESS);
+    }
+#endif /* !HAVE_WORKING_FORK */
   jump_to_top_level (EXITPROG);
   /*NOTREACHED*/
 }
 
 void
 bash_logout ()
 {
   /* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
   if (login_shell && sourced_logout++ == 0 && subshell_environment == 0)
     {
+#if defined (__MSDOS__)
+      if (maybe_execute_file ("~/_blogout", 1) == 0)
+        if (pathconf (NULL, _PC_NAME_MAX) > 12)
+#endif /* __MSDOS__ */
       maybe_execute_file ("~/.bash_logout", 1);
 #ifdef SYS_BASH_LOGOUT
       maybe_execute_file (SYS_BASH_LOGOUT, 1);
 #endif
     }
diff -aprNU5 bash-4.1.orig/builtins/psize.c bash-4.1/builtins/psize.c
--- bash-4.1.orig/builtins/psize.c	2008-08-14 19:56:52 +0000
+++ bash-4.1/builtins/psize.c	2019-02-01 23:37:12 +0000
@@ -28,10 +28,14 @@
 #    include <sys/types.h>
 #  endif
 #  include <unistd.h>
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
 #include <stdio.h>
 #ifndef _MINIX
 #include "../bashtypes.h"
 #endif
 #include <signal.h>
@@ -58,10 +62,15 @@ sigpipe (sig)
 int
 main (argc, argv)
      int argc;
      char **argv;
 {
+#if defined (PIPE_BUF)
+  /* If the POSIX standard PIPE_BUF is defined, just report its value.  */
+  sigpipe (PIPE_BUF);
+#else  /* !PIPE_BUF */
+#error PIPE_BUF not defined
   char buf[128];
   register int i;
 
   for (i = 0; i < 128; i++)
     buf[i] = ' ';
@@ -73,7 +82,8 @@ main (argc, argv)
     {
       int n;
       n = write (1, buf, 128);
       nw += n;
     }
+#endif /* !PIPE_BUF */
   return (0);
 }
diff -aprNU5 bash-4.1.orig/config-bot.h bash-4.1/config-bot.h
--- bash-4.1.orig/config-bot.h	2009-08-14 19:11:38 +0000
+++ bash-4.1/config-bot.h	2019-02-01 23:37:12 +0000
@@ -127,10 +127,18 @@
 
 #if !defined (HAVE_SYSLOG) || !defined (HAVE_SYSLOG_H)
 #  undef SYSLOG_HISTORY
 #endif
 
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__OS2__)
+#  define HAVE_DOS_BASED_FILE_SYSTEM
+#endif
+
+#if !(defined (__DJGPP__) || defined (__MINGW__))
+#  define HAVE_WORKING_FORK
+#endif
+
 /************************************************/
 /* check multibyte capability for I18N code	*/
 /************************************************/
 
 /* For platforms which support the ISO C amendement 1 functionality we
diff -aprNU5 bash-4.1.orig/config-top.h bash-4.1/config-top.h
--- bash-4.1.orig/config-top.h	2009-12-22 20:29:38 +0000
+++ bash-4.1/config-top.h	2019-02-01 23:37:12 +0000
@@ -16,10 +16,15 @@
 
    You should have received a copy of the GNU General Public License
    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#if defined (__DJGPP__)
+#define DEFAULT_PATH_VALUE "/dev/env/DJDIR/bin"
+#define STANDARD_UTILS_PATH "/dev/env/DJDIR/bin"
+#endif
+
 /* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
    continue processing arguments after one of them fails.  This is
    what POSIX.2 specifies. */
 #define CONTINUE_AFTER_KILL_ERROR
 
diff -aprNU5 bash-4.1.orig/dospath.c bash-4.1/dospath.c
--- bash-4.1.orig/dospath.c	1970-01-01 00:00:00 +0000
+++ bash-4.1/dospath.c	2019-02-01 23:37:12 +0000
@@ -0,0 +1,661 @@
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "variables.h"
+#include "dospath.h"
+
+#define ARRAY_INIT_LEN 32
+
+struct dynamic_array
+{
+  char *start;
+  char *ptr;
+  char *end;
+};
+
+struct dos_var_info
+{
+  const char *name;
+  void (*init_func)(const char *);
+  char found;
+};
+
+char path_separator = ';';
+int path_expand = 0;
+int test_finds_exe = 0;
+
+static void path_separator_init (const char *);
+static void path_expand_init (const char *);
+static void test_finds_exe_init (const char *);
+static int make_bash_path (const char *in, struct dynamic_array *buffer,
+                           char stop_char, char **in_end);
+static int make_bash_path_var (const char *in, struct dynamic_array *buffer);
+static int make_dos_path (const char *in, struct dynamic_array *buffer,
+                          char stop_char, char **in_end);
+static int make_dos_path_var (const char *in, struct dynamic_array *buffer);
+static int make_export_path_var (const char *in, struct dynamic_array *buffer);
+static void restore_cwd (void);
+
+static void array_resize(struct dynamic_array *array);
+static const char *array_puts(struct dynamic_array *array, const char *s);
+static void array_putc(struct dynamic_array *array, const char ch);
+static void array_init(struct dynamic_array *array, const char *s, size_t size);
+static void array_done(struct dynamic_array *array);
+static int array_len(struct dynamic_array *array);
+
+static const char * path_sep_vars[] =
+{
+/*  "CDPATH", */
+  "COMSPEC",
+  "HOME",
+  "MAILPATH",
+  "OLDPWD",
+  "PATH",
+  "PWD",
+  "TMPDIR",
+};
+
+static char path_var_found[] =
+{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static struct dos_var_info dos_var_init[] =
+{
+  { "PATH_EXPAND", &path_expand_init, 0},
+  { "TEST_FINDS_EXE", &test_finds_exe_init, 0},
+};
+
+static char path_buffer[256];
+
+static char *init_cwd;
+
+/* Called at startup. Certain variables containing a list of path like PATH and
+   are used by Bash must be in a form that Bash understands.
+   When PATH_SEPARATOR=:, the list is separated by ':' and uses the special
+   '/dev/x/' form understood by DJGPP. When PATH_SEPARATOR=;, the list is
+   separated by ';' as normal but backslashes are converted to slashes.  */
+int try_init_path_var(const char *name, char **val)
+{
+  int i;
+  struct dynamic_array buffer;
+
+  for (i = 0; i < sizeof (path_sep_vars) / sizeof (path_sep_vars[0]); i++)
+  {
+    if (!path_var_found[i] && strcmp (name, path_sep_vars[i]) == 0)
+    {
+      path_var_found[i] = 1;
+      array_init(&buffer, 0, ARRAY_INIT_LEN);
+      make_bash_path_var(*val, &buffer);
+      *val = buffer.start;
+      return 1;
+    }
+  }
+  for (i = 0; i < sizeof (dos_var_init) / sizeof (dos_var_init[0]); i++)
+  {
+    if (!dos_var_init[i].found && strcmp (name, dos_var_init[i].name) == 0)
+    {
+      dos_var_init[i].found = 1;
+      if ((*val)[0] != '\0')
+        (dos_var_init[i].init_func)(*val);
+      break;
+    }
+  }
+  return 0;
+}
+
+void init_path_separator(void)
+{
+  char *path_sep = getenv("PATH_SEPARATOR");
+  if (path_sep)
+    path_separator_init(path_sep);
+}
+
+/* Put a path variable to be exported Bash into a form that native DOS programs
+   can understand. Do that by changing paths containing '/dev/x/foo' path to
+   canonical form and change slashes to backslashes. */
+char *
+export_path_var(const char *name, const char *val)
+{
+  int out_len;
+  struct dynamic_array buffer;
+
+  array_init(&buffer, 0, ARRAY_INIT_LEN);
+  array_puts(&buffer, name);
+  array_putc(&buffer, '=');
+
+  out_len = make_export_path_var(val, &buffer);
+  array_putc(&buffer, '\0');
+
+  return buffer.start;
+}
+
+void expand_argv_words(WORD_LIST *list)
+{
+  struct dynamic_array buffer;
+
+  if (!path_expand)
+    return;
+
+  list = list->next;
+
+  while (list)
+  {
+    if (list->word->flags != W_QUOTED)
+    {
+      char *arg = list->word->word;
+
+      if (strncmp(arg, "/dev/", 5) == 0 && arg[5]
+          && (arg[6] == '/' || arg[6] == '\0'))
+      {
+        /* Setup a fake dynamic buffer. Set end to 0 to ensure
+           no attempt is made to increase the size of the array.  */
+        buffer.start = arg;
+        buffer.ptr = arg;
+        buffer.end = (char *)0 - 1;
+        make_dos_path(arg, &buffer, '\0', NULL);
+        array_putc(&buffer, '\0');
+      }
+    }
+    list = list->next;
+  }
+
+  return;
+}
+
+
+void make_path_vars_bash(void)
+{
+  int i;
+  struct dynamic_array buffer;
+  SHELL_VAR *var;
+
+  array_init(&buffer, 0, ARRAY_INIT_LEN);
+
+  for (i = 0; i < sizeof(path_sep_vars) / sizeof(path_sep_vars[0]); i++)
+  {
+    var = find_variable((char *)path_sep_vars[i]);
+    if (!var || !var->value)
+      continue;
+    buffer.ptr = buffer.start;
+    make_bash_path_var(var->value, &buffer);
+    free(var->value);
+    var->value = malloc(array_len(&buffer) + 1);
+    strcpy(var->value, buffer.start);
+  }
+  array_done(&buffer);
+}
+
+void make_path_vars_dos(void)
+{
+  int i;
+  struct dynamic_array buffer;
+  SHELL_VAR *var;
+
+  array_init(&buffer, 0, ARRAY_INIT_LEN);
+
+  for (i = 0; i < sizeof(path_sep_vars) / sizeof(path_sep_vars[0]); i++)
+  {
+    var = find_variable((char *)path_sep_vars[i]);
+    if (!var || !var->value)
+      continue;
+    buffer.ptr = buffer.start;
+    make_dos_path_var(var->value, &buffer);
+    free(var->value);
+    var->value = malloc(array_len(&buffer) + 1);
+    strcpy(var->value, buffer.start);
+  }
+  array_done(&buffer);
+}
+
+char *make_posix_path_from_filename(const char *in)
+{
+  struct dynamic_array buffer;
+
+  array_init(&buffer, 0, ARRAY_INIT_LEN);
+
+  if (in[1] == ':')
+  {
+    array_puts(&buffer, "/dev/");
+    array_putc(&buffer, in[0]);
+    in += 2;
+  }
+  while (*in)
+  {
+     array_putc(&buffer, ((*in != '\\') ? *in : '/'));
+     ++in;
+  }
+
+  array_putc(&buffer, '\0');
+  return buffer.start;
+
+}
+
+void save_cwd(void)
+{
+  if (init_cwd == NULL)
+    init_cwd = rpl_getcwd(NULL, FILENAME_MAX + 1);
+  atexit (restore_cwd);
+}
+
+char *dospath_getcwd(char *buf, size_t size)
+{
+  char ch;
+
+  if (buf == NULL)
+  {
+    buf = (char *)xmalloc(PATH_MAX + 1);
+    buf[0] = '\0';
+  }
+  if (size == 0)
+    size = PATH_MAX;
+
+  if (path_separator == ';')
+    return rpl_getcwd(buf, size);
+
+  rpl_getcwd(buf + 4, size - 4);
+  ch = *(buf + 4);
+  strcpy(buf, "/dev/");
+  buf[5] = ch;
+  buf[6] = '/';
+
+  return buf;
+}
+
+/* This shall replace lib/sh/getcwd and ensure
+   that always DJGPP's own implementation is used.  */
+char *rpl_getcwd(char *buf, size_t size)
+{
+  size_t buf_size = size ? size : PATH_MAX;
+
+  return getcwd(buf, buf_size);
+}
+
+static const char *exec_extensions[] =
+{"exe", "bat", "com", "btm"};
+
+const char *
+find_extension(const char *path)
+{
+  char *ptr, *ext, *file;
+  int dot, i;
+
+  dot = 0;
+  ptr = (char *)path;
+  ext = file = path_buffer;
+
+  while (*ptr)
+  {
+    *ext = *ptr;
+    if (*ext == '.')
+      dot = 1;
+    else if (*ext == '/')
+    {
+      dot = 0;
+      file = ext;
+      ++file;
+    }
+    ++ext;
+    ++ptr;
+  }
+
+  if (dot)
+    return NULL;
+
+  *ext = '\0';
+  if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+    return path_buffer;
+
+  *ext = '.';
+  ++ext;
+
+  for (i = 0; i < sizeof (exec_extensions) / sizeof (exec_extensions[0]); i++)
+  {
+    strcpy (ext, exec_extensions[i]);
+    if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+      return path_buffer;
+  }
+  return NULL;
+}
+
+const char *find_path_extension(const char *path, const char *file)
+{
+  char *ext, *file_ptr;
+  int dot, i;
+
+  ext = path_buffer;
+
+  while (*path)
+  {
+    *ext = *((char *)(path));
+    ++path;
+    ++ext;
+  }
+  if (ext[-1] != '/')
+  {
+    *ext = '/';
+    ++ext;
+  }
+  dot = 0;
+  file_ptr = ext;
+
+  while (*file)
+  {
+    *ext = *(char *)file;
+    if (*ext == '.')
+      dot = 1;
+    ++file;
+    ++ext;
+  }
+  if (dot)
+    return NULL;
+
+  *ext = '\0';
+  if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+    return file_ptr;
+
+  *ext = '.';
+  ++ext;
+
+  for (i = 0; i < sizeof (exec_extensions) / sizeof (exec_extensions[0]); i++)
+  {
+    strcpy(ext, exec_extensions[i]);
+    if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+      return file_ptr;
+  }
+  return NULL;
+}
+
+const char *find_one_extension(const char *path, const char *extension)
+{
+  char *ptr, *ext, *file;
+  int dot;
+
+  dot = 0;
+  ptr = (char *)path;
+  ext = file = path_buffer;
+
+  while (*ptr)
+  {
+    *ext = *ptr;
+    if (*ext == '.')
+      dot = 1;
+    else if (*ext == '/')
+    {
+      dot = 0;
+      file = ext;
+      ++file;
+    }
+    ++ext;
+    ++ptr;
+  }
+
+  if (dot)
+    return NULL;
+
+#if 0
+  *ext = '\0';
+  if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+    return path_buffer;
+#endif
+
+  *ext = '.';
+  ++ext;
+
+  strcpy(ext, extension);
+
+  if (access(path_buffer, F_OK) == 0 && !(access(path_buffer, D_OK) == 0))
+    return path_buffer;
+
+  return NULL;
+}
+
+char *
+get_real_path(const char *path)
+{
+  _fixpath(path, path_buffer);
+  return path_buffer;
+}
+
+char *
+encode_drive_letter(char *buffer, const char letter)
+{
+  if (path_separator == ':')
+  {
+    strcpy(buffer, "/dev/");
+    buffer[5] = letter;
+    buffer[6] = '\0';
+  }
+  else
+  {
+    buffer[0] = letter;
+    buffer[1] = ':';
+    buffer[2] = '\0';
+  }
+  return buffer;
+}
+
+static void restore_cwd(void)
+{
+  if (init_cwd && init_cwd[0] != '\0')
+    chdir(init_cwd);
+}
+
+static void
+path_separator_init(const char *val)
+{
+  char ch = *val;
+  if (ch == ':' || ch == ';')
+    path_separator = ch;
+}
+
+static void
+path_expand_init(const char *val)
+{
+  char ch = *val;
+  if (tolower(ch) == 'y')
+    path_expand = 1;
+}
+
+static void
+test_finds_exe_init(const char *val)
+{
+  char ch = *val;
+  if (tolower(ch) == 'y')
+    test_finds_exe = 1;
+  else
+    test_finds_exe = 0;
+}
+
+static int
+make_bash_path(const char *in, struct dynamic_array *buffer, char stop_char, char **in_end)
+{
+  if (in == NULL)
+    return 0;
+
+  if (path_separator == ':' && *in && *in != '.' && in[1] == ':')
+  {
+    if (in[2] == '\\' || in[2] == '/')
+    {
+      array_puts(buffer, "/dev/");
+      array_putc(buffer, *in);
+      in += 2;
+    }
+    else
+    {
+      char ch;
+      char *eop = (char *)in + 2;
+      char fixbuf[PATH_MAX];
+
+      while (*eop && *eop != stop_char)
+        ++eop;
+      ch = *eop;
+      *eop = '\0';
+      _fixpath(in, fixbuf);
+      *eop = ch;
+      ch = fixbuf[0];
+      array_puts(buffer, "/dev/");
+      array_putc(buffer, ch);
+      in = eop;
+    }
+  }
+  while (*in && *in != stop_char)
+  {
+    array_putc(buffer, (*in != '\\') ? *in : '/');
+    ++in;
+  }
+
+  if (in_end)
+    *in_end = (char *)in;
+
+  return 0;
+}
+
+static int
+make_bash_path_var(const char *in, struct dynamic_array *buffer)
+{
+  char *in_ptr = (char *)in;
+
+  while (*in_ptr)
+  {
+    make_bash_path(in_ptr, buffer, ';', &in_ptr);
+    if (*in_ptr == ';')
+    {
+      array_putc(buffer, path_separator);
+      ++in_ptr;
+    }
+  }
+  array_putc(buffer, '\0');
+  return buffer->ptr - buffer->start;
+}
+
+static int
+make_dos_path(const char *in, struct dynamic_array *buffer, char stop_char, char **in_end)
+{
+  if (in == NULL)
+    return 0;
+
+  if (strncmp(in, "/dev/", 5) == 0)
+  {
+    array_putc(buffer, in[5]);
+    array_putc(buffer, ':');
+    in += 6;
+  }
+
+  while (*in && *in != stop_char)
+  {
+    array_putc(buffer, (*in != '/') ? *in : '\\');
+    ++in;
+  }
+
+  if (in_end)
+    *in_end = (char *)in;
+
+  return buffer->ptr - buffer->start;
+}
+
+static int
+make_dos_path_var(const char *in, struct dynamic_array *buffer)
+{
+  char *in_ptr = (char *)in;
+
+  while (*in_ptr)
+  {
+    make_dos_path(in_ptr, buffer, ':', &in_ptr);
+    if (*in_ptr == ':')
+    {
+      array_putc(buffer, path_separator);
+      ++in_ptr;
+    }
+  }
+  array_putc(buffer, '\0');
+  return buffer->ptr - buffer->start;
+}
+
+static int
+make_export_path_var(const char *in, struct dynamic_array *buffer)
+{
+  char *in_ptr = (char *)in;
+
+  while (*in_ptr)
+  {
+    make_dos_path(in_ptr, buffer, path_separator, &in_ptr);
+    if (*in_ptr == path_separator)
+    {
+      array_putc(buffer, ';');
+      ++in_ptr;
+    }
+  }
+  array_putc(buffer, '\0');
+  return buffer->ptr - buffer->start;
+}
+
+static void
+array_resize(struct dynamic_array *array)
+{
+  char *xstart;
+  size_t len;
+
+  len = (array->end - array->start);
+  len *= 2;
+
+  xstart = realloc(array->start, len + 1);
+  array->ptr = xstart + (array->ptr - array->start);
+  array->start = xstart;
+  array->end = xstart + len;
+}
+
+static const char *
+array_puts(struct dynamic_array *array, const char *s)
+{
+  while (*s)
+  {
+    while (*s && (array->ptr < array->end))
+    {
+      *(array->ptr) = *s;
+      ++(array->ptr);
+      ++s;
+    }
+    if (*s)
+      array_resize(array);
+  }
+
+  return array->ptr;
+}
+
+static void
+array_putc(struct dynamic_array *array, const char ch)
+{
+  if (array->ptr >= array->end)
+    array_resize(array);
+  *(array->ptr) = ch;
+  ++(array->ptr);
+}
+
+static void
+array_init(struct dynamic_array *array, const char *s, size_t size)
+{
+  array->start = malloc(size + 1);
+  array->ptr = array->start;
+  array->end = array->start + size;
+  if (s)
+    array_puts(array, s);
+}
+
+static void
+array_done(struct dynamic_array *array)
+{
+  free(array->start);
+}
+
+static int
+array_len(struct dynamic_array *array)
+{
+  return array->ptr - array->start + 1;
+}
diff -aprNU5 bash-4.1.orig/dospath.h bash-4.1/dospath.h
--- bash-4.1.orig/dospath.h	1970-01-01 00:00:00 +0000
+++ bash-4.1/dospath.h	2019-02-01 23:37:12 +0000
@@ -0,0 +1,39 @@
+#ifndef PATH_SEP_H
+#define PATH_SEP_H
+
+#include <string.h>
+#include "stdc.h"
+#include "command.h"
+
+extern char path_separator;
+extern int path_expand;
+extern int test_finds_exe;
+
+void initialize_dos_vars __P (());
+void expand_argv_words __P ((WORD_LIST *list));
+int try_init_path_var __P ((const char *name, char **val));
+char *export_path_var __P ((const char *name, const char *val));
+char *make_posix_path_from_filename __P ((const char *in));
+void save_cwd __P (());
+void make_path_vars_bash __P (());
+void make_path_vars_dos __P (());
+const char * find_extension __P ((const char *path));
+const char * find_path_extension __P ((const char *path, const char *file));
+const char * find_one_extension __P ((const char *path, const char *ext));
+char * get_real_path __P ((const char *path));
+void reserve_fds __P ((void));
+void init_path_separator __P ((void));
+char *rpl_getcwd __P ((char *buf, size_t size));
+char *dospath_getcwd __P ((char *buf, size_t size));
+char *encode_drive_letter __P ((char *buffer, const char letter));
+static inline
+int is_dev_drive_path (const char *path)
+{
+  if (strncmp ("/dev/", path, 5) == 0 && path[5]
+      && (path[6] == '/' || path[6] == '\0'))
+    return 1;
+  return 0;
+}
+
+#endif
+
diff -aprNU5 bash-4.1.orig/dospipe.c bash-4.1/dospipe.c
--- bash-4.1.orig/dospipe.c	1970-01-01 00:00:00 +0000
+++ bash-4.1/dospipe.c	2019-02-01 23:37:12 +0000
@@ -0,0 +1,240 @@
+/* A cheap pipe emulation for DOS.
+   Uses one read/write file descriptor. */
+
+
+#if defined (__DJGPP__)
+
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <io.h>
+
+
+struct pipe_t
+{
+  int rewind;
+  int fds[3];
+  char *name;
+};
+
+/*
+ * RW_BIT:  0 = read end
+ *          1 = write end
+ */
+#define RW_BIT     0x40000000
+
+#define READ_END   0
+#define WRITE_END  1
+#define BACK_UP    2
+
+#define IS_CLOSED(FD)      (pipes[i].fds[READ_END] == -1 && pipes[i].fds[WRITE_END] == -1 && pipes[i].fds[BACK_UP] == ((FD) & ~RW_BIT))
+#define IS_NOT_CLOSED(FD)  (pipes[i].fds[BACK_UP] == ((FD) & ~RW_BIT) && !IS_CLOSED((FD)))
+#define PIPE_FOUND(FD)     (pipes[i].fds[READ_END] == (FD) || pipes[i].fds[WRITE_END] == ((FD) | RW_BIT) || IS_CLOSED((FD)))
+
+#if !defined (OPEN_MAX)
+#define OPEN_MAX 256
+#endif
+
+static struct pipe_t pipes[OPEN_MAX];
+static int pipes_max = 0;
+
+void
+remove_pipe(int fd)
+{
+  int i, orig_errno = errno;
+
+  for (i = 0; i < pipes_max; i++)
+  {
+    if (PIPE_FOUND(fd))
+    {
+      close(fd & ~RW_BIT);
+      remove(pipes[i].name);
+      free(pipes[i].name);
+      errno = orig_errno;
+      pipes[i].fds[BACK_UP] = -1;
+      pipes[i].name = NULL;
+      if (++i == pipes_max)
+        pipes_max--;
+      return 0;
+    }
+  }
+
+  errno = orig_errno;
+}
+
+int
+rpl_close(int fd)
+{
+  int i;
+
+  for (i = 0; i < pipes_max; i++)
+  {
+    if (pipes[i].fds[READ_END] == fd)
+    {
+      /* read end closed.  */
+      pipes[i].fds[READ_END] = -1;
+      return 0;
+    }
+    else
+    if (pipes[i].fds[WRITE_END] == fd)
+    {
+      /* write end closed.  */
+      int orig_errno = errno;
+      if (pipes[i].rewind++)
+        pipes[i].fds[WRITE_END] = -1;
+      llseek(fd & ~RW_BIT, 0L, SEEK_SET);
+      errno = orig_errno;
+      return 0;
+    }
+    else
+    if (IS_CLOSED(fd))
+    {
+      /* both end closed; pipe file removed.  */
+      int orig_errno = errno;
+      close(fd & ~RW_BIT);
+      remove(pipes[i].name);
+      free(pipes[i].name);
+      errno = orig_errno;
+      pipes[i].fds[BACK_UP] = -1;
+      pipes[i].name = NULL;
+      if (++i == pipes_max)
+        pipes_max--;
+      return 0;
+    }
+    else
+    if (IS_NOT_CLOSED(fd))
+      return 0;  /* one of the ends still open.  */
+  }
+
+  return close(fd & ~RW_BIT);
+}
+
+int
+rpl_pipe(int fds[2])
+{
+  int fd, i;
+  char *tmpdir;
+  char *filename;
+
+  if (pipes_max >= OPEN_MAX)
+  {
+    errno = EMFILE;
+    return -1;
+  }
+
+  tmpdir = "/dev/env/TMPDIR";
+  if (access(tmpdir, D_OK))
+  {
+    tmpdir = "/dev/env/TMP";
+    if (access(tmpdir, D_OK))
+    {
+      tmpdir = "/dev/env/TEMP";
+      if (access(tmpdir, D_OK))
+      {
+        tmpdir = P_tmpdir;
+        if (access(tmpdir, D_OK))
+          tmpdir = ".";
+      }
+    }
+  }
+  filename = malloc(strlen(tmpdir) + sizeof("/spXXXXXX"));
+  if (filename == NULL)
+    return -1;
+  sprintf(filename, "%s/spXXXXXX", tmpdir);
+  filename = mktemp(filename);
+  if (filename == NULL)
+    return -1;
+
+  fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
+  if (fd < 0)
+  {
+    free(filename);
+    return -1;
+  }
+  if (fd < 20)
+  {
+    int tfd;
+
+    tfd = fcntl(fd, F_DUPFD, 20);
+    close(fd);
+    if (tfd < 0)
+    {
+      remove(filename);
+      free(filename);
+      return -1;
+    }
+    fd = tfd;
+  }
+
+  for (i = 0; i < pipes_max; i++)
+    if (pipes[i].name == NULL)
+      break;
+
+  pipes[i].rewind = 0;
+  pipes[i].name = filename;
+  pipes[i].fds[BACK_UP] = fd;
+  fds[0] = pipes[i].fds[READ_END] = fd;
+  fds[1] = pipes[i].fds[WRITE_END] = fd | RW_BIT;  /* Signals write end of pipe.  */
+  if (i == pipes_max && pipes_max < OPEN_MAX)
+    pipes_max++;
+
+  return 0;
+}
+
+int
+rpl_dup(int old_handle)
+{
+  return dup(old_handle & ~RW_BIT);
+}
+
+int
+rpl_dup2(int existing_handle, int new_handle)
+{
+  return dup2(existing_handle & ~RW_BIT, new_handle);
+}
+
+ssize_t
+rpl_read(int fd, void *buffer, size_t count)
+{
+  return read(fd & ~RW_BIT, buffer, count);
+}
+
+ssize_t
+rpl__read(int fd, void *buffer, size_t count)
+{
+  return _read(fd & ~RW_BIT, buffer, count);
+}
+
+int
+rpl_write(int fd, const void *buffer, size_t count)
+{
+  return write(fd & ~RW_BIT, buffer, count);
+}
+
+static void
+remove_pipe_files(void)
+{
+  int i;
+
+  for (i = 0; i < pipes_max; i++)
+  {
+    if (pipes[i].fds[BACK_UP] != -1)
+      close(pipes[i].fds[BACK_UP]);
+    if (pipes[i].name)
+      remove(pipes[i].name);
+  }
+}
+
+/* This is called before `main' to install the temporary file deleter at exit.  */
+static void __attribute__((constructor))
+djgpp_bash_startup (void)
+{
+  atexit(remove_pipe_files);
+}
+
+#endif /* __DJGPP__ */
diff -aprNU5 bash-4.1.orig/dospipe.h bash-4.1/dospipe.h
--- bash-4.1.orig/dospipe.h	1970-01-01 00:00:00 +0000
+++ bash-4.1/dospipe.h	2019-02-01 23:37:12 +0000
@@ -0,0 +1,39 @@
+#ifndef DOS_PIPE_SUPPORT
+#define DOS_PIPE_SUPPORT
+
+/* Always use DJGPP's implementations of these functions.
+   In a sequence of headers, this header must be included as last! */
+
+
+void
+remove_pipe(int fd);
+
+#undef  close
+#define close rpl_close
+int rpl_close(int fd);
+
+#undef  dup
+#define dup rpl_dup
+int rpl_dup(int old_handle);
+
+#undef  dup2
+#define dup2 rpl_dup2
+int rpl_dup2(int existing_handle, int new_handle);
+
+#undef  pipe
+#define pipe rpl_pipe
+int rpl_pipe(int fds[2]);
+
+#undef  read
+#define read rpl_read 
+ssize_t rpl_read(int fd, void *buffer, size_t count);
+
+#undef  _read
+#define _read rpl__read 
+ssize_t rpl__read(int fd, void *buffer, size_t count);
+
+#undef  write
+#define write rpl_write 
+int rpl_write(int fd, const void *buffer, size_t count);
+
+#endif /* DOS_PIPE_SUPPORT */
diff -aprNU5 bash-4.1.orig/execute_cmd.c bash-4.1/execute_cmd.c
--- bash-4.1.orig/execute_cmd.c	2009-12-30 17:55:36 +0000
+++ bash-4.1/execute_cmd.c	2019-02-01 23:37:12 +0000
@@ -57,16 +57,28 @@
 extern int errno;
 #endif
 
 #define NEED_FPURGE_DECL
 
+#if !defined (HAVE_WORKING_FORK)
+#  include "nofork.h"
+#endif /* !HAVE_WORKING_FORK */
+
+#if defined (__DJGPP__)
+#  include "dospath.h"
+#endif
+
 #include "bashansi.h"
 #include "bashintl.h"
 
 #include "memalloc.h"
 #include "shell.h"
+#if defined (__MSDOS__) && !defined (__DJGPP__)
+#include <y_tab.h>	/* use <...> so we pick it up from the build directory */
+#else  /* !__MSDOS__ */
 #include <y.tab.h>	/* use <...> so we pick it up from the build directory */
+#endif /* !__MSDOS__ */
 #include "flags.h"
 #include "builtins.h"
 #include "hashlib.h"
 #include "jobs.h"
 #include "execute_cmd.h"
@@ -96,10 +108,17 @@ extern int errno;
 
 #if defined (HISTORY)
 #  include "bashhist.h"
 #endif
 
+#if defined (__DJGPP__)
+/* DJGPP always uses its own pipe implementation.
+   Required for close, dup2 and pipe.  */
+
+#  include "dospipe.h"
+#endif /* __DJGPP__ */
+
 extern int posixly_correct;
 extern int expand_aliases;
 extern int autocd;
 extern int breaking, continuing, loop_level;
 extern int parse_and_execute_level, running_trap, sourcelevel;
@@ -522,10 +541,15 @@ execute_command_internal (command, async
   int exec_result, user_subshell, invert, ignore_return, was_error_trap;
   REDIRECT *my_undo_list, *exec_undo_list;
   volatile int last_pid;
   volatile int save_line_number;
 
+#if !defined (HAVE_WORKING_FORK)
+  if (subshell_skip_commands)
+    return (EXECUTION_SUCCESS);
+#endif /* !HAVE_WORKING_FORK */
+
 #if 0
   if (command == 0 || breaking || continuing || read_but_dont_execute)
     return (EXECUTION_SUCCESS);
 #else
   if (breaking || continuing)
@@ -575,10 +599,15 @@ execute_command_internal (command, async
       /* Fork a subshell, turn off the subshell bit, turn off job
 	 control and call execute_command () on the command again. */
       line_number_for_err_trap = line_number;
       paren_pid = make_child (savestring (make_command_string (command)),
 			      asynchronous);
+#if !defined (HAVE_WORKING_FORK)
+      /* force execute in parent shell */
+      nofork_wait_status = execute_in_subshell (command, asynchronous, pipe_in,
+                                                pipe_out, fds_to_close);
+#endif /* !HAVE_WORKING_FORK */
       if (paren_pid == 0)
 	exit (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
 	/* NOTREACHED */
       else
 	{
@@ -637,10 +666,13 @@ execute_command_internal (command, async
 
 	      run_pending_traps ();
 
 	      return (EXECUTION_SUCCESS);
 	    }
+#if !defined (HAVE_WORKING_FORK)
+        return 0;
+#endif /* !HAVE_WORKING_FORK */
 	}
     }
 
 #if defined (COMMAND_TIMING)
   if (command->flags & CMD_TIME_PIPELINE)
@@ -752,10 +784,13 @@ execute_command_internal (command, async
 	    stop_pipeline (asynchronous, (COMMAND *)NULL);
 
 	    if (asynchronous)
 	      {
 		DESCRIBE_PID (last_made_pid);
+#if !defined (HAVE_WORKING_FORK)
+                last_made_pid = NO_PID;
+#endif /* !HAVE_WORKING_FORK */
 	      }
 	    else
 #if !defined (JOB_CONTROL)
 	      /* Do not wait for asynchronous processes started from
 		 startup files. */
@@ -784,10 +819,19 @@ execute_command_internal (command, async
 	  ((posixly_correct && interactive == 0 && special_builtin_failed) ||
 	   (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)))
 	{
 	  last_command_exit_value = exec_result;
 	  run_pending_traps ();
+#if !defined (HAVE_WORKING_FORK)
+          if (subshell_environment)
+            {
+              subshell_exit_value = exec_result;
+              subshell_exit_builtin = 0;
+              subshell_skip_commands = 1;
+              return (EXECUTION_SUCCESS);
+            }
+#endif /* !HAVE_WORKING_FORK */
 	  jump_to_top_level (ERREXIT);
 	}
 
       break;
 
@@ -1292,10 +1336,25 @@ execute_in_subshell (command, asynchrono
 {
   int user_subshell, return_code, function_value, should_redir_stdin, invert;
   int ois, user_coproc;
   int result;
   COMMAND *tcom;
+#if !defined (HAVE_WORKING_FORK)
+  COMMAND *old_command;
+  OLDENVBUF oldenvbuf;
+  char *old_trap_list[1];
+  int old_sigmodes[1];
+#endif /* !HAVE_WORKING_FORK */
+
+#if !defined (HAVE_WORKING_FORK)
+  /* save arg list */
+  old_command = command;
+  command = copy_command (old_command);
+  
+  /* Save everything relevant.  */
+  nofork_save_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
 
   USE_VAR(user_subshell);
   USE_VAR(user_coproc);
   USE_VAR(invert);
   USE_VAR(tcom);
@@ -1363,10 +1422,11 @@ execute_in_subshell (command, asynchrono
 	subshell_environment |= SUBSHELL_PIPE;
       if (user_coproc)
 	subshell_environment |= SUBSHELL_COPROC;
     }
 
+#if defined (HAVE_WORKING_FORK)
   reset_terminating_signals ();		/* in sig.c */
   /* Cancel traps, in trap.c. */
   restore_original_signals ();
 
   /* Make sure restore_original_signals doesn't undo the work done by
@@ -1376,10 +1436,23 @@ execute_in_subshell (command, asynchrono
   if (asynchronous)
     {
       setup_async_signals ();
       asynchronous = 0;
     }
+#else /* ! HAVE_WORKING_FORK */
+  /* Save exit trap and signal. */
+#if 0
+  old_trap_list[0] = trap_list[0] ? savestring (trap_list[0]) : NULL;
+#else
+  old_trap_list[0] = trap_list[0];
+  trap_list[0] = NULL;
+#endif
+  old_sigmodes[0] = get_signal_modes (0);
+
+  /* Cancel exit trap .*/
+  restore_default_signal (0);
+#endif /* ! HAVE_WORKING_FORK */
 
 #if defined (JOB_CONTROL)
   set_sigchld_handler ();
 #endif /* JOB_CONTROL */
 
@@ -1418,11 +1491,18 @@ execute_in_subshell (command, asynchrono
 
   /* Do redirections, then dispose of them before recursive call. */
   if (command->redirects)
     {
       if (do_redirections (command->redirects, RX_ACTIVE) != 0)
+#if defined (HAVE_WORKING_FORK)
 	exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+#else /* !HAVE_WORKING_FORK */
+        {
+          return_code = invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
+          goto subshell_exit;
+        }
+#endif /* !HAVE_WORKING_FORK */
 
       dispose_redirects (command->redirects);
       command->redirects = (REDIRECT *)NULL;
     }
 
@@ -1465,10 +1545,21 @@ execute_in_subshell (command, asynchrono
      need to handle a possible `return'. */
   function_value = 0;
   if (return_catch_flag)
     function_value = setjmp (return_catch);
 
+#if !defined (HAVE_WORKING_FORK)
+  begin_unwind_frame ("subshell-execute-command");
+  unwind_protect_int (subshell_exit_value);
+  unwind_protect_int (subshell_exit_builtin);
+  unwind_protect_int (subshell_skip_commands);
+
+  subshell_exit_value = 0;
+  subshell_exit_builtin = 1;
+  subshell_skip_commands = 0;
+#endif /* !HAVE_WORKING_FORK */
+
   /* If we're going to exit the shell, we don't want to invert the return
      status. */
   if (result == EXITPROG)
     invert = 0, return_code = last_command_exit_value;
   else if (result)
@@ -1476,10 +1567,19 @@ execute_in_subshell (command, asynchrono
   else if (function_value)
     return_code = return_catch_value;
   else
     return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
 
+#if !defined (HAVE_WORKING_FORK)
+  if (subshell_skip_commands)
+    {
+      return_code = subshell_exit_value;
+      last_command_exit_value = return_code;
+    }
+  run_unwind_frame ("subshell-execute-command");
+#endif /* !HAVE_WORKING_FORK */
+
   /* If we are asked to, invert the return value. */
   if (invert)
     return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE
 						     : EXECUTION_SUCCESS;
 
@@ -1490,10 +1590,24 @@ execute_in_subshell (command, asynchrono
       last_command_exit_value = return_code;
       return_code = run_exit_trap ();
     }
 
   subshell_level--;
+#if !defined (HAVE_WORKING_FORK)
+subshell_exit:
+  /* restore exit trap and signal.  */
+  restore_default_signal (0);
+  trap_list[0] = old_trap_list[0];
+  set_signal_modes (0, old_sigmodes[0]);
+
+  /* Restore fd, jmp_buf, current directory, global variables.  */
+  nofork_restore_all_environment (&oldenvbuf);
+
+  /* Restore arg list.  */
+  dispose_command (command);
+  command = old_command;
+#endif /* !HAVE_WORKING_FORK */
   return (return_code);
   /* NOTREACHED */
 }
 
 #if defined (COPROCESS_SUPPORT)
@@ -2107,11 +2221,13 @@ execute_pipeline (command, asynchronous,
 
       /* Now copy the old information into the new bitmap. */
       xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size);
 
       /* And mark the pipe file descriptors to be closed. */
+#if defined (HAVE_WORKING_FORK) /* XXX Check on the validity of this.  */
       fd_bitmap->bitmap[fildes[0]] = 1;
+#endif /* HAVE_WORKING_FORK */
 
       /* In case there are pipe or out-of-processes errors, we
 	 want all these file descriptors to be closed when
 	 unwind-protects are run, and the storage used for the
 	 bitmaps freed up. */
@@ -2413,10 +2529,14 @@ execute_for_command (for_command)
 	}
       retval = execute_command (for_command->action);
       REAP ();
       QUIT;
 
+#if !defined (HAVE_WORKING_SHELL)
+      if (subshell_skip_commands)
+        break;
+#endif /* ! HAVE_WORKING_SHELL */
       if (breaking)
 	{
 	  breaking--;
 	  break;
 	}
@@ -2569,10 +2689,15 @@ execute_arith_for_command (arith_for_com
       /* Execute the body of the arithmetic for command. */
       QUIT;
       body_status = execute_command (arith_for_command->action);
       QUIT;
 
+#if !defined (HAVE_WORKING_SHELL)
+      if (subshell_skip_commands)
+        break;
+#endif /* ! HAVE_WORKING_SHELL */
+
       /* Handle any `break' or `continue' commands executed by the body. */
       if (breaking)
 	{
 	  breaking--;
 	  break;
@@ -2879,10 +3004,14 @@ execute_select_command (select_command)
       retval = execute_command (select_command->action);
 
       REAP ();
       QUIT;
 
+#if !defined (HAVE_WORKING_SHELL)
+      if (subshell_skip_commands)
+        break;
+#endif
       if (breaking)
 	{
 	  breaking--;
 	  break;
 	}
@@ -3059,10 +3188,15 @@ execute_while_or_until (while_command, t
   while (1)
     {
       return_value = execute_command (while_command->test);
       REAP ();
 
+#if !defined (HAVE_WORKING_FORK)
+      if (subshell_skip_commands)
+        break;
+#endif /* !HAVE_WORKING_FORK */
+
       /* Need to handle `break' in the test when we would break out of the
          loop.  The job control code will set `breaking' to loop_level
          when a job in a loop is stopped with SIGTSTP.  If the stopped job
          is in the loop test, `breaking' will not be reset unless we do
          this, and the shell will cease to execute commands. */
@@ -3113,10 +3247,15 @@ execute_if_command (if_command)
   save_line_number = line_number;
   if_command->test->flags |= CMD_IGNORE_RETURN;
   return_value = execute_command (if_command->test);
   line_number = save_line_number;
 
+#if !defined (HAVE_WORKING_FORK)
+  if (subshell_skip_commands)
+     return (EXECUTION_SUCCESS);
+#endif /* !HAVE_WORKING_FORK */
+
   if (return_value == EXECUTION_SUCCESS)
     {
       QUIT;
 
       if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN))
@@ -3400,15 +3539,21 @@ execute_null_command (redirects, pipe_in
 
   if (forcefork || pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
     {
       /* We have a null command, but we really want a subshell to take
 	 care of it.  Just fork, do piping and redirections, and exit. */
+#if defined (HAVE_WORKING_FORK)
       if (make_child ((char *)NULL, async) == 0)
 	{
 	  /* Cancel traps, in trap.c. */
 	  restore_original_signals ();		/* XXX */
 
+#else  /* !HAVE_WORKING_FORK */
+          int ofds[] = { -1, -1, -1 };
+          make_child ((char *)NULL, async);
+          nofork_save_std_fds (ofds);
+#endif /* !HAVE_WORKING_FORK */
 	  do_piping (pipe_in, pipe_out);
 
 #if defined (COPROCESS_SUPPORT)
 	  coproc_closeall ();
 #endif
@@ -3418,22 +3563,36 @@ execute_null_command (redirects, pipe_in
 	    subshell_environment |= SUBSHELL_ASYNC;
 	  if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
 	    subshell_environment |= SUBSHELL_PIPE;
 
 	  if (do_redirections (redirects, RX_ACTIVE) == 0)
+#if defined (HAVE_WORKING_FORK)
 	    exit (EXECUTION_SUCCESS);
 	  else
 	    exit (EXECUTION_FAILURE);
+#else  /* !HAVE_WORKING_FORK */
+	    nofork_wait_status = (EXECUTION_SUCCESS);
+	  else
+	    nofork_wait_status = (EXECUTION_FAILURE);
+#endif /* !HAVE_WORKING_FORK */
+
+#if defined (HAVE_WORKING_FORK)
 	}
       else
 	{
+#endif /* HAVE_WORKING_FORK */
 	  close_pipes (pipe_in, pipe_out);
+#if !defined (HAVE_WORKING_FORK)
+          nofork_restore_std_fds (ofds);
+#endif /* !HAVE_WORKING_FORK */
 #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
 	  unlink_fifo_list ();
 #endif
 	  return (EXECUTION_SUCCESS);
+#if defined (HAVE_WORKING_FORK)
 	}
+#endif /* HAVE_WORKING_FORK */
     }
   else
     {
       /* Even if there aren't any command names, pretend to do the
 	 redirections that are specified.  The user expects the side
@@ -3594,10 +3753,11 @@ execute_simple_command (simple_command,
 	 vast majority of cases. */
       maybe_make_export_env ();
 
       /* Don't let a DEBUG trap overwrite the command string to be saved with
 	 the process/job associated with this child. */
+#if defined (HAVE_WORKING_FORK)
       if (make_child (savestring (the_printed_command_except_trap), async) == 0)
 	{
 	  already_forked = 1;
 	  simple_command->flags |= CMD_NO_FORK;
 
@@ -3629,10 +3789,15 @@ execute_simple_command (simple_command,
 #endif
 	  command_line = (char *)NULL;      /* don't free this. */
 	  bind_lastarg ((char *)NULL);
 	  return (result);
 	}
+#else  /* ! HAVE_WORKING_FORK */
+      /* Just set already_forked and CMD_NO_FORK.  */
+      already_forked = 1;
+      simple_command->flags |= CMD_NO_FORK;
+#endif /* ! HAVE_WORKING_FORK */
     }
 
   /* If we are re-running this as the result of executing the `command'
      builtin, do not expand the command words a second time. */
   if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
@@ -3658,11 +3823,19 @@ execute_simple_command (simple_command,
       this_command_name = 0;
       result = execute_null_command (simple_command->redirects,
 				     pipe_in, pipe_out,
 				     already_forked ? 0 : async);
       if (already_forked)
+#if defined (HAVE_WORKING_FORK)
 	exit (result);
+#else  /* !HAVE_WORKING_FORK */
+        {
+          bind_lastarg ((char *)NULL);
+          FREE (command_line);
+          return (result);
+        }
+#endif /* !HAVE_WORKING_FORK */
       else
 	{
 	  bind_lastarg ((char *)NULL);
 	  set_pipestatus_from_exit (result);
 	  return (result);
@@ -3779,10 +3952,11 @@ run_builtin:
     {
       if (builtin)
 	unwind_protect_int (executing_builtin);	/* modified in execute_builtin */
       if (already_forked)
 	{
+#if defined (HAVE_WORKING_FORK)
 	  /* reset_terminating_signals (); */	/* XXX */
 	  /* Cancel traps, in trap.c. */
 	  restore_original_signals ();
 
 	  if (async)
@@ -3791,17 +3965,22 @@ run_builtin:
 		    pipe_in == NO_PIPE &&
 		    (stdin_redirects (simple_command->redirects) == 0))
 		async_redirect_stdin ();
 	      setup_async_signals ();
 	    }
+#endif /* HAVE_WORKING_FORK */
 
 	  subshell_level++;
 	  execute_subshell_builtin_or_function
 	    (words, simple_command->redirects, builtin, func,
 	     pipe_in, pipe_out, async, fds_to_close,
 	     simple_command->flags);
 	  subshell_level--;
+#if !defined (HAVE_WORKING_FORK)
+          result = nofork_wait_status; 
+          goto return_result;
+#endif /* !HAVE_WORKING_FORK */
 	}
       else
 	{
 	  result = execute_builtin_or_function
 	    (words, builtin, func, simple_command->redirects, fds_to_close,
@@ -3851,10 +4030,26 @@ run_builtin:
 
   execute_disk_command (words, simple_command->redirects, command_line,
 			pipe_in, pipe_out, async, fds_to_close,
 			simple_command->flags);
 
+#if !defined (HAVE_WORKING_FORK)
+/* Set result code. */
+  result = nofork_wait_status;
+
+#if 0
+  /* Set result code for sh -c "foo" */
+  if (startup_state == 2)
+    {
+      if ((result & 0x0000ff00) == 0x0000ff00)
+        result &= 0x000000ff;
+    }
+#endif
+  /* lastarg may no longer be valid if path expansion took place.  */
+  lastarg = lastword->word->word;
+#endif /* !HAVE_WORKING_FORK */
+
  return_result:
   bind_lastarg (lastarg);
   FREE (command_line);
   dispose_words (words);
   discard_unwind_frame ("simple-command");
@@ -3967,10 +4162,16 @@ execute_builtin (builtin, words, flags,
   /* This shouldn't happen, but in case `return' comes back instead of
      longjmp'ing, we need to unwind. */
   if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
     discard_unwind_frame ("return_temp_env");
 
+#if !defined (HAVE_WORKING_FORK)
+  /* check subshell return */
+  if (builtin == exit_builtin && result == EXECUTION_SUCCESS)
+    result = last_command_exit_value;
+#endif /* !HAVE_WORKING_FORK */
+
   if (subshell == 0 && isbltinenv)
     run_unwind_frame ("builtin_env");
 
   if (eval_unwind)
     {
@@ -4245,17 +4446,24 @@ execute_subshell_builtin_or_function (wo
      int pipe_in, pipe_out, async;
      struct fd_bitmap *fds_to_close;
      int flags;
 {
   int result, r, funcvalue;
+#if !defined (HAVE_WORKING_FORK)
+  OLDENVBUF oldenvbuf;
+#endif /* !HAVE_WORKING_FORK */
 #if defined (JOB_CONTROL)
   int jobs_hack;
 
   jobs_hack = (builtin == jobs_builtin) &&
 		((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE);
 #endif
 
+#if !defined (HAVE_WORKING_FORK)
+  /* save fd, jmp_buf, current directory, global variables */
+  nofork_save_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
   /* A subshell is neither a login shell nor interactive. */
   login_shell = interactive = 0;
 
   if (async)
     subshell_environment |= SUBSHELL_ASYNC;
@@ -4284,18 +4492,27 @@ execute_subshell_builtin_or_function (wo
     close_fd_bitmap (fds_to_close);
 
   do_piping (pipe_in, pipe_out);
 
   if (do_redirections (redirects, RX_ACTIVE) != 0)
+#if defined (HAVE_WORKING_FORK)
     exit (EXECUTION_FAILURE);
+#else  /* !HAVE_WORKING_FORK */
+    {
+      nofork_wait_status = (EXECUTION_FAILURE);
+      nofork_restore_all_environment (&oldenvbuf);
+      return;
+    }
+#endif /* !HAVE_WORKING_FORK */
 
   if (builtin)
     {
       /* Give builtins a place to jump back to on failure,
 	 so we don't go back up to main(). */
       result = setjmp (top_level);
 
+#if defined (HAVE_WORKING_FORK)
       /* Give the return builtin a place to jump to when executed in a subshell
          or pipeline */
       funcvalue = 0;
       if (return_catch_flag && builtin == return_builtin)
         funcvalue = setjmp (return_catch);
@@ -4319,10 +4536,28 @@ execute_subshell_builtin_or_function (wo
     {
       r = execute_function (var, words, flags, fds_to_close, async, 1);
       fflush (stdout);
       exit (r);
     }
+#else  /* !HAVE_WORKING_FORK */
+      if (result == EXITPROG)
+	nofork_wait_status = (last_command_exit_value);
+      else if (result)
+	nofork_wait_status = (EXECUTION_FAILURE);
+      else
+	{
+	  r = execute_builtin (builtin, words, flags, 1);
+	  if (r == EX_USAGE)
+	    r = EX_BADUSAGE;
+	  nofork_wait_status = r;
+	}
+    }
+  else
+    nofork_wait_status = (execute_function (var, words, flags, fds_to_close, async, 1));
+  /* restore fd, jmp_buf, current directory, global variables */
+  nofork_restore_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
 }
 
 /* Execute a builtin or function in the current shell context.  If BUILTIN
    is non-null, it is the builtin command to execute, otherwise VAR points
    to the body of a function.  WORDS are the command's arguments, REDIRECTS
@@ -4470,10 +4705,13 @@ execute_disk_command (words, redirects,
   char *pathname, *command, **args;
   int nofork;
   pid_t pid;
   SHELL_VAR *hookf;
   WORD_LIST *wl;
+#if !defined (HAVE_WORKING_FORK)
+  int ofds[3] = { -1, -1, -1 };
+#endif /* !HAVE_WORKING_FORK */
 
   nofork = (cmdflags & CMD_NO_FORK);  /* Don't fork, just exec, if no pipes */
   pathname = words->word->word;
 
 #if defined (RESTRICTED_SHELL)
@@ -4503,27 +4741,45 @@ execute_disk_command (words, redirects,
 
   /* We have to make the child before we check for the non-existence
      of COMMAND, since we want the error messages to be redirected. */
   /* If we can get away without forking and there are no pipes to deal with,
      don't bother to fork, just directly exec the command. */
+#if defined (HAVE_WORKING_FORK)
   if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
     pid = 0;
   else
     pid = make_child (savestring (command_line), async);
+#else  /* !HAVE_WORKING_FORK */
+  if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
+    pid = nofork_current_pid;
+  else
+    {
+      pid = make_child (savestring (command_line), async);
+      nofork_save_std_fds (ofds);
+    }
+#endif /* !HAVE_WORKING_FORK */
 
+#if defined (HAVE_WORKING_FORK)
   if (pid == 0)
+#else  /* !HAVE_WORKING_FORK */
+  if (pid)
+#endif /* !HAVE_WORKING_FORK */
     {
       int old_interactive;
+#if !defined (HAVE_WORKING_FORK)
+      int old_subshell_environment = subshell_environment;
+#endif /* !HAVE_WORKING_FORK */
 
 #if 0
       /* This has been disabled for the time being. */
 #if !defined (ARG_MAX) || ARG_MAX >= 10240
       if (posixly_correct == 0)
 	put_gnu_argv_flags_into_env ((long)getpid (), glob_argv_flags);
 #endif
 #endif
 
+#if defined (HAVE_WORKING_FORK)
       /* Cancel traps, in trap.c. */
       restore_original_signals ();
 
       /* restore_original_signals may have undone the work done
 	 by make_child to ensure that SIGINT and SIGQUIT are ignored
@@ -4534,10 +4790,11 @@ execute_disk_command (words, redirects,
 		pipe_in == NO_PIPE &&
 		(stdin_redirects (redirects) == 0))
 	    async_redirect_stdin ();
 	  setup_async_signals ();
 	}
+#endif /* HAVE_WORKING_FORK */
 
       /* This functionality is now provided by close-on-exec of the
 	 file descriptors manipulated by redirection and piping.
 	 Some file descriptors still need to be closed in all children
 	 because of the way bash does pipes; fds_to_close is a
@@ -4558,11 +4815,16 @@ execute_disk_command (words, redirects,
 #if defined (PROCESS_SUBSTITUTION)
 	  /* Try to remove named pipes that may have been created as the
 	     result of redirections. */
 	  unlink_fifo_list ();
 #endif /* PROCESS_SUBSTITUTION */
+#if defined (HAVE_WORKING_FORK)
 	  exit (EXECUTION_FAILURE);
+#else  /* !HAVE_WORKING_FORK */
+	  nofork_wait_status = (EXECUTION_FAILURE);
+	  goto return_exit;
+#endif /* !HAVE_WORKING_FORK */
 	}
 
       if (async)
 	interactive = old_interactive;
 
@@ -4570,52 +4832,91 @@ execute_disk_command (words, redirects,
 	{
 	  hookf = find_function (NOTFOUND_HOOK);
 	  if (hookf == 0)
 	    {
 	      internal_error (_("%s: command not found"), pathname);
+#if defined (HAVE_WORKING_FORK)
 	      exit (EX_NOTFOUND);	/* Posix.2 says the exit status is 127 */
+#else  /* !HAVE_WORKING_FORK */
+	  nofork_wait_status = (EX_NOTFOUND);
+	  goto return_exit;
+#endif /* !HAVE_WORKING_FORK */
 	    }
 
 	  wl = make_word_list (make_word (NOTFOUND_HOOK), words);
+#if defined (HAVE_WORKING_FORK)
+	  exit (execute_shell_function (hookf, wl));
+#else  /* !HAVE_WORKING_FORK */
+#if 0
+// TO BE DONE!!!!!!!!!!
 	  exit (execute_shell_function (hookf, wl));
+#else
+printf("exit (execute_shell_function (hookf, wl));\n");
+printf("%s: %d\n", __FUNCTION__, __LINE__);
+#endif
+	  nofork_wait_status = (EX_NOTFOUND);
+	  goto return_exit;
+#endif /* !HAVE_WORKING_FORK */
 	}
 
+#if defined (__DJGPP__)
+     if (path_expand)
+       expand_argv_words (words);
+#endif /* __DJGPP__ */
+
       /* Execve expects the command name to be in args[0].  So we
 	 leave it there, in the same format that the user used to
 	 type it in. */
       args = strvec_from_word_list (words, 0, 0, (int *)NULL);
+#if defined (HAVE_WORKING_FORK)
       exit (shell_execve (command, args, export_env));
+#else  /* !HAVE_WORKING_FORK */
+      nofork_wait_status = shell_execve (command, args, export_env);
+      free (args);
+return_exit:
+      nofork_restore_std_fds (ofds);
+
+      /* for parent shell */
+      if (nofork && pid == nofork_current_pid)
+        goto disk_command_nofork;
+
+      /* restore parent environment */
+      subshell_environment = old_subshell_environment;
     }
   else
     {
 parent_return:
+#endif /* !HAVE_WORKING_FORK */
       /* Make sure that the pipes are closed in the parent. */
       close_pipes (pipe_in, pipe_out);
 #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
       if (variable_context == 0)
         unlink_fifo_list ();
 #endif
+#if defined (__MSDOS__)
+disk_command_nofork:
+#endif /* __MSDOS__ */
       FREE (command);
     }
 }
 
 /* CPP defines to decide whether a particular index into the #! line
    corresponds to a valid interpreter name or argument character, or
    whitespace.  The MSDOS define is to allow \r to be treated the same
    as \n. */
 
-#if !defined (MSDOS)
+#if !defined (__MSDOS__)
 #  define STRINGCHAR(ind) \
     (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n')
 #  define WHITECHAR(ind) \
     (ind < sample_len && whitespace (sample[ind]))
-#else	/* MSDOS */
+#else	/* __MSDOS__ */
 #  define STRINGCHAR(ind) \
     (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r')
 #  define WHITECHAR(ind) \
     (ind < sample_len && whitespace (sample[ind]))
-#endif	/* MSDOS */
+#endif	/* __MSDOS__ */
 
 static char *
 getinterp (sample, sample_len, endp)
      char *sample;
      int sample_len, *endp;
@@ -4732,11 +5033,19 @@ initialize_subshell ()
      sourced file with a temporary environment supplied to the `source/.'
      builtin.  Such variables are not supposed to be exported (empirical
      testing with sh and ksh).  Just throw it away; don't worry about a
      memory leak. */
   if (vc_isbltnenv (shell_variables))
+#if defined (HAVE_WORKING_FORK)
     shell_variables = shell_variables->down;
+#else  /* !HAVE_WORKING_FORK */
+    {
+      VAR_CONTEXT *sv = shell_variables;
+      shell_variables = shell_variables->down;
+      dispose_var_context (shell_variables);
+    }
+#endif /* !HAVE_WORKING_FORK */
 
   clear_unwind_protect_list (0);
   /* XXX -- are there other things we should be resetting here? */
   parse_and_execute_level = 0;		/* nothing left to restore it */
 
@@ -4781,11 +5090,19 @@ shell_execve (command, args, env)
   int larray, i, fd;
   char sample[80];
   int sample_len;
 
   SETOSTYPE (0);		/* Some systems use for USG/POSIX semantics */
+#if defined (HAVE_WORKING_FORK)
   execve (command, args, env);
+#else  /* !HAVE_WORKING_FORK */
+  {
+    int status = bash_spawnve (command, args, env);
+    if (status > -1)
+      return status;
+  }
+#endif /* !HAVE_WORKING_FORK */
   i = errno;			/* error from execve() */
   CHECK_TERMSIG;
   SETOSTYPE (1);
 
   /* If we get to this point, then start checking out the file.
@@ -4869,13 +5186,15 @@ shell_execve (command, args, env)
     }
 
   /* We have committed to attempting to execute the contents of this file
      as shell commands. */
 
+#if defined (HAVE_WORKING_FORK)
   initialize_subshell ();
 
   set_sigint_handler ();
+#endif /* HAVE_WORKING_FORK */
 
   /* Insert the name of this shell into the argument list. */
   larray = strvec_len (args) + 1;
   args = strvec_resize (args, larray + 1);
 
@@ -4900,10 +5219,11 @@ shell_execve (command, args, env)
       for (i = 1; i < subshell_argc; i++)
 	free (subshell_argv[i]);
       free (subshell_argv);
     }
 
+#if defined (HAVE_WORKING_FORK)
   dispose_command (currently_executing_command);	/* XXX */
   currently_executing_command = (COMMAND *)NULL;
 
   subshell_argc = larray;
   subshell_argv = args;
@@ -4911,10 +5231,13 @@ shell_execve (command, args, env)
 
   unbind_args ();	/* remove the positional parameters */
 
   longjmp (subshell_top_level, 1);
   /*NOTREACHED*/
+#else  /* !HAVE_WORKING_FORK */
+  return bash_spawnve (shell_name, args, env);
+#endif /* !HAVE_WORKING_FORK */
 }
 
 static int
 execute_intern_function (name, function)
      WORD_DESC *name;
diff -aprNU5 bash-4.1.orig/externs.h bash-4.1/externs.h
--- bash-4.1.orig/externs.h	2009-12-22 20:56:46 +0000
+++ bash-4.1/externs.h	2019-02-01 23:37:12 +0000
@@ -214,11 +214,18 @@ extern int fpurge __P((FILE *stream));
 #endif /* HAVE_DECL_FPURGE */
 #endif /* NEED_FPURGE_DECL */
 
 /* Declarations for functions defined in lib/sh/getcwd.c */
 #if !defined (HAVE_GETCWD)
+#if !defined (__DJGPP__)
 extern char *getcwd __P((char *, size_t));
+#else  /* __DJGPP__ */
+/* DJGPP always uses its own getcwd implementation. */
+#undef  getcwd
+#define getcwd rpl_getcwd
+extern char *rpl_getcwd __P((char *, size_t));
+#endif /* __DJGPP__ */
 #endif
 
 /* Declarations for functions defined in lib/sh/input_avail.c */
 extern int input_avail __P((int));
 
diff -aprNU5 bash-4.1.orig/findcmd.c bash-4.1/findcmd.c
--- bash-4.1.orig/findcmd.c	2009-06-05 20:25:38 +0000
+++ bash-4.1/findcmd.c	2019-02-01 23:37:12 +0000
@@ -41,10 +41,14 @@
 #include "hashlib.h"
 #include "pathexp.h"
 #include "hashcmd.h"
 #include "findcmd.h"	/* matching prototypes and declarations */
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+#endif
+
 extern int posixly_correct;
 
 /* Static functions defined and used in this file. */
 static char *_find_user_command_internal __P((const char *, int));
 static char *find_user_command_internal __P((const char *, int));
@@ -293,10 +297,13 @@ search_for_command (pathname)
      const char *pathname;
 {
   char *hashed_file, *command;
   int temp_path, st;
   SHELL_VAR *path;
+#if defined (__DJGPP__)
+  int bin_cmd = 0;
+#endif /* __DJGPP__ */
 
   hashed_file = command = (char *)NULL;
 
   /* If PATH is in the temporary environment for this command, don't use the
      hash table to search for the full pathname. */
@@ -309,10 +316,19 @@ search_for_command (pathname)
      that is already completely specified or if we're using a command-
      specific value for PATH. */
   if (path == 0 && absolute_program (pathname) == 0)
     hashed_file = phash_search (pathname);
 
+#if defined (__DJGPP__)
+  if (strncmp (pathname, "/bin/", 5) == 0)
+    {
+      bin_cmd = 1;
+      if (path == 0 && !hashed_file)
+        hashed_file = phash_search (pathname);
+    }
+#endif /* __DJGPP__ */
+
   /* If a command found in the hash table no longer exists, we need to
      look for it in $PATH.  Thank you Posix.2.  This forces us to stat
      every command found in the hash table. */
 
   if (hashed_file && (posixly_correct || check_hashed_filenames))
@@ -326,14 +342,43 @@ search_for_command (pathname)
 	}
     }
 
   if (hashed_file)
     command = hashed_file;
+#if defined (__DJGPP__)
+  else if (bin_cmd)
+    {
+      char *base;
+      command = find_absolute_program (pathname, FS_NODIRS | FS_EXISTS);
+      if (command)
+        return command;
+      base = basename (pathname);
+      if (temp_path)
+        {
+          command = find_user_command_in_path (pathname, value_cell (path),
+                                               FS_EXEC_PREFERRED|FS_NODIRS);
+          if (tempvar_p (path))
+            dispose_variable (path);
+        }
+      else
+        command = find_user_command (base);
+      if (command && hashing_enabled && temp_path == 0)
+        phash_insert ((char *)pathname, command, dot_found_in_search, 1);
+
+      return command;
+    }
+  else if (absolute_program (pathname))
+    {
+      const char *path = find_extension (pathname);
+      return path ? savestring (path) : savestring (pathname);
+    }
+#else /* !__DJGPP__ */
   else if (absolute_program (pathname))
     /* A command containing a slash is not looked up in PATH or saved in
        the hash table. */
     command = savestring (pathname);
+#endif /* !__DJGPP__ */
   else
     {
       /* If $PATH is in the temporary environment, we've already retrieved
 	 it, so don't bother trying again. */
       if (temp_path)
@@ -436,10 +481,15 @@ static char *
 find_absolute_program (name, flags)
      const char *name;
      int flags;
 {
   int st;
+#if defined (__DJGPP__)
+  const char *path = find_extension (name);
+  if (path)
+    return (savestring (path));
+#endif /* __DJGPP__ */
 
   st = file_status (name);
 
   /* If the file doesn't exist, quit now. */
   if ((st & FS_EXISTS) == 0)
@@ -461,20 +511,35 @@ find_in_path_element (name, path, flags,
      int flags, name_len;
      struct stat *dotinfop;
 {
   int status;
   char *full_path, *xpath;
+#if defined (__DJGPP__)
+  const char *ext_path;
+#endif /* __DJGPP__ */
 
   xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
 
   /* Remember the location of "." in the path, in all its forms
      (as long as they begin with a `.', e.g. `./.') */
   if (dot_found_in_search == 0 && *xpath == '.')
     dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL);
 
+#if defined (__DJGPP__)
+  if ((ext_path = find_path_extension (xpath, name)))
+    full_path = sh_makepath (xpath, (char *)ext_path, 0);
+  else
+#endif /* __DJGPP__ */
+
   full_path = sh_makepath (xpath, name, 0);
 
+#if defined (__DJGPP__)
+  if (ext_path)
+    status = FS_EXISTS | FS_EXECABLE;
+  else
+#endif /* __DJGPP__ */
+
   status = file_status (full_path);
 
   if (xpath != path)
     free (xpath);
 
diff -aprNU5 bash-4.1.orig/general.c bash-4.1/general.c
--- bash-4.1.orig/general.c	2009-11-29 02:44:46 +0000
+++ bash-4.1/general.c	2019-02-01 23:37:12 +0000
@@ -41,10 +41,21 @@
 #include "shell.h"
 #include "test.h"
 
 #include <tilde/tilde.h>
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+#include <dos.h>
+#endif /* __DJGPP__ */
+
+#if defined (__DJGPP__)
+#define PATHLISTSEP path_separator
+#else  /* !__DJGPP__ */
+#define PATHLISTSEP ':'
+#endif /* !__DJGPP__ */
+
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
 
 extern int expand_aliases;
@@ -469,10 +480,25 @@ check_binary_file (sample, sample_len)
      int sample_len;
 {
   register int i;
   unsigned char c;
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (sample_len >= 2)
+    {
+      /* Check for MZ EXE signature.  */
+      if (sample[0] == 'M' && sample[1] == 'Z')
+        return 1;
+
+#if defined (__DJGPP__)
+      /* Check for unstubbed COFF signature.  */
+      if (sample[0] == 0x4c && sample[1] == 0x01)
+        return 1;
+#endif /* __DJGPP__ */
+    }
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
   for (i = 0; i < sample_len; i++)
     {
       c = sample[i];
       if (c == '\n')
 	return (0);
@@ -594,10 +620,33 @@ char *
 make_absolute (string, dot_path)
      char *string, *dot_path;
 {
   char *result;
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if ((string && string[1] == ':')
+      || is_dev_drive_path(string))
+    {
+      result = savestring (string);
+      return result;
+    }
+#if defined (__DJGPP__)
+  else if (ISDIRSEP(*string))
+    {
+      char drive;
+      char buffer[10];
+      unsigned int cur_drive;
+
+      _dos_getdrive(&cur_drive);
+      drive = cur_drive - 1 + 'a';
+      encode_drive_letter(buffer, drive);
+      result = sh_makepath (buffer, string + 1, 0);
+    }
+#endif /* __DJGPP__ */
+  else
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
   if (dot_path == 0 || ABSPATH(string))
 #ifdef __CYGWIN__
     {
       char pathbuf[PATH_MAX + 1];
 
@@ -624,11 +673,11 @@ base_pathname (string)
 #if 0
   if (absolute_pathname (string) == 0)
     return (string);
 #endif
 
-  if (string[0] == '/' && string[1] == 0)
+  if (ABSPATH(string) && string[1] == 0)
     return (string);
 
   p = (char *)strrchr (string, '/');
   return (p ? ++p : string);
 }
@@ -769,14 +818,14 @@ extract_colon_unit (string, p_index)
   /* Each call to this routine leaves the index pointing at a colon if
      there is more to the path.  If I is > 0, then increment past the
      `:'.  If I is 0, then the path has a leading colon.  Trailing colons
      are handled OK by the `else' part of the if statement; an empty
      string is returned in that case. */
-  if (i && string[i] == ':')
+  if (i && string[i] == PATHLISTSEP)
     i++;
 
-  for (start = i; string[i] && string[i] != ':'; i++)
+  for (start = i; string[i] && string[i] != PATHLISTSEP; i++)
     ;
 
   *p_index = i;
 
   if (i == start)
diff -aprNU5 bash-4.1.orig/general.h bash-4.1/general.h
--- bash-4.1.orig/general.h	2009-04-24 22:28:10 +0000
+++ bash-4.1/general.h	2019-02-01 23:37:12 +0000
@@ -245,22 +245,26 @@ typedef int QSFUNC ();
 #endif 
 
 /* Some useful definitions for Unix pathnames.  Argument convention:
    x == string, c == character */
 
-#if !defined (__CYGWIN__)
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__OS2__)
+#define HAVE_DRIVE_LETTER_FILE_SYSTEM
+#endif
+
+#if !defined (HAVE_DRIVE_LETTER_FILE_SYSTEM)
 #  define ABSPATH(x)	((x)[0] == '/')
 #  define RELPATH(x)	((x)[0] != '/')
 #else /* __CYGWIN__ */
-#  define ABSPATH(x)	(((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':') || ISDIRSEP((x)[0]))
+#  define ABSPATH(x)	(((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':' && ISDIRSEP((x)[2])) || ISDIRSEP((x)[0]))
 #  define RELPATH(x)	(ABSPATH(x) == 0)
 #endif /* __CYGWIN__ */
 
 #define ROOTEDPATH(x)	(ABSPATH(x))
 
 #define DIRSEP	'/'
-#if !defined (__CYGWIN__)
+#if !defined (HAVE_DRIVE_LETTER_FILE_SYSTEM)
 #  define ISDIRSEP(c)	((c) == '/')
 #else
 #  define ISDIRSEP(c)	((c) == '/' || (c) == '\\')
 #endif /* __CYGWIN__ */
 #define PATHSEP(c)	(ISDIRSEP(c) || (c) == 0)
diff -aprNU5 bash-4.1.orig/include/filecntl.h bash-4.1/include/filecntl.h
--- bash-4.1.orig/include/filecntl.h	2008-08-12 14:00:12 +0000
+++ bash-4.1/include/filecntl.h	2019-02-01 23:37:12 +0000
@@ -31,10 +31,18 @@
 #define FD_NCLOEXEC    0
 
 #define SET_CLOSE_ON_EXEC(fd)  (fcntl ((fd), F_SETFD, FD_CLOEXEC))
 #define SET_OPEN_ON_EXEC(fd)   (fcntl ((fd), F_SETFD, FD_NCLOEXEC))
 
+/* DOS applies the inherit bit to fd and any other descriptors that
+   refer to the same file. Bash expects Posix behavior instead, so
+   it's best not to use this feature.  */
+#if defined (__MSDOS__)
+#  undef SET_CLOSE_ON_EXEC
+#  define SET_CLOSE_ON_EXEC(fd)
+#endif /* __MSDOS__ */
+
 /* How to open a file in non-blocking mode, the Posix.1 way. */
 #if !defined (O_NONBLOCK)
 #  if defined (O_NDELAY)
 #    define O_NONBLOCK O_NDELAY
 #  else
diff -aprNU5 bash-4.1.orig/include/posixdir.h bash-4.1/include/posixdir.h
--- bash-4.1.orig/include/posixdir.h	2008-08-12 14:01:56 +0000
+++ bash-4.1/include/posixdir.h	2019-02-01 23:37:12 +0000
@@ -48,11 +48,11 @@
 
 #if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO)
 #  define d_fileno d_ino
 #endif
 
-#if defined (_POSIX_SOURCE) && (!defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO))
+#if !defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO)
 /* Posix does not require that the d_ino field be present, and some
    systems do not provide it. */
 #  define REAL_DIR_ENTRY(dp) 1
 #else
 #  define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
diff -aprNU5 bash-4.1.orig/input.c bash-4.1/input.c
--- bash-4.1.orig/input.c	2009-01-04 19:32:28 +0000
+++ bash-4.1/input.c	2019-02-01 23:37:12 +0000
@@ -361,10 +361,12 @@ duplicate_buffered_stream (fd1, fd2)
 }
 
 /* Return 1 if a seek on FD will succeed. */
 #ifndef __CYGWIN__
 #  define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
+#elif __DJGPP__
+#  define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0 && !isatty(fd))
 #else
 #  define fd_is_seekable(fd) 0
 #endif /* __CYGWIN__ */
 
 /* Take FD, a file descriptor, and create and return a buffered stream
@@ -385,10 +387,14 @@ fd_to_buffered_stream (fd)
     }
 
   size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
   if (size == 0)
     size = 1;
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (size > 1)
+    setmode (fd, O_BINARY);
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
   buffer = (char *)xmalloc (size);
 
   return (make_buffered_stream (fd, buffer, size));
 }
 
@@ -541,19 +547,19 @@ sync_buffered_stream (bfd)
 int
 buffered_getchar ()
 {
   CHECK_TERMSIG;
 
-#if !defined (DJGPP)
+#if !defined (__DJGPP__)
   return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
-#else
+#else  /* __DJGPP__ */
   /* On DJGPP, ignore \r. */
   int ch;
   while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
     ;
   return ch;
-#endif
+#endif /* __DJGPP__ */
 }
 
 int
 buffered_ungetchar (c)
      int c;
diff -aprNU5 bash-4.1.orig/lib/glob/glob.c bash-4.1/lib/glob/glob.c
--- bash-4.1.orig/lib/glob/glob.c	2009-11-14 23:39:30 +0000
+++ bash-4.1/lib/glob/glob.c	2019-02-01 23:37:12 +0000
@@ -435,10 +435,13 @@ glob_vector (pat, dir, flags)
   int mflags;		/* Flags passed to strmatch (). */
   int pflags;		/* flags passed to sh_makepath () */
   int nalloca;
   struct globval *firstmalloc, *tmplink;
   char *convfn;
+#if defined (__DJGPP__)
+  int use_lfn = (pathconf (NULL, _PC_NAME_MAX) > 12);
+#endif /* __DJGPP__ */
 
   lastlink = 0;
   count = lose = skip = add_current = 0;
 
   firstmalloc = 0;
@@ -539,10 +542,30 @@ glob_vector (pat, dir, flags)
       /* Compute the flags that will be passed to strmatch().  We don't
 	 need to do this every time through the loop. */
       mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
 
 #ifdef FNM_CASEFOLD
+#if defined (__DJGPP__)
+      /* DJGPP's globbing does not ignore case
+         when in an LFN environment and either FNCASE=Y
+         or an uppercase letter is in the pattern. */
+
+      glob_ignore_case = !(use_lfn && (_preserve_fncase() != 0));
+      if (glob_ignore_case && use_lfn)
+        {
+          char *cur_pat = pat;
+          char ch;
+          while ((ch = *cur_pat++))
+            {
+              if ((ch >= 'A') && (ch <= 'Z'))
+                {
+                  glob_ignore_case = 0;
+                  break;
+                }
+            }
+        }
+#endif /* __DJGPP__ */
       if (glob_ignore_case)
 	mflags |= FNM_CASEFOLD;
 #endif
 
       if (extended_glob)
@@ -554,10 +577,13 @@ glob_vector (pat, dir, flags)
 	 For each name that matches, allocate a struct globval
 	 on the stack and store the name in it.
 	 Chain those structs together; lastlink is the front of the chain.  */
       while (1)
 	{
+#if defined (__DJGPP__)
+	  char short_name[13];
+#endif /* __DJGPP__ */
 	  /* Make globbing interruptible in the shell. */
 	  if (interrupt_state || terminating_signal)
 	    {
 	      lose = 1;
 	      break;
@@ -579,10 +605,28 @@ glob_vector (pat, dir, flags)
 #if HANDLE_MULTIBYTE
 	  if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name, flags))
 	    continue;
 	  else
 #endif
+#if defined (__DJGPP__)
+         /* Downcase if the short name and long name are equal and
+            case is being ignored.  */
+
+         if (glob_ignore_case
+             && (strcmp(dp->d_name, _lfn_gen_short_fname (dp->d_name, short_name)) == 0)
+             )
+           {
+             /* Downcase when the SFN matches the LFN */
+             int i;
+             char c;
+             for (i = 0; dp->d_name[i]; i++)
+               {
+                 c = dp->d_name[i];
+                 dp->d_name[i] = ((c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c);
+               }
+           }
+#endif /* __DJGPP__ */
 	  if (skipname (pat, dp->d_name, flags))
 	    continue;
 
 	  /* If we're only interested in directories, don't bother with files */
 	  if (flags & (GX_MATCHDIRS|GX_ALLDIRS))
@@ -789,11 +833,15 @@ glob_dir_to_array (dir, array, flags)
 	      }
 	  }
       return (array);
     }
 
+#if defined (HAVE_DOS_STYLE_FILE_SYSTEM)
+  add_slash = dir[l - 1] != '/' && dir[l - 1] != ':';
+#else  /* !HAVE_DOS_STYLE_FILE_SYSTEM */
   add_slash = dir[l - 1] != '/';
+#endif /* !HAVE_DOS_STYLE_FILE_SYSTEM */
 
   i = 0;
   while (array[i] != NULL)
     ++i;
 
@@ -860,10 +908,16 @@ glob_filename (pathname, flags)
 
   directory_name = NULL;
 
   /* Find the filename.  */
   filename = strrchr (pathname, '/');
+#if defined (HAVE_DOS_STYLE_FILE_SYSTEM)
+  /* Skip drive name.  */
+  if (filename == NULL && isalpha (pathname[0]) && pathname[1] == ':')
+    filename = pathname + 1;
+#endif /* HAVE_DOS_STYLE_FILE_SYSTEM */
+
   if (filename == NULL)
     {
       filename = pathname;
       directory_name = "";
       directory_len = 0;
@@ -1037,13 +1091,19 @@ glob_filename (pathname, flags)
 	     dlen == 0 */
 #endif
 	  if (directory_len == 0 && (flags & GX_ALLDIRS) == 0)
 	    dflags &= ~GX_ADDCURDIR;
 	}
+#if defined (__DJGPP__)
+      __opendir_flags = __OPENDIR_PRESERVE_CASE;
+#endif /* __DJGPP__ */
       temp_results = glob_vector (filename,
 				  (directory_len == 0 ? "." : directory_name),
 				  dflags);
+#if defined (__DJGPP__)
+      __opendir_flags = 0;
+#endif /* __DJGPP__ */
 
       if (temp_results == NULL || temp_results == (char **)&glob_error_return)
 	{
 	  if (free_dirname)
 	    free (directory_name);
diff -aprNU5 bash-4.1.orig/lib/malloc/malloc.c bash-4.1/lib/malloc/malloc.c
--- bash-4.1.orig/lib/malloc/malloc.c	2008-08-12 14:23:50 +0000
+++ bash-4.1/lib/malloc/malloc.c	2019-02-01 23:37:12 +0000
@@ -213,10 +213,14 @@ typedef union _malloc_guard {
 
 /* Use this when we want to be sure that NB is in bucket NU. */
 #define RIGHT_BUCKET(nb, nu) \
 	(((nb) > binsizes[(nu)-1]) && ((nb) <= binsizes[(nu)]))
 
+#ifndef SIGCHLD
+#define SIGCHLD SIGINT
+#endif
+
 /* nextf[i] is free list of blocks of size 2**(i + 3)  */
 
 static union mhead *nextf[NBUCKETS];
 
 /* busy[i] is nonzero while allocation or free of block size i is in progress. */
diff -aprNU5 bash-4.1.orig/lib/readline/complete.c bash-4.1/lib/readline/complete.c
--- bash-4.1.orig/lib/readline/complete.c	2019-02-01 23:36:36 +0000
+++ bash-4.1/lib/readline/complete.c	2019-02-01 23:42:14 +0000
@@ -152,11 +152,11 @@ int _rl_complete_mark_symlink_dirs = 0;
 /* If non-zero, completions are printed horizontally in alphabetical order,
    like `ls -x'. */
 int _rl_print_completions_horizontally;
 
 /* Non-zero means that case is not significant in filename completion. */
-#if defined (__MSDOS__) && !defined (__DJGPP__)
+#if defined (__MSDOS__) && !defined (__DJGPPXXX__)
 int _rl_completion_case_fold = 1;
 #else
 int _rl_completion_case_fold;
 #endif
 
@@ -593,16 +593,17 @@ printable_part (pathname)
   char *temp, *x;
 
   if (rl_filename_completion_desired == 0)	/* don't need to do anything */
     return (pathname);
 
-  temp = strrchr (pathname, '/');
-#if defined (__MSDOS__)
-  if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
-    temp = pathname + 1;
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  temp = basename(pathname);
+  return temp;
 #endif
 
+  temp = strrchr (pathname, '/');
+
   if (temp == 0 || *temp == '\0')
     return (pathname);
   /* If the basename is NULL, we might have a pathname like '/usr/src/'.
      Look for a previous slash and, if one is found, return the portion
      following that slash.  If there's no previous slash, just return the
@@ -964,10 +965,15 @@ _rl_find_completion_word (fp, dp)
 	  scan = rl_line_buffer[rl_point];
 
 	  if (strchr (brkchars, scan) == 0)
 	    continue;
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+	  /* Ignore colons.  */
+	  if (scan == ':' && (rl_completion_entry_function == NULL || (rl_completion_entry_function == rl_filename_completion_function)))
+	    continue;
+#endif
 	  /* Call the application-specific function to tell us whether
 	     this word break character is quoted and should be skipped. */
 	  if (rl_char_is_quoted_p && found_quote &&
 	      (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
 	    continue;
@@ -1548,14 +1554,28 @@ make_quoted_replacement (match, mtype, q
   if (should_quote)
     {
       /* If there is a single match, see if we need to quote it.
          This also checks whether the common prefix of several
 	 matches needs to be quoted. */
+#if !defined (HAVE_DOS_BASED_FILE_SYSTEM)
       should_quote = rl_filename_quote_characters
 			? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
 			: 0;
 
+#else /* HAVE_DOS_BASED_FILE_SYSTEM */
+     {
+        /* To get here, the match must be a filename.
+           Do not allow ':' to be quoted in DOS-style filenames,
+           to avoid confusing people.  */
+        char *token = NULL;
+        should_quote = rl_filename_quote_characters
+                        ? ((token = _rl_strpbrk (match, rl_filename_quote_characters)) != 0)
+			: 0;
+        if (token && *token == ':')
+          should_quote = 0;
+      }
+#endif
       do_replace = should_quote ? mtype : NO_MATCH;
       /* Quote the replacement, since we found an embedded
 	 word break character in a potential match. */
       if (do_replace != NO_MATCH && rl_filename_quoting_function)
 	replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
@@ -2042,11 +2062,11 @@ rl_filename_completion_function (text, s
 	text = ".";
       dirname = savestring (text);
 
       temp = strrchr (dirname, '/');
 
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       /* special hack for //X/... */
       if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
         temp = strrchr (dirname + 3, '/');
 #endif
 
diff -aprNU5 bash-4.1.orig/lib/readline/display.c bash-4.1/lib/readline/display.c
--- bash-4.1.orig/lib/readline/display.c	2009-09-26 18:37:32 +0000
+++ bash-4.1/lib/readline/display.c	2019-02-01 23:42:14 +0000
@@ -39,10 +39,14 @@
 #  include "ansi_stdlib.h"
 #endif /* HAVE_STDLIB_H */
 
 #include <stdio.h>
 
+#ifdef __DJGPP__
+#  include <pc.h>
+#endif
+
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
 #include "rlmbutil.h"
 
 /* Termcap library stuff. */
@@ -1074,11 +1078,11 @@ rl_redisplay ()
 	      _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
 #else
 	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
 #endif
 	    {
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
 	      putc ('\r', rl_outstream);
 #else
 	      if (_rl_term_cr)
 		tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
@@ -1516,11 +1520,11 @@ update_line (old, new, current_line, oma
   od = ofd - old;	/* index of first difference in visible line */
   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
       od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
     {
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       putc ('\r', rl_outstream);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       if (modmark)
@@ -1973,11 +1977,11 @@ _rl_move_cursor_relative (new, data)
 #endif
   i = _rl_last_c_pos - woff;
   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
       (_rl_term_autowrap && i == _rl_screenwidth))
     {
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       putc ('\r', rl_outstream);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif /* !__MSDOS__ */
       cpos = _rl_last_c_pos = 0;
@@ -2045,11 +2049,11 @@ _rl_move_vert (to)
 
   if ((delta = to - _rl_last_v_pos) > 0)
     {
       for (i = 0; i < delta; i++)
 	putc ('\n', rl_outstream);
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       putc ('\r', rl_outstream);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
@@ -2457,11 +2461,11 @@ _rl_update_final ()
 static void
 cr ()
 {
   if (_rl_term_cr)
     {
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       putc ('\r', rl_outstream);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
@@ -2506,17 +2510,17 @@ _rl_redisplay_after_sigwinch ()
      screen line. */
   if (_rl_term_cr)
     {
       _rl_move_vert (_rl_vis_botlin);
 
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       putc ('\r', rl_outstream);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
       space_to_eol (_rl_screenwidth);
       putc ('\r', rl_outstream);
 #else
       if (_rl_term_clreol)
 	tputs (_rl_term_clreol, 1, _rl_output_character_function);
diff -aprNU5 bash-4.1.orig/lib/readline/funmap.c bash-4.1/lib/readline/funmap.c
--- bash-4.1.orig/lib/readline/funmap.c	2009-08-26 21:14:10 +0000
+++ bash-4.1/lib/readline/funmap.c	2019-02-01 23:43:36 +0000
@@ -111,11 +111,11 @@ static const FUNMAP default_funmap[] = {
   { "non-incremental-reverse-search-history", rl_noninc_reverse_search },
   { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
   { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
   { "old-menu-complete", rl_old_menu_complete },
   { "overwrite-mode", rl_overwrite_mode },
-#ifdef __CYGWIN__
+#if defined (__WIN32__) || defined (__DJGPP__)
   { "paste-from-clipboard", rl_paste_from_clipboard },
 #endif
   { "possible-completions", rl_possible_completions },
   { "previous-history", rl_get_previous_history },
   { "quoted-insert", rl_quoted_insert },
diff -aprNU5 bash-4.1.orig/lib/readline/histfile.c bash-4.1/lib/readline/histfile.c
--- bash-4.1.orig/lib/readline/histfile.c	2009-01-04 19:32:32 +0000
+++ bash-4.1/lib/readline/histfile.c	2019-02-01 23:42:14 +0000
@@ -74,21 +74,22 @@
 #  endif
 
 #endif /* HISTORY_USE_MMAP */
 
 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
-   on win 95/98/nt), we want to open files with O_BINARY mode so that there
-   is no \n -> \r\n conversion performed.  On other systems, we don't want to
-   mess around with O_BINARY at all, so we ensure that it's defined to 0. */
-#if defined (__EMX__) || defined (__CYGWIN__)
+   on win 95/98/nt), or DJGPP (DOS), we want to open files with O_BINARY mode
+   so that there is no \n -> \r\n conversion performed.  On other systems,
+   we don't want to mess around with O_BINARY at all, so we ensure that
+   it's defined to 0. */
+#if defined (__EMX__) || defined (__CYGWIN__) || defined (__DJGPP__)
 #  ifndef O_BINARY
 #    define O_BINARY 0
 #  endif
-#else /* !__EMX__ && !__CYGWIN__ */
+#else /* !__EMX__ && !__CYGWIN__ && !__DJGPP__ */
 #  undef O_BINARY
 #  define O_BINARY 0
-#endif /* !__EMX__ && !__CYGWIN__ */
+#endif /* !__EMX__ && !__CYGWIN__ && !__DJGPP__ */
 
 #include <errno.h>
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
diff -aprNU5 bash-4.1.orig/lib/readline/kill.c bash-4.1/lib/readline/kill.c
--- bash-4.1.orig/lib/readline/kill.c	2008-08-12 21:59:30 +0000
+++ bash-4.1/lib/readline/kill.c	2019-02-01 23:42:14 +0000
@@ -654,12 +654,12 @@ rl_yank_last_arg (count, key)
 
   undo_needed = retval == 0;
   return retval;
 }
 
-/* A special paste command for users of Cygnus's cygwin32. */
-#if defined (__CYGWIN__)
+/* A special paste command for Win32. */
+#if defined (__WIN32__)
 #include <windows.h>
 
 int
 rl_paste_from_clipboard (count, key)
      int count, key;
@@ -689,6 +689,75 @@ rl_paste_from_clipboard (count, key)
 	xfree (ptr);
       CloseClipboard ();
     }
   return (0);
 }
-#endif /* __CYGWIN__ */
+#endif /* __WIN32__ */
+
+/* A special paste command to allow DJGPP users to paste
+   from the Windows clipboard. */
+#if defined (__DJGPP__)
+#  include <dpmi.h>
+#  include <sys/farptr.h>
+#  include <go32.h>
+
+int
+rl_paste_from_clipboard (count, key)
+     int count, key;
+{
+  char *data, *ptr;
+  int len, index;
+  __dpmi_regs r;
+  unsigned long offset;
+  char ch;
+ 
+  /* Open the Windows clipboard.  */
+  r.x.ax = 0x1701;
+  __dpmi_int (0x2f, &r);
+  if (r.x.ax == 0)
+    return 0;
+
+  /* Get the size of the text in the clipboard.  */
+  r.x.ax = 0x1704;
+  r.x.dx = 1; /* Select plain text.  */
+  __dpmi_int (0x2f, &r);
+  len = r.x.ax + 65536 * r.x.dx;
+  if (len == 0)
+    return (0);
+
+  /* Get a pointer to the text.  */
+  r.x.ax = 0x1705;
+  r.x.dx = 1;
+  __dpmi_int (0x2f, &r);
+
+  offset = r.x.bx + 16 * r.x.es;
+  if (offset == 0)
+    return 0;
+
+  _farsetsel(_dos_ds);
+  while ((ch = _farnspeekb(offset++)) != '\0')
+    if (ch == '\r')
+      break;
+  len = offset - (r.x.bx + 16 * r.x.es);
+  if (ch == '\r')
+    --len;
+
+  ptr = xmalloc (len + 1);
+  offset = r.x.bx + 16 * r.x.es;
+
+  index = 0;
+  _farsetsel(_dos_ds);
+  while (index < len)
+  {
+    ch = _farnspeekb(offset++);
+    ptr[index++] = ch;
+  }
+  ptr[len] = '\0';
+
+  /* Close the clipboard.  */
+  r.x.ax = 0x1708;
+  __dpmi_int (0x2f, &r);
+
+  rl_insert_text (ptr);
+  free (ptr);
+}
+#endif /* __DJGPP__ */
diff -aprNU5 bash-4.1.orig/lib/readline/readline.c bash-4.1/lib/readline/readline.c
--- bash-4.1.orig/lib/readline/readline.c	2009-08-31 12:45:30 +0000
+++ bash-4.1/lib/readline/readline.c	2019-02-01 23:42:14 +0000
@@ -1131,11 +1131,11 @@ bind_arrow_keys_internal (map)
   Keymap xkeymap;
 
   xkeymap = _rl_keymap;
   _rl_keymap = map;
 
-#if defined (__MSDOS__)
+#if defined (__MSDOS__) && !defined (__DJGPP__)
   rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history);
   rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char);
   rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char);
   rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history);
 #endif
@@ -1215,11 +1215,13 @@ rl_save_state (sp)
   sp->outf = rl_outstream;
   sp->pendingin = rl_pending_input;
   sp->macro = rl_executing_macro;
 
   sp->catchsigs = rl_catch_signals;
+#ifdef SIGWINCH
   sp->catchsigwinch = rl_catch_sigwinch;
+#endif
 
   return (0);
 }
 
 int
@@ -1249,9 +1251,11 @@ rl_restore_state (sp)
   rl_outstream = sp->outf;
   rl_pending_input = sp->pendingin;
   rl_executing_macro = sp->macro;
 
   rl_catch_signals = sp->catchsigs;
+#ifdef SIGWINCH
   rl_catch_sigwinch = sp->catchsigwinch;
+#endif
 
   return (0);
 }
diff -aprNU5 bash-4.1.orig/lib/readline/readline.h bash-4.1/lib/readline/readline.h
--- bash-4.1.orig/lib/readline/readline.h	2009-08-27 03:05:54 +0000
+++ bash-4.1/lib/readline/readline.h	2019-02-01 23:42:14 +0000
@@ -171,11 +171,11 @@ extern int rl_copy_backward_word PARAMS(
 extern int rl_yank PARAMS((int, int));
 extern int rl_yank_pop PARAMS((int, int));
 extern int rl_yank_nth_arg PARAMS((int, int));
 extern int rl_yank_last_arg PARAMS((int, int));
 /* Not available unless __CYGWIN__ is defined. */
-#ifdef __CYGWIN__
+#if defined (__WIN32__) || defined (__DJGPP__)
 extern int rl_paste_from_clipboard PARAMS((int, int));
 #endif
 
 /* Bindable commands for incremental searching. */
 extern int rl_reverse_search_history PARAMS((int, int));
diff -aprNU5 bash-4.1.orig/lib/readline/signals.c bash-4.1/lib/readline/signals.c
--- bash-4.1.orig/lib/readline/signals.c	2009-11-30 00:27:40 +0000
+++ bash-4.1/lib/readline/signals.c	2019-02-02 00:27:22 +0000
@@ -588,11 +588,13 @@ _rl_block_sigwinch ()
     return;
 
 #if defined (HAVE_POSIX_SIGNALS)
   sigemptyset (&sigwinch_set);
   sigemptyset (&sigwinch_oset);
+#  if defined (SIGWINCH) && 0
   sigaddset (&sigwinch_set, SIGWINCH);
+#  endif /* SIGWINCH */
   sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset);
 #else /* !HAVE_POSIX_SIGNALS */
 #  if defined (HAVE_BSD_SIGNALS)
   sigwinch_oldmask = sigblock (sigmask (SIGWINCH));
 #  else /* !HAVE_BSD_SIGNALS */
diff -aprNU5 bash-4.1.orig/lib/readline/terminal.c bash-4.1/lib/readline/terminal.c
--- bash-4.1.orig/lib/readline/terminal.c	2009-09-30 18:58:44 +0000
+++ bash-4.1/lib/readline/terminal.c	2019-02-01 23:42:14 +0000
@@ -180,11 +180,11 @@ int _rl_enable_keypad;
 /* Non-zero means the user wants to enable a meta key. */
 int _rl_enable_meta = 1;
 
 #if defined (__EMX__)
 static void
-_emx_get_screensize (swp, shp)
+_get_screensize (swp, shp)
      int *swp, *shp;
 {
   int sz[2];
 
   _scrsize (sz);
@@ -214,10 +214,24 @@ _win_get_screensize (swp, shp)
 	}
     }
 }
 #endif
 
+#if defined (__MSDOS__)
+#  include <conio.h>
+
+static void
+_get_screensize (swp, shp)
+     int *swp, *shp;
+{
+  struct text_info screen_info;
+  gettextinfo (&screen_info);
+  *swp = (int)screen_info.screenwidth;
+  *shp = (int)screen_info.screenheight;
+}
+#endif
+
 /* Get readline's idea of the screen size.  TTY is a file descriptor open
    to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
    values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
    non-null serve to check whether or not we have initialized termcap. */
 void
@@ -237,12 +251,12 @@ _rl_get_screen_size (tty, ignore_env)
       wc = (int) window_size.ws_col;
       wr = (int) window_size.ws_row;
     }
 #endif /* TIOCGWINSZ */
 
-#if defined (__EMX__)
-  _emx_get_screensize (&wc, &wr);
+#if defined (__EMX__) || defined (__DJGPP__)
+  _get_screensize (&wc, &wr);
 #elif defined (__MINGW32__)
   _win_get_screensize (&wc, &wr);
 #endif
 
   if (ignore_env || rl_prefer_env_winsize == 0)
@@ -262,14 +276,12 @@ _rl_get_screen_size (tty, ignore_env)
 	_rl_screenwidth = atoi (ss);
 
       if (_rl_screenwidth <= 0)
         _rl_screenwidth = wc;
 
-#if !defined (__DJGPP__)
       if (_rl_screenwidth <= 0 && term_string_buffer)
 	_rl_screenwidth = tgetnum ("co");
-#endif
     }
 
   /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
      is unset. */
   if (_rl_screenheight <= 0)
@@ -278,14 +290,12 @@ _rl_get_screen_size (tty, ignore_env)
 	_rl_screenheight = atoi (ss);
 
       if (_rl_screenheight <= 0)
         _rl_screenheight = wr;
 
-#if !defined (__DJGPP__)
       if (_rl_screenheight <= 0 && term_string_buffer)
 	_rl_screenheight = tgetnum ("li");
-#endif
     }
 
   /* If all else fails, default to 80x24 terminal. */
   if (_rl_screenwidth <= 1)
     _rl_screenwidth = 80;
@@ -406,16 +416,14 @@ static const struct _tc_string tc_string
    are described in the TC_STRINGS table. */
 static void
 get_term_capabilities (bp)
      char **bp;
 {
-#if !defined (__DJGPP__)	/* XXX - doesn't DJGPP have a termcap library? */
   register int i;
 
   for (i = 0; i < NUM_TC_STRINGS; i++)
     *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
-#endif
   tcap_initialized = 1;
 }
 
 int
 _rl_init_terminal_io (terminal_name)
@@ -462,12 +470,12 @@ _rl_init_terminal_io (terminal_name)
 
       /* Allow calling application to set default height and width, using
 	 rl_set_screen_size */
       if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
 	{
-#if defined (__EMX__)
-	  _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
+#if defined (__EMX__) || defined (__DJGPP__)
+	  _get_screensize (&_rl_screenwidth, &_rl_screenheight);
 	  _rl_screenwidth--;
 #else /* !__EMX__ */
 	  _rl_get_screen_size (tty, 0);
 #endif /* !__EMX__ */
 	}
@@ -659,15 +667,20 @@ rl_ding ()
         {
 	case NO_BELL:
 	default:
 	  break;
 	case VISIBLE_BELL:
+#ifdef __MSDOS__
+	  ScreenVisualBell ();
+	  break;
+#else
 	  if (_rl_visible_bell)
 	    {
 	      tputs (_rl_visible_bell, 1, _rl_output_character_function);
 	      break;
 	    }
+#endif
 	  /* FALLTHROUGH */
 	case AUDIBLE_BELL:
 	  fprintf (stderr, "\007");
 	  fflush (stderr);
 	  break;
@@ -684,26 +697,22 @@ rl_ding ()
 /* **************************************************************** */
 
 void
 _rl_enable_meta_key ()
 {
-#if !defined (__DJGPP__)
   if (term_has_meta && _rl_term_mm)
     tputs (_rl_term_mm, 1, _rl_output_character_function);
-#endif
 }
 
 void
 _rl_control_keypad (on)
      int on;
 {
-#if !defined (__DJGPP__)
   if (on && _rl_term_ks)
     tputs (_rl_term_ks, 1, _rl_output_character_function);
   else if (!on && _rl_term_ke)
     tputs (_rl_term_ke, 1, _rl_output_character_function);
-#endif
 }
 
 /* **************************************************************** */
 /*								    */
 /*	 		Controlling the Cursor			    */
diff -aprNU5 bash-4.1.orig/lib/sh/getcwd.c bash-4.1/lib/sh/getcwd.c
--- bash-4.1.orig/lib/sh/getcwd.c	2009-06-17 00:16:54 +0000
+++ bash-4.1/lib/sh/getcwd.c	2019-02-01 23:37:12 +0000
@@ -18,11 +18,11 @@
    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include <config.h>
 
-#if !defined (HAVE_GETCWD)
+#if !defined (HAVE_GETCWD) && !defined (__DJGPP__)
 
 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
   #pragma alloca
 #endif /* _AIX && RISC6000 && !__GNUC__ */
 
diff -aprNU5 bash-4.1.orig/lib/sh/pathcanon.c bash-4.1/lib/sh/pathcanon.c
--- bash-4.1.orig/lib/sh/pathcanon.c	2008-08-12 18:01:36 +0000
+++ bash-4.1/lib/sh/pathcanon.c	2019-02-01 23:37:12 +0000
@@ -68,10 +68,14 @@ _is_cygdrive (path)
     }
   return !strcasecmp (path, user) || !strcasecmp (path, system);
 }
 #endif /* __CYGWIN__ */	
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+#endif /* __DJGPP__ */
+
 /* Return 1 if PATH corresponds to a directory.  A function for debugging. */
 static int
 _path_isdir (path)
      char *path;
 {
@@ -117,10 +121,17 @@ sh_canonpath (path, flags)
   if (rooted = ROOTEDPATH(path))
     {
       stub_char = DIRSEP;
 #if defined (__CYGWIN__)
       base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 3 : result + 1;
+#elif defined (__DJGPP__)
+      if ((ISALPHA((unsigned char)result[0])) && result[1])
+        base = result + 3;
+      else if (is_dev_drive_path (result))
+        base = result + 7;
+      else
+        base = result + 1;
 #else
       base = result + 1;
 #endif
       double_slash_path = DOUBLE_SLASH (path);
       base += double_slash_path;
@@ -128,10 +139,17 @@ sh_canonpath (path, flags)
   else
     {
       stub_char = '.';
 #if defined (__CYGWIN__)
       base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 2 : result;
+#elif defined (__DJGPP__)
+      if ((isalpha(result[0])) && result[1])
+        base = result + 3;
+      else if (is_dev_drive_path (result))
+        base = result + 7;
+      else
+        base = result + 1;
 #else
       base = result;
 #endif
       double_slash_path = 0;
     }
@@ -185,10 +203,52 @@ sh_canonpath (path, flags)
 	      *q++ = '.';
 	      *q++ = '.';
 	      dotdot = q;
 	    }
 	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+      /* Handle three or more dots (Windows compatible) */
+      else if (p[0] == '.' && p[1] == '.' && p[2] == '.') 
+	{
+	  p += 1; /* skip `..' */
+	  while (*p == '.')
+	  {
+	  if (q > dotdot)	/* can backtrack */
+	    {
+	      if (flags & PATH_CHECKDOTDOT)
+		{
+		  char c;
+
+		  /* Make sure what we have so far corresponds to a valid
+		     path before we chop some of it off. */
+		  c = *q;
+		  *q = '\0';
+		  if (_path_isdir (result) == 0)
+		    {
+		      if ((flags & PATH_NOALLOC) == 0)
+			free (result);
+		      return ((char *)NULL);
+		    }
+		  *q = c;
+		}
+
+	      while (--q > dotdot && ISDIRSEP(*q) == 0)
+		;
+	    }
+	  else if (rooted == 0)
+	    {
+	      /* /.. is / but ./../ is .. */
+	      if (q != base)
+		*q++ = DIRSEP;
+	      *q++ = '.';
+	      *q++ = '.';
+	      dotdot = q;
+	    }
+	  ++p;
+	  }
+	}
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
       else	/* real path element */
 	{
 	  /* add separator if not at start of work portion of result */
 	  if (q != base)
 	    *q++ = DIRSEP;
diff -aprNU5 bash-4.1.orig/lib/sh/tmpfile.c bash-4.1/lib/sh/tmpfile.c
--- bash-4.1.orig/lib/sh/tmpfile.c	2008-08-12 17:50:12 +0000
+++ bash-4.1/lib/sh/tmpfile.c	2019-02-01 23:37:12 +0000
@@ -38,15 +38,29 @@
 
 #ifndef errno
 extern int errno;
 #endif
 
-#define BASEOPENFLAGS	(O_CREAT | O_TRUNC | O_EXCL)
+#ifndef O_TEMPORARY
+#define O_TEMPORARY 0
+#endif
+
+#define BASEOPENFLAGS   (O_CREAT | O_TRUNC | O_EXCL | O_TEMPORARY)
 
 #define DEFAULT_TMPDIR		"."	/* bogus default, should be changed */
 #define DEFAULT_NAMEROOT	"shtmp"
 
+#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
+#  define HAS_LFN_SUPPORT(name)  (pathconf ((name), _PC_NAME_MAX) > 12)
+#else
+#  if defined (__MSDOS__)
+#    define HAS_LFN_SUPPORT(name)  (0)
+#  else  /* !__MSDOS__ */
+#    define HAS_LFN_SUPPORT(name)  (1)
+#  endif /* !__MSDOS__ */
+#endif
+
 extern pid_t dollar_dollar_pid;
 
 static char *get_sys_tmpdir __P((void));
 static char *get_tmpdir __P((int));
 
@@ -65,10 +79,19 @@ get_sys_tmpdir ()
   sys_tmpdir = P_tmpdir;
   if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
 #endif
 
+#if defined (__DJGPP__)
+  sys_tmpdir = "/dev/env/TEMP";
+  if (access (sys_tmpdir, D_OK) == 0)
+    return sys_tmpdir;
+
+  sys_tmpdir = "/dev/env/TMP";
+  if (access (sys_tmpdir, D_OK) == 0)
+    return sys_tmpdir;
+#else /* !__DJGPP__ */
   sys_tmpdir = "/tmp";
   if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
 
   sys_tmpdir = "/var/tmp";
@@ -76,10 +99,11 @@ get_sys_tmpdir ()
     return sys_tmpdir;
 
   sys_tmpdir = "/usr/tmp";
   if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
+#endif /* !__DJGPP__ */
 
   sys_tmpdir = DEFAULT_TMPDIR;
 
   return sys_tmpdir;
 }
@@ -88,10 +112,14 @@ static char *
 get_tmpdir (flags)
      int flags;
 {
   char *tdir;
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  flags |= MT_USETMPDIR;
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
   tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL;
   if (tdir && (file_iswdir (tdir) == 0 || strlen (tdir) > PATH_MAX))
     tdir = 0;
 
   if (tdir == 0)
@@ -104,11 +132,17 @@ get_tmpdir (flags)
   tmpnamelen = 0;
 #endif
 
   return tdir;
 }
-
+#if __OBSOLETE_FOR_PORT__
+#if defined (__MSDOS__)
+#define TEMPLATE_STR "%s/%sXXXXXX"
+#else  /* !__MSDOS__ */
+#define TEMPLATE_STR "%s/%s.XXXXXX"
+#endif /* !__MSDOS__ */
+#endif /* __OBSOLETE_FOR_PORT__ */
 char *
 sh_mktmpname (nameroot, flags)
      char *nameroot;
      int flags;
 {
@@ -120,12 +154,26 @@ sh_mktmpname (nameroot, flags)
   tdir = get_tmpdir (flags);
   tdlen = strlen (tdir);
 
   lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
 
+#if defined (__MSDOS__)
+#if __OBSOLETE_FOR_PORT__
+  if (pathconf (tdir, _PC_NAME_MAX) < 13
+#else  /* !__OBSOLETE_FOR_PORT__ */
+  if (!HAS_LFN_SUPPORT(tdir)
+#endif /* !__OBSOLETE_FOR_PORT__ */
+      && lroot[0] && lroot[1] && lroot[2])
+    lroot = "sh";
+#endif /* __MSDOS__ */
+
 #ifdef USE_MKTEMP
-  sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+#if __OBSOLETE_FOR_PORT__
+  sprintf (filename, TEMPLATE_STR, tdir, lroot);
+#else  /* !__OBSOLETE_FOR_PORT__ */
+  sprintf (filename, HAS_LFN_SUPPORT(".") ? "%s/%s.XXXXXX" : "%s/%sXXXXXX", tdir, lroot);
+#endif /* !__OBSOLETE_FOR_PORT__ */
   if (mktemp (filename) == 0)
     {
       free (filename);
       filename = NULL;
     }
@@ -134,11 +182,19 @@ sh_mktmpname (nameroot, flags)
     {
       filenum = (filenum << 1) ^
 		(unsigned long) time ((time_t *)0) ^
 		(unsigned long) dollar_dollar_pid ^
 		(unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
+#if __OBSOLETE_FOR_PORT__
+#if defined (__MSDOS__)
+      sprintf (filename, "%s/%s%lu", tdir, lroot, filenum);
+#else  /* !__MSDOS__ */
       sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
+#endif /* !__MSDOS__ */
+#else  /* !__OBSOLETE_FOR_PORT__ */
+      sprintf (filename, HAS_LFN_SUPPORT(".") ? "%s/%s-%lu" : "%s/%s%lu", tdir, lroot, filenum);
+#endif /* !__OBSOLETE_FOR_PORT__ */
       if (tmpnamelen > 0 && tmpnamelen < 32)
 	filename[tdlen + 1 + tmpnamelen] = '\0';
 #  ifdef HAVE_LSTAT
       r = lstat (filename, &sb);
 #  else
@@ -165,12 +221,26 @@ sh_mktmpfd (nameroot, flags, namep)
   tdir = get_tmpdir (flags);
   tdlen = strlen (tdir);
 
   lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
 
+#if defined (__MSDOS__)
+#if __OBSOLETE_FOR_PORT__
+  if (pathconf (tdir, _PC_NAME_MAX) < 13
+#else  /* !__OBSOLETE_FOR_PORT__ */
+  if (!HAS_LFN_SUPPORT(tdir)
+#endif /* !__OBSOLETE_FOR_PORT__ */
+      && lroot[0] && lroot[1] && lroot[2])
+    lroot = "sh";
+#endif /* __MSDOS__ */
+
 #ifdef USE_MKSTEMP
-  sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+#if __OBSOLETE_FOR_PORT__
+  sprintf (filename, TEMPLATE_STR, tdir, lroot);
+#else  /* !__OBSOLETE_FOR_PORT__ */
+  sprintf (filename, HAS_LFN_SUPPORT(".") ? "%s/%s.XXXXXX" : "%s/%sXXXXXX", tdir, lroot);
+#endif /* !__OBSOLETE_FOR_PORT__ */
   fd = mkstemp (filename);
   if (fd < 0 || namep == 0)
     {
       free (filename);
       filename = NULL;
diff -aprNU5 bash-4.1.orig/lib/sh/zread.c bash-4.1/lib/sh/zread.c
--- bash-4.1.orig/lib/sh/zread.c	2009-03-02 13:54:44 +0000
+++ bash-4.1/lib/sh/zread.c	2019-02-01 23:37:12 +0000
@@ -34,10 +34,17 @@ extern int errno;
 
 #ifndef SEEK_CUR
 #  define SEEK_CUR 1
 #endif
 
+#if defined (__DJGPP__)
+/* DJGPP always uses its own pipe implementation.
+   Required for read.  */
+
+#  include "dospipe.h"
+#endif /* __DJGPP__ */
+
 /* Read LEN bytes from FD into BUF.  Retry the read on EINTR.  Any other
    error causes the loop to break. */
 ssize_t
 zread (fd, buf, len)
      int fd;
@@ -49,10 +56,29 @@ zread (fd, buf, len)
   while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
     ;
   return r;
 }
 
+#if defined (__DJGPP__)
+/* Read LEN bytes from FD into BUF.  Retry the read on EINTR.  Any other
+   error causes the loop to break. */
+static ssize_t
+zreadbin (fd, buf, len)
+     int fd;
+     char *buf;
+     size_t len;
+{
+  ssize_t r;
+
+  while ((r = _read (fd, buf, len)) < 0 && errno == EINTR)
+    ;
+  return r;
+}
+#else  /* !__DJGPP__ */
+#define zreadbin zread
+#endif /* !__DJGPP__ */
+
 /* Read LEN bytes from FD into BUF.  Retry the read on EINTR, up to three
    interrupts.  Any other error causes the loop to break. */
 
 #ifdef NUM_INTR
 #  undef NUM_INTR
@@ -105,23 +131,28 @@ zreadc (fd, cp)
      int fd;
      char *cp;
 {
   ssize_t nr;
 
-  if (lind == lused || lused == 0)
+  do
     {
-      nr = zread (fd, lbuf, sizeof (lbuf));
-      lind = 0;
-      if (nr <= 0)
+      if (lind == lused || lused == 0)
 	{
-	  lused = 0;
-	  return nr;
+	  nr = zreadbin (fd, lbuf, sizeof (lbuf));
+	  lind = 0;
+	  if (nr <= 0)
+	    {
+	      lused = 0;
+	      return nr;
+	    }
+	  lused = nr;
 	}
-      lused = nr;
+      if (cp)
+	*cp = lbuf[lind++];
     }
-  if (cp)
-    *cp = lbuf[lind++];
+  while (*cp == '\r');
+
   return 1;
 }
 
 /* Don't mix calls to zreadc and zreadcintr in the same function, since they
    use the same local buffer. */
diff -aprNU5 bash-4.1.orig/lib/sh/zwrite.c bash-4.1/lib/sh/zwrite.c
--- bash-4.1.orig/lib/sh/zwrite.c	2008-08-12 17:58:48 +0000
+++ bash-4.1/lib/sh/zwrite.c	2019-02-01 23:37:12 +0000
@@ -30,10 +30,17 @@
 
 #if !defined (errno)
 extern int errno;
 #endif
 
+#if defined (__DJGPP__)
+/* DJGPP always uses its own pipe implementation.
+   Required for write.  */
+
+#  include "dospipe.h"
+#endif /* __DJGPP__ */
+
 /* Write NB bytes from BUF to file descriptor FD, retrying the write if
    it is interrupted.  We retry three times if we get a zero-length
    write.  Any other signal causes this function to return prematurely. */
 int
 zwrite (fd, buf, nb)
diff -aprNU5 bash-4.1.orig/lib/termcap/termcap.c bash-4.1/lib/termcap/termcap.c
--- bash-4.1.orig/lib/termcap/termcap.c	2009-01-04 19:39:56 +0000
+++ bash-4.1/lib/termcap/termcap.c	2019-02-01 23:37:12 +0000
@@ -100,10 +100,14 @@ int bufsize = 128;
 #endif
 #endif
 
 #include "ltcap.h"
 
+#if defined (__DJGPP__)
+#define TERMCAP_FILE "/dev/env/DJDIR/etc/termcap"
+#endif /* __DJGPP__ */
+
 #ifndef TERMCAP_FILE
 #define TERMCAP_FILE "/etc/termcap"
 #endif
 
 #ifndef emacs
@@ -417,21 +421,21 @@ valid_filename_p (fn)
   return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
 }
 
 #else /* !VMS */
 
-#ifdef MSDOS /* MW, May 1993 */
+#if defined (__MSDOS__) /* MW, May 1993 */
 static int
 valid_filename_p (fn)
      char *fn;
 {
   return *fn == '\\' || *fn == '/' ||
     (*fn >= 'A' && *fn <= 'z' && fn[1] == ':');
 }
-#else
+#else  /* !__MSDOS__ */
 #define valid_filename_p(fn) (*(fn) == '/')
-#endif
+#endif  /* !__MSDOS__ */
 
 #endif /* !VMS */
 
 /* Find the termcap entry data for terminal type NAME
    and store it in the block that BP points to.
@@ -523,15 +527,15 @@ tgetent (bp, name)
   if (!termcap_name || !filep)
     termcap_name = TERMCAP_FILE;
 
   /* Here we know we must search a file and termcap_name has its name.  */
 
-#ifdef MSDOS
+#if defined (__MSDOS__)
   fd = open (termcap_name, O_RDONLY|O_TEXT, 0);
-#else
+#else  /* !__MSDOS__ */
   fd = open (termcap_name, O_RDONLY, 0);
-#endif
+#endif /* !__MSDOS__ */
   if (fd < 0)
     return -1;
 
   buf.size = BUFSIZE;
   /* Add 1 to size to ensure room for terminating null.  */
diff -aprNU5 bash-4.1.orig/lib/tilde/tilde.c bash-4.1/lib/tilde/tilde.c
--- bash-4.1.orig/lib/tilde/tilde.c	2009-01-04 19:32:36 +0000
+++ bash-4.1/lib/tilde/tilde.c	2019-02-01 23:37:12 +0000
@@ -237,11 +237,11 @@ tilde_expand (string)
 
       expansion = tilde_expand_word (tilde_word);
       xfree (tilde_word);
 
       len = strlen (expansion);
-#ifdef __CYGWIN__
+#if defined (_WIN32) || defined (__MSDOS__)
       /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
 	 $HOME for `user' is /.  On cygwin, // denotes a network drive. */
       if (len > 1 || *expansion != '/' || *string != '/')
 #endif
 	{
@@ -269,15 +269,15 @@ isolate_tilde_prefix (fname, lenp)
 {
   char *ret;
   int i;
 
   ret = (char *)xmalloc (strlen (fname));
-#if defined (__MSDOS__)
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
   for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
-#else
+#else  /* !HAVE_DOS_BASED_FILE_SYSTEM */
   for (i = 1; fname[i] && fname[i] != '/'; i++)
-#endif
+#endif /* !HAVE_DOS_BASED_FILE_SYSTEM */
     ret[i - 1] = fname[i];
   ret[i - 1] = '\0';
   if (lenp)
     *lenp = i;
   return ret;
diff -aprNU5 bash-4.1.orig/nofork.c bash-4.1/nofork.c
--- bash-4.1.orig/nofork.c	1970-01-01 00:00:00 +0000
+++ bash-4.1/nofork.c	2019-02-01 23:37:12 +0000
@@ -0,0 +1,345 @@
+#include <config.h>
+
+#if !defined (HAVE_WORKING_FORK)
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dpmi.h>
+#include <sys/system.h>
+
+#include "nofork.h"
+#include "dospath.h"
+
+#include "command.h"
+#include "general.h"
+#include "error.h"
+#include "variables.h"
+#include "subst.h"
+#include "externs.h"
+#include "builtins/common.h"
+#include "hashcmd.h"
+#include "flags.h"
+#include "bashjmp.h"
+
+#define SAVESTRING(p)  ((p != NULL) ? savestring (p) : NULL)
+#define FREE_AND_CLEAR(p)  (free (p), p = NULL)
+
+#define CURRENT_PID ((pid_t) 1)
+
+pid_t nofork_current_pid = CURRENT_PID;
+int nofork_wait_status = -1;
+OLDENVBUF *current_environment = NULL;
+
+static void
+save_jmp_buf(jmp_buf save, jmp_buf now)
+{
+  memcpy((char *)save, (char *)now, sizeof(jmp_buf));
+}
+
+static void
+restore_jmp_buf(jmp_buf save, jmp_buf now)
+{
+  memcpy((char *)now, (char *)save, sizeof(jmp_buf));
+}
+
+extern jmp_buf top_level, subshell_top_level;
+extern int interactive, interactive_shell, login_shell;
+extern int subshell_environment;
+extern int subshell_exit_builtin, exit_immediately_on_error;
+extern int dollar_dollar_pid;
+extern int array_needs_making;
+extern SHELL_VAR *ifs_var;
+
+static void
+save_current_directory (OLDENVBUF *envp)
+{
+  envp->pwd    = SAVESTRING (get_string_value ("PWD"));
+  envp->curdir = getcwd (NULL, PATH_MAX);
+}
+
+static void
+restore_current_directory(OLDENVBUF *envp)
+{
+  /* change old directory */
+  if (envp->curdir != NULL)
+  {
+    chdir(envp->curdir);
+    if (envp->pwd != NULL)
+      set_working_directory(envp->pwd);
+    else
+      set_working_directory(envp->curdir);
+    FREE_AND_CLEAR (envp->curdir);
+  }
+  else if (envp->pwd != NULL)
+  {
+    chdir(envp->pwd);
+    set_working_directory(envp->pwd);
+  }
+
+  if (envp->pwd)
+    FREE_AND_CLEAR(envp->pwd);
+}
+
+extern WORD_LIST *subst_assign_varlist;
+
+static void
+save_global_variables(OLDENVBUF *envp)
+{
+  envp->interactive               = interactive;
+  envp->interactive_shell         = interactive_shell;
+  envp->login_shell               = login_shell;
+  envp->subshell_environment      = subshell_environment;
+  envp->subshell_exit_builtin     = subshell_exit_builtin;
+  envp->exit_immediately_on_error = exit_immediately_on_error;
+  envp->variable_context          = variable_context;
+  envp->dollar_dollar_pid         = dollar_dollar_pid;
+  envp->subst_assign_varlist      = subst_assign_varlist;
+  envp->echo_command_at_execute   = echo_command_at_execute;
+  subst_assign_varlist = NULL;
+}
+
+static void
+restore_global_variables(OLDENVBUF *envp)
+{
+  interactive               = envp->interactive;
+  interactive_shell         = envp->interactive_shell;
+  login_shell               = envp->login_shell;
+  subshell_environment      = envp->subshell_environment;
+  subshell_exit_builtin     = envp->subshell_exit_builtin;
+  exit_immediately_on_error = envp->exit_immediately_on_error;
+  variable_context          = envp->variable_context;
+  dollar_dollar_pid         = envp->dollar_dollar_pid;
+  subst_assign_varlist      = envp->subst_assign_varlist;
+  echo_command_at_execute   = envp->echo_command_at_execute;
+}
+
+
+static VAR_CONTEXT *
+copy_var_context(VAR_CONTEXT *fvc)
+{
+  VAR_CONTEXT *vc;
+
+  vc = (VAR_CONTEXT *)xmalloc(sizeof(VAR_CONTEXT));
+  vc->name = fvc->name ? savestring(fvc->name) : (char *)NULL;
+  vc->scope = fvc->scope;
+  vc->flags = fvc->flags & ~(VC_COPYONCHANGE);
+
+  vc->table = hash_copy(fvc->table, (sh_string_func_t *)copy_variable);
+  vc->up = vc->down = (VAR_CONTEXT *)NULL;
+
+  return vc;
+}
+
+static void
+save_all_var_contexts(OLDENVBUF *envp)
+{
+  VAR_CONTEXT *vc;
+  VAR_CONTEXT *vc_copy, *sv, *vc_copy_prev;
+
+  vc = shell_variables;
+  sv = vc_copy = copy_var_context(vc);
+
+  while (vc->down)
+  {
+    vc_copy_prev = vc_copy;
+    vc = vc->down;
+    vc_copy = copy_var_context(vc);
+    vc_copy_prev->down = vc_copy;
+    vc_copy->up = vc_copy_prev;
+  }
+
+#if NOFORK_COPY_ON_CHANGE
+  envp->global_variables = vc_copy;
+  envp->shell_variables = sv;
+#else
+  envp->shell_variables = shell_variables;
+  envp->global_variables = global_variables;
+  shell_variables = sv;
+  global_variables = vc_copy;
+#endif
+}
+
+static void
+restore_all_var_contexts(OLDENVBUF *envp)
+{
+  delete_all_contexts(shell_variables);
+  dispose_var_context(global_variables);
+
+  global_variables = envp->global_variables;
+  shell_variables = envp->shell_variables;
+  delete_all_variables(shell_functions);
+  hash_dispose(shell_functions);
+  shell_functions = envp->shell_functions;
+}
+
+void
+copy_var_contexts_on_change(void)
+{
+  if (current_environment == NULL)
+    return;
+
+  save_all_var_contexts(current_environment);
+  global_variables->flags &= ~(VC_COPYONCHANGE);
+}
+
+
+static void
+save_shell_variables(OLDENVBUF *envp)
+{
+#if NOFORK_COPY_ON_CHANGE
+  SHELL_VAR *lastarg_var;
+#endif
+
+  maybe_make_export_env();
+
+  envp->global_variables = NULL;
+  envp->shell_variables = NULL;
+  global_variables->flags |= VC_COPYONCHANGE;
+
+#if NOFORK_COPY_ON_CHANGE || 1
+  /* Must be copied to be restored later because the shell variables
+     may be modified by the subshell call. */
+  save_all_var_contexts(envp);
+#endif
+
+  envp->shell_functions = shell_functions;
+  shell_functions = hash_copy(envp->shell_functions, (sh_string_func_t *)copy_variable);
+
+  envp->temporary_env = temporary_env;
+  if (temporary_env)
+    temporary_env = hash_copy(envp->temporary_env, (sh_string_func_t *)copy_variable);
+
+#if NOFORK_COPY_ON_CHANGE
+  lastarg_var = find_variable("_");
+  if (lastarg_var)
+    envp->lastarg = savestring(value_cell(lastarg_var));
+#endif
+
+  envp->rest_of_args = list_rest_of_args();
+}
+
+static void
+restore_shell_variables(OLDENVBUF *envp)
+{
+  SHELL_VAR *temp_ifs;
+
+  if (envp->global_variables)
+    restore_all_var_contexts(envp);
+  else
+    global_variables->flags &= ~(VC_COPYONCHANGE);
+
+  if (temporary_env)
+  {
+    delete_all_variables(temporary_env);
+    hash_dispose(temporary_env);
+  }
+  temporary_env = envp->temporary_env;
+
+  temp_ifs = find_variable("IFS");
+  setifs(temp_ifs);
+
+#if NOFORK_COPY_ON_CHANGE
+  bind_variable("_", envp->lastarg);
+  free(envp->lastarg);
+#endif
+
+  remember_args(envp->rest_of_args, 1);
+
+  array_needs_making = 1;
+  maybe_make_export_env();
+}
+
+extern int return_catch_flag;
+
+int
+nofork_save_all_environment(OLDENVBUF *envp)
+{
+  save_jmp_buf(envp->return_catch, return_catch);
+  envp->return_catch_flag = return_catch_flag;
+  save_jmp_buf(envp->top_level, top_level);
+  save_jmp_buf(envp->subshell_top_level, subshell_top_level);
+  nofork_save_std_fds(envp->fds);
+  save_current_directory(envp);
+  save_global_variables(envp);
+  save_shell_variables(envp);
+
+  envp->prev_environment = current_environment;
+  current_environment = envp;
+
+  return 0;
+}
+
+int
+nofork_restore_all_environment(OLDENVBUF *envp)
+{
+  restore_shell_variables(envp);
+  restore_global_variables(envp);
+  restore_current_directory(envp);
+  nofork_restore_std_fds(envp->fds);
+  restore_jmp_buf(envp->top_level, top_level);
+  restore_jmp_buf(envp->subshell_top_level, subshell_top_level);
+
+  restore_jmp_buf(envp->return_catch, return_catch);
+  return_catch_flag = envp->return_catch_flag;
+
+  current_environment = envp->prev_environment;
+
+  return 0;
+}
+
+#include <sys/param.h>
+#if !defined (MAXPID)
+#define MAXPID ((pid_t) 30000)
+#endif
+
+static pid_t last_pid = CURRENT_PID;
+
+pid_t
+nofork_make_child_pid(void)
+{
+  if (++last_pid > MAXPID)
+    last_pid = CURRENT_PID + 1;
+
+  return last_pid;
+}
+
+void
+nofork_save_std_fds(int fds[3])
+{
+  int i;
+
+  /* save stdin/out/err */
+  for (i = 0; i < 3; i++)
+#if defined (F_DUPFD)
+    if ((fds[i] = fcntl(i, F_DUPFD, 20)) < 0)
+#else
+    if ((fds[i] = dup(i)) < 0)
+#endif
+      internal_error("Cannot duplicate fd %d: %s", i, strerror(errno));
+}
+
+void
+nofork_restore_std_fds(int fds[3])
+{
+  int i;
+
+  /* restore stdin/out/err */
+  for (i = 0; i < 3; i++)
+    if (fds[i] >= 0)
+    {
+      if (dup2(fds[i], i) < 0)
+        internal_error("cannot duplicate fd %d to fd %d: %s", fds[i], i, strerror(errno));
+      close (fds[i]);
+      fds[i] = -1;
+    }
+}
+
+#endif /* !HAVE_WORKING_FORK */
diff -aprNU5 bash-4.1.orig/nofork.h bash-4.1/nofork.h
--- bash-4.1.orig/nofork.h	1970-01-01 00:00:00 +0000
+++ bash-4.1/nofork.h	2019-02-01 23:37:12 +0000
@@ -0,0 +1,83 @@
+#ifndef BASH_NOFORK_H
+#define BASH_NOFORK_H
+
+#define NOFORK_COPY_ON_CHANGE 0
+
+#include <setjmp.h>
+
+#include "command.h"
+#include "general.h"
+#include "hashlib.h"
+#include "variables.h"
+#include "stdc.h"
+
+typedef struct oldenvbuf
+{
+  int fds[3];
+
+  jmp_buf top_level;
+  jmp_buf subshell_top_level;
+
+  int return_catch_flag;
+  jmp_buf return_catch;
+
+  VAR_CONTEXT *global_variables;
+  VAR_CONTEXT *shell_variables;
+  HASH_TABLE *shell_functions;
+
+  HASH_TABLE *temporary_env;
+  char **non_unsettable_vars;
+
+  char *dollar_vars[10];
+  WORD_LIST *rest_of_args;
+
+  char *pwd;
+  char *oldpwd;
+  char *curdir;
+
+  int interactive;
+  int interactive_shell;
+  int login_shell;
+  int subshell_environment;
+  int subshell_exit_builtin;
+  int exit_immediately_on_error;
+  int variable_context;
+  int dollar_dollar_pid;
+  WORD_LIST *subst_assign_varlist;
+  int echo_command_at_execute;
+
+  SHELL_VAR *ifs_var;
+  char *ifs_value;
+
+  char *lastarg;
+
+  struct oldenvbuf *prev_environment;
+} OLDENVBUF;
+
+typedef struct
+{
+  char *trap_val;
+  int signal_mode;
+} TRAPBUF;
+
+extern int subshell_exit_value;
+extern int subshell_exit_builtin;
+extern int subshell_skip_commands;
+extern int nofork_wait_status;
+extern pid_t nofork_current_pid;
+
+pid_t nofork_make_child_pid __P ((void));
+void nofork_save_std_fds __P ((int fds[3]));
+void nofork_restore_std_fds __P ((int fds[3]));
+int nofork_save_all_environment __P ((OLDENVBUF *));
+int nofork_restore_all_environment __P ((OLDENVBUF *));
+void save_trap __P ((TRAPBUF *));
+void restore_trap __P ((TRAPBUF *));
+void copy_var_contexts_on_change(void);
+
+int get_signal_modes __P ((int sig));
+int set_signal_modes __P ((int sig, int modes));
+
+int bash_spawnve __P ((char *path, char **args, char **envp));
+
+#endif /* BASH_NOFORK_H */
diff -aprNU5 bash-4.1.orig/nojobs.c bash-4.1/nojobs.c
--- bash-4.1.orig/nojobs.c	2009-01-16 21:50:30 +0000
+++ bash-4.1/nojobs.c	2019-02-01 23:37:12 +0000
@@ -22,10 +22,11 @@
 */
 
 #include "config.h"
 
 #include "bashtypes.h"
+#include "trap.h"
 #include "filecntl.h"
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
@@ -47,10 +48,14 @@
 #include "jobs.h"
 #include "execute_cmd.h"
 
 #include "builtins/builtext.h"	/* for wait_builtin */
 
+#if !defined (HAVE_WORKING_FORK)
+#include "nofork.h"
+#endif /* !HAVE_WORKING_FORK */
+
 #define DEFAULT_CHILD_MAX 32
 
 #if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
 #  define killpg(pg, sig)		kill(-(pg),(sig))
 #endif /* USG || _POSIX_VERSION */
@@ -405,17 +410,19 @@ reap_dead_jobs ()
   mark_dead_jobs_as_notified (0);
   cleanup_dead_jobs ();
 }
 
 /* Initialize the job control mechanism, and set up the tty stuff. */
+int
 initialize_job_control (force)
      int force;
 {
   shell_tty = fileno (stderr);
 
   if (interactive)
     get_tty_state ();
+  return 1;
 }
 
 /* Setup this shell to handle C-C, etc. */
 void
 initialize_job_signals ()
@@ -445,10 +452,13 @@ reap_zombie_children ()
   CHECK_TERMSIG;
 }
 #endif /* WAITPID */
 
 #if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
+#if !defined (SA_RESTART)
+#  define SA_RESTART 0
+#endif
 static int
 siginterrupt (sig, flag)
      int sig, flag;
 {
   struct sigaction act;
@@ -466,17 +476,21 @@ siginterrupt (sig, flag)
 
 /* Fork, handling errors.  Returns the pid of the newly made child, or 0.
    COMMAND is just for remembering the name of the command; we don't do
    anything else with it.  ASYNC_P says what to do with the tty.  If
    non-zero, then don't give it away. */
+#if defined (HAVE_WORKING_FORK)
 pid_t
 make_child (command, async_p)
      char *command;
      int async_p;
 {
   pid_t pid;
   int forksleep;
+#if defined (HAVE_WAITPID)
+  int retry = 1;
+#endif /* HAVE_WAITPID */
 
   /* Discard saved memory. */
   if (command)
     free (command);
 
@@ -545,10 +559,48 @@ make_child (command, async_p)
 
       add_pid (pid, async_p);
     }
   return (pid);
 }
+#else  /* !HAVE_WORKING_FORK */
+pid_t
+make_child (command, async_p)
+     char *command;
+     int async_p;
+{
+  pid_t pid;
+
+  /* Discard saved memory. */
+  if (command)
+    free (command);
+
+  start_pipeline ();
+
+#if defined (BUFFERED_INPUT)
+  /* If default_buffered_input is active, we are reading a script.  If
+     the command is asynchronous, we have already duplicated /dev/null
+     as fd 0, but have not changed the buffered stream corresponding to
+     the old fd 0.  We don't want to sync the stream in this case. */
+  if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
+    sync_buffered_stream (default_buffered_input);
+#endif /* BUFFERED_INPUT */
+
+  /* Create the child, handle severe errors. */
+  pid = nofork_make_child_pid ();
+
+  last_made_pid = pid;
+
+  if (async_p)
+    last_asynchronous_pid = pid;
+
+  add_pid (pid, async_p);
+
+  nofork_current_pid = pid;
+  
+  return (pid);
+}
+#endif /* !HAVE_WORKING_FORK */
 
 void
 ignore_tty_job_signals ()
 {
 #if defined (SIGTSTP)
@@ -746,10 +798,11 @@ wait_for (pid)
      a child to exit.  The loop below does some of this, but not all. */
   wait_sigint_received = 0;
   if (interactive_shell == 0)
     old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
 
+#if defined (HAVE_WORKING_FORK)
   while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */
     {
       CHECK_TERMSIG;
       if (got_pid < 0 && errno == ECHILD)
 	{
@@ -766,10 +819,21 @@ wait_for (pid)
 	set_pid_status (got_pid, status);
     }
 
   if (got_pid > 0)
     set_pid_status (got_pid, status);
+#else  /* !HAVE_WORKING_FORK */
+  {
+    status = nofork_wait_status;
+    if ((status & 0x0000ff00) == 0x0000ff00)
+      status &= 0x000000ff;
+    errno = 0;
+    got_pid = pid;
+
+    last_made_pid = NO_PID;
+  }
+#endif /* !HAVE_WORKING_FORK */
 
 #if defined (HAVE_WAITPID)
   if (got_pid >= 0)
     reap_zombie_children ();
 #endif /* HAVE_WAITPID */
@@ -846,10 +910,11 @@ kill_pid (pid, signal, group)
 
 static TTYSTRUCT shell_tty_info;
 static int got_tty_state;
 
 /* Fill the contents of shell_tty_info with the current tty info. */
+int
 get_tty_state ()
 {
   int tty;
 
   tty = input_tty ();
@@ -858,10 +923,11 @@ get_tty_state ()
       ttgetattr (tty, &shell_tty_info);
       got_tty_state = 1;
       if (check_window_size)
 	get_new_window_size (0, (int *)0, (int *)0);
     }
+  return 0;
 }
 
 /* Make the current tty use the state in shell_tty_info. */
 int
 set_tty_state ()
@@ -877,14 +943,16 @@ set_tty_state ()
     }
   return 0;
 }
 
 /* Give the terminal to PGRP.  */
+int
 give_terminal_to (pgrp, force)
      pid_t pgrp;
      int force;
 {
+  return 0;
 }
 
 /* Stop a pipeline. */
 int
 stop_pipeline (async, ignore)
diff -aprNU5 bash-4.1.orig/parse.y bash-4.1/parse.y
--- bash-4.1.orig/parse.y	2019-02-01 23:36:36 +0000
+++ bash-4.1/parse.y	2019-02-01 23:37:12 +0000
@@ -86,10 +86,14 @@ typedef void *alias_t;
 #    include <sys/time.h>
 #  endif /* TM_IN_SYS_TIME */
 #  include "maxpath.h"
 #endif /* PROMPT_STRING_DECODE */
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+#include "general.h"
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
 #define RE_READ_TOKEN	-99
 #define NO_EXPANSION	-100
 
 #ifdef DEBUG
 #  define YYDEBUG 1
@@ -5129,10 +5133,17 @@ decode_prompt_string (string)
 	      goto add_string;
 
 	    case 's':
 	      temp = base_pathname (shell_name);
 	      temp = savestring (temp);
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+	      {
+	        char *dot = strchr (temp, '.');
+	        if (dot)
+	          *dot = '\0';
+	      }
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
 	      goto add_string;
 
 	    case 'v':
 	    case 'V':
 	      temp = (char *)xmalloc (16);
@@ -5178,11 +5189,11 @@ decode_prompt_string (string)
 #define ROOT_PATH(x)	((x)[0] == '/' && (x)[1] == 0)
 #define DOUBLE_SLASH_ROOT(x)	((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
 		/* Abbreviate \W as ~ if $PWD == $HOME */
 		if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
 		  {
-		    if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
+		    if (ROOTEDPATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
 		      {
 			t = strrchr (t_string, '/');
 			if (t)
 			  memmove (t_string, t + 1, strlen (t));
 		      }
diff -aprNU5 bash-4.1.orig/pathnames.h.in bash-4.1/pathnames.h.in
--- bash-4.1.orig/pathnames.h.in	2009-01-04 19:32:40 +0000
+++ bash-4.1/pathnames.h.in	2019-02-01 23:37:12 +0000
@@ -20,14 +20,22 @@
 
 #if !defined (_PATHNAMES_H_)
 #define _PATHNAMES_H_
 
 /* The default file for hostname completion. */
+#if defined (__DJGPP__)
+#define DEFAULT_HOSTS_FILE "/dev/env/DJDIR/etc/hosts"
+#else  /* !__DJGPP__ */
 #define DEFAULT_HOSTS_FILE "/etc/hosts"
+#endif /* !__DJGPP__ */
 
 /* The default login shell startup file. */
+#if defined (__DJGPP__)
+#define SYS_PROFILE "/dev/env/DJDIR/etc/profile"
+#else  /* !__DJGPP__ */
 #define SYS_PROFILE "/etc/profile"
+#endif /* !__DJGPP__ */
 
 /* The default location of the bash debugger initialization/startup file. */
 #define DEBUGGER_START_FILE	"@DEBUGGER_START_FILE@"
 
 #endif /* _PATHNAMES_H */
diff -aprNU5 bash-4.1.orig/print_cmd.c bash-4.1/print_cmd.c
--- bash-4.1.orig/print_cmd.c	2019-02-01 23:36:36 +0000
+++ bash-4.1/print_cmd.c	2019-02-01 23:37:12 +0000
@@ -38,11 +38,15 @@
 #include "bashansi.h"
 #include "bashintl.h"
 
 #include "shell.h"
 #include "flags.h"
+#if defined (__MSDOS__) && !defined (__DJGPP__)
+#include <y_tab.h>	/* use <...> so we pick it up from the build directory */
+#else  /* !__MSDOS__ */
 #include <y.tab.h>	/* use <...> so we pick it up from the build directory */
+#endif /* !__MSDOS__ */
 
 #include "shmbutil.h"
 
 #include "builtins/common.h"
 
diff -aprNU5 bash-4.1.orig/redir.c bash-4.1/redir.c
--- bash-4.1.orig/redir.c	2009-09-17 14:04:18 +0000
+++ bash-4.1/redir.c	2019-02-01 23:37:12 +0000
@@ -55,11 +55,25 @@ extern int errno;
 
 #if defined (BUFFERED_INPUT)
 #  include "input.h"
 #endif
 
+#if !defined (__MSDOS__)
 #define SHELL_FD_BASE	10
+#else  /* __MSDOS__ */
+#define SHELL_FD_BASE   20
+#endif /* __MSDOS__ */
+
+#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
+#  define HAS_LFN_SUPPORT(name)  (pathconf ((name), _PC_NAME_MAX) > 12)
+#else
+#  if defined (__MSDOS__)
+#    define HAS_LFN_SUPPORT(name)  (0)
+#  else  /* !__MSDOS__ */
+#    define HAS_LFN_SUPPORT(name)  (1)
+#  endif /* !__MSDOS__ */
+#endif
 
 int expanding_redir;
 
 extern int posixly_correct;
 extern REDIRECT *redirection_undo_list;
@@ -91,10 +105,31 @@ static REDIRECTEE rd;
 
 /* Set to errno when a here document cannot be created for some reason.
    Used to print a reasonable error message. */
 static int heredoc_errno;
 
+#if __OBSOLETE_FOR_PORT__
+#else  /* !__OBSOLETE_FOR_PORT__ */
+#endif /* !__OBSOLETE_FOR_PORT__ */
+
+#if __OBSOLETE_FOR_PORT__
+#ifdef O_TEMPORARY
+/* File will be unlinked automatically.  */
+#define UNLINK(x) (0)
+#else
+/* File must be unlinked explicitly.  */
+#define UNLINK(x) unlink(x)
+#endif
+#else  /* !__OBSOLETE_FOR_PORT__ */
+#ifdef O_TEMPORARY
+/* File will be unlinked automatically,
+   else file must be unlinked explicitly.  */
+#undef unlink
+#define unlink(x) (0)
+#endif /* O_TEMPORARY */
+#endif /* !__OBSOLETE_FOR_PORT__ */
+
 void
 redirection_error (temp, error)
      REDIRECT *temp;
      int error;
 {
@@ -408,11 +443,11 @@ here_document_to_fd (redirectee, ri)
      enum r_instruction ri;
 {
   char *filename;
   int r, fd, fd2;
 
-  fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);
+  fd = sh_mktmpfd (HAS_LFN_SUPPORT(".") ? "sh-thd" : "hd", MT_USERANDOM|MT_USETMPDIR, &filename);
 
   /* If we failed for some reason other than the file existing, abort */
   if (fd < 0)
     {
       FREE (filename);
@@ -423,36 +458,58 @@ here_document_to_fd (redirectee, ri)
   /* write_here_document returns 0 on success, errno on failure. */
   if (redirectee->word)
     r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
 				 : write_here_string (fd, redirectee);
 
+#if defined (__MSDOS__)
+  if (r == ENOTTY)
+      errno = r = 0;
+#endif /* __MSDOS__ */
+
   if (r)
     {
       close (fd);
+#if __OBSOLETE_FOR_PORT__
+      UNLINK (filename);
+#else  /* !__OBSOLETE_FOR_PORT__ */
       unlink (filename);
+#endif /* !__OBSOLETE_FOR_PORT__ */
       free (filename);
       errno = r;
       return (-1);
     }
 
+#if defined (__MSDOS__)
+  /* Commit here document to disk before opening again.  */
+  fsync (fd);
+#endif /* __MSDOS__ */
+
   /* In an attempt to avoid races, we close the first fd only after opening
      the second. */
   /* Make the document really temporary.  Also make it the input. */
   fd2 = open (filename, O_RDONLY, 0600);
 
   if (fd2 < 0)
     {
       r = errno;
+#if __OBSOLETE_FOR_PORT__
+      UNLINK (filename);
+#else  /* !__OBSOLETE_FOR_PORT__ */
       unlink (filename);
+#endif /* !__OBSOLETE_FOR_PORT__ */
       free (filename);
       close (fd);
       errno = r;
       return -1;
     }
 
   close (fd);
+#if __OBSOLETE_FOR_PORT__
+  if (UNLINK (filename) < 0)
+#else  /* !__OBSOLETE_FOR_PORT__ */
   if (unlink (filename) < 0)
+#endif /* !__OBSOLETE_FOR_PORT__ */
     {
       r = errno;
 #if defined (__CYGWIN__)
       /* Under CygWin 1.1.0, the unlink will fail if the file is
 	 open. This hack will allow the previous action of silently
diff -aprNU5 bash-4.1.orig/shell.c bash-4.1/shell.c
--- bash-4.1.orig/shell.c	2009-11-19 15:05:54 +0000
+++ bash-4.1/shell.c	2019-02-01 23:37:12 +0000
@@ -37,10 +37,11 @@
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
 #include "filecntl.h"
 #include <pwd.h>
+#include <ctype.h>
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
 
@@ -55,10 +56,12 @@
 #include "builtins.h"
 #include "builtins/common.h"
 
 #if defined (JOB_CONTROL)
 #include "jobs.h"
+#else  /* !JOB_CONTROL */
+extern int get_tty_state __P((void));
 #endif /* JOB_CONTROL */
 
 #include "input.h"
 #include "execute_cmd.h"
 #include "findcmd.h"
@@ -81,10 +84,24 @@
 
 #if defined (__OPENNT)
 #  include <opennt/opennt.h>
 #endif
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+#include <termios.h>
+#include <sys/system.h>
+#endif /* __DJGPP__ */
+
+#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
+#  define HAS_LFN_SUPPORT(name)  (pathconf ((name), _PC_NAME_MAX) > 12)
+#else
+#  if defined (__MSDOS__)
+#    define HAS_LFN_SUPPORT(name)  (0)
+#  endif /* __MSDOS__ */
+#endif
+
 #if !defined (HAVE_GETPW_DECLS)
 extern struct passwd *getpwuid ();
 #endif /* !HAVE_GETPW_DECLS */
 
 #if !defined (errno)
@@ -191,10 +208,17 @@ int have_devfd = 0;
 #endif
 
 /* The name of the .(shell)rc file. */
 static char *bashrc_file = "~/.bashrc";
 
+#if defined (__MSDOS__)
+/* DOS filenames cannot begin with a '.' in a short filename environment.  */
+const char *def_bashrc_file = "~/.bashrc";
+char *dos_bashrc_file = "~/_bashrc";
+char *dos_profile = "~/_profile";
+#endif /* __MSDOS__ */
+
 /* Non-zero means to act more like the Bourne shell on startup. */
 static int act_like_sh;
 
 /* Non-zero if this shell is being run by `su'. */
 static int su_shell;
@@ -390,10 +414,17 @@ main (argc, argv, env)
 
 #ifdef __CYGWIN__
   _cygwin32_check_tmp ();
 #endif /* __CYGWIN__ */
 
+#if defined (__DJGPP__)
+  /* Save stat some effort.  */
+  _djstat_flags |= _STAT_INODE | _STAT_DIRSIZE;
+  save_cwd();
+  init_path_separator();
+#endif /* __DJGPP__ */
+
   /* Wait forever if we are debugging a login shell. */
   while (debugging_login_shell) sleep (3);
 
   set_default_locale ();
 
@@ -523,11 +554,13 @@ main (argc, argv, env)
        isatty (fileno (stderr))))	/* error output is a terminal. */
     init_interactive ();
   else
     init_noninteractive ();
 
+#if !defined (HAVE_DOS_BASED_FILE_SYSTEM)
 #define CLOSE_FDS_AT_LOGIN
+#endif /* !HAVE_DOS_BASED_FILE_SYSTEM */
 #if defined (CLOSE_FDS_AT_LOGIN)
   /*
    * Some systems have the bad habit of starting login shells with lots of open
    * file descriptors.  For instance, most systems that have picked up the
    * pre-4.0 Sun YP code leave a file descriptor open each time you call one
@@ -1023,10 +1056,20 @@ run_startup_files ()
 	  maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
 #  else
 	  maybe_execute_file (SYS_BASHRC, 1);
 #  endif
 #endif
+#if defined (__MSDOS__)
+          /* Try _bashrc first.  */
+          if (strcmp (def_bashrc_file, bashrc_file) == 0)
+            if (maybe_execute_file (dos_bashrc_file, 1))
+              return;
+          /* Don't bother trying to read .bashrc in an SFN environment.  */
+          if (!HAS_LFN_SUPPORT("."))
+            return;
+          /* Now try .bashrc.  */
+#endif /* __MSDOS__ */
 	  maybe_execute_file (bashrc_file, 1);
 	  return;
 	}
     }
 
@@ -1054,15 +1097,29 @@ run_startup_files ()
 	 initialization files. */
       if (no_profile == 0)
 	{
 	  maybe_execute_file (SYS_PROFILE, 1);
 
+#if defined (__MSDOS__)
+          if (act_like_sh)
+            {
+              if (maybe_execute_file ("~/.profile", 1) == 0)
+                maybe_execute_file ("~/_profile", 1);
+            }
+	  else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
+		   (maybe_execute_file ("~/_bprof", 1) == 0) &&
+		   (maybe_execute_file ("~/.bash_login", 1) == 0) &&
+		   (maybe_execute_file ("~/_blogin", 1) == 0) &&
+		   (maybe_execute_file ("~/.profile", 1) == 0))
+	    maybe_execute_file ("~/_profile", 1);
+#else  /* !__MSDOS__ */
 	  if (act_like_sh)	/* sh */
 	    maybe_execute_file ("~/.profile", 1);
 	  else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
 		   (maybe_execute_file ("~/.bash_login", 1) == 0))	/* bash */
 	    maybe_execute_file ("~/.profile", 1);
+#endif /* !__MSDOS__ */
 	}
 
       sourced_login = 1;
     }
 
@@ -1090,15 +1147,29 @@ run_startup_files ()
 	     initialization files. */
 	  if (no_profile == 0)
 	    {
 	      maybe_execute_file (SYS_PROFILE, 1);
 
+#if defined (__MSDOS__)
+              if (act_like_sh)
+                {
+                  if (maybe_execute_file ("~/.profile", 1) == 0)
+                    maybe_execute_file ("~/_profile", 1);
+                }
+              else if ((maybe_execute_file ("~/.bash_profile", 1) == 0)
+                       && (maybe_execute_file ("~/_bprof", 1) == 0)
+                       && (maybe_execute_file ("~/.bash_login", 1) == 0)
+                       && (maybe_execute_file ("~/_blogin", 1) == 0)
+                       && (maybe_execute_file ("~/.profile", 1) == 0))
+                maybe_execute_file ("~/_profile", 1);
+#else  /* !__MSDOS__ */
 	      if (act_like_sh)	/* sh */
 		maybe_execute_file ("~/.profile", 1);
 	      else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
 		       (maybe_execute_file ("~/.bash_login", 1) == 0))	/* bash */
 		maybe_execute_file ("~/.profile", 1);
+#endif /* !__MSDOS__ */
 	    }
 	}
 
       /* bash */
       if (act_like_sh == 0 && no_rc == 0)
@@ -1108,11 +1179,17 @@ run_startup_files ()
 	  maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
 #  else
 	  maybe_execute_file (SYS_BASHRC, 1);
 #  endif
 #endif
+#if defined (__MSDOS__)
+	  if ( (maybe_execute_file (bashrc_file, 1) == 0)
+	       && (strcmp (def_bashrc_file, bashrc_file) == 0))
+            maybe_execute_file (dos_bashrc_file, 1);
+#else  /* !__MSDOS__ */
 	  maybe_execute_file (bashrc_file, 1);
+#endif /* !__MSDOS__ */
 	}
       /* sh */
       else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
 	execute_env_file (get_string_value ("ENV"));
     }
@@ -1583,14 +1660,23 @@ set_shell_name (argv0)
       if (*shell_name == '-')
 	shell_name++;
       login_shell++;
     }
 
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (islower (shell_name[0]) == 's' && islower (shell_name[1]) == 'h'
+      && (shell_name[2] == '.' || shell_name[2] == '\0'))
+    act_like_sh++;
+  if (islower (shell_name[0]) == 's' && islower (shell_name[1]) == 'u'
+      && (shell_name[2] == '.' || shell_name[2] == '\0'))
+    su_shell++;
+#else  /* !HAVE_DOS_BASED_FILE_SYSTEM */
   if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
     act_like_sh++;
   if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
     su_shell++;
+#endif /* !HAVE_DOS_BASED_FILE_SYSTEM */
 
   shell_name = argv0 ? argv0 : PROGRAM;
   FREE (dollar_vars[0]);
   dollar_vars[0] = savestring (shell_name);
 
@@ -1639,10 +1725,16 @@ get_current_user_info ()
     {
       entry = getpwuid (current_user.uid);
       if (entry)
 	{
 	  current_user.user_name = savestring (entry->pw_name);
+#if defined (__DJGPP__)
+          /* Don't use a DOS shell for Unix work.  */
+          if (entry->pw_shell && _is_dos_shell(entry->pw_shell))
+            current_user.shell = make_posix_path_from_filename (get_real_path(shell_name));
+          else
+#endif /* __DJGPP__ */
 	  current_user.shell = (entry->pw_shell && entry->pw_shell[0])
 				? savestring (entry->pw_shell)
 				: savestring ("/bin/sh");
 	  current_user.home_dir = savestring (entry->pw_dir);
 	}
@@ -1709,11 +1801,13 @@ shell_initialize ()
 #else
   initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
 #endif
 
   /* Initialize the data structures for storing and running jobs. */
+#if defined (JOB_CONTROL)
   initialize_job_control (0);
+#endif /* JOB_CONTROL */
 
   /* Initialize input streams to null. */
   initialize_bash_input ();
 
   initialize_flags ();
diff -aprNU5 bash-4.1.orig/sig.c bash-4.1/sig.c
--- bash-4.1.orig/sig.c	2019-02-01 23:36:36 +0000
+++ bash-4.1/sig.c	2019-02-02 00:13:58 +0000
@@ -539,10 +539,17 @@ termsig_handler (sig)
   loop_level = continuing = breaking = 0;
   executing_list = comsub_ignore_return = return_catch_flag = 0;
 
   run_exit_trap ();
   set_signal_handler (sig, SIG_DFL);
+#if defined (__DJGPP__)
+  /* Fake a hardware exception. A software exception would just print a
+     long traceback.  */
+  if (sig == SIGINT)
+    __asm__ __volatile__ ("movb $0x79,%al;call ___djgpp_hw_exception");
+  else
+#endif /* __DJGPP__ */
   kill (getpid (), sig);
 }
 
 /* What we really do when SIGINT occurs. */
 sighandler
@@ -654,12 +661,14 @@ set_signal_handler (sig, handler)
   if (sig == SIGALRM)
     act.sa_flags |= SA_INTERRUPT;	/* XXX */
   else
     act.sa_flags |= SA_RESTART;		/* XXX */
 #else
+#if defined (SIGCHLD)
   if (sig == SIGCHLD)
     act.sa_flags |= SA_RESTART;
+#endif /* SIGCHLD */
 #endif
   sigemptyset (&act.sa_mask);
   sigemptyset (&oact.sa_mask);
   sigaction (sig, &act, &oact);
   return (oact.sa_handler);
diff -aprNU5 bash-4.1.orig/subst.c bash-4.1/subst.c
--- bash-4.1.orig/subst.c	2009-12-30 13:24:28 +0000
+++ bash-4.1/subst.c	2019-02-01 23:37:12 +0000
@@ -58,10 +58,21 @@
 #include "builtins/builtext.h"
 
 #include <tilde/tilde.h>
 #include <glob/strmatch.h>
 
+#if !defined (HAVE_WORKING_FORK)
+#  include "nofork.h"
+#endif /* !HAVE_WORKING_FORK */
+
+#if defined (__DJGPP__)
+/* DJGPP always uses its own pipe implementation.
+   Required for close and pipe.  */
+
+#  include "dospipe.h"
+#endif /* __DJGPP__ */
+
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
 
 /* The size that strings change by. */
@@ -4740,10 +4751,13 @@ process_substitute (string, open_for_rea
   int fildes[2];
 #endif /* HAVE_DEV_FD */
 #if defined (JOB_CONTROL)
   pid_t old_pipeline_pgrp;
 #endif
+#if !defined (HAVE_WORKING_FORK)
+  OLDENVBUF oldenvbuf;
+#endif /* !HAVE_WORKING_FORK */
 
   if (!string || !*string || wordexp_only)
     return ((char *)NULL);
 
 #if !defined (HAVE_DEV_FD)
@@ -4777,20 +4791,25 @@ process_substitute (string, open_for_rea
   old_pipeline_pgrp = pipeline_pgrp;
   pipeline_pgrp = shell_pgrp;
   save_pipeline (1);
 #endif /* JOB_CONTROL */
 
+#if !defined (HAVE_WORKING_FORK)
+  nofork_save_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
   pid = make_child ((char *)NULL, 1);
+#if defined (HAVE_WORKING_FORK)
   if (pid == 0)
     {
       reset_terminating_signals ();	/* XXX */
       free_pushed_string_input ();
       /* Cancel traps, in trap.c. */
       restore_original_signals ();
       setup_async_signals ();
       subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
     }
+#endif /* HAVE_WORKING_FORK */
 
 #if defined (JOB_CONTROL)
   set_sigchld_handler ();
   stop_making_children ();
   /* XXX - should we only do this in the parent? (as in command subst) */
@@ -4803,15 +4822,25 @@ process_substitute (string, open_for_rea
       free (pathname);
 #if defined (HAVE_DEV_FD)
       close (parent_pipe_fd);
       close (child_pipe_fd);
 #endif /* HAVE_DEV_FD */
+#if !defined (HAVE_WORKING_FORK)
+      nofork_restore_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
       return ((char *)NULL);
     }
 
+#if defined (HAVE_WORKING_FORK)
   if (pid > 0)
-    {
+#else  /* !HAVE_WORKING_FORK */
+  if (0)
+#endif /* !HAVE_WORKING_FORK */
+    {
+#if !defined (HAVE_WORKING_FORK)
+      process_substitute_parent:
+#endif /* !HAVE_WORKING_FORK */
 #if defined (JOB_CONTROL)
       restore_pipeline (1);
 #endif
 
 #if !defined (HAVE_DEV_FD)
@@ -4846,11 +4875,17 @@ process_substitute (string, open_for_rea
       if (open_for_read_in_child)
 	sys_error (_("cannot open named pipe %s for reading"), pathname);
       else
 	sys_error (_("cannot open named pipe %s for writing"), pathname);
 
+#if defined (HAVE_WORKING_FORK)
       exit (127);
+#else  /* !HAVE_WORKING_FORK */
+      nofork_restore_all_environment (&oldenvbuf);
+      nofork_wait_status = 127;
+      goto process_substitute_exit;
+#endif /* !HAVE_WORKING_FORK */
     }
   if (open_for_read_in_child)
     {
       if (sh_unset_nodelay_mode (fd) < 0)
 	{
@@ -4864,11 +4899,17 @@ process_substitute (string, open_for_rea
 
   if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
     {
       sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
 	open_for_read_in_child ? 0 : 1);
+#if defined (HAVE_WORKING_FORK)
       exit (127);
+#else  /* !HAVE_WORKING_FORK */
+      nofork_restore_all_environment (&oldenvbuf);
+      nofork_wait_status = 127;
+      goto process_substitute_exit;
+#endif /* !HAVE_WORKING_FORK */
     }
 
   if (fd != (open_for_read_in_child ? 0 : 1))
     close (fd);
 
@@ -4893,11 +4934,21 @@ process_substitute (string, open_for_rea
 #if !defined (HAVE_DEV_FD)
   /* Make sure we close the named pipe in the child before we exit. */
   close (open_for_read_in_child ? 0 : 1);
 #endif /* !HAVE_DEV_FD */
 
+#if defined (HAVE_WORKING_FORK)
   exit (result);
+#else  /* !HAVE_WORKING_FORK */
+  nofork_wait_status = result;
+
+process_substitute_exit:
+  nofork_restore_all_environment (&oldenvbuf);
+
+  /* run parent side */
+  goto process_substitute_parent;
+#endif /* !HAVE_WORKING_FORK */
   /*NOTREACHED*/
 }
 #endif /* PROCESS_SUBSTITUTION */
 
 /***********************************/
@@ -5026,10 +5077,13 @@ command_substitute (string, quoted)
 {
   pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
   char *istring;
   int result, fildes[2], function_value, pflags, rc, tflag;
   WORD_DESC *ret;
+#if !defined (HAVE_WORKING_FORK)
+  OLDENVBUF oldenvbuf;
+#endif /* !HAVE_WORKING_FORK */
 
   istring = (char *)NULL;
 
   /* Don't fork () if there is no need to.  In the case of no command to
      run, just return NULL. */
@@ -5072,17 +5126,22 @@ command_substitute (string, quoted)
     pipeline_pgrp = shell_pgrp;
   cleanup_the_pipeline ();
 #endif /* JOB_CONTROL */
 
   old_async_pid = last_asynchronous_pid;
+#if !defined (HAVE_WORKING_FORK)
+  nofork_save_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
   pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
   last_asynchronous_pid = old_async_pid;
 
+#if defined (HAVE_WORKING_FORK)
   if (pid == 0)
     /* Reset the signal handlers in the child, but don't free the
        trap strings. */
     reset_signal_handlers ();
+#endif /* HAVE_WORKING_FORK */
 
 #if defined (JOB_CONTROL)
   /* XXX DO THIS ONLY IN PARENT ? XXX */
   set_sigchld_handler ();
   stop_making_children ();
@@ -5093,30 +5152,44 @@ command_substitute (string, quoted)
 #endif /* JOB_CONTROL */
 
   if (pid < 0)
     {
       sys_error (_("cannot make child for command substitution"));
+#if !defined (HAVE_WORKING_FORK)
+      nofork_restore_all_environment (&oldenvbuf);
+#endif /* !HAVE_WORKING_FORK */
     error_exit:
 
       FREE (istring);
       close (fildes[0]);
       close (fildes[1]);
       return ((WORD_DESC *)NULL);
     }
 
+#if defined (HAVE_WORKING_FORK)
   if (pid == 0)
+#else  /* !HAVE_WORKING_FORK */
+  if (1)
+#endif /* !HAVE_WORKING_FORK */
     {
       set_sigint_handler ();	/* XXX */
 
       free_pushed_string_input ();
 
       if (dup2 (fildes[1], 1) < 0)
 	{
 	  sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
+#if defined (HAVE_WORKING_FORK)
 	  exit (EXECUTION_FAILURE);
+#else  /* !HAVE_WORKING_FORK */
+          nofork_restore_all_environment (&oldenvbuf);
+	  nofork_wait_status = (EXECUTION_FAILURE);
+	  goto error_exit;
+#endif /* !HAVE_WORKING_FORK */
 	}
 
+#if defined (HAVE_WORKING_FORK)
       /* If standard output is closed in the parent shell
 	 (such as after `exec >&-'), file descriptor 1 will be
 	 the lowest available file descriptor, and end up in
 	 fildes[0].  This can happen for stdin and stderr as well,
 	 but stdout is more important -- it will cause no output
@@ -5128,10 +5201,11 @@ command_substitute (string, quoted)
 
       if ((fildes[0] != fileno (stdin)) &&
 	  (fildes[0] != fileno (stdout)) &&
 	  (fildes[0] != fileno (stderr)))
 	close (fildes[0]);
+#endif /* HAVE_WORKING_FORK */
 
       /* The currently executing shell is not interactive. */
       interactive = 0;
 
       /* This is a subshell environment. */
@@ -5147,18 +5221,29 @@ command_substitute (string, quoted)
       startup_state = 2;	/* see if we can avoid a fork */
       /* Give command substitution a place to jump back to on failure,
 	 so we don't go back up to main (). */
       result = setjmp (top_level);
 
+#if !defined (HAVE_WORKING_FORK)
+      /* return_catch and return_catch_flag will be restored
+         after call to nofork_restore_all_environment(). */
+      if (result == 0)
+        return_catch_flag = 0;
+#endif /* !HAVE_WORKING_FORK */
+
       /* If we're running a command substitution inside a shell function,
 	 trap `return' so we don't return from the function in the subshell
 	 and go off to never-never land. */
       if (result == 0 && return_catch_flag)
 	function_value = setjmp (return_catch);
       else
 	function_value = 0;
 
+#if !defined (HAVE_WORKING_FORK)
+#undef exit
+#define exit(x) (nofork_wait_status = (x))
+#endif /* !HAVE_WORKING_FORK */
       if (result == ERREXIT)
 	rc = last_command_exit_value;
       else if (result == EXITPROG)
 	rc = last_command_exit_value;
       else if (result)
@@ -5171,28 +5256,44 @@ command_substitute (string, quoted)
 	  rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
 	  subshell_level--;
 	}
 
       last_command_exit_value = rc;
+#if !defined (HAVE_WORKING_FORK) && 0
+      /* The call of run_exit_trap has been disabled to avoid
+         that trap code is executed every time when a . (dot)
+         command is started.
+         May be there is a better way to solve this!!! */
       rc = run_exit_trap ();
+#endif /* !HAVE_WORKING_FORK */
 #if defined (PROCESS_SUBSTITUTION)
       unlink_fifo_list ();
 #endif
       exit (rc);
+      nofork_restore_all_environment (&oldenvbuf);
+#if !defined (HAVE_WORKING_FORK)
+#undef exit
+#endif /* !HAVE_WORKING_FORK */
+#if defined (HAVE_WORKING_FORK)
     }
   else
     {
+#endif /* HAVE_WORKING_FORK */
 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
       close_pgrp_pipe ();
 #endif /* JOB_CONTROL && PGRP_PIPE */
 
       close (fildes[1]);
 
       tflag = 0;
       istring = read_comsub (fildes[0], quoted, &tflag);
 
       close (fildes[0]);
+#if defined (__DJGPP__)
+      /* Required to trigger pipe file removal.  */
+      remove_pipe (fildes[0]);
+#endif /*__DJGPP__ */
 
       current_command_subst_pid = pid;
       last_command_exit_value = wait_for (pid);
       last_command_subst_pid = pid;
       last_made_pid = old_pid;
@@ -7409,11 +7510,14 @@ comsub:
 	  tdesc = command_substitute (temp, quoted);
 	  temp1 = tdesc ? tdesc->word : (char *)NULL;
 	  if (tdesc)
 	    dispose_word_desc (tdesc);
 	}
+#if defined (HAVE_WORKING_FORK)
+/* Already freed by parse_and_execute() when fork isn't available.  */
       FREE (temp);
+#endif /* HAVE_WORKING_FORK */
       temp = temp1;
       break;
 
     /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
        away in a future bash release. */
@@ -7855,11 +7959,14 @@ add_string:
 		tword = command_substitute (temp, quoted);
 		temp1 = tword ? tword->word : (char *)NULL;
 		if (tword)
 		  dispose_word_desc (tword);
 	      }
+#if defined (HAVE_WORKING_FORK)
+/* Already freed by parse_and_execute() when fork isn't available.  */
 	    FREE (temp);
+#endif /* HAVE_WORKING_FORK */
 	    temp = temp1;
 	    goto dollar_add_string;
 	  }
 
 	case '\\':
diff -aprNU5 bash-4.1.orig/test.c bash-4.1/test.c
--- bash-4.1.orig/test.c	2009-10-27 12:58:48 +0000
+++ bash-4.1/test.c	2019-02-01 23:37:12 +0000
@@ -58,10 +58,14 @@ extern int errno;
 #include "test.h"
 #include "builtins/common.h"
 
 #include <glob/strmatch.h>
 
+#if defined (__DJGPP__)
+#include "dospath.h"
+#endif
+
 #if !defined (STRLEN)
 #  define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
 #endif
 
 #if !defined (STREQ)
@@ -510,11 +514,23 @@ unary_test (op, arg)
 
     case 'w':			/* File is writeable? */
       return (sh_eaccess (arg, W_OK) == 0);
 
     case 'x':			/* File is executable? */
+#if !defined (__DJGPP__)
       return (sh_eaccess (arg, X_OK) == 0);
+#else  /* __DJGPP__ */
+      {
+        int ret = access (arg, X_OK);
+        const char *path;
+        
+        if (ret == 0)
+          return (ret == 0);
+        path = find_extension (arg);
+        return (path != 0);
+      }
+#endif /* __DJGPP__ */
 
     case 'O':			/* File is owned by you? */
       return (sh_stat (arg, &stat_buf) == 0 &&
 	      (uid_t) current_user.euid == (uid_t) stat_buf.st_uid);
 
@@ -525,12 +541,24 @@ unary_test (op, arg)
     case 'N':
       return (sh_stat (arg, &stat_buf) == 0 &&
 	      stat_buf.st_atime <= stat_buf.st_mtime);
 
     case 'f':			/* File is a file? */
+#if !defined (__DJGPP__)
       if (sh_stat (arg, &stat_buf) < 0)
 	return (FALSE);
+#else  /* __DJGPP__ */
+      if (sh_stat (arg, &stat_buf) < 0)
+      {
+        if (test_finds_exe)
+          {
+            const char *path = find_one_extension (arg, "exe");
+            return (path != NULL);
+          }
+        return (FALSE);
+      }
+#endif /* __DJGPP__ */
 
       /* -f is true if the given file exists and is a regular file. */
 #if defined (S_IFMT)
       return (S_ISREG (stat_buf.st_mode) || (stat_buf.st_mode & S_IFMT) == 0);
 #else
diff -aprNU5 bash-4.1.orig/trap.c bash-4.1/trap.c
--- bash-4.1.orig/trap.c	2009-10-10 21:21:44 +0000
+++ bash-4.1/trap.c	2019-02-01 23:37:12 +0000
@@ -735,10 +735,14 @@ _run_trap_internal (sig, tag)
   char *trap_command, *old_trap;
   int trap_exit_value, *token_state;
   int save_return_catch_flag, function_code, flags;
   procenv_t save_return_catch;
   WORD_LIST *save_subst_varlist;
+#if !defined (HAVE_WORKING_FORK)
+  int old_subshell_exit_builtin;
+  extern int subshell_exit_builtin;
+#endif /* !HAVE_WORKING_FORK */
 
   trap_exit_value = function_code = 0;
   /* Run the trap only if SIG is trapped and not ignored, and we are not
      currently executing in the trap handler. */
   if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
@@ -750,10 +754,14 @@ _run_trap_internal (sig, tag)
       sigmodes[sig] &= ~SIG_CHANGED;		/* just to be sure */
       trap_command =  savestring (old_trap);
 
       running_trap = sig + 1;
       trap_saved_exit_value = last_command_exit_value;
+#if !defined (HAVE_WORKING_FORK)
+      old_subshell_exit_builtin = subshell_exit_builtin; 
+      subshell_exit_builtin = 0;
+#endif /* !HAVE_WORKING_FORK */
 
       token_state = save_token_state ();
       save_subst_varlist = subst_assign_varlist;
       subst_assign_varlist = 0;
 
@@ -776,10 +784,13 @@ _run_trap_internal (sig, tag)
 
       subst_assign_varlist = save_subst_varlist;
 
       trap_exit_value = last_command_exit_value;
       last_command_exit_value = trap_saved_exit_value;
+#if !defined (HAVE_WORKING_FORK)
+      subshell_exit_builtin = old_subshell_exit_builtin;
+#endif /* !HAVE_WORKING_FORK */
       running_trap = 0;
 
       sigmodes[sig] &= ~SIG_INPROGRESS;
 
       if (sigmodes[sig] & SIG_CHANGED)
@@ -1061,5 +1072,27 @@ int
 signal_in_progress (sig)
      int sig;
 {
   return (sigmodes[sig] & SIG_INPROGRESS);
 }
+
+#if !defined (HAVE_WORKING_FORK)
+/* Static variables wrapper. */
+int
+get_signal_modes (int sig)
+{
+  if (sig < 0 || sig >= NSIG)
+    return -1;
+  return sigmodes[sig];
+}
+
+int
+set_signal_modes (int sig, int modes)
+{
+  int oldmodes;
+  if (sig < 0 || sig >= NSIG)
+    return -1;
+  oldmodes = sigmodes[sig];
+  sigmodes[sig] = modes;
+  return oldmodes;
+}
+#endif /* !HAVE_WORKING_FORK */
diff -aprNU5 bash-4.1.orig/variables.c bash-4.1/variables.c
--- bash-4.1.orig/variables.c	2019-02-01 23:36:36 +0000
+++ bash-4.1/variables.c	2019-02-02 00:11:08 +0000
@@ -73,10 +73,18 @@
 
 #if defined (PROGRAMMABLE_COMPLETION)
 #  include "pcomplete.h"
 #endif
 
+#if defined (__DJGPP__)
+#  include "dospath.h"
+#endif /* __DJGPP__ */
+
+#if !defined (HAVE_WORKING_FORK)
+#  include "nofork.h"
+#endif /* !HAVE_WORKING_FORK */
+
 #define TEMPENV_HASH_BUCKETS	4	/* must be power of two */
 
 #define ifsname(s)	((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
 
 #define BASHFUNC_PREFIX		"BASH_FUNC_"
@@ -397,15 +405,27 @@ initialize_shell_variables (env, privmod
       else if (legal_identifier (name))
 #else
       else
 #endif
 	{
+#ifdef att_pathconv
+	  char *orig_string = string;
+	  int is_converted_path = try_init_path_var (name, &string);
+#endif
 	  temp_var = bind_variable (name, string, 0);
 	  if (legal_identifier (name))
 	    VSETATTR (temp_var, (att_exported | att_imported));
 	  else
 	    VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+#ifdef att_pathconv
+          if (is_converted_path)
+	    {
+              VSETATTR (temp_var, att_pathconv);
+              if (orig_string != string)
+                free(string);
+	    }
+#endif
 	  array_needs_making = 1;
 	}
 
       name[char_index] = '=';
       /* temp_var can be NULL if it was an exported function with a syntax
@@ -529,11 +549,19 @@ initialize_shell_variables (env, privmod
   /* Set history variables to defaults, and then do whatever we would
      do if the variable had just been set.  Do this only in the case
      that we are remembering commands on the history list. */
   if (remember_on_history)
     {
-      name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
+#if !defined (__MSDOS__)
+#define SHHIST "~/_shhist"
+#define BHIST "~/_bhist"
+#else  /* !__MSDOS__ */
+#define SHHIST "~/.sh_history"
+#define BHIST "~/.bash_history"
+#endif /* !__MSDOS__ */
+
+      name = bash_tilde_expand (posixly_correct ? SHHIST : BHIST, 0);
 
       set_if_not ("HISTFILE", name);
       free (name);
 
 #if 0
@@ -642,10 +670,13 @@ set_home_var ()
   SHELL_VAR *temp_var;
 
   temp_var = find_variable ("HOME");
   if (temp_var == 0)
     temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
+#ifdef att_pathconv
+  VSETATTR (temp_var, att_pathconv);
+#endif
 #if 0
   VSETATTR (temp_var, att_exported);
 #endif
 }
 
@@ -826,19 +857,25 @@ set_pwd ()
       temp_string = get_working_directory ("shell-init");
       if (temp_string)
 	{
 	  temp_var = bind_variable ("PWD", temp_string, 0);
 	  set_auto_export (temp_var);
+#ifdef att_pathconv
+	  VSETATTR (temp_var, att_pathconv);
+#endif
 	  free (temp_string);
 	}
     }
 
   /* According to the Single Unix Specification, v2, $OLDPWD is an
      `environment variable' and therefore should be auto-exported.
      Make a dummy invisible variable for OLDPWD, and mark it as exported. */
   temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
   VSETATTR (temp_var, (att_exported | att_invisible));
+#ifdef att_pathconv
+  VSETATTR (temp_var, att_pathconv);
+#endif
 }
 
 /* Make a variable $PPID, which holds the pid of the shell's parent.  */
 void
 set_ppid ()
@@ -2192,10 +2229,17 @@ bind_variable_internal (name, value, tab
      int hflags, aflags;
 {
   char *newval;
   SHELL_VAR *entry;
 
+#if !defined (HAVE_WORKING_FORK)
+#if NOFORK_COPY_ON_CHANGE
+  if (vc_copyonchange(global_variables) && !(name[0] == '_' && name[1] == '\0'))
+    copy_var_contexts_on_change();
+#endif
+#endif /* !HAVE_WORKING_FORK */
+
   entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
 
   if (entry == 0)
     {
       entry = make_new_variable (name, table);
@@ -2558,11 +2602,11 @@ assign_in_env (word)
 /*								    */
 /*			Copying variables			    */
 /*								    */
 /* **************************************************************** */
 
-#ifdef INCLUDE_UNUSED
+#if defined (INCLUDE_UNUSED) || !defined (HAVE_WORKING_FORK)
 /* Copy VAR to a new data structure and return that structure. */
 SHELL_VAR *
 copy_variable (var)
      SHELL_VAR *var;
 {
@@ -2595,11 +2639,11 @@ copy_variable (var)
 
       copy->context = var->context;
     }
   return (copy);
 }
-#endif
+#endif /* !HAVE_WORKING_FORK */
 
 /* **************************************************************** */
 /*								    */
 /*		  Deleting and unsetting variables		    */
 /*								    */
@@ -3475,12 +3519,24 @@ make_env_array_from_var_list (vars)
 
       if (value)
 	{
 	  /* Gee, I'd like to get away with not using savestring() if we're
 	     using the cached exportstr... */
+#ifndef att_pathconv
 	  list[list_index] = USE_EXPORTSTR ? savestring (value)
 					   : mk_env_string (var->name, value, function_p (var));
+#else
+          if (USE_EXPORTSTR)
+            list[list_index] = savestring (value);
+          else
+            {
+              if (pathconv_p (var))
+                list[list_index] = export_path_var (var->name, value);
+              else
+                list[list_index] = mk_env_string (var->name, value, function_p (var));
+            }
+#endif
 
 	  if (USE_EXPORTSTR == 0)
 	    SAVE_EXPORTSTR (var, list[list_index]);
 
 	  list_index++;
@@ -4203,10 +4259,16 @@ static struct name_and_function special_
   { "histchars", sv_histchars },
 #endif /* HISTORY && BANG_HISTORY */
 
   { "ignoreeof", sv_ignoreeof },
 
+#if defined (__DJGPP__)
+  { "PATH_SEPARATOR", sv_path_separator },
+  { "TEST_FINDS_EXE", sv_test_finds_exe },
+  { "PATH_EXPAND", sv_path_expand },
+#endif
+
   { (char *)0, (sh_sv_func_t *)0 }
 };
 
 #define N_SPECIAL_VARS	(sizeof (special_vars) / sizeof (special_vars[0]) - 1)
 
@@ -4720,5 +4782,59 @@ sv_xtracefd (name)
 	}
       else
 	internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
     }
 }
+
+#if defined (__DJGPP__)
+void
+sv_path_separator (char *name)
+{
+  char *p;
+  char old_path_separator = path_separator;
+  
+  p = get_string_value (name);
+  path_separator = ';';
+  if (p && *p)
+    {
+      if (*p == ':' || *p == ';')
+	path_separator = *p;
+    }
+
+  if (old_path_separator != path_separator)
+    {
+      if (path_separator == ':')
+        make_path_vars_bash();
+      else
+        make_path_vars_dos();
+    }
+}
+
+void
+sv_test_finds_exe (char *name)
+{
+  char *p;
+
+  p = get_string_value (name);
+  test_finds_exe = 0;
+  if (p && *p)
+    {
+      if (*p == 'y' || *p == 'Y')
+        test_finds_exe = 1;
+    }
+}
+
+void
+sv_path_expand (char *name)
+{
+  char *p;
+
+  path_expand = 0;
+  p = get_string_value (name);
+  if (p && *p)
+    {
+      if (*p == 'y' || *p == 'Y')
+        path_expand = 1;
+    }
+}
+
+#endif /* __DJGPP__ */
diff -aprNU5 bash-4.1.orig/variables.h bash-4.1/variables.h
--- bash-4.1.orig/variables.h	2009-08-16 20:10:14 +0000
+++ bash-4.1/variables.h	2019-02-01 23:37:12 +0000
@@ -47,20 +47,28 @@ typedef struct var_context {
 #define VC_BLTNENV	0x08	/* builtin_env */
 #define VC_TEMPENV	0x10	/* temporary_env */
 
 #define VC_TEMPFLAGS	(VC_FUNCENV|VC_BLTNENV|VC_TEMPENV)
 
+#if !defined (HAVE_WORKING_FORK)
+#define VC_COPYONCHANGE 0x100
+#endif /* !HAVE_WORKING_FORK */
+
 /* Accessing macros */
 #define vc_isfuncenv(vc)	(((vc)->flags & VC_FUNCENV) != 0)
 #define vc_isbltnenv(vc)	(((vc)->flags & VC_BLTNENV) != 0)
 #define vc_istempenv(vc)	(((vc)->flags & (VC_TEMPFLAGS)) == VC_TEMPENV)
 
 #define vc_istempscope(vc)	(((vc)->flags & (VC_TEMPENV|VC_BLTNENV)) != 0)
 
 #define vc_haslocals(vc)	(((vc)->flags & VC_HASLOCAL) != 0)
 #define vc_hastmpvars(vc)	(((vc)->flags & VC_HASTMPVAR) != 0)
 
+#if !defined (HAVE_WORKING_FORK)
+#define vc_copyonchange(vc)	(((vc)->flags & (VC_COPYONCHANGE)) == VC_COPYONCHANGE)
+#endif /* !HAVE_WORKING_FORK */
+
 /* What a shell variable looks like. */
 
 typedef struct variable *sh_var_value_func_t __P((struct variable *));
 typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t, char *));
 
@@ -381,6 +389,16 @@ extern void sv_histtimefmt __P((char *))
 
 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
 extern void sv_tz __P((char *));
 #endif
 
+#if defined (__DJGPP__)
+#define att_pathconv  0x20000    /* Convert a path to use forward slashes and
+                                   use the path separator in PATH_SEPARATOR */
+#define pathconv_p(var)		((((var)->attributes) & (att_pathconv)))
+
+void sv_path_expand __P((char *name));
+void sv_path_separator __P((char *name));
+void sv_test_finds_exe __P((char *name));
+#endif /* __DJGPP__ */
+
 #endif /* !_VARIABLES_H_ */
