diff --git a/recipes/bash/redox.patch b/recipes/bash/redox.patch
index 7dba459f3..21631f5cd 100644
--- a/recipes/bash/redox.patch
+++ b/recipes/bash/redox.patch
@@ -1,6 +1,18 @@
+diff -ruwN source/builtins/ulimit.def source-new/builtins/ulimit.def
+--- source/builtins/ulimit.def 2016-03-11 07:18:54.000000000 -0700
++++ source-new/builtins/ulimit.def 2020-07-14 20:52:15.875646752 -0600
+@@ -598,7 +598,7 @@
+ }
+ else
+ {
+-#if defined (HAVE_RESOURCE)
++#if defined (HAVE_RESOURCE) && !defined(__redox__)
+ if (getrlimit (limits[ind].parameter, &limit) < 0)
+ return -1;
+ # if defined (HPUX9)
diff -ruwN source/config-top.h source-new/config-top.h
--- source/config-top.h 2016-05-19 12:34:02.000000000 -0600
-+++ source-new/config-top.h 2019-01-28 12:42:45.660815213 -0700
++++ source-new/config-top.h 2020-07-14 20:50:54.546545430 -0600
@@ -63,14 +63,14 @@
/* The default value of the PATH variable. */
#ifndef DEFAULT_PATH_VALUE
@@ -20,7 +32,7 @@ diff -ruwN source/config-top.h source-new/config-top.h
/* Default primary and secondary prompt strings. */
diff -ruwN source/configure.ac source-new/configure.ac
--- source/configure.ac 2016-09-07 14:56:28.000000000 -0600
-+++ source-new/configure.ac 2019-01-28 13:53:45.000616985 -0700
++++ source-new/configure.ac 2020-07-14 20:50:54.550545485 -0600
@@ -90,6 +90,7 @@
*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
*-nsk*) opt_bash_malloc=no ;; # HP NonStop
@@ -31,7 +43,7 @@ diff -ruwN source/configure.ac source-new/configure.ac
# memory scrambling on free()
diff -ruwN source/execute_cmd.c source-new/execute_cmd.c
--- source/execute_cmd.c 2016-08-26 05:10:08.000000000 -0600
-+++ source-new/execute_cmd.c 2019-01-28 12:42:52.680865726 -0700
++++ source-new/execute_cmd.c 2020-07-14 20:50:54.550545485 -0600
@@ -1335,15 +1335,17 @@
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
if (posixly_correct && nullcmd)
@@ -53,7 +65,7 @@ diff -ruwN source/execute_cmd.c source-new/execute_cmd.c
old_flags = command->flags;
diff -ruwN source/general.c source-new/general.c
--- source/general.c 2016-08-11 09:16:56.000000000 -0600
-+++ source-new/general.c 2019-01-28 12:45:41.801895779 -0700
++++ source-new/general.c 2020-07-14 20:50:54.550545485 -0600
@@ -476,6 +476,7 @@
void
check_dev_tty ()
@@ -83,1338 +95,9 @@ diff -ruwN source/general.c source-new/general.c
;
*p_index = i;
-diff -ruwN source/general.c.orig source-new/general.c.orig
---- source/general.c.orig 1969-12-31 17:00:00.000000000 -0700
-+++ source-new/general.c.orig 2019-01-28 12:42:40.972781097 -0700
-@@ -0,0 +1,1325 @@
-+/* general.c -- Stuff that is used by all files. */
-+
-+/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
-+
-+ This file is part of GNU Bash, the Bourne Again SHell.
-+
-+ Bash is free software: you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation, either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ Bash is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with Bash. If not, see .
-+*/
-+
-+#include "config.h"
-+
-+#include "bashtypes.h"
-+#if defined (HAVE_SYS_PARAM_H)
-+# include
-+#endif
-+#include "posixstat.h"
-+
-+#if defined (HAVE_UNISTD_H)
-+# include
-+#endif
-+
-+#include "filecntl.h"
-+#include "bashansi.h"
-+#include
-+#include "chartypes.h"
-+#include
-+
-+#include "bashintl.h"
-+
-+#include "shell.h"
-+#include "test.h"
-+#include "trap.h"
-+
-+#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
-+# include /* mbschr */
-+#endif
-+
-+#include
-+
-+#if !defined (errno)
-+extern int errno;
-+#endif /* !errno */
-+
-+extern int expand_aliases;
-+extern int interactive_comments;
-+extern int check_hashed_filenames;
-+extern int source_uses_path;
-+extern int source_searches_cwd;
-+extern int posixly_correct;
-+extern int inherit_errexit;
-+
-+static char *bash_special_tilde_expansions __P((char *));
-+static int unquoted_tilde_word __P((const char *));
-+static void initialize_group_array __P((void));
-+
-+/* A standard error message to use when getcwd() returns NULL. */
-+const char * const bash_getcwd_errstr = N_("getcwd: cannot access parent directories");
-+
-+/* Do whatever is necessary to initialize `Posix mode'. */
-+void
-+posix_initialize (on)
-+ int on;
-+{
-+ /* Things that should be turned on when posix mode is enabled. */
-+ if (on != 0)
-+ {
-+ interactive_comments = source_uses_path = expand_aliases = 1;
-+ inherit_errexit = 1;
-+ source_searches_cwd = 0;
-+ }
-+
-+ /* Things that should be turned on when posix mode is disabled. */
-+ if (on == 0)
-+ {
-+ source_searches_cwd = 1;
-+ expand_aliases = interactive_shell;
-+ }
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to convert to and from and display non-standard types */
-+/* */
-+/* **************************************************************** */
-+
-+#if defined (RLIMTYPE)
-+RLIMTYPE
-+string_to_rlimtype (s)
-+ char *s;
-+{
-+ RLIMTYPE ret;
-+ int neg;
-+
-+ ret = 0;
-+ neg = 0;
-+ while (s && *s && whitespace (*s))
-+ s++;
-+ if (s && (*s == '-' || *s == '+'))
-+ {
-+ neg = *s == '-';
-+ s++;
-+ }
-+ for ( ; s && *s && DIGIT (*s); s++)
-+ ret = (ret * 10) + TODIGIT (*s);
-+ return (neg ? -ret : ret);
-+}
-+
-+void
-+print_rlimtype (n, addnl)
-+ RLIMTYPE n;
-+ int addnl;
-+{
-+ char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
-+
-+ p = s + sizeof(s);
-+ *--p = '\0';
-+
-+ if (n < 0)
-+ {
-+ do
-+ *--p = '0' - n % 10;
-+ while ((n /= 10) != 0);
-+
-+ *--p = '-';
-+ }
-+ else
-+ {
-+ do
-+ *--p = '0' + n % 10;
-+ while ((n /= 10) != 0);
-+ }
-+
-+ printf ("%s%s", p, addnl ? "\n" : "");
-+}
-+#endif /* RLIMTYPE */
-+
-+/* **************************************************************** */
-+/* */
-+/* Input Validation Functions */
-+/* */
-+/* **************************************************************** */
-+
-+/* Return non-zero if all of the characters in STRING are digits. */
-+int
-+all_digits (string)
-+ const char *string;
-+{
-+ register const char *s;
-+
-+ for (s = string; *s; s++)
-+ if (DIGIT (*s) == 0)
-+ return (0);
-+
-+ return (1);
-+}
-+
-+/* Return non-zero if the characters pointed to by STRING constitute a
-+ valid number. Stuff the converted number into RESULT if RESULT is
-+ not null. */
-+int
-+legal_number (string, result)
-+ const char *string;
-+ intmax_t *result;
-+{
-+ intmax_t value;
-+ char *ep;
-+
-+ if (result)
-+ *result = 0;
-+
-+ if (string == 0)
-+ return 0;
-+
-+ errno = 0;
-+ value = strtoimax (string, &ep, 10);
-+ if (errno || ep == string)
-+ return 0; /* errno is set on overflow or underflow */
-+
-+ /* Skip any trailing whitespace, since strtoimax does not. */
-+ while (whitespace (*ep))
-+ ep++;
-+
-+ /* If *string is not '\0' but *ep is '\0' on return, the entire string
-+ is valid. */
-+ if (*string && *ep == '\0')
-+ {
-+ if (result)
-+ *result = value;
-+ /* The SunOS4 implementation of strtol() will happily ignore
-+ overflow conditions, so this cannot do overflow correctly
-+ on those systems. */
-+ return 1;
-+ }
-+
-+ return (0);
-+}
-+
-+/* Return 1 if this token is a legal shell `identifier'; that is, it consists
-+ solely of letters, digits, and underscores, and does not begin with a
-+ digit. */
-+int
-+legal_identifier (name)
-+ const char *name;
-+{
-+ register const char *s;
-+ unsigned char c;
-+
-+ if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
-+ return (0);
-+
-+ for (s = name + 1; (c = *s) != 0; s++)
-+ {
-+ if (legal_variable_char (c) == 0)
-+ return (0);
-+ }
-+ return (1);
-+}
-+
-+/* Return 1 if NAME is a valid value that can be assigned to a nameref
-+ variable. FLAGS can be 2, in which case the name is going to be used
-+ to create a variable. Other values are currently unused, but could
-+ be used to allow values to be stored and indirectly referenced, but
-+ not used in assignments. */
-+int
-+valid_nameref_value (name, flags)
-+ const char *name;
-+ int flags;
-+{
-+ if (name == 0 || *name == 0)
-+ return 0;
-+
-+ /* valid identifier */
-+#if defined (ARRAY_VARS)
-+ if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
-+#else
-+ if (legal_identifier (name))
-+#endif
-+ return 1;
-+
-+ return 0;
-+}
-+
-+int
-+check_selfref (name, value, flags)
-+ const char *name;
-+ char *value;
-+ int flags;
-+{
-+ char *t;
-+
-+ if (STREQ (name, value))
-+ return 1;
-+
-+#if defined (ARRAY_VARS)
-+ if (valid_array_reference (value, 0))
-+ {
-+ t = array_variable_name (value, (char **)NULL, (int *)NULL);
-+ if (t && STREQ (name, t))
-+ {
-+ free (t);
-+ return 1;
-+ }
-+ free (t);
-+ }
-+#endif
-+
-+ return 0; /* not a self reference */
-+}
-+
-+/* Make sure that WORD is a valid shell identifier, i.e.
-+ does not contain a dollar sign, nor is quoted in any way. Nor
-+ does it consist of all digits. If CHECK_WORD is non-zero,
-+ the word is checked to ensure that it consists of only letters,
-+ digits, and underscores. */
-+int
-+check_identifier (word, check_word)
-+ WORD_DESC *word;
-+ int check_word;
-+{
-+ if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
-+ {
-+ internal_error (_("`%s': not a valid identifier"), word->word);
-+ return (0);
-+ }
-+ else if (check_word && legal_identifier (word->word) == 0)
-+ {
-+ internal_error (_("`%s': not a valid identifier"), word->word);
-+ return (0);
-+ }
-+ else
-+ return (1);
-+}
-+
-+/* Return 1 if STRING is a function name that the shell will import from
-+ the environment. Currently we reject attempts to import shell functions
-+ containing slashes, beginning with newlines or containing blanks. In
-+ Posix mode, we require that STRING be a valid shell identifier. Not
-+ used yet. */
-+int
-+importable_function_name (string, len)
-+ const char *string;
-+ size_t len;
-+{
-+ if (absolute_program (string)) /* don't allow slash */
-+ return 0;
-+ if (*string == '\n') /* can't start with a newline */
-+ return 0;
-+ if (shellblank (*string) || shellblank(string[len-1]))
-+ return 0;
-+ return (posixly_correct ? legal_identifier (string) : 1);
-+}
-+
-+int
-+exportable_function_name (string)
-+ const char *string;
-+{
-+ if (absolute_program (string))
-+ return 0;
-+ if (mbschr (string, '=') != 0)
-+ return 0;
-+ return 1;
-+}
-+
-+/* Return 1 if STRING comprises a valid alias name. The shell accepts
-+ essentially all characters except those which must be quoted to the
-+ parser (which disqualifies them from alias expansion anyway) and `/'. */
-+int
-+legal_alias_name (string, flags)
-+ const char *string;
-+ int flags;
-+{
-+ register const char *s;
-+
-+ for (s = string; *s; s++)
-+ if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
-+ return 0;
-+ return 1;
-+}
-+
-+/* Returns non-zero if STRING is an assignment statement. The returned value
-+ is the index of the `=' sign. */
-+int
-+assignment (string, flags)
-+ const char *string;
-+ int flags;
-+{
-+ register unsigned char c;
-+ register int newi, indx;
-+
-+ c = string[indx = 0];
-+
-+#if defined (ARRAY_VARS)
-+ if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
-+#else
-+ if (legal_variable_starter (c) == 0)
-+#endif
-+ return (0);
-+
-+ while (c = string[indx])
-+ {
-+ /* The following is safe. Note that '=' at the start of a word
-+ is not an assignment statement. */
-+ if (c == '=')
-+ return (indx);
-+
-+#if defined (ARRAY_VARS)
-+ if (c == '[')
-+ {
-+ newi = skipsubscript (string, indx, 0);
-+ if (string[newi++] != ']')
-+ return (0);
-+ if (string[newi] == '+' && string[newi+1] == '=')
-+ return (newi + 1);
-+ return ((string[newi] == '=') ? newi : 0);
-+ }
-+#endif /* ARRAY_VARS */
-+
-+ /* Check for `+=' */
-+ if (c == '+' && string[indx+1] == '=')
-+ return (indx + 1);
-+
-+ /* Variable names in assignment statements may contain only letters,
-+ digits, and `_'. */
-+ if (legal_variable_char (c) == 0)
-+ return (0);
-+
-+ indx++;
-+ }
-+ return (0);
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to manage files and file descriptors */
-+/* */
-+/* **************************************************************** */
-+
-+/* A function to unset no-delay mode on a file descriptor. Used in shell.c
-+ to unset it on the fd passed as stdin. Should be called on stdin if
-+ readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
-+
-+#if !defined (O_NDELAY)
-+# if defined (FNDELAY)
-+# define O_NDELAY FNDELAY
-+# endif
-+#endif /* O_NDELAY */
-+
-+/* Make sure no-delay mode is not set on file descriptor FD. */
-+int
-+sh_unset_nodelay_mode (fd)
-+ int fd;
-+{
-+ int flags, bflags;
-+
-+ if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
-+ return -1;
-+
-+ bflags = 0;
-+
-+ /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
-+ and O_NDELAY is defined. */
-+#ifdef O_NONBLOCK
-+ bflags |= O_NONBLOCK;
-+#endif
-+
-+#ifdef O_NDELAY
-+ bflags |= O_NDELAY;
-+#endif
-+
-+ if (flags & bflags)
-+ {
-+ flags &= ~bflags;
-+ return (fcntl (fd, F_SETFL, flags));
-+ }
-+
-+ return 0;
-+}
-+
-+/* Return 1 if file descriptor FD is valid; 0 otherwise. */
-+int
-+sh_validfd (fd)
-+ int fd;
-+{
-+ return (fcntl (fd, F_GETFD, 0) >= 0);
-+}
-+
-+int
-+fd_ispipe (fd)
-+ int fd;
-+{
-+ errno = 0;
-+ return ((lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE));
-+}
-+
-+/* There is a bug in the NeXT 2.1 rlogind that causes opens
-+ of /dev/tty to fail. */
-+
-+#if defined (__BEOS__)
-+/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
-+ into a no-op. This should probably go away in the future. */
-+# undef O_NONBLOCK
-+# define O_NONBLOCK 0
-+#endif /* __BEOS__ */
-+
-+void
-+check_dev_tty ()
-+{
-+#if 0
-+ int tty_fd;
-+ char *tty;
-+
-+ tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
-+
-+ if (tty_fd < 0)
-+ {
-+ tty = (char *)ttyname (fileno (stdin));
-+ if (tty == 0)
-+ return;
-+ tty_fd = open (tty, O_RDWR|O_NONBLOCK);
-+ }
-+ if (tty_fd >= 0)
-+ close (tty_fd);
-+#endif
-+}
-+
-+/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
-+ expensive. If non-NULL STP1 and STP2 point to stat structures
-+ corresponding to PATH1 and PATH2, respectively. */
-+int
-+same_file (path1, path2, stp1, stp2)
-+ const char *path1, *path2;
-+ struct stat *stp1, *stp2;
-+{
-+ struct stat st1, st2;
-+
-+ if (stp1 == NULL)
-+ {
-+ if (stat (path1, &st1) != 0)
-+ return (0);
-+ stp1 = &st1;
-+ }
-+
-+ if (stp2 == NULL)
-+ {
-+ if (stat (path2, &st2) != 0)
-+ return (0);
-+ stp2 = &st2;
-+ }
-+
-+ return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
-+}
-+
-+/* Move FD to a number close to the maximum number of file descriptors
-+ allowed in the shell process, to avoid the user stepping on it with
-+ redirection and causing us extra work. If CHECK_NEW is non-zero,
-+ we check whether or not the file descriptors are in use before
-+ duplicating FD onto them. MAXFD says where to start checking the
-+ file descriptors. If it's less than 20, we get the maximum value
-+ available from getdtablesize(2). */
-+int
-+move_to_high_fd (fd, check_new, maxfd)
-+ int fd, check_new, maxfd;
-+{
-+ int script_fd, nfds, ignore;
-+
-+ if (maxfd < 20)
-+ {
-+ nfds = getdtablesize ();
-+ if (nfds <= 0)
-+ nfds = 20;
-+ if (nfds > HIGH_FD_MAX)
-+ nfds = HIGH_FD_MAX; /* reasonable maximum */
-+ }
-+ else
-+ nfds = maxfd;
-+
-+ for (nfds--; check_new && nfds > 3; nfds--)
-+ if (fcntl (nfds, F_GETFD, &ignore) == -1)
-+ break;
-+
-+ if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
-+ {
-+ if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
-+ close (fd);
-+ return (script_fd);
-+ }
-+
-+ /* OK, we didn't find one less than our artificial maximum; return the
-+ original file descriptor. */
-+ return (fd);
-+}
-+
-+/* Return non-zero if the characters from SAMPLE are not all valid
-+ characters to be found in the first line of a shell script. We
-+ check up to the first newline, or SAMPLE_LEN, whichever comes first.
-+ All of the characters must be printable or whitespace. */
-+
-+int
-+check_binary_file (sample, sample_len)
-+ const char *sample;
-+ int sample_len;
-+{
-+ register int i;
-+ unsigned char c;
-+
-+ for (i = 0; i < sample_len; i++)
-+ {
-+ c = sample[i];
-+ if (c == '\n')
-+ return (0);
-+ if (c == '\0')
-+ return (1);
-+ }
-+
-+ return (0);
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to manipulate pipes */
-+/* */
-+/* **************************************************************** */
-+
-+int
-+sh_openpipe (pv)
-+ int *pv;
-+{
-+ int r;
-+
-+ if ((r = pipe (pv)) < 0)
-+ return r;
-+
-+ pv[0] = move_to_high_fd (pv[0], 1, 64);
-+ pv[1] = move_to_high_fd (pv[1], 1, 64);
-+
-+ return 0;
-+}
-+
-+int
-+sh_closepipe (pv)
-+ int *pv;
-+{
-+ if (pv[0] >= 0)
-+ close (pv[0]);
-+
-+ if (pv[1] >= 0)
-+ close (pv[1]);
-+
-+ pv[0] = pv[1] = -1;
-+ return 0;
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to inspect pathnames */
-+/* */
-+/* **************************************************************** */
-+
-+int
-+file_exists (fn)
-+ const char *fn;
-+{
-+ struct stat sb;
-+
-+ return (stat (fn, &sb) == 0);
-+}
-+
-+int
-+file_isdir (fn)
-+ const char *fn;
-+{
-+ struct stat sb;
-+
-+ return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
-+}
-+
-+int
-+file_iswdir (fn)
-+ const char *fn;
-+{
-+ return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
-+}
-+
-+/* Return 1 if STRING is "." or "..", optionally followed by a directory
-+ separator */
-+int
-+path_dot_or_dotdot (string)
-+ const char *string;
-+{
-+ if (string == 0 || *string == '\0' || *string != '.')
-+ return (0);
-+
-+ /* string[0] == '.' */
-+ if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
-+ return (1);
-+
-+ return (0);
-+}
-+
-+/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
-+ to decide whether or not to look up a directory name in $CDPATH. */
-+int
-+absolute_pathname (string)
-+ const char *string;
-+{
-+ if (string == 0 || *string == '\0')
-+ return (0);
-+
-+ if (ABSPATH(string))
-+ return (1);
-+
-+ if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
-+ return (1);
-+
-+ if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
-+ return (1);
-+
-+ return (0);
-+}
-+
-+/* Return 1 if STRING is an absolute program name; it is absolute if it
-+ contains any slashes. This is used to decide whether or not to look
-+ up through $PATH. */
-+int
-+absolute_program (string)
-+ const char *string;
-+{
-+ return ((char *)mbschr (string, '/') != (char *)NULL);
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to manipulate pathnames */
-+/* */
-+/* **************************************************************** */
-+
-+/* Turn STRING (a pathname) into an absolute pathname, assuming that
-+ DOT_PATH contains the symbolic location of `.'. This always
-+ returns a new string, even if STRING was an absolute pathname to
-+ begin with. */
-+char *
-+make_absolute (string, dot_path)
-+ const char *string, *dot_path;
-+{
-+ char *result;
-+
-+ if (dot_path == 0 || ABSPATH(string))
-+#ifdef __CYGWIN__
-+ {
-+ char pathbuf[PATH_MAX + 1];
-+
-+ cygwin_conv_to_full_posix_path (string, pathbuf);
-+ result = savestring (pathbuf);
-+ }
-+#else
-+ result = savestring (string);
-+#endif
-+ else
-+ result = sh_makepath (dot_path, string, 0);
-+
-+ return (result);
-+}
-+
-+/* Return the `basename' of the pathname in STRING (the stuff after the
-+ last '/'). If STRING is `/', just return it. */
-+char *
-+base_pathname (string)
-+ char *string;
-+{
-+ char *p;
-+
-+#if 0
-+ if (absolute_pathname (string) == 0)
-+ return (string);
-+#endif
-+
-+ if (string[0] == '/' && string[1] == 0)
-+ return (string);
-+
-+ p = (char *)strrchr (string, '/');
-+ return (p ? ++p : string);
-+}
-+
-+/* Return the full pathname of FILE. Easy. Filenames that begin
-+ with a '/' are returned as themselves. Other filenames have
-+ the current working directory prepended. A new string is
-+ returned in either case. */
-+char *
-+full_pathname (file)
-+ char *file;
-+{
-+ char *ret;
-+
-+ file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
-+
-+ if (ABSPATH(file))
-+ return (file);
-+
-+ ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
-+ free (file);
-+
-+ return (ret);
-+}
-+
-+/* A slightly related function. Get the prettiest name of this
-+ directory possible. */
-+static char tdir[PATH_MAX];
-+
-+/* Return a pretty pathname. If the first part of the pathname is
-+ the same as $HOME, then replace that with `~'. */
-+char *
-+polite_directory_format (name)
-+ char *name;
-+{
-+ char *home;
-+ int l;
-+
-+ home = get_string_value ("HOME");
-+ l = home ? strlen (home) : 0;
-+ if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
-+ {
-+ strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
-+ tdir[0] = '~';
-+ tdir[sizeof(tdir) - 1] = '\0';
-+ return (tdir);
-+ }
-+ else
-+ return (name);
-+}
-+
-+/* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
-+ keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
-+ and replace the intervening characters with `...' */
-+char *
-+trim_pathname (name, maxlen)
-+ char *name;
-+ int maxlen;
-+{
-+ int nlen, ndirs;
-+ intmax_t nskip;
-+ char *nbeg, *nend, *ntail, *v;
-+
-+ if (name == 0 || (nlen = strlen (name)) == 0)
-+ return name;
-+ nend = name + nlen;
-+
-+ v = get_string_value ("PROMPT_DIRTRIM");
-+ if (v == 0 || *v == 0)
-+ return name;
-+ if (legal_number (v, &nskip) == 0 || nskip <= 0)
-+ return name;
-+
-+ /* Skip over tilde prefix */
-+ nbeg = name;
-+ if (name[0] == '~')
-+ for (nbeg = name; *nbeg; nbeg++)
-+ if (*nbeg == '/')
-+ {
-+ nbeg++;
-+ break;
-+ }
-+ if (*nbeg == 0)
-+ return name;
-+
-+ for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
-+ if (*ntail == '/')
-+ ndirs++;
-+ if (ndirs < nskip)
-+ return name;
-+
-+ for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
-+ {
-+ if (*ntail == '/')
-+ nskip--;
-+ if (nskip == 0)
-+ break;
-+ }
-+ if (ntail == nbeg)
-+ return name;
-+
-+ /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
-+ nlen = ntail - nbeg;
-+ if (nlen <= 3)
-+ return name;
-+
-+ *nbeg++ = '.';
-+ *nbeg++ = '.';
-+ *nbeg++ = '.';
-+
-+ nlen = nend - ntail;
-+ memmove (nbeg, ntail, nlen);
-+ nbeg[nlen] = '\0';
-+
-+ return name;
-+}
-+
-+/* Return a printable representation of FN without special characters. The
-+ caller is responsible for freeing memory if this returns something other
-+ than its argument. If FLAGS is non-zero, we are printing for portable
-+ re-input and should single-quote filenames appropriately. */
-+char *
-+printable_filename (fn, flags)
-+ char *fn;
-+ int flags;
-+{
-+ char *newf;
-+
-+ if (ansic_shouldquote (fn))
-+ newf = ansic_quote (fn, 0, NULL);
-+ else if (flags && sh_contains_shell_metas (fn))
-+ newf = sh_single_quote (fn);
-+ else
-+ newf = fn;
-+
-+ return newf;
-+}
-+
-+/* Given a string containing units of information separated by colons,
-+ return the next one pointed to by (P_INDEX), or NULL if there are no more.
-+ Advance (P_INDEX) to the character after the colon. */
-+char *
-+extract_colon_unit (string, p_index)
-+ char *string;
-+ int *p_index;
-+{
-+ int i, start, len;
-+ char *value;
-+
-+ if (string == 0)
-+ return (string);
-+
-+ len = strlen (string);
-+ if (*p_index >= len)
-+ return ((char *)NULL);
-+
-+ i = *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] == ':')
-+ i++;
-+
-+ for (start = i; string[i] && string[i] != ':'; i++)
-+ ;
-+
-+ *p_index = i;
-+
-+ if (i == start)
-+ {
-+ if (string[i])
-+ (*p_index)++;
-+ /* Return "" in the case of a trailing `:'. */
-+ value = (char *)xmalloc (1);
-+ value[0] = '\0';
-+ }
-+ else
-+ value = substring (string, start, i);
-+
-+ return (value);
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Tilde Initialization and Expansion */
-+/* */
-+/* **************************************************************** */
-+
-+#if defined (PUSHD_AND_POPD)
-+extern char *get_dirstack_from_string __P((char *));
-+#endif
-+
-+static char **bash_tilde_prefixes;
-+static char **bash_tilde_prefixes2;
-+static char **bash_tilde_suffixes;
-+static char **bash_tilde_suffixes2;
-+
-+/* If tilde_expand hasn't been able to expand the text, perhaps it
-+ is a special shell expansion. This function is installed as the
-+ tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
-+ If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
-+ directory stack. */
-+static char *
-+bash_special_tilde_expansions (text)
-+ char *text;
-+{
-+ char *result;
-+
-+ result = (char *)NULL;
-+
-+ if (text[0] == '+' && text[1] == '\0')
-+ result = get_string_value ("PWD");
-+ else if (text[0] == '-' && text[1] == '\0')
-+ result = get_string_value ("OLDPWD");
-+#if defined (PUSHD_AND_POPD)
-+ else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
-+ result = get_dirstack_from_string (text);
-+#endif
-+
-+ return (result ? savestring (result) : (char *)NULL);
-+}
-+
-+/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
-+ well as handling special tilde prefixes; `:~" and `=~' are indications
-+ that we should do tilde expansion. */
-+void
-+tilde_initialize ()
-+{
-+ static int times_called = 0;
-+
-+ /* Tell the tilde expander that we want a crack first. */
-+ tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
-+
-+ /* Tell the tilde expander about special strings which start a tilde
-+ expansion, and the special strings that end one. Only do this once.
-+ tilde_initialize () is called from within bashline_reinitialize (). */
-+ if (times_called++ == 0)
-+ {
-+ bash_tilde_prefixes = strvec_create (3);
-+ bash_tilde_prefixes[0] = "=~";
-+ bash_tilde_prefixes[1] = ":~";
-+ bash_tilde_prefixes[2] = (char *)NULL;
-+
-+ bash_tilde_prefixes2 = strvec_create (2);
-+ bash_tilde_prefixes2[0] = ":~";
-+ bash_tilde_prefixes2[1] = (char *)NULL;
-+
-+ tilde_additional_prefixes = bash_tilde_prefixes;
-+
-+ bash_tilde_suffixes = strvec_create (3);
-+ bash_tilde_suffixes[0] = ":";
-+ bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
-+ bash_tilde_suffixes[2] = (char *)NULL;
-+
-+ tilde_additional_suffixes = bash_tilde_suffixes;
-+
-+ bash_tilde_suffixes2 = strvec_create (2);
-+ bash_tilde_suffixes2[0] = ":";
-+ bash_tilde_suffixes2[1] = (char *)NULL;
-+ }
-+}
-+
-+/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
-+ at the beginning of the word, followed by all of the characters preceding
-+ the first unquoted slash in the word, or all the characters in the word
-+ if there is no slash...If none of the characters in the tilde-prefix are
-+ quoted, the characters in the tilde-prefix following the tilde shell be
-+ treated as a possible login name. */
-+
-+#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
-+
-+static int
-+unquoted_tilde_word (s)
-+ const char *s;
-+{
-+ const char *r;
-+
-+ for (r = s; TILDE_END(*r) == 0; r++)
-+ {
-+ switch (*r)
-+ {
-+ case '\\':
-+ case '\'':
-+ case '"':
-+ return 0;
-+ }
-+ }
-+ return 1;
-+}
-+
-+/* Find the end of the tilde-prefix starting at S, and return the tilde
-+ prefix in newly-allocated memory. Return the length of the string in
-+ *LENP. FLAGS tells whether or not we're in an assignment context --
-+ if so, `:' delimits the end of the tilde prefix as well. */
-+char *
-+bash_tilde_find_word (s, flags, lenp)
-+ const char *s;
-+ int flags, *lenp;
-+{
-+ const char *r;
-+ char *ret;
-+ int l;
-+
-+ for (r = s; *r && *r != '/'; r++)
-+ {
-+ /* Short-circuit immediately if we see a quote character. Even though
-+ POSIX says that `the first unquoted slash' (or `:') terminates the
-+ tilde-prefix, in practice, any quoted portion of the tilde prefix
-+ will cause it to not be expanded. */
-+ if (*r == '\\' || *r == '\'' || *r == '"')
-+ {
-+ ret = savestring (s);
-+ if (lenp)
-+ *lenp = 0;
-+ return ret;
-+ }
-+ else if (flags && *r == ':')
-+ break;
-+ }
-+ l = r - s;
-+ ret = xmalloc (l + 1);
-+ strncpy (ret, s, l);
-+ ret[l] = '\0';
-+ if (lenp)
-+ *lenp = l;
-+ return ret;
-+}
-+
-+/* Tilde-expand S by running it through the tilde expansion library.
-+ ASSIGN_P is 1 if this is a variable assignment, so the alternate
-+ tilde prefixes should be enabled (`=~' and `:~', see above). If
-+ ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
-+ so `=~' is not valid. */
-+char *
-+bash_tilde_expand (s, assign_p)
-+ const char *s;
-+ int assign_p;
-+{
-+ int old_immed, old_term, r;
-+ char *ret;
-+
-+#if 0
-+ old_immed = interrupt_immediately;
-+ old_term = terminate_immediately;
-+ /* We want to be able to interrupt tilde expansion. Ordinarily, we can just
-+ jump to top_level, but we don't want to run any trap commands in a signal
-+ handler context. We might be able to get away with just checking for
-+ things like SIGINT and SIGQUIT. */
-+ if (any_signals_trapped () < 0)
-+ interrupt_immediately = 1;
-+ terminate_immediately = 1;
-+#endif
-+
-+ tilde_additional_prefixes = assign_p == 0 ? (char **)0
-+ : (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
-+ if (assign_p == 2)
-+ tilde_additional_suffixes = bash_tilde_suffixes2;
-+
-+ r = (*s == '~') ? unquoted_tilde_word (s) : 1;
-+ ret = r ? tilde_expand (s) : savestring (s);
-+
-+#if 0
-+ interrupt_immediately = old_immed;
-+ terminate_immediately = old_term;
-+#endif
-+
-+ QUIT;
-+
-+ return (ret);
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Functions to manipulate and search the group list */
-+/* */
-+/* **************************************************************** */
-+
-+static int ngroups, maxgroups;
-+
-+/* The set of groups that this user is a member of. */
-+static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
-+
-+#if !defined (NOGROUP)
-+# define NOGROUP (gid_t) -1
-+#endif
-+
-+static void
-+initialize_group_array ()
-+{
-+ register int i;
-+
-+ if (maxgroups == 0)
-+ maxgroups = getmaxgroups ();
-+
-+ ngroups = 0;
-+ group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
-+
-+#if defined (HAVE_GETGROUPS)
-+ ngroups = getgroups (maxgroups, group_array);
-+#endif
-+
-+ /* If getgroups returns nothing, or the OS does not support getgroups(),
-+ make sure the groups array includes at least the current gid. */
-+ if (ngroups == 0)
-+ {
-+ group_array[0] = current_user.gid;
-+ ngroups = 1;
-+ }
-+
-+ /* If the primary group is not in the groups array, add it as group_array[0]
-+ and shuffle everything else up 1, if there's room. */
-+ for (i = 0; i < ngroups; i++)
-+ if (current_user.gid == (gid_t)group_array[i])
-+ break;
-+ if (i == ngroups && ngroups < maxgroups)
-+ {
-+ for (i = ngroups; i > 0; i--)
-+ group_array[i] = group_array[i - 1];
-+ group_array[0] = current_user.gid;
-+ ngroups++;
-+ }
-+
-+ /* If the primary group is not group_array[0], swap group_array[0] and
-+ whatever the current group is. The vast majority of systems should
-+ not need this; a notable exception is Linux. */
-+ if (group_array[0] != current_user.gid)
-+ {
-+ for (i = 0; i < ngroups; i++)
-+ if (group_array[i] == current_user.gid)
-+ break;
-+ if (i < ngroups)
-+ {
-+ group_array[i] = group_array[0];
-+ group_array[0] = current_user.gid;
-+ }
-+ }
-+}
-+
-+/* Return non-zero if GID is one that we have in our groups list. */
-+int
-+#if defined (__STDC__) || defined ( _MINIX)
-+group_member (gid_t gid)
-+#else
-+group_member (gid)
-+ gid_t gid;
-+#endif /* !__STDC__ && !_MINIX */
-+{
-+#if defined (HAVE_GETGROUPS)
-+ register int i;
-+#endif
-+
-+ /* Short-circuit if possible, maybe saving a call to getgroups(). */
-+ if (gid == current_user.gid || gid == current_user.egid)
-+ return (1);
-+
-+#if defined (HAVE_GETGROUPS)
-+ if (ngroups == 0)
-+ initialize_group_array ();
-+
-+ /* In case of error, the user loses. */
-+ if (ngroups <= 0)
-+ return (0);
-+
-+ /* Search through the list looking for GID. */
-+ for (i = 0; i < ngroups; i++)
-+ if (gid == (gid_t)group_array[i])
-+ return (1);
-+#endif
-+
-+ return (0);
-+}
-+
-+char **
-+get_group_list (ngp)
-+ int *ngp;
-+{
-+ static char **group_vector = (char **)NULL;
-+ register int i;
-+
-+ if (group_vector)
-+ {
-+ if (ngp)
-+ *ngp = ngroups;
-+ return group_vector;
-+ }
-+
-+ if (ngroups == 0)
-+ initialize_group_array ();
-+
-+ if (ngroups <= 0)
-+ {
-+ if (ngp)
-+ *ngp = 0;
-+ return (char **)NULL;
-+ }
-+
-+ group_vector = strvec_create (ngroups);
-+ for (i = 0; i < ngroups; i++)
-+ group_vector[i] = itos (group_array[i]);
-+
-+ if (ngp)
-+ *ngp = ngroups;
-+ return group_vector;
-+}
-+
-+int *
-+get_group_array (ngp)
-+ int *ngp;
-+{
-+ int i;
-+ static int *group_iarray = (int *)NULL;
-+
-+ if (group_iarray)
-+ {
-+ if (ngp)
-+ *ngp = ngroups;
-+ return (group_iarray);
-+ }
-+
-+ if (ngroups == 0)
-+ initialize_group_array ();
-+
-+ if (ngroups <= 0)
-+ {
-+ if (ngp)
-+ *ngp = 0;
-+ return (int *)NULL;
-+ }
-+
-+ group_iarray = (int *)xmalloc (ngroups * sizeof (int));
-+ for (i = 0; i < ngroups; i++)
-+ group_iarray[i] = (int)group_array[i];
-+
-+ if (ngp)
-+ *ngp = ngroups;
-+ return group_iarray;
-+}
-+
-+/* **************************************************************** */
-+/* */
-+/* Miscellaneous functions */
-+/* */
-+/* **************************************************************** */
-+
-+/* Return a value for PATH that is guaranteed to find all of the standard
-+ utilities. This uses Posix.2 configuration variables, if present. It
-+ uses a value defined in config.h as a last resort. */
-+char *
-+conf_standard_path ()
-+{
-+#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
-+ char *p;
-+ size_t len;
-+
-+ len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
-+ if (len > 0)
-+ {
-+ p = (char *)xmalloc (len + 2);
-+ *p = '\0';
-+ confstr (_CS_PATH, p, len);
-+ return (p);
-+ }
-+ else
-+ return (savestring (STANDARD_UTILS_PATH));
-+#else /* !_CS_PATH || !HAVE_CONFSTR */
-+# if defined (CS_PATH)
-+ return (savestring (CS_PATH));
-+# else
-+ return (savestring (STANDARD_UTILS_PATH));
-+# endif /* !CS_PATH */
-+#endif /* !_CS_PATH || !HAVE_CONFSTR */
-+}
diff -ruwN source/include/posixwait.h source-new/include/posixwait.h
--- source/include/posixwait.h 2008-08-12 08:03:03.000000000 -0600
-+++ source-new/include/posixwait.h 2019-01-28 12:42:40.972781097 -0700
++++ source-new/include/posixwait.h 2020-07-14 20:50:54.554545541 -0600
@@ -34,7 +34,7 @@
/* How to get the status of a job. For Posix, this is just an
@@ -1435,7 +118,7 @@ diff -ruwN source/include/posixwait.h source-new/include/posixwait.h
# define WSTOPSIG(s) ((s) >> 8)
diff -ruwN source/lib/sh/getcwd.c source-new/lib/sh/getcwd.c
--- source/lib/sh/getcwd.c 2012-03-10 08:48:50.000000000 -0700
-+++ source-new/lib/sh/getcwd.c 2019-01-28 14:02:28.573259186 -0700
++++ source-new/lib/sh/getcwd.c 2020-07-14 20:50:54.554545541 -0600
@@ -20,7 +20,7 @@
#include
@@ -1447,7 +130,7 @@ diff -ruwN source/lib/sh/getcwd.c source-new/lib/sh/getcwd.c
#pragma alloca
diff -ruwN source/sig.c source-new/sig.c
--- source/sig.c 2016-02-11 13:02:45.000000000 -0700
-+++ source-new/sig.c 2019-01-28 13:48:08.303876705 -0700
++++ source-new/sig.c 2020-07-14 20:50:54.554545541 -0600
@@ -680,7 +680,9 @@
}