diff options
author | John Vogel <jvogel4@stny.rr.com> | 2015-08-09 00:02:42 +0700 |
---|---|---|
committer | Willy Sudiarto Raharjo <willysr@slackbuilds.org> | 2015-08-09 23:03:27 +0700 |
commit | 4f2c7ddfcac03c32546c65f49f67c27461108e85 (patch) | |
tree | e1d883882ef7eb75aef58ee4fd8ab99b3df4b559 | |
parent | 0109484690abd3ab96e67a1466ac03273792bbb2 (diff) |
system/dash: Updated for version 0.5.8 + new maintainer.
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
-rw-r--r-- | system/dash/README | 11 | ||||
-rw-r--r-- | system/dash/dash.SlackBuild | 12 | ||||
-rw-r--r-- | system/dash/dash.info | 10 | ||||
-rw-r--r-- | system/dash/patches/dash-0.5.8-git_d7582e6.diff | 2371 |
4 files changed, 2397 insertions, 7 deletions
diff --git a/system/dash/README b/system/dash/README index c41d3417a6bac..4daf9c0301f37 100644 --- a/system/dash/README +++ b/system/dash/README @@ -1,4 +1,13 @@ DASH is a POSIX-compliant implementation of /bin/sh that aims to be as small as possible. It does this without sacrificing speed where possible. In fact, it is significantly faster than bash (the GNU Bourne-Again SHell) -for most tasks. +for most tasks. + +To patch in fixes from current git, add 'USE_GIT_PATCH=yes' to the command +line when building, like this: + +# USE_GIT_PATCH=yes sh dash.Slackbuild + +or, if you use fakeroot to build: + +$ fakeroot env USE_GIT_PATCH=yes sh dash.SlackBuild diff --git a/system/dash/dash.SlackBuild b/system/dash/dash.SlackBuild index 47b92009297e7..f0c362a7d5c99 100644 --- a/system/dash/dash.SlackBuild +++ b/system/dash/dash.SlackBuild @@ -5,9 +5,11 @@ # Written by Vincent Batts, http://hashbangbash.com/ PRGNAM=dash -VERSION=${VERSION:-0.5.6.1} +VERSION=${VERSION:-0.5.8} +_PATCH_VERS=${PATCH_VERS:-git_d7582e6} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} +USE_GIT_PATCH=${USE_GIT_PATCH:-no} if [ -z "$ARCH" ]; then case "$( uname -m )" in @@ -44,6 +46,14 @@ cd $TMP rm -rf $PRGNAM-$VERSION tar xvf $CWD/$PRGNAM-$VERSION.tar.gz cd $PRGNAM-$VERSION + +# add fixes from upstream devel, if requested +if [ "$USE_GIT_PATCH" = "yes" ] && \ + [ -f $CWD/patches/dash-${VERSION}-${_PATCH_VERS}.diff ]; then + patch -p1 < $CWD/patches/dash-${VERSION}-${_PATCH_VERS}.diff + VERSION="${VERSION}.${_PATCH_VERS}" +fi + chown -R root:root . find -L . \ \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 -o -perm 511 \) \ diff --git a/system/dash/dash.info b/system/dash/dash.info index 3e3ed5c8876f5..6d206c8caa877 100644 --- a/system/dash/dash.info +++ b/system/dash/dash.info @@ -1,10 +1,10 @@ PRGNAM="dash" -VERSION="0.5.6.1" +VERSION="0.5.8" HOMEPAGE="http://gondor.apana.org.au/~herbert/dash/" -DOWNLOAD="http://gondor.apana.org.au/~herbert/dash/files/dash-0.5.6.1.tar.gz" -MD5SUM="1c846f4f5a33c0050b2045a6f7037e56" +DOWNLOAD="http://gondor.apana.org.au/~herbert/dash/files/dash-0.5.8.tar.gz" +MD5SUM="5c152209680dab3c319e8923f6c51378" DOWNLOAD_x86_64="" MD5SUM_x86_64="" REQUIRES="" -MAINTAINER="Vincent Batts" -EMAIL="vbatts@hashbangbash.com" +MAINTAINER="John Vogel" +EMAIL="jvogel4@stny.rr.com" diff --git a/system/dash/patches/dash-0.5.8-git_d7582e6.diff b/system/dash/patches/dash-0.5.8-git_d7582e6.diff new file mode 100644 index 0000000000000..ac5c6903d572b --- /dev/null +++ b/system/dash/patches/dash-0.5.8-git_d7582e6.diff @@ -0,0 +1,2371 @@ +diff -Naur dash-0.5.8/ChangeLog dash-0.5.8-git_d7582e6/ChangeLog +--- dash-0.5.8/ChangeLog 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/ChangeLog 2015-08-05 13:55:25.055358032 -0400 +@@ -1,3 +1,73 @@ ++2014-11-17 Stéphane Aulery <saulery@free.fr> ++ ++ * Correct typo in manual page. ++ * Document redirection file descriptor limitation. ++ ++2014-10-30 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Catch variable length expansions on non-existant specials. ++ ++2014-10-28 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Removed unnecessary pungetc on EOF from parser. ++ * Simplify EOF/newline handling in list parser. ++ ++2014-10-27 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Add printf support for format string a, A, and F. ++ * Handle embedded NULs correctly in printf. ++ * Replace open-coded flushall in preadbuffer. ++ * Add likely tag in outmem. ++ * Add ifdefs around MEM_OUT handling in outmem. ++ * Remove unnecessary restoration of format string in printf. ++ * Remove getintmax in printf. ++ * Use error instead of warnx for fatal errors in printf. ++ * Optimise handling of backslash octals in printf. ++ * Simplify echo command. ++ * Handle -- in dotcmd. ++ ++2014-10-13 Eric Blake <eblake@redhat.com> ++ ++ * cd: support drive letters on Cygwin. ++ ++2014-10-08 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Split unquoted $@/$* correctly when IFS is set but empty. ++ * Do not split quoted VSLENGTH and VSTRIM. ++ * Optimise nulonly away and just use quoted as before. ++ ++2014-10-07 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Use setvareq to set OPTIND initially. ++ ++2014-10-06 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Exit without arguments in a trap should use status outside traps. ++ * Do not allow break to break across function calls. ++ * Move common skipcount logic into skiploop. ++ * Allow return in loop conditional to set exit status. ++ * Return without arguments in a trap should use status outside traps. ++ ++2014-10-03 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Do not clobber exitstatus in evalcommand. ++ ++2014-10-02 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Fix use-after-free in dotrap/evalstring. ++ * Make sure evalskip is zero before running traps. ++ * Set exitstatus in onint. ++ ++2014-09-29 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Kill pgetc_macro. ++ * Handle backslash newlines properly after dollar sign. ++ * Add nlprompt/nlnoprompt helpers. ++ ++2014-09-28 Herbert Xu <herbert@gondor.apana.org.au> ++ ++ * Correctly handle test ! ! = !. ++ + 2014-09-26 Herbert Xu <herbert@gondor.apana.org.au> + + * Small optimisation of command -pv change. +diff -Naur dash-0.5.8/Makefile.in dash-0.5.8-git_d7582e6/Makefile.in +--- dash-0.5.8/Makefile.in 2014-09-28 04:19:40.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/Makefile.in 2015-08-05 13:57:40.555361584 -0400 +@@ -1,4 +1,4 @@ +-# Makefile.in generated by automake 1.11.6 from Makefile.am. ++# Makefile.in generated by automake 1.11.5 from Makefile.am. + # @configure_input@ + + # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +@@ -527,7 +527,7 @@ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac +- chmod -R a-w $(distdir); chmod u+w $(distdir) ++ chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) +diff -Naur dash-0.5.8/aclocal.m4 dash-0.5.8-git_d7582e6/aclocal.m4 +--- dash-0.5.8/aclocal.m4 2014-09-28 04:19:39.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/aclocal.m4 2015-08-05 13:57:39.728694896 -0400 +@@ -1,4 +1,4 @@ +-# generated automatically by aclocal 1.11.6 -*- Autoconf -*- ++# generated automatically by aclocal 1.11.5 -*- Autoconf -*- + + # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +@@ -38,7 +38,7 @@ + [am__api_version='1.11' + dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to + dnl require some minimum version. Point them to the right macro. +-m4_if([$1], [1.11.6], [], ++m4_if([$1], [1.11.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl + ]) + +@@ -54,7 +54,7 @@ + # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. + # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. + AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +-[AM_AUTOMAKE_VERSION([1.11.6])dnl ++[AM_AUTOMAKE_VERSION([1.11.5])dnl + m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl + _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) +diff -Naur dash-0.5.8/config.h.in dash-0.5.8-git_d7582e6/config.h.in +--- dash-0.5.8/config.h.in 2014-09-28 04:19:39.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/config.h.in 2015-08-05 13:57:40.062028238 -0400 +@@ -88,6 +88,9 @@ + /* Define to 1 if you have the <sys/types.h> header file. */ + #undef HAVE_SYS_TYPES_H + ++/* Define if your faccessat tells root all files are executable */ ++#undef HAVE_TRADITIONAL_FACCESSAT ++ + /* Define to 1 if you have the <unistd.h> header file. */ + #undef HAVE_UNISTD_H + +diff -Naur dash-0.5.8/configure dash-0.5.8-git_d7582e6/configure +--- dash-0.5.8/configure 2014-09-28 04:19:40.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/configure 2015-08-05 13:57:40.772028257 -0400 +@@ -714,6 +714,7 @@ + enable_static + enable_fnmatch + enable_glob ++enable_test_workaround + with_libedit + enable_lineno + ' +@@ -1347,6 +1348,9 @@ + --enable-static Build statical linked program + --enable-fnmatch Use fnmatch(3) from libc + --enable-glob Use glob(3) from libc ++ --enable-test-workaround ++ Guard against faccessat(2) that tells root all files ++ are executable + --disable-lineno Disable LINENO support + + Optional Packages: +@@ -4614,6 +4618,29 @@ + done + + ++ ++# Check whether --enable-test-workaround was given. ++if test "${enable_test_workaround+set}" = set; then : ++ enableval=$enable_test_workaround; ++else ++ enable_test_workaround=auto ++fi ++ ++ ++if test "enable_test_workaround" = "auto" && ++ test "$ac_cv_func_faccessat" = yes; then ++ case `uname -s 2>/dev/null` in ++ GNU/kFreeBSD | \ ++ FreeBSD) ++ enable_test_workaround=yes ++ esac ++fi ++if test "$enable_test_workaround" = "yes"; then ++ ++$as_echo "#define HAVE_TRADITIONAL_FACCESSAT 1" >>confdefs.h ++ ++fi ++ + if test "$enable_fnmatch" = yes; then + use_fnmatch= + for ac_func in fnmatch +diff -Naur dash-0.5.8/configure.ac dash-0.5.8-git_d7582e6/configure.ac +--- dash-0.5.8/configure.ac 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/configure.ac 2015-08-05 13:55:25.055358032 -0400 +@@ -90,6 +90,37 @@ + sigsetmask stpcpy strchrnul strsignal strtod strtoimax \ + strtoumax sysconf) + ++dnl Check whether it's worth working around FreeBSD PR kern/125009. ++dnl The traditional behavior of access/faccessat is crazy, but ++dnl POSIX.1-2008 explicitly allows those functions to misbehave. ++dnl ++dnl Unaffected kernels: ++dnl ++dnl - all versions of Linux ++dnl - NetBSD sys/kern/vfs_subr.c 1.64, 1997-04-23 ++dnl - FreeBSD 9 (r212002), 2010-09-10 ++dnl - OpenBSD sys/kern/vfs_subr.c 1.166, 2008-06-09 ++dnl ++dnl Also worked around in Debian's libc0.1 2.13-19 when using ++dnl kFreeBSD 8. ++ ++AC_ARG_ENABLE(test-workaround, AS_HELP_STRING(--enable-test-workaround, \ ++ [Guard against faccessat(2) that tells root all files are executable]),, ++ [enable_test_workaround=auto]) ++ ++if test "enable_test_workaround" = "auto" && ++ test "$ac_cv_func_faccessat" = yes; then ++ case `uname -s 2>/dev/null` in ++ GNU/kFreeBSD | \ ++ FreeBSD) ++ enable_test_workaround=yes ++ esac ++fi ++if test "$enable_test_workaround" = "yes"; then ++ AC_DEFINE([HAVE_TRADITIONAL_FACCESSAT], [1], ++ [Define if your faccessat tells root all files are executable]) ++fi ++ + if test "$enable_fnmatch" = yes; then + use_fnmatch= + AC_CHECK_FUNCS(fnmatch, use_fnmatch=yes) +diff -Naur dash-0.5.8/src/Makefile.am dash-0.5.8-git_d7582e6/src/Makefile.am +--- dash-0.5.8/src/Makefile.am 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/Makefile.am 2015-08-05 13:55:25.058691365 -0400 +@@ -26,7 +26,7 @@ + dash_SOURCES = \ + $(dash_CFILES) \ + alias.h arith_yacc.h bltin/bltin.h cd.h error.h eval.h exec.h \ +- expand.h hetio.h \ ++ expand.h \ + init.h input.h jobs.h machdep.h mail.h main.h memalloc.h miscbltin.h \ + myhistedit.h mystring.h options.h output.h parser.h redir.h shell.h \ + show.h system.h trap.h var.h +diff -Naur dash-0.5.8/src/Makefile.in dash-0.5.8-git_d7582e6/src/Makefile.in +--- dash-0.5.8/src/Makefile.in 2014-09-28 04:19:40.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/Makefile.in 2015-08-05 13:57:40.525361584 -0400 +@@ -1,4 +1,4 @@ +-# Makefile.in generated by automake 1.11.6 from Makefile.am. ++# Makefile.in generated by automake 1.11.5 from Makefile.am. + # @configure_input@ + + # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +@@ -236,7 +236,7 @@ + dash_SOURCES = \ + $(dash_CFILES) \ + alias.h arith_yacc.h bltin/bltin.h cd.h error.h eval.h exec.h \ +- expand.h hetio.h \ ++ expand.h \ + init.h input.h jobs.h machdep.h mail.h main.h memalloc.h miscbltin.h \ + myhistedit.h mystring.h options.h output.h parser.h redir.h shell.h \ + show.h system.h trap.h var.h +diff -Naur dash-0.5.8/src/bltin/printf.c dash-0.5.8-git_d7582e6/src/bltin/printf.c +--- dash-0.5.8/src/bltin/printf.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/bltin/printf.c 2015-08-05 13:55:25.058691365 -0400 +@@ -40,12 +40,11 @@ + #include <string.h> + #include <unistd.h> + +-static int conv_escape_str(char *); ++static int conv_escape_str(char *, char **); + static char *conv_escape(char *, int *); + static int getchr(void); + static double getdouble(void); +-static intmax_t getintmax(void); +-static uintmax_t getuintmax(void); ++static uintmax_t getuintmax(int); + static char *getstr(void); + static char *mklong(const char *, const char *); + static void check_conversion(const char *, const char *); +@@ -73,6 +72,53 @@ + } \ + } + ++#define ASPF(sp, f, func) ({ \ ++ int ret; \ ++ switch ((char *)param - (char *)array) { \ ++ default: \ ++ ret = xasprintf(sp, f, array[0], array[1], func); \ ++ break; \ ++ case sizeof(*param): \ ++ ret = xasprintf(sp, f, array[0], func); \ ++ break; \ ++ case 0: \ ++ ret = xasprintf(sp, f, func); \ ++ break; \ ++ } \ ++ ret; \ ++}) ++ ++ ++static int print_escape_str(const char *f, int *param, int *array, char *s) ++{ ++ struct stackmark smark; ++ char *p, *q; ++ int done; ++ int len; ++ int total; ++ ++ setstackmark(&smark); ++ done = conv_escape_str(s, &p); ++ q = stackblock(); ++ len = p - q; ++ ++ p = makestrspace(len, p); ++ memset(p, 'X', len - 1); ++ p[len - 1] = 0; ++ ++ q = stackblock(); ++ total = ASPF(&p, f, p); ++ ++ len = strchrnul(p, 'X') - p; ++ memcpy(p + len, q, strchrnul(p + len, ' ') - (p + len)); ++ ++ out1mem(p, total); ++ ++ popstackmark(&smark); ++ return done; ++} ++ ++ + int printfcmd(int argc, char *argv[]) + { + char *fmt; +@@ -86,10 +132,8 @@ + argv = argptr; + format = *argv; + +- if (!format) { +- warnx("usage: printf format [arg ...]"); +- goto err; +- } ++ if (!format) ++ error("usage: printf format [arg ...]"); + + gargv = ++argv; + +@@ -132,39 +176,33 @@ + /* skip to field width */ + fmt += strspn(fmt, SKIP1); + if (*fmt == '*') +- *param++ = getintmax(); ++ *param++ = getuintmax(1); + + /* skip to possible '.', get following precision */ + fmt += strspn(fmt, SKIP2); + if (*fmt == '.') + ++fmt; + if (*fmt == '*') +- *param++ = getintmax(); ++ *param++ = getuintmax(1); + + fmt += strspn(fmt, SKIP2); + + ch = *fmt; +- if (!ch) { +- warnx("missing format character"); +- goto err; +- } ++ if (!ch) ++ error("missing format character"); + /* null terminate format string to we can use it + as an argument to printf. */ + nextch = fmt[1]; + fmt[1] = 0; + switch (ch) { + +- case 'b': { +- int done = conv_escape_str(getstr()); +- char *p = stackblock(); ++ case 'b': + *fmt = 's'; +- PF(start, p); + /* escape if a \c was encountered */ +- if (done) ++ if (print_escape_str(start, param, array, ++ getstr())) + goto out; +- *fmt = 'b'; + break; +- } + case 'c': { + int p = getchr(); + PF(start, p); +@@ -177,23 +215,26 @@ + } + case 'd': + case 'i': { +- intmax_t p = getintmax(); +- char *f = mklong(start, fmt); +- PF(f, p); ++ uintmax_t p = getuintmax(1); ++ start = mklong(start, fmt); ++ PF(start, p); + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { +- uintmax_t p = getuintmax(); +- char *f = mklong(start, fmt); +- PF(f, p); ++ uintmax_t p = getuintmax(0); ++ start = mklong(start, fmt); ++ PF(start, p); + break; + } ++ case 'a': ++ case 'A': + case 'e': + case 'E': + case 'f': ++ case 'F': + case 'g': + case 'G': { + double p = getdouble(); +@@ -201,8 +242,7 @@ + break; + } + default: +- warnx("%s: invalid directive", start); +- goto err; ++ error("%s: invalid directive", start); + } + *++fmt = nextch; + } +@@ -210,8 +250,6 @@ + + out: + return rval; +-err: +- return 1; + } + + +@@ -220,8 +258,9 @@ + * Halts processing string if a \c escape is encountered. + */ + static int +-conv_escape_str(char *str) ++conv_escape_str(char *str, char **sp) + { ++ int c; + int ch; + char *cp; + +@@ -229,16 +268,14 @@ + STARTSTACKSTR(cp); + + do { +- int c; +- +- ch = *str++; ++ c = ch = *str++; + if (ch != '\\') + continue; + +- ch = *str++; +- if (ch == 'c') { ++ c = *str++; ++ if (c == 'c') { + /* \c as in SYSV echo - abort all processing.... */ +- ch = 0x100; ++ c = ch = 0x100; + continue; + } + +@@ -247,25 +284,14 @@ + * They start with a \0, and are followed by 0, 1, 2, + * or 3 octal digits. + */ +- if (ch == '0') { +- unsigned char i; +- i = 3; +- ch = 0; +- do { +- unsigned k = octtobin(*str); +- if (k > 7) +- break; +- str++; +- ch <<= 3; +- ch += k; +- } while (--i); +- continue; +- } ++ if (c == '0' && isodigit(*str)) ++ str++; + + /* Finally test for sequences valid in the format string */ + str = conv_escape(str - 1, &c); +- ch = c; +- } while (STPUTC(ch, cp), (char)ch); ++ } while (STPUTC(c, cp), (char)ch); ++ ++ *sp = cp; + + return ch; + } +@@ -283,12 +309,11 @@ + + switch (ch) { + default: +- case 0: +- value = '\\'; +- goto out; ++ if (!isodigit(*str)) { ++ value = '\\'; ++ goto out; ++ } + +- case '0': case '1': case '2': case '3': +- case '4': case '5': case '6': case '7': + ch = 3; + value = 0; + do { +@@ -357,30 +382,8 @@ + return val; + } + +-static intmax_t +-getintmax(void) +-{ +- intmax_t val = 0; +- char *cp, *ep; +- +- cp = *gargv; +- if (cp == NULL) +- goto out; +- gargv++; +- +- val = (unsigned char) cp[1]; +- if (*cp == '\"' || *cp == '\'') +- goto out; +- +- errno = 0; +- val = strtoimax(cp, &ep, 0); +- check_conversion(cp, ep); +-out: +- return val; +-} +- + static uintmax_t +-getuintmax(void) ++getuintmax(int sign) + { + uintmax_t val = 0; + char *cp, *ep; +@@ -395,7 +398,7 @@ + goto out; + + errno = 0; +- val = strtoumax(cp, &ep, 0); ++ val = sign ? strtoimax(cp, &ep, 0) : strtoumax(cp, &ep, 0); + check_conversion(cp, ep); + out: + return val; +@@ -439,34 +442,21 @@ + int + echocmd(int argc, char **argv) + { +- int nonl = 0; +- struct output *outs = out1; ++ int nonl; + +- if (!*++argv) +- goto end; +- if (equal(*argv, "-n")) { +- nonl = ~nonl; +- if (!*++argv) +- goto end; +- } ++ nonl = *++argv ? equal(*argv, "-n") : 0; ++ argv += nonl; + + do { + int c; + +- nonl += conv_escape_str(*argv); +- outstr(stackblock(), outs); ++ if (likely(*argv)) ++ nonl += print_escape_str("%s", NULL, NULL, *argv++); + if (nonl > 0) + break; + +- c = ' '; +- if (!*++argv) { +-end: +- if (nonl) { +- break; +- } +- c = '\n'; +- } +- outc(c, outs); ++ c = *argv ? ' ' : '\n'; ++ out1c(c); + } while (*argv); + return 0; + } +diff -Naur dash-0.5.8/src/bltin/test.c dash-0.5.8-git_d7582e6/src/bltin/test.c +--- dash-0.5.8/src/bltin/test.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/bltin/test.c 2015-08-05 13:55:25.058691365 -0400 +@@ -155,6 +155,14 @@ + static int bash_group_member(gid_t); + #endif + ++#ifdef HAVE_FACCESSAT ++# ifdef HAVE_TRADITIONAL_FACCESSAT ++static inline int faccessat_confused_about_superuser(void) { return 1; } ++# else ++static inline int faccessat_confused_about_superuser(void) { return 0; } ++# endif ++#endif ++ + static inline intmax_t getn(const char *s) + { + return atomax10(s); +@@ -177,7 +185,7 @@ + { + const struct t_op *op; + enum token n; +- int res; ++ int res = 1; + + if (*argv[0] == '[') { + if (*argv[--argc] != ']') +@@ -185,11 +193,12 @@ + argv[argc] = NULL; + } + ++recheck: + argv++; + argc--; + + if (argc < 1) +- return 1; ++ return res; + + /* + * POSIX prescriptions: he who wrote this deserves the Nobel +@@ -209,6 +218,9 @@ + argv[--argc] = NULL; + argv++; + argc--; ++ } else if (!strcmp(argv[0], "!")) { ++ res = 0; ++ goto recheck; + } + } + +@@ -216,7 +228,7 @@ + + eval: + t_wp = argv; +- res = !oexpr(n); ++ res ^= oexpr(n); + argv = t_wp; + + if (argv[0] != NULL && argv[1] != NULL) +@@ -489,8 +501,20 @@ + } + + #ifdef HAVE_FACCESSAT ++static int has_exec_bit_set(const char *path) ++{ ++ struct stat64 st; ++ ++ if (stat64(path, &st)) ++ return 0; ++ return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH); ++} ++ + static int test_file_access(const char *path, int mode) + { ++ if (faccessat_confused_about_superuser() && ++ mode == X_OK && geteuid() == 0 && !has_exec_bit_set(path)) ++ return 0; + return !faccessat(AT_FDCWD, path, mode, AT_EACCESS); + } + #else /* HAVE_FACCESSAT */ +diff -Naur dash-0.5.8/src/cd.c dash-0.5.8-git_d7582e6/src/cd.c +--- dash-0.5.8/src/cd.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/cd.c 2015-08-05 13:55:25.058691365 -0400 +@@ -38,6 +38,9 @@ + #include <string.h> + #include <unistd.h> + #include <limits.h> ++#ifdef __CYGWIN__ ++#include <sys/cygwin.h> ++#endif + + /* + * The cd and pwd commands. +@@ -194,6 +197,17 @@ + char *cdcomppath; + const char *lim; + ++#ifdef __CYGWIN__ ++ /* On cygwin, thanks to drive letters, some absolute paths do ++ not begin with slash; but cygwin includes a function that ++ forces normalization to the posix form */ ++ char pathbuf[PATH_MAX]; ++ if (cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, dir, pathbuf, ++ sizeof(pathbuf)) < 0) ++ sh_error("can't normalize %s", dir); ++ dir = pathbuf; ++#endif ++ + cdcomppath = sstrdup(dir); + STARTSTACKSTR(new); + if (*dir != '/') { +diff -Naur dash-0.5.8/src/dash.1 dash-0.5.8-git_d7582e6/src/dash.1 +--- dash-0.5.8/src/dash.1 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/dash.1 2015-08-05 13:55:25.058691365 -0400 +@@ -385,7 +385,7 @@ + Following is a list of the possible redirections. + The + .Bq n +-is an optional number, as in ++is an optional number between 0 and 9, as in + .Sq 3 + (not + .Sq Bq 3 ) , +@@ -402,11 +402,13 @@ + .It [n] Ns \*[Lt] file + Redirect standard input (or n) from file. + .It [n1] Ns \*[Lt]& Ns n2 +-Duplicate standard input (or n1) from file descriptor n2. ++Copy file descriptor n2 as stdout (or fd n1). ++fd n2. + .It [n] Ns \*[Lt]&- + Close standard input (or n). + .It [n1] Ns \*[Gt]& Ns n2 +-Duplicate standard output (or n1) to n2. ++Copy file descriptor n2 as stdin (or fd n1). ++fd n2. + .It [n] Ns \*[Gt]&- + Close standard output (or n). + .It [n] Ns \*[Lt]\*[Gt] file +@@ -596,7 +598,7 @@ + characters. + The commands in a list are executed in the order they are written. + If command is followed by an ampersand, the shell starts the +-command and immediately proceed onto the next command; otherwise it waits ++command and immediately proceeds onto the next command; otherwise it waits + for the command to terminate before proceeding to the next one. + .Ss Short-Circuit List Operators + .Dq && +@@ -1400,14 +1402,9 @@ + .Va optstring + all errors will be ignored. + .Pp +-A nonzero value is returned when the last option is reached. +-If there are no remaining arguments, ++After the last option + .Ic getopts +-will set +-.Va var +-to the special option, +-.Dq -- , +-otherwise, it will set ++will return a non-zero value and set + .Va var + to + .Dq \&? . +diff -Naur dash-0.5.8/src/error.c dash-0.5.8-git_d7582e6/src/error.c +--- dash-0.5.8/src/error.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/error.c 2015-08-05 13:55:25.058691365 -0400 +@@ -105,6 +105,7 @@ + signal(SIGINT, SIG_DFL); + raise(SIGINT); + } ++ exitstatus = SIGINT + 128; + exraise(EXINT); + /* NOTREACHED */ + } +diff -Naur dash-0.5.8/src/eval.c dash-0.5.8-git_d7582e6/src/eval.c +--- dash-0.5.8/src/eval.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/eval.c 2015-08-05 13:55:25.058691365 -0400 +@@ -74,6 +74,7 @@ + char *commandname; + int exitstatus; /* exit status of last command */ + int back_exitstatus; /* exit status of backquoted command */ ++int savestatus = -1; /* exit status of last command outside traps */ + + + #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) +@@ -114,6 +115,10 @@ + RESET { + evalskip = 0; + loopnest = 0; ++ if (savestatus >= 0) { ++ exitstatus = savestatus; ++ savestatus = -1; ++ } + } + #endif + +@@ -160,6 +165,7 @@ + struct stackmark smark; + int status; + ++ s = sstrdup(s); + setinputstring(s); + setstackmark(&smark); + +@@ -171,7 +177,9 @@ + if (evalskip) + break; + } ++ popstackmark(&smark); + popfile(); ++ stunalloc(s); + + return status; + } +@@ -194,6 +202,9 @@ + TRACE(("evaltree(NULL) called\n")); + goto out; + } ++ ++ dotrap(); ++ + #ifndef SMALL + displayhist = 1; /* show history substitutions done with fc */ + #endif +@@ -305,8 +316,7 @@ + if (checkexit & exitstatus) + goto exexit; + +- if (pendingsigs) +- dotrap(); ++ dotrap(); + + if (flags & EV_EXIT) { + exexit: +@@ -329,27 +339,45 @@ + #endif + + ++static int skiploop(void) ++{ ++ int skip = evalskip; ++ ++ switch (skip) { ++ case 0: ++ break; ++ ++ case SKIPBREAK: ++ case SKIPCONT: ++ if (likely(--skipcount <= 0)) { ++ evalskip = 0; ++ break; ++ } ++ ++ skip = SKIPBREAK; ++ break; ++ } ++ ++ return skip; ++} ++ ++ + STATIC void + evalloop(union node *n, int flags) + { ++ int skip; + int status; + + loopnest++; + status = 0; + flags &= EV_TESTED; +- for (;;) { ++ do { + int i; + + evaltree(n->nbinary.ch1, EV_TESTED); +- if (evalskip) { +-skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { +- evalskip = 0; +- continue; +- } +- if (evalskip == SKIPBREAK && --skipcount <= 0) +- evalskip = 0; +- break; +- } ++ skip = skiploop(); ++ if (skip) ++ continue; + i = exitstatus; + if (n->type != NWHILE) + i = !i; +@@ -357,11 +385,11 @@ + break; + evaltree(n->nbinary.ch2, flags); + status = exitstatus; +- if (evalskip) +- goto skipping; +- } ++ skip = skiploop(); ++ } while (!(skip & ~SKIPCONT)); ++ if (skip != SKIPFUNC) ++ exitstatus = status; + loopnest--; +- exitstatus = status; + } + + +@@ -382,9 +410,6 @@ + arglist.lastp = &arglist.list; + for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { + expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); +- /* XXX */ +- if (evalskip) +- goto out; + } + *arglist.lastp = NULL; + +@@ -394,18 +419,10 @@ + for (sp = arglist.list ; sp ; sp = sp->next) { + setvar(n->nfor.var, sp->text, 0); + evaltree(n->nfor.body, flags); +- if (evalskip) { +- if (evalskip == SKIPCONT && --skipcount <= 0) { +- evalskip = 0; +- continue; +- } +- if (evalskip == SKIPBREAK && --skipcount <= 0) +- evalskip = 0; ++ if (skiploop() & ~SKIPCONT) + break; +- } + } + loopnest--; +-out: + popstackmark(&smark); + } + +@@ -848,21 +865,12 @@ + listsetvar(varlist.list, VEXPORT); + } + if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { +- int status; +- int i; +- +- i = exception; +- if (i == EXEXIT) +- goto raise; +- +- status = (i == EXINT) ? SIGINT + 128 : 2; +- exitstatus = status; +- +- if (i == EXINT || spclbltin > 0) { +-raise: +- longjmp(handler->loc, 1); ++ if (exception == EXERROR && spclbltin <= 0) { ++ FORCEINTON; ++ break; + } +- FORCEINTON; ++raise: ++ longjmp(handler->loc, 1); + } + break; + +@@ -927,9 +935,11 @@ + struct jmploc jmploc; + int e; + int savefuncline; ++ int saveloopnest; + + saveparam = shellparam; + savefuncline = funcline; ++ saveloopnest = loopnest; + savehandler = handler; + if ((e = setjmp(jmploc.loc))) { + goto funcdone; +@@ -939,6 +949,7 @@ + shellparam.malloc = 0; + func->count++; + funcline = func->n.ndefun.linno; ++ loopnest = 0; + INTON; + shellparam.nparam = argc - 1; + shellparam.p = argv + 1; +@@ -949,13 +960,14 @@ + poplocalvars(0); + funcdone: + INTOFF; ++ loopnest = saveloopnest; + funcline = savefuncline; + freefunc(func); + freeparam(&shellparam); + shellparam = saveparam; + handler = savehandler; + INTON; +- evalskip &= ~SKIPFUNC; ++ evalskip &= ~(SKIPFUNC | SKIPFUNCDEF); + return e; + } + +@@ -1035,12 +1047,23 @@ + int + returncmd(int argc, char **argv) + { ++ int skip; ++ int status; ++ + /* + * If called outside a function, do what ksh does; + * skip the rest of the file. + */ +- evalskip = SKIPFUNC; +- return argv[1] ? number(argv[1]) : exitstatus; ++ if (argv[1]) { ++ skip = SKIPFUNC; ++ status = number(argv[1]); ++ } else { ++ skip = SKIPFUNCDEF; ++ status = exitstatus; ++ } ++ evalskip = skip; ++ ++ return status; + } + + +diff -Naur dash-0.5.8/src/eval.h dash-0.5.8-git_d7582e6/src/eval.h +--- dash-0.5.8/src/eval.h 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/eval.h 2015-08-05 13:55:25.058691365 -0400 +@@ -37,6 +37,7 @@ + extern char *commandname; /* currently executing command */ + extern int exitstatus; /* exit status of last command */ + extern int back_exitstatus; /* exit status of backquoted command */ ++extern int savestatus; /* exit status of last command outside traps */ + + + struct backcmd { /* result of evalbackcmd */ +@@ -61,3 +62,4 @@ + #define SKIPBREAK (1 << 0) + #define SKIPCONT (1 << 1) + #define SKIPFUNC (1 << 2) ++#define SKIPFUNCDEF (1 << 3) +diff -Naur dash-0.5.8/src/expand.c dash-0.5.8-git_d7582e6/src/expand.c +--- dash-0.5.8/src/expand.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/expand.c 2015-08-05 13:55:25.058691365 -0400 +@@ -116,7 +116,7 @@ + STATIC char *evalvar(char *, int); + STATIC size_t strtodest(const char *, const char *, int); + STATIC void memtodest(const char *, size_t, const char *, int); +-STATIC ssize_t varvalue(char *, int, int); ++STATIC ssize_t varvalue(char *, int, int, int *); + STATIC void expandmeta(struct strlist *, int); + #ifdef HAVE_GLOB + STATIC void addglob(const glob_t *); +@@ -736,7 +736,7 @@ + p = strchr(p, '=') + 1; + + again: +- varlen = varvalue(var, varflags, flag); ++ varlen = varvalue(var, varflags, flag, "ed); + if (varflags & VSNUL) + varlen--; + +@@ -751,28 +751,22 @@ + argstr(p, flag | EXP_TILDE | EXP_WORD); + goto end; + } +- if (easy) +- goto record; +- goto end; ++ goto record; + } + + if (subtype == VSASSIGN || subtype == VSQUESTION) { +- if (varlen < 0) { +- if (subevalvar(p, var, 0, subtype, startloc, +- varflags, flag & ~QUOTES_ESC)) { +- varflags &= ~VSNUL; +- /* +- * Remove any recorded regions beyond +- * start of variable +- */ +- removerecordregions(startloc); +- goto again; +- } +- goto end; +- } +- if (easy) ++ if (varlen >= 0) + goto record; +- goto end; ++ ++ subevalvar(p, var, 0, subtype, startloc, varflags, ++ flag & ~QUOTES_ESC); ++ varflags &= ~VSNUL; ++ /* ++ * Remove any recorded regions beyond ++ * start of variable ++ */ ++ removerecordregions(startloc); ++ goto again; + } + + if (varlen < 0 && uflag) +@@ -784,9 +778,9 @@ + } + + if (subtype == VSNORMAL) { ++record: + if (!easy) + goto end; +-record: + recordregion(startloc, expdest - (char *)stackblock(), quoted); + goto end; + } +@@ -892,7 +886,7 @@ + */ + + STATIC ssize_t +-varvalue(char *name, int varflags, int flags) ++varvalue(char *name, int varflags, int flags, int *quotedp) + { + int num; + char *p; +@@ -901,13 +895,13 @@ + char sepc; + char **ap; + char const *syntax; +- int quoted = flags & EXP_QUOTED; ++ int quoted = *quotedp; + int subtype = varflags & VSTYPE; + int discard = subtype == VSPLUS || subtype == VSLENGTH; + int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL; + ssize_t len = 0; + +- sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0; ++ sep = (flags & EXP_FULL) << CHAR_BIT; + syntax = quoted ? DQSYNTAX : BASESYNTAX; + + switch (*name) { +@@ -938,15 +932,18 @@ + expdest = p; + break; + case '@': +- if (sep) ++ if (quoted && sep) + goto param; + /* fall through */ + case '*': +- sep = ifsset() ? ifsval()[0] : ' '; ++ if (quoted) ++ sep = 0; ++ sep |= ifsset() ? ifsval()[0] : ' '; + param: ++ sepc = sep; ++ *quotedp = !sepc; + if (!(ap = shellparam.p)) + return -1; +- sepc = sep; + while ((p = *ap++)) { + len += strtodest(p, syntax, quotes); + +diff -Naur dash-0.5.8/src/hetio.h dash-0.5.8-git_d7582e6/src/hetio.h +--- dash-0.5.8/src/hetio.h 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/hetio.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,22 +0,0 @@ +-/* +- * Termios command line History and Editting for NetBSD sh (ash) +- * Copyright (c) 1999 +- * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu> +- * Etc: Dave Cinege <dcinege@psychosis.com> +- * +- * You may use this code as you wish, so long as the original author(s) +- * are attributed in any redistributions of the source code. +- * This code is 'as is' with no warranty. +- * This code may safely be consumed by a BSD or GPL license. +- * +- * v 0.5 19990328 Initial release +- * +- * Future plans: Simple file and path name completion. (like BASH) +- * +- */ +- +-void hetio_init(void); +-int hetio_read_input(int fd); +-void hetio_reset_term(void); +- +-extern int hetio_inter; +diff -Naur dash-0.5.8/src/histedit.c dash-0.5.8-git_d7582e6/src/histedit.c +--- dash-0.5.8/src/histedit.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/histedit.c 2015-08-05 13:55:25.062024698 -0400 +@@ -372,8 +372,7 @@ + out2str(s); + } + +- evalstring(strcpy(stalloc(strlen(s) + 1), s), +- 0); ++ evalstring(s, 0); + if (displayhist && hist) { + /* + * XXX what about recursive and +diff -Naur dash-0.5.8/src/input.c dash-0.5.8-git_d7582e6/src/input.c +--- dash-0.5.8/src/input.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/input.c 2015-08-05 13:55:25.062024698 -0400 +@@ -58,45 +58,10 @@ + #include "myhistedit.h" + #endif + +-#ifdef HETIO +-#include "hetio.h" +-#endif +- + #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ + #define IBUFSIZ (BUFSIZ + 1) + +-MKINIT +-struct strpush { +- struct strpush *prev; /* preceding string on stack */ +- char *prevstring; +- int prevnleft; +- struct alias *ap; /* if push was associated with an alias */ +- char *string; /* remember the string since it may change */ +-}; +- +-/* +- * The parsefile structure pointed to by the global variable parsefile +- * contains information about the current file being read. +- */ + +-MKINIT +-struct parsefile { +- struct parsefile *prev; /* preceding file on stack */ +- int linno; /* current line */ +- int fd; /* file descriptor (or -1 if string) */ +- int nleft; /* number of chars left in this line */ +- int lleft; /* number of chars left in this buffer */ +- char *nextc; /* next char in buffer */ +- char *buf; /* input buffer */ +- struct strpush *strpush; /* for pushing strings at this level */ +- struct strpush basestrpush; /* so pushing one is fast */ +-}; +- +- +-int plinno = 1; /* input line number */ +-int parsenleft; /* copy of parsefile->nleft */ +-MKINIT int parselleft; /* copy of parsefile->lleft */ +-char *parsenextc; /* copy of parsefile->nextc */ + MKINIT struct parsefile basepf; /* top level input file */ + MKINIT char basebuf[IBUFSIZ]; /* buffer for top level input file */ + struct parsefile *parsefile = &basepf; /* current input file */ +@@ -109,6 +74,7 @@ + STATIC void pushfile(void); + static int preadfd(void); + static void setinputfd(int fd, int push); ++static int preadbuffer(void); + + #ifdef mkinit + INCLUDE <stdio.h> +@@ -117,10 +83,12 @@ + + INIT { + basepf.nextc = basepf.buf = basebuf; ++ basepf.linno = 1; + } + + RESET { +- parselleft = parsenleft = 0; /* clear input buffer */ ++ /* clear input buffer */ ++ basepf.lleft = basepf.nleft = 0; + popallfiles(); + } + #endif +@@ -134,7 +102,20 @@ + int + pgetc(void) + { +- return pgetc_macro(); ++ int c; ++ ++ if (parsefile->unget) ++ return parsefile->lastc[--parsefile->unget]; ++ ++ if (--parsefile->nleft >= 0) ++ c = (signed char)*parsefile->nextc++; ++ else ++ c = preadbuffer(); ++ ++ parsefile->lastc[1] = parsefile->lastc[0]; ++ parsefile->lastc[0] = c; ++ ++ return c; + } + + +@@ -147,7 +128,7 @@ + { + int c; + do { +- c = pgetc_macro(); ++ c = pgetc(); + } while (c == PEOA); + return c; + } +@@ -158,7 +139,7 @@ + { + int nr; + char *buf = parsefile->buf; +- parsenextc = buf; ++ parsefile->nextc = buf; + + retry: + #ifndef SMALL +@@ -184,11 +165,6 @@ + + } else + #endif +- +-#ifdef HETIO +- nr = hetio_read_input(parsefile->fd); +- if (nr == -255) +-#endif + nr = read(parsefile->fd, buf, IBUFSIZ - 1); + + +@@ -219,8 +195,7 @@ + * 4) Process input up to the next newline, deleting nul characters. + */ + +-int +-preadbuffer(void) ++static int preadbuffer(void) + { + char *q; + int more; +@@ -229,34 +204,33 @@ + #endif + char savec; + +- while (unlikely(parsefile->strpush)) { ++ if (unlikely(parsefile->strpush)) { + if ( +- parsenleft == -1 && parsefile->strpush->ap && +- parsenextc[-1] != ' ' && parsenextc[-1] != '\t' ++ parsefile->nleft == -1 && ++ parsefile->strpush->ap && ++ parsefile->nextc[-1] != ' ' && ++ parsefile->nextc[-1] != '\t' + ) { + return PEOA; + } + popstring(); +- if (--parsenleft >= 0) +- return (signed char)*parsenextc++; ++ return pgetc(); + } +- if (unlikely(parsenleft == EOF_NLEFT || parsefile->buf == NULL)) ++ if (unlikely(parsefile->nleft == EOF_NLEFT || ++ parsefile->buf == NULL)) + return PEOF; +- flushout(&output); +-#ifdef FLUSHERR +- flushout(&errout); +-#endif ++ flushall(); + +- more = parselleft; ++ more = parsefile->lleft; + if (more <= 0) { + again: + if ((more = preadfd()) <= 0) { +- parselleft = parsenleft = EOF_NLEFT; ++ parsefile->lleft = parsefile->nleft = EOF_NLEFT; + return PEOF; + } + } + +- q = parsenextc; ++ q = parsefile->nextc; + + /* delete nul characters */ + #ifndef SMALL +@@ -274,7 +248,7 @@ + q++; + + if (c == '\n') { +- parsenleft = q - parsenextc - 1; ++ parsefile->nleft = q - parsefile->nextc - 1; + break; + } + +@@ -291,13 +265,13 @@ + } + + if (more <= 0) { +- parsenleft = q - parsenextc - 1; +- if (parsenleft < 0) ++ parsefile->nleft = q - parsefile->nextc - 1; ++ if (parsefile->nleft < 0) + goto again; + break; + } + } +- parselleft = more; ++ parsefile->lleft = more; + + savec = *q; + *q = '\0'; +@@ -307,13 +281,13 @@ + HistEvent he; + INTOFF; + history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND, +- parsenextc); ++ parsefile->nextc); + INTON; + } + #endif + + if (vflag) { +- out2str(parsenextc); ++ out2str(parsefile->nextc); + #ifdef FLUSHERR + flushout(out2); + #endif +@@ -321,19 +295,18 @@ + + *q = savec; + +- return (signed char)*parsenextc++; ++ return (signed char)*parsefile->nextc++; + } + + /* +- * Undo the last call to pgetc. Only one character may be pushed back. ++ * Undo a call to pgetc. Only two characters may be pushed back. + * PEOF may be pushed back. + */ + + void + pungetc(void) + { +- parsenleft++; +- parsenextc--; ++ parsefile->unget++; + } + + /* +@@ -355,15 +328,18 @@ + parsefile->strpush = sp; + } else + sp = parsefile->strpush = &(parsefile->basestrpush); +- sp->prevstring = parsenextc; +- sp->prevnleft = parsenleft; ++ sp->prevstring = parsefile->nextc; ++ sp->prevnleft = parsefile->nleft; ++ sp->unget = parsefile->unget; ++ memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc)); + sp->ap = (struct alias *)ap; + if (ap) { + ((struct alias *)ap)->flag |= ALIASINUSE; + sp->string = s; + } +- parsenextc = s; +- parsenleft = len; ++ parsefile->nextc = s; ++ parsefile->nleft = len; ++ parsefile->unget = 0; + INTON; + } + +@@ -374,7 +350,8 @@ + + INTOFF; + if (sp->ap) { +- if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') { ++ if (parsefile->nextc[-1] == ' ' || ++ parsefile->nextc[-1] == '\t') { + checkkwd |= CHKALIAS; + } + if (sp->string != sp->ap->val) { +@@ -385,8 +362,10 @@ + unalias(sp->ap->name); + } + } +- parsenextc = sp->prevstring; +- parsenleft = sp->prevnleft; ++ parsefile->nextc = sp->prevstring; ++ parsefile->nleft = sp->prevnleft; ++ parsefile->unget = sp->unget; ++ memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc)); + /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ + parsefile->strpush = sp->prev; + if (sp != &(parsefile->basestrpush)) +@@ -435,7 +414,7 @@ + parsefile->fd = fd; + if (parsefile->buf == NULL) + parsefile->buf = ckmalloc(IBUFSIZ); +- parselleft = parsenleft = 0; ++ parsefile->lleft = parsefile->nleft = 0; + plinno = 1; + } + +@@ -449,8 +428,8 @@ + { + INTOFF; + pushfile(); +- parsenextc = string; +- parsenleft = strlen(string); ++ parsefile->nextc = string; ++ parsefile->nleft = strlen(string); + parsefile->buf = NULL; + plinno = 1; + INTON; +@@ -468,15 +447,12 @@ + { + struct parsefile *pf; + +- parsefile->nleft = parsenleft; +- parsefile->lleft = parselleft; +- parsefile->nextc = parsenextc; +- parsefile->linno = plinno; + pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); + pf->prev = parsefile; + pf->fd = -1; + pf->strpush = NULL; + pf->basestrpush.prev = NULL; ++ pf->unget = 0; + parsefile = pf; + } + +@@ -495,10 +471,6 @@ + popstring(); + parsefile = pf->prev; + ckfree(pf); +- parsenleft = parsefile->nleft; +- parselleft = parsefile->lleft; +- parsenextc = parsefile->nextc; +- plinno = parsefile->linno; + INTON; + } + +diff -Naur dash-0.5.8/src/input.h dash-0.5.8-git_d7582e6/src/input.h +--- dash-0.5.8/src/input.h 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/input.h 2015-08-05 13:55:25.062024698 -0400 +@@ -41,18 +41,56 @@ + INPUT_NOFILE_OK = 2, + }; + ++struct alias; ++ ++struct strpush { ++ struct strpush *prev; /* preceding string on stack */ ++ char *prevstring; ++ int prevnleft; ++ struct alias *ap; /* if push was associated with an alias */ ++ char *string; /* remember the string since it may change */ ++ ++ /* Remember last two characters for pungetc. */ ++ int lastc[2]; ++ ++ /* Number of outstanding calls to pungetc. */ ++ int unget; ++}; ++ ++/* ++ * The parsefile structure pointed to by the global variable parsefile ++ * contains information about the current file being read. ++ */ ++ ++struct parsefile { ++ struct parsefile *prev; /* preceding file on stack */ ++ int linno; /* current line */ ++ int fd; /* file descriptor (or -1 if string) */ ++ int nleft; /* number of chars left in this line */ ++ int lleft; /* number of chars left in this buffer */ ++ char *nextc; /* next char in buffer */ ++ char *buf; /* input buffer */ ++ struct strpush *strpush; /* for pushing strings at this level */ ++ struct strpush basestrpush; /* so pushing one is fast */ ++ ++ /* Remember last two characters for pungetc. */ ++ int lastc[2]; ++ ++ /* Number of outstanding calls to pungetc. */ ++ int unget; ++}; ++ ++extern struct parsefile *parsefile; ++ + /* + * The input line number. Input.c just defines this variable, and saves + * and restores it when files are pushed and popped. The user of this + * package must set its value. + */ +-extern int plinno; +-extern int parsenleft; /* number of characters left in input buffer */ +-extern char *parsenextc; /* next character in input buffer */ ++#define plinno (parsefile->linno) + + int pgetc(void); + int pgetc2(void); +-int preadbuffer(void); + void pungetc(void); + void pushstring(char *, void *); + void popstring(void); +@@ -61,6 +99,3 @@ + void popfile(void); + void popallfiles(void); + void closescript(void); +- +-#define pgetc_macro() \ +- (--parsenleft >= 0 ? (signed char)*parsenextc++ : preadbuffer()) +diff -Naur dash-0.5.8/src/main.c dash-0.5.8-git_d7582e6/src/main.c +--- dash-0.5.8/src/main.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/main.c 2015-08-05 13:55:25.062024698 -0400 +@@ -60,10 +60,6 @@ + #include "exec.h" + #include "cd.h" + +-#ifdef HETIO +-#include "hetio.h" +-#endif +- + #define PROFILE 0 + + int rootpid; +@@ -206,10 +202,6 @@ + int numeof = 0; + + TRACE(("cmdloop(%d) called\n", top)); +-#ifdef HETIO +- if(iflag && top) +- hetio_init(); +-#endif + for (;;) { + int skip; + +@@ -242,7 +234,7 @@ + + skip = evalskip; + if (skip) { +- evalskip &= ~SKIPFUNC; ++ evalskip &= ~(SKIPFUNC | SKIPFUNCDEF); + break; + } + } +@@ -321,15 +313,19 @@ + { + int status = 0; + +- if (argc >= 2) { /* That's what SVR2 does */ ++ nextopt(nullstr); ++ argv = argptr; ++ ++ if (*argv) { + char *fullname; + +- fullname = find_dot_file(argv[1]); ++ fullname = find_dot_file(*argv); + setinputfile(fullname, INPUT_PUSH_FILE); + commandname = fullname; + status = cmdloop(0); + popfile(); + } ++ + return status; + } + +@@ -339,8 +335,15 @@ + { + if (stoppedjobs()) + return 0; +- if (argc > 1) +- exitstatus = number(argv[1]); ++ ++ if (argc > 1) { ++ int status = number(argv[1]); ++ ++ exitstatus = status; ++ if (savestatus >= 0) ++ savestatus = status; ++ } ++ + exraise(EXEXIT); + /* NOTREACHED */ + } +diff -Naur dash-0.5.8/src/mkbuiltins dash-0.5.8-git_d7582e6/src/mkbuiltins +--- dash-0.5.8/src/mkbuiltins 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/mkbuiltins 2015-08-05 13:55:25.062024698 -0400 +@@ -69,7 +69,7 @@ + #include "builtins.h" + + ! +-< $builtins sed '/^#/d; /^$/d' > $temp ++< $builtins sed '/^#/d; /^ *$/d' > $temp + awk '{ printf "int %s(int, char **);\n", $1}' $temp + echo ' + const struct builtincmd builtincmd[] = {' +@@ -78,7 +78,7 @@ + if ($i ~ /^-/) + line = $(++i) "\t" line + print line +- }}' $temp | LC_COLLATE=C sort -k 1,1 | tee $temp2 | awk '{ ++ }}' $temp | LC_ALL= LC_COLLATE=C sort -k 1,1 | tee $temp2 | awk '{ + opt = "" + if (NF > 2) { + opt = substr($2, 2) +@@ -97,8 +97,9 @@ + */ + + ! +-sed 's/ -[a-z]*//' $temp2 | nl -b a -v 0 | LC_COLLATE=C sort -u -k 3,3 | +-tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | ++sed 's/ -[a-z]*//' $temp2 | nl -b a -v 0 | ++ LC_ALL= LC_COLLATE=C sort -u -k 3,3 | ++ tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | + awk '{ printf "#define %s (builtincmd + %d)\n", $3, $1}' + printf '\n#define NUMBUILTINS %d\n' $(wc -l < $temp2) + echo ' +diff -Naur dash-0.5.8/src/output.c dash-0.5.8-git_d7582e6/src/output.c +--- dash-0.5.8/src/output.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/output.c 2015-08-05 13:55:25.062024698 -0400 +@@ -99,9 +99,6 @@ + struct output *out2 = &errout; + + +-#ifndef USE_GLIBC_STDIO +-static void __outstr(const char *, size_t, struct output *); +-#endif + static int xvsnprintf(char *, size_t, const char *, va_list); + + +@@ -134,16 +131,20 @@ + #endif + + +-#ifndef USE_GLIBC_STDIO +-static void +-__outstr(const char *p, size_t len, struct output *dest) ++void ++outmem(const char *p, size_t len, struct output *dest) + { ++#ifdef USE_GLIBC_STDIO ++ INTOFF; ++ fwrite(p, 1, len, dest->stream); ++ INTON; ++#else + size_t bufsize; + size_t offset; + size_t nleft; + + nleft = dest->end - dest->nextc; +- if (nleft >= len) { ++ if (likely(nleft >= len)) { + buffered: + dest->nextc = mempcpy(dest->nextc, p, len); + return; +@@ -153,10 +154,13 @@ + if (!bufsize) { + ; + } else if (dest->buf == NULL) { ++#ifdef notyet + if (dest->fd == MEM_OUT && len > bufsize) { + bufsize = len; + } ++#endif + offset = 0; ++#ifdef notyet + goto alloc; + } else if (dest->fd == MEM_OUT) { + offset = bufsize; +@@ -168,6 +172,7 @@ + if (bufsize < offset) + goto err; + alloc: ++#endif + INTOFF; + dest->buf = ckrealloc(dest->buf, bufsize); + dest->bufsize = bufsize; +@@ -183,11 +188,13 @@ + goto buffered; + + if ((xwrite(dest->fd, p, len))) { ++#ifdef notyet + err: ++#endif + dest->flags |= OUTPUT_ERR; + } +-} + #endif ++} + + + void +@@ -201,7 +208,7 @@ + size_t len; + + len = strlen(p); +- __outstr(p, len, file); ++ outmem(p, len, file); + #endif + } + +@@ -213,7 +220,7 @@ + outcslow(int c, struct output *dest) + { + char buf = c; +- __outstr(&buf, 1, dest); ++ outmem(&buf, 1, dest); + } + #endif + +@@ -283,35 +290,58 @@ + } + + ++static int xvasprintf(char **sp, size_t size, const char *f, va_list ap) ++{ ++ char *s; ++ int len; ++ va_list ap2; ++ ++ va_copy(ap2, ap); ++ len = xvsnprintf(*sp, size, f, ap2); ++ va_end(ap2); ++ if (len < 0) ++ sh_error("xvsnprintf failed"); ++ if (len < size) ++ return len; ++ ++ s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1); ++ *sp = s; ++ len = xvsnprintf(s, len + 1, f, ap); ++ return len; ++} ++ ++ ++int xasprintf(char **sp, const char *f, ...) ++{ ++ va_list ap; ++ int ret; ++ ++ va_start(ap, f); ++ ret = xvasprintf(sp, 0, f, ap); ++ va_end(ap); ++ return ret; ++} ++ ++ + #ifndef USE_GLIBC_STDIO + void + doformat(struct output *dest, const char *f, va_list ap) + { + struct stackmark smark; + char *s; +- int len, ret; +- size_t size; +- va_list ap2; ++ int len; ++ int olen; + +- va_copy(ap2, ap); +- size = dest->end - dest->nextc; +- len = xvsnprintf(dest->nextc, size, f, ap2); +- va_end(ap2); +- if (len < 0) { +- dest->flags |= OUTPUT_ERR; +- return; +- } +- if (len < size) { ++ setstackmark(&smark); ++ s = dest->nextc; ++ olen = dest->end - dest->nextc; ++ len = xvasprintf(&s, olen, f, ap); ++ if (likely(olen > len)) { + dest->nextc += len; +- return; ++ goto out; + } +- setstackmark(&smark); +- s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1); +- ret = xvsnprintf(s, len + 1, f, ap); +- if (ret == len) +- __outstr(s, len, dest); +- else +- dest->flags |= OUTPUT_ERR; ++ outmem(s, len, dest); ++out: + popstackmark(&smark); + } + #endif +diff -Naur dash-0.5.8/src/output.h dash-0.5.8-git_d7582e6/src/output.h +--- dash-0.5.8/src/output.h 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/output.h 2015-08-05 13:55:25.062024698 -0400 +@@ -63,6 +63,7 @@ + extern struct output *out1; + extern struct output *out2; + ++void outmem(const char *, size_t, struct output *); + void outstr(const char *, struct output *); + #ifndef USE_GLIBC_STDIO + void outcslow(int, struct output *); +@@ -75,6 +76,7 @@ + __attribute__((__format__(__printf__,1,2))); + int fmtstr(char *, size_t, const char *, ...) + __attribute__((__format__(__printf__,3,4))); ++int xasprintf(char **, const char *, ...); + #ifndef USE_GLIBC_STDIO + void doformat(struct output *, const char *, va_list); + #endif +@@ -115,6 +117,7 @@ + #endif + #define out1c(c) outc((c), out1) + #define out2c(c) outcslow((c), out2) ++#define out1mem(s, l) outmem((s), (l), out1) + #define out1str(s) outstr((s), out1) + #define out2str(s) outstr((s), out2) + #define outerr(f) (f)->flags +diff -Naur dash-0.5.8/src/parser.c dash-0.5.8-git_d7582e6/src/parser.c +--- dash-0.5.8/src/parser.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/parser.c 2015-08-05 13:55:25.062024698 -0400 +@@ -135,19 +135,13 @@ + union node * + parsecmd(int interact) + { +- int t; +- + tokpushback = 0; ++ checkkwd = 0; ++ heredoclist = 0; + doprompt = interact; + if (doprompt) + setprompt(doprompt); + needprompt = 0; +- t = readtoken(); +- if (t == TEOF) +- return NEOF; +- if (t == TNL) +- return NULL; +- tokpushback++; + return list(1); + } + +@@ -158,11 +152,27 @@ + union node *n1, *n2, *n3; + int tok; + +- checkkwd = CHKNL | CHKKWD | CHKALIAS; +- if (nlflag == 2 && tokendlist[peektoken()]) +- return NULL; + n1 = NULL; + for (;;) { ++ switch (peektoken()) { ++ case TNL: ++ if (!(nlflag & 1)) ++ break; ++ parseheredoc(); ++ return n1; ++ ++ case TEOF: ++ if (!n1 && (nlflag & 1)) ++ n1 = NEOF; ++ parseheredoc(); ++ return n1; ++ } ++ ++ checkkwd = CHKNL | CHKKWD | CHKALIAS; ++ if (nlflag == 2 && tokendlist[peektoken()]) ++ return n1; ++ nlflag |= 2; ++ + n2 = andor(); + tok = readtoken(); + if (tok == TBACKGND) { +@@ -189,31 +199,15 @@ + n1 = n3; + } + switch (tok) { +- case TBACKGND: +- case TSEMI: +- tok = readtoken(); +- /* fall through */ + case TNL: +- if (tok == TNL) { +- parseheredoc(); +- if (nlflag == 1) +- return n1; +- } else { +- tokpushback++; +- } +- checkkwd = CHKNL | CHKKWD | CHKALIAS; +- if (tokendlist[peektoken()]) +- return n1; +- break; + case TEOF: +- if (heredoclist) +- parseheredoc(); +- else +- pungetc(); /* push back EOF on input */ + tokpushback++; +- return n1; ++ /* fall through */ ++ case TBACKGND: ++ case TSEMI: ++ break; + default: +- if (nlflag == 1) ++ if ((nlflag & 1)) + synexpect(-1); + tokpushback++; + return n1; +@@ -743,6 +737,19 @@ + return (t); + } + ++static void nlprompt(void) ++{ ++ plinno++; ++ if (doprompt) ++ setprompt(2); ++} ++ ++static void nlnoprompt(void) ++{ ++ plinno++; ++ needprompt = doprompt; ++} ++ + + /* + * Read the next input token. +@@ -775,7 +782,7 @@ + setprompt(2); + } + for (;;) { /* until token or start of word found */ +- c = pgetc_macro(); ++ c = pgetc(); + switch (c) { + case ' ': case '\t': + case PEOA: +@@ -786,16 +793,13 @@ + continue; + case '\\': + if (pgetc() == '\n') { +- plinno++; +- if (doprompt) +- setprompt(2); ++ nlprompt(); + continue; + } + pungetc(); + goto breakloop; + case '\n': +- plinno++; +- needprompt = doprompt; ++ nlnoprompt(); + RETURN(TNL); + case PEOF: + RETURN(TEOF); +@@ -827,6 +831,22 @@ + #undef RETURN + } + ++static int pgetc_eatbnl(void) ++{ ++ int c; ++ ++ while ((c = pgetc()) == '\\') { ++ if (pgetc() != '\n') { ++ pungetc(); ++ break; ++ } ++ ++ nlprompt(); ++ } ++ ++ return c; ++} ++ + + + /* +@@ -895,9 +915,7 @@ + if (syntax == BASESYNTAX) + goto endword; /* exit outer loop */ + USTPUTC(c, out); +- plinno++; +- if (doprompt) +- setprompt(2); ++ nlprompt(); + c = pgetc(); + goto loop; /* continue outer loop */ + case CWORD: +@@ -916,9 +934,7 @@ + USTPUTC('\\', out); + pungetc(); + } else if (c == '\n') { +- plinno++; +- if (doprompt) +- setprompt(2); ++ nlprompt(); + } else { + if ( + dblquote && +@@ -1009,7 +1025,7 @@ + USTPUTC(c, out); + } + } +- c = pgetc_macro(); ++ c = pgetc(); + } + } + endword: +@@ -1074,8 +1090,7 @@ + + if (c == '\n' || c == PEOF) { + c = PEOF; +- plinno++; +- needprompt = doprompt; ++ nlnoprompt(); + } else { + int len; + +@@ -1179,7 +1194,7 @@ + char *p; + static const char types[] = "}-+?="; + +- c = pgetc(); ++ c = pgetc_eatbnl(); + if ( + (checkkwd & CHKEOFMARK) || + c <= PEOA || +@@ -1188,7 +1203,7 @@ + USTPUTC('$', out); + pungetc(); + } else if (c == '(') { /* $(command) or $((arith)) */ +- if (pgetc() == '(') { ++ if (pgetc_eatbnl() == '(') { + PARSEARITH(); + } else { + pungetc(); +@@ -1200,25 +1215,24 @@ + STADJUST(1, out); + subtype = VSNORMAL; + if (likely(c == '{')) { +- c = pgetc(); ++ c = pgetc_eatbnl(); + subtype = 0; + } + varname: + if (is_name(c)) { + do { + STPUTC(c, out); +- c = pgetc(); ++ c = pgetc_eatbnl(); + } while (is_in_name(c)); + } else if (is_digit(c)) { + do { + STPUTC(c, out); +- c = pgetc(); ++ c = pgetc_eatbnl(); + } while (is_digit(c)); +- } +- else if (is_special(c)) { ++ } else { + int cc = c; + +- c = pgetc(); ++ c = pgetc_eatbnl(); + + if (!subtype && cc == '#') { + subtype = VSLENGTH; +@@ -1227,7 +1241,7 @@ + goto varname; + + cc = c; +- c = pgetc(); ++ c = pgetc_eatbnl(); + if (cc == '}' || c != '}') { + pungetc(); + subtype = 0; +@@ -1236,16 +1250,20 @@ + } + } + ++ if (!is_special(cc)) { ++ if (subtype == VSLENGTH) ++ subtype = 0; ++ goto badsub; ++ } ++ + USTPUTC(cc, out); + } +- else +- goto badsub; + + if (subtype == 0) { + switch (c) { + case ':': + subtype = VSNUL; +- c = pgetc(); ++ c = pgetc_eatbnl(); + /*FALLTHROUGH*/ + default: + p = strchr(types, c); +@@ -1259,7 +1277,7 @@ + int cc = c; + subtype = c == '#' ? VSTRIMLEFT : + VSTRIMRIGHT; +- c = pgetc(); ++ c = pgetc_eatbnl(); + if (c == cc) + subtype++; + else +@@ -1324,9 +1342,7 @@ + + case '\\': + if ((pc = pgetc()) == '\n') { +- plinno++; +- if (doprompt) +- setprompt(2); ++ nlprompt(); + /* + * If eating a newline, avoid putting + * the newline into the new character +@@ -1348,8 +1364,7 @@ + synerror("EOF in backquote substitution"); + + case '\n': +- plinno++; +- needprompt = doprompt; ++ nlnoprompt(); + break; + + default: +@@ -1427,10 +1442,6 @@ + + #ifdef mkinit + INCLUDE "parser.h" +-RESET { +- tokpushback = 0; +- checkkwd = 0; +-} + #endif + + +diff -Naur dash-0.5.8/src/trap.c dash-0.5.8-git_d7582e6/src/trap.c +--- dash-0.5.8/src/trap.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/trap.c 2015-08-05 13:55:25.062024698 -0400 +@@ -51,10 +51,6 @@ + #include "trap.h" + #include "mystring.h" + +-#ifdef HETIO +-#include "hetio.h" +-#endif +- + /* + * Sigmode records the current value of the signal handlers for the various + * modes. A value of zero means that the current handler is not known. +@@ -314,25 +310,40 @@ + char *p; + char *q; + int i; +- int savestatus; ++ int status, last_status; + +- savestatus = exitstatus; ++ if (!pendingsigs) ++ return; ++ ++ status = savestatus; ++ last_status = status; ++ if (likely(status < 0)) { ++ status = exitstatus; ++ savestatus = status; ++ } + pendingsigs = 0; + barrier(); + + for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) { + if (!*q) + continue; ++ ++ if (evalskip) { ++ pendingsigs = i + 1; ++ break; ++ } ++ + *q = 0; + + p = trap[i + 1]; + if (!p) + continue; + evalstring(p, 0); +- exitstatus = savestatus; +- if (evalskip) +- break; ++ if (evalskip != SKIPFUNC) ++ exitstatus = status; + } ++ ++ savestatus = last_status; + } + + +@@ -366,18 +377,11 @@ + { + struct jmploc loc; + char *p; +- volatile int status; + +-#ifdef HETIO +- hetio_reset_term(); +-#endif +- status = exitstatus; +- TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); +- if (setjmp(loc.loc)) { +- if (exception == EXEXIT) +- status = exitstatus; ++ savestatus = exitstatus; ++ TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus)); ++ if (setjmp(loc.loc)) + goto out; +- } + handler = &loc; + if ((p = trap[0])) { + trap[0] = NULL; +@@ -392,7 +396,7 @@ + if (likely(!setjmp(loc.loc))) + setjobctl(0); + flushall(); +- _exit(status); ++ _exit(savestatus); + /* NOTREACHED */ + } + +diff -Naur dash-0.5.8/src/var.c dash-0.5.8-git_d7582e6/src/var.c +--- dash-0.5.8/src/var.c 2014-09-28 04:19:32.000000000 -0400 ++++ dash-0.5.8-git_d7582e6/src/var.c 2015-08-05 13:55:25.065358031 -0400 +@@ -80,6 +80,7 @@ + #else + const char defifs[] = " \t\n"; + #endif ++MKINIT char defoptindvar[] = "OPTIND=1"; + + int lineno; + char linenovar[sizeof("LINENO=")+sizeof(int)*CHAR_BIT/3+1] = "LINENO="; +@@ -100,7 +101,7 @@ + { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, + { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, + { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 }, +- { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, ++ { 0, VSTRFIXED|VTEXTFIXED, defoptindvar, getoptsreset }, + #ifdef WITH_LINENO + { 0, VSTRFIXED|VTEXTFIXED, linenovar, 0 }, + #endif +@@ -142,7 +143,7 @@ + } + } + +- setvarint("OPTIND", 1, 0); ++ setvareq(defoptindvar, VTEXTFIXED); + + fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid()); + setvareq(ppid, VTEXTFIXED); |