summaryrefslogtreecommitdiffstats
path: root/source/ap/ksh93
diff options
context:
space:
mode:
author Patrick J Volkerding <volkerdi@slackware.com>2016-06-30 20:26:57 +0000
committer Eric Hameleers <alien@slackware.com>2018-05-31 23:31:18 +0200
commitd31c50870d0bee042ce660e445c9294a59a3a65b (patch)
tree6bfc0de3c95267b401b620c2c67859557dc60f97 /source/ap/ksh93
parent76fc4757ac91ac7947a01fb7b53dddf9a78a01d1 (diff)
downloadcurrent-d31c50870d0bee042ce660e445c9294a59a3a65b.tar.gz
current-d31c50870d0bee042ce660e445c9294a59a3a65b.tar.xz
Slackware 14.2slackware-14.2
Thu Jun 30 20:26:57 UTC 2016 Slackware 14.2 x86_64 stable is released! The long development cycle (the Linux community has lately been living in "interesting times", as they say) is finally behind us, and we're proud to announce the release of Slackware 14.2. The new release brings many updates and modern tools, has switched from udev to eudev (no systemd), and adds well over a hundred new packages to the system. Thanks to the team, the upstream developers, the dedicated Slackware community, and everyone else who pitched in to help make this release a reality. The ISOs are off to be replicated, a 6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD. Please consider supporting the Slackware project by picking up a copy from store.slackware.com. We're taking pre-orders now, and offer a discount if you sign up for a subscription. Have fun! :-)
Diffstat (limited to 'source/ap/ksh93')
-rwxr-xr-xsource/ap/ksh93/ksh93.SlackBuild71
-rw-r--r--source/ap/ksh93/patches/ksh-20070328-builtins.patch31
-rw-r--r--source/ap/ksh93/patches/ksh-20080202-manfix.patch47
-rw-r--r--source/ap/ksh93/patches/ksh-20100202-pathvar.patch20
-rw-r--r--source/ap/ksh93/patches/ksh-20100621-fdstatus.patch54
-rw-r--r--source/ap/ksh93/patches/ksh-20100621-manfix3.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-alarmifs.patch33
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-argvfix.patch13
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-assoc-unset-leak.patch20
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-cdfix3.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-cdfork.patch40
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-covsfix.patch58
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-crash.patch64
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-diskfull.patch20
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-emptyarrayinit.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-fd2lost.patch64
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-filecomsubst.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-forkbomb.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-fununset.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-heresub.patch32
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-kshmfix.patch66
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-lexfix.patch56
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-locking.patch26
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-macro.patch205
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-manfix4.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-memlik.patch37
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-memlik3.patch76
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-mlikfiks.patch34
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-mtty.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-noexeccdfix.patch40
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-nohupfork.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-nomulti.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-oldenvinit.patch95
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-retfix.patch20
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-rmdirfix.patch (renamed from source/ap/ksh93/patches/rmdirfix.patch)2
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-roundit.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-sufix.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-tpstl.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-trapcom.patch47
-rw-r--r--source/ap/ksh93/patches/ksh-20120801-xufix.patch29
-rw-r--r--source/ap/ksh93/patches/ksh-20130613-cdfix4.patch15
-rw-r--r--source/ap/ksh93/patches/ksh-20130628-longer.patch58
-rw-r--r--source/ap/ksh93/patches/ksh-20140301-fikspand.patch12
-rw-r--r--source/ap/ksh93/patches/ksh-20140415-hokaido.patch37
-rw-r--r--source/ap/ksh93/patches/ksh-20140801-arraylen.patch11
-rw-r--r--source/ap/ksh93/patches/ksh-20140929-safefd.patch52
46 files changed, 1602 insertions, 34 deletions
diff --git a/source/ap/ksh93/ksh93.SlackBuild b/source/ap/ksh93/ksh93.SlackBuild
index 5eacc82af..44db3a9e3 100755
--- a/source/ap/ksh93/ksh93.SlackBuild
+++ b/source/ap/ksh93/ksh93.SlackBuild
@@ -1,7 +1,7 @@
#!/bin/sh
# Copyright 2001 BSDi, Inc. Concord, CA, USA
# Copyright 2004 Slackware Linux, Inc. Concord, CA, USA
-# Copyright 2007, 2008, 2009, 2010, 2013 Patrick J. Volkerding, Sebeka, MN, USA
+# Copyright 2007, 2008, 2009, 2010, 2013, 2016 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -25,13 +25,14 @@
VERSION=2012-08-01
PKGVER=2012_08_01
# Not packaged?
+# Seems to conflict with locations already used by glibc.
#KSHLOCALE=2010-02-02
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
case "$( uname -m )" in
- i?86) export ARCH=i486 ;;
+ i?86) export ARCH=i586 ;;
arm*) export ARCH=arm ;;
# Unless $ARCH is already set, use uname -m for all other archs:
*) export ARCH=$( uname -m ) ;;
@@ -71,13 +72,69 @@ find . \
zcat $CWD/patches/ksh-20070328-builtins.patch.gz | patch -p1 --verbose || exit 1
zcat $CWD/patches/ksh-20100826-fixregr.patch.gz | patch -p1 --verbose || exit 1
-zcat $CWD/patches/rmdirfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20080202-manfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20100202-pathvar.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20100621-fdstatus.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-rmdirfix.patch.gz | patch -p1 --verbose || exit 1
zcat $CWD/patches/ksh-20120801-cdfix.patch.gz | patch -p1 --verbose || exit 1
-zcat $CWD/patches/ksh-20120801-tabfix.patch.gz | patch -p1 --verbose || exit 1
zcat $CWD/patches/ksh-20120801-cdfix2.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-tabfix.patch.gz | patch -p1 --verbose || exit 1
zcat $CWD/patches/ksh-20130214-fixkill.patch.gz | patch -p1 --verbose || exit 1
-
-/bin/ksh bin/package make || exit 1
+zcat $CWD/patches/ksh-20120801-kshmfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-memlik.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-forkbomb.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-macro.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20130628-longer.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-mlikfiks.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-covsfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20100621-manfix3.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-nomulti.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-fd2lost.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-memlik3.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-filecomsubst.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-crash.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-sufix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-argvfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20140301-fikspand.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-roundit.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-heresub.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20140415-hokaido.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-tpstl.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-mtty.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-manfix4.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-fununset.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-cdfix3.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-locking.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20130613-cdfix4.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-retfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-oldenvinit.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-noexeccdfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-cdfork.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-emptyarrayinit.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-xufix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-assoc-unset-leak.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-alarmifs.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20140929-safefd.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-trapcom.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-lexfix.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20140801-arraylen.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-diskfull.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/patches/ksh-20120801-nohupfork.patch.gz | patch -p1 --verbose || exit 1
+
+#/dev/fd test does not work because of mock
+sed -i 's|ls /dev/fd|ls /proc/self/fd|' src/cmd/ksh93/features/options
+
+# sh/main.c was not using CCFLAGS
+sed -i '/-c sh\/main.c/s|${mam_cc_FLAGS} |${mam_cc_FLAGS} ${CCFLAGS} |p' src/cmd/ksh93/Mamfile
+
+# disable register for debugging
+sed -i 1i"#define register" src/lib/libast/include/ast.h
+
+/bin/ksh ./bin/package
+/bin/ksh ./bin/package make mamake ||:
+/bin/ksh ./bin/package make mamake ||:
+export CC=gcc
+/bin/ksh ./bin/package make -S || exit 1
mkdir -p $PKG/bin
cp arch/linux.$SARCH/bin/ksh $PKG/bin/ksh.new
diff --git a/source/ap/ksh93/patches/ksh-20070328-builtins.patch b/source/ap/ksh93/patches/ksh-20070328-builtins.patch
index 5c6b21c2f..061bf9aa0 100644
--- a/source/ap/ksh93/patches/ksh-20070328-builtins.patch
+++ b/source/ap/ksh93/patches/ksh-20070328-builtins.patch
@@ -1,32 +1,11 @@
-diff -up ksh-20120620/src/cmd/ksh93/data/builtins.c.builtins ksh-20120620/src/cmd/ksh93/data/builtins.c
---- ksh-20120620/src/cmd/ksh93/data/builtins.c.builtins 2012-06-19 10:02:12.000000000 +0200
-+++ ksh-20120620/src/cmd/ksh93/data/builtins.c 2012-06-22 12:35:05.587717588 +0200
-@@ -131,20 +131,28 @@ const struct shtable3 shtab_builtins[] =
- #undef mktemp /* undo possible map-libc mktemp => _ast_mktemp */
- #include SHOPT_CMDLIB_HDR
- #else
-+#if 1
- CMDLIST(basename)
- CMDLIST(chmod)
+diff -up ksh-20080202/src/cmd/ksh93/data/builtins.c.builtins ksh-20080202/src/cmd/ksh93/data/builtins.c
+--- ksh-20080202/src/cmd/ksh93/data/builtins.c.builtins 2008-10-01 09:24:46.000000000 +0200
++++ ksh-20080202/src/cmd/ksh93/data/builtins.c 2008-10-01 09:24:58.000000000 +0200
+@@ -129,7 +129,6 @@ const struct shtable3 shtab_builtins[] =
CMDLIST(dirname)
CMDLIST(getconf)
CMDLIST(head)
-+#if 0
-+does not work when ACLs are used
- CMDLIST(mkdir)
-+#endif
+- CMDLIST(mkdir)
CMDLIST(logname)
-+#if 1
-+//does not work in chrooted environments, because /dev/fd/? is missing
CMDLIST(cat)
-+#endif
CMDLIST(cmp)
- CMDLIST(cut)
- CMDLIST(uname)
- CMDLIST(wc)
- CMDLIST(sync)
- #endif
-+#endif
- #if SHOPT_REGRESS
- "__regress__", NV_BLTIN|BLT_ENV, bltin(__regress__),
- #endif
diff --git a/source/ap/ksh93/patches/ksh-20080202-manfix.patch b/source/ap/ksh93/patches/ksh-20080202-manfix.patch
new file mode 100644
index 000000000..8fe422572
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20080202-manfix.patch
@@ -0,0 +1,47 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh.1.manfix ksh-20120801/src/cmd/ksh93/sh.1
+--- ksh-20120801/src/cmd/ksh93/sh.1.manfix 2012-06-18 16:16:22.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh.1 2013-04-30 13:35:17.393909479 +0200
+@@ -39,7 +39,7 @@ ksh93, rksh93, pfksh93 \- KornShell, a s
+ .B ksh93
+ .\}
+ [
+-.B \(+-abcefhikmnoprstuvxBCDP
++.B \(+-abcefhiknoprstuvxBCDP
+ ] [
+ .B \-R
+ file ] [
+@@ -47,25 +47,6 @@ file ] [
+ option ] .\|.\|. [
+ .B \-
+ ] [ arg .\|.\|. ]
+-.br
+-.if \nZ=0 \{\
+-.B rsh
+-.\}
+-.if \nZ=1 \{\
+-.B rksh
+-.\}
+-.if \nZ=2 \{\
+-.B rksh93
+-.\}
+-[
+-.B \(+-abcefhikmnoprstuvxBCD
+-] [
+-.B \-R
+-file ] [
+-.B \(+-o
+-option ] .\|.\|. [
+-.B \-
+-] [ arg .\|.\|. ]
+ .SH DESCRIPTION
+ .if \nZ=0 .I Sh\^
+ .if \nZ=1 .I Ksh\^
+@@ -7963,6 +7944,8 @@ option is used
+ to generate a cross reference database
+ that can be used by a separate utility
+ to find definitions and references for variables and commands.
++The filename argument specifies the generated database. A script file must be
++provided on the command line as well.
+ .PP
+ The remaining options and arguments are described under the
+ .B set
diff --git a/source/ap/ksh93/patches/ksh-20100202-pathvar.patch b/source/ap/ksh93/patches/ksh-20100202-pathvar.patch
new file mode 100644
index 000000000..508649962
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20100202-pathvar.patch
@@ -0,0 +1,20 @@
+diff -up ksh-20100202/src/cmd/ksh93/sh.1.pathvar ksh-20100202/src/cmd/ksh93/sh.1
+--- ksh-20100202/src/cmd/ksh93/sh.1.pathvar 2011-04-26 16:42:08.000000000 +0200
++++ ksh-20100202/src/cmd/ksh93/sh.1 2011-04-27 09:09:00.315883280 +0200
+@@ -4025,13 +4025,9 @@ the directory containing the command.
+ Alternative directory names are separated by
+ a colon
+ .RB ( : ).
+-The default path is
+-.B /bin:/usr/bin:
+-(specifying
+-.BR /bin ,
+-.BR /usr/bin ,
+-and the current directory
+-in that order).
++The default path is equal to
++.BI getconf\ PATH
++output.
+ The current directory can be specified by
+ two or more adjacent colons, or by a colon
+ at the beginning or end of the path list.
diff --git a/source/ap/ksh93/patches/ksh-20100621-fdstatus.patch b/source/ap/ksh93/patches/ksh-20100621-fdstatus.patch
new file mode 100644
index 000000000..99abb5533
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20100621-fdstatus.patch
@@ -0,0 +1,54 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/io.c.fdstatus ksh-20120801/src/cmd/ksh93/sh/io.c
+--- ksh-20120801/src/cmd/ksh93/sh/io.c.fdstatus 2013-07-04 18:01:27.187516655 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/io.c 2013-07-04 18:01:38.249607392 +0200
+@@ -1508,7 +1508,7 @@ int sh_redirect(Shell_t *shp,struct iono
+ fn = fd;
+ if(fd<10)
+ {
+- if((fn=fcntl(fd,F_DUPFD,10)) < 0)
++ if((fn=sh_fcntl(fd,F_DUPFD,10)) < 0)
+ goto fail;
+ if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
+ goto fail;
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.fdstatus ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.fdstatus 2012-07-17 23:54:21.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2013-07-04 17:56:20.342000310 +0200
+@@ -122,7 +122,7 @@ void sh_subtmpfile(Shell_t *shp)
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ register struct subshell *sp = subshell_data->pipe;
+ /* save file descriptor 1 if open */
+- if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
++ if((sp->tmpfd = fd = sh_fcntl(1,F_DUPFD,10)) >= 0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
+@@ -554,7 +554,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ sp->pwdfd = n;
+ if(n<10)
+ {
+- sp->pwdfd = fcntl(n,F_DUPFD,10);
++ sp->pwdfd = sh_fcntl(n,F_DUPFD,10);
+ close(n);
+ }
+ if(sp->pwdfd>0)
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.fdstatus ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.fdstatus 2012-07-23 16:49:32.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2013-07-04 17:57:47.153712116 +0200
+@@ -116,7 +116,7 @@ static int iousepipe(Shell_t *shp)
+ return(0);
+ usepipe++;
+ fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
+- subpipe[2] = fcntl(1,F_DUPFD,10);
++ subpipe[2] = sh_fcntl(1,F_DUPFD,10);
+ fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
+ close(1);
+@@ -3622,7 +3622,7 @@ static void coproc_init(Shell_t *shp, in
+ sh_pipe(shp->cpipe);
+ if((outfd=shp->cpipe[1]) < 10)
+ {
+- int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
++ int fd=sh_fcntl(shp->cpipe[1],F_DUPFD,10);
+ if(fd>=10)
+ {
+ shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
diff --git a/source/ap/ksh93/patches/ksh-20100621-manfix3.patch b/source/ap/ksh93/patches/ksh-20100621-manfix3.patch
new file mode 100644
index 000000000..bced57514
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20100621-manfix3.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20100621/src/cmd/ksh93/sh.1.manfix3 ksh-20100621/src/cmd/ksh93/sh.1
+--- ksh-20100621/src/cmd/ksh93/sh.1.manfix3 2013-05-02 13:07:51.180529762 +0200
++++ ksh-20100621/src/cmd/ksh93/sh.1 2013-05-02 13:11:30.469327199 +0200
+@@ -7585,7 +7585,7 @@ file descriptor 2.
+ If the
+ .B \-i
+ option is present or
+-if the shell input and output are attached to a terminal (as told by
++if the shell input and error output are attached to a terminal (as told by
+ .IR tcgetattr (2)),
+ then this shell is
+ .IR interactive .
diff --git a/source/ap/ksh93/patches/ksh-20120801-alarmifs.patch b/source/ap/ksh93/patches/ksh-20120801-alarmifs.patch
new file mode 100644
index 000000000..88b0ba9e5
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-alarmifs.patch
@@ -0,0 +1,33 @@
+--- ksh-20120801/src/cmd/ksh93/sh/init.c 2014-12-10 20:11:17.693446084 -0200
++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2014-12-10 20:11:24.753442619 -0200
+@@ -576,6 +576,7 @@ static char* get_ifs(register Namval_t*
+ shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
+ shp->ifstable['\n'] = S_NL;
+ }
++ shp->ifstable[0] = S_EOF;
+ }
+ return(value);
+ }
+--- ksh-20120801/src/cmd/ksh93/bltins/alarm.c 2014-12-18 12:03:39.198461933 -0200
++++ ksh-20120801/src/cmd/ksh93/bltins/alarm.c 2014-12-18 12:04:32.464421268 -0200
+@@ -130,6 +130,7 @@ void sh_timetraps(Shell_t *shp)
+ {
+ register struct tevent *tp, *tpnext;
+ register struct tevent *tptop;
++ char ifstable[256];
+ while(1)
+ {
+ shp->sigflag[SIGALRM] &= ~SH_SIGALRM;
+@@ -141,7 +142,11 @@ void sh_timetraps(Shell_t *shp)
+ {
+ tp->flags &= ~L_FLAG;
+ if(tp->action)
++ {
++ memcpy(ifstable,shp->ifstable,sizeof(ifstable));
+ sh_fun(tp->action,tp->node,(char**)0);
++ memcpy(shp->ifstable,ifstable,sizeof(ifstable));
++ }
+ tp->flags &= ~L_FLAG;
+ if(!tp->flags)
+ {
+
diff --git a/source/ap/ksh93/patches/ksh-20120801-argvfix.patch b/source/ap/ksh93/patches/ksh-20120801-argvfix.patch
new file mode 100644
index 000000000..b0e1a7823
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-argvfix.patch
@@ -0,0 +1,13 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/main.c.fixargs ksh-20120801/src/cmd/ksh93/sh/main.c
+--- ksh-20120801/src/cmd/ksh93/sh/main.c.fixargs 2013-12-31 11:32:14.917874134 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/main.c 2013-12-31 11:32:58.028847126 +0100
+@@ -757,7 +757,7 @@ static void fixargs(char **argv, int mod
+ offset += size;
+ buff[offset++] = ' ';
+ }
+- buff[offset-1] = 0;
++ memset(&buff[offset - 1], 0, command_len - offset + 1);
+ # ifdef PSTAT
+ un.pst_command = stakptr(0);
+ pstat(PSTAT_SETCMD,un,0,0,0);
+
diff --git a/source/ap/ksh93/patches/ksh-20120801-assoc-unset-leak.patch b/source/ap/ksh93/patches/ksh-20120801-assoc-unset-leak.patch
new file mode 100644
index 000000000..1af7d1664
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-assoc-unset-leak.patch
@@ -0,0 +1,20 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/name.c.orig ksh-20120801/src/cmd/ksh93/sh/name.c
+--- ksh-20120801/src/cmd/ksh93/sh/name.c.orig 2015-02-10 17:15:37.180783550 -0200
++++ ksh-20120801/src/cmd/ksh93/sh/name.c 2015-02-10 18:25:51.726228437 -0200
+@@ -1298,7 +1298,16 @@ void nv_delete(Namval_t* np, Dt_t *root,
+ if(dtdelete(root,np))
+ {
+ if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np,flags&NV_TABLE)))
++ {
++ Namarr_t *ap;
++ if(nv_isarray(np) && np->nvfun && (ap=nv_arrayptr(np)) && array_assoc(ap)) {
++ while(nv_associative(np,0,NV_ANEXT))
++ nv_associative(np, 0, NV_ADELETE);
++ nv_associative(np, 0, NV_AFREE);
++ free((void*)np->nvfun);
++ }
+ free((void*)np);
++ }
+ }
+ #if 0
+ else
diff --git a/source/ap/ksh93/patches/ksh-20120801-cdfix3.patch b/source/ap/ksh93/patches/ksh-20120801-cdfix3.patch
new file mode 100644
index 000000000..7e47f711e
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-cdfix3.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix3 ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c
+--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix3 2014-06-20 12:39:02.757407689 +0200
++++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2014-06-20 12:40:19.530998070 +0200
+@@ -290,7 +290,7 @@ int b_cd(int argc, char *argv[],Shbltin_
+ if(newdirfd >=0)
+ {
+ /* chdir for directories on HSM/tapeworms may take minutes */
+- if(fchdir(newdirfd) >= 0)
++ if((rval=fchdir(newdirfd)) >= 0)
+ {
+ if(shp->pwdfd >= 0)
+ sh_close(shp->pwdfd);
diff --git a/source/ap/ksh93/patches/ksh-20120801-cdfork.patch b/source/ap/ksh93/patches/ksh-20120801-cdfork.patch
new file mode 100644
index 000000000..c82cb4c00
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-cdfork.patch
@@ -0,0 +1,40 @@
+--- ksh-20120801/src/cmd/ksh93/sh/path.c 2014-09-01 15:08:06.738969962 -0300
++++ ksh-20120801/src/cmd/ksh93/sh/path.c 2014-09-01 15:13:51.321459978 -0300
+@@ -229,13 +229,12 @@ static pid_t path_xargs(Shell_t *shp,con
+ /*
+ * make sure PWD is set up correctly
+ * Return the present working directory
+- * Invokes getcwd() if flag==0 and if necessary
++ * Invokes getcwd() if necessary
+ * Sets the PWD variable to this value
+ */
+ char *path_pwd(Shell_t *shp,int flag)
+ {
+ register char *cp;
+- register char *dfault = (char*)e_dot;
+ register int count = 0;
+ if(shp->pwd)
+ return((char*)shp->pwd);
+@@ -254,11 +253,6 @@ char *path_pwd(Shell_t *shp,int flag)
+ cp = "/";
+ break;
+ case 3:
+- cp = (char*)e_crondir;
+- if(flag) /* skip next case when non-zero flag */
+- ++count;
+- break;
+- case 4:
+ {
+ if(cp=getcwd(NIL(char*),0))
+ {
+@@ -269,8 +263,8 @@ char *path_pwd(Shell_t *shp,int flag)
+ }
+ break;
+ }
+- case 5:
++ case 4:
+- return(dfault);
++ return((char*)e_dot);
+ }
+ if(cp && *cp=='/' && test_inode(cp,e_dot))
+ break;
diff --git a/source/ap/ksh93/patches/ksh-20120801-covsfix.patch b/source/ap/ksh93/patches/ksh-20120801-covsfix.patch
new file mode 100644
index 000000000..c64e2a79e
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-covsfix.patch
@@ -0,0 +1,58 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.covsfix ksh-20120801/src/cmd/ksh93/sh/init.c
+--- ksh-20120801/src/cmd/ksh93/sh/init.c.covsfix 2013-07-22 17:41:34.674054068 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2013-07-22 17:42:50.761361921 +0200
+@@ -1237,9 +1237,11 @@ static void put_mode(Namval_t* np, const
+ mode = *(double*)val;
+ }
+ else
++ {
+ mode = strperm(val, &last,0);
+- if(*last)
+- errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
++ if(*last)
++ errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
++ }
+ nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
+ }
+ else
+diff -up ksh-20120801/src/cmd/ksh93/sh/io.c.covsfix ksh-20120801/src/cmd/ksh93/sh/io.c
+--- ksh-20120801/src/cmd/ksh93/sh/io.c.covsfix 2013-07-22 17:06:30.282927080 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/io.c 2013-07-22 17:08:49.645721280 +0200
+@@ -954,6 +954,7 @@ int sh_pipe(register int pv[])
+ socklen_t slen;
+ if ((pv[out] = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
++ memset(&sin.sin_zero, 0, sizeof(sin.sin_zero));
+ do
+ {
+ sin.sin_family = AF_INET;
+diff -up ksh-20120801/src/cmd/ksh93/sh/name.c.covsfix ksh-20120801/src/cmd/ksh93/sh/name.c
+--- ksh-20120801/src/cmd/ksh93/sh/name.c.covsfix 2013-07-22 17:40:31.644635604 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/name.c 2013-07-22 17:41:15.828227073 +0200
+@@ -3094,6 +3094,7 @@ void nv_newattr (register Namval_t *np,
+ if(!mp)
+ nv_putval (np, cp, NV_RDONLY);
+ free(cp);
++ cp = NULL;
+ }
+ }
+ while(ap && nv_nextsub(np));
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.covsfix ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.covsfix 2013-07-22 17:46:15.607533423 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2013-07-22 17:48:36.739290968 +0200
+@@ -205,7 +205,14 @@ void sh_subfork(void)
+ shp->comsub = 0;
+ SH_SUBSHELLNOD->nvalue.s = 0;
+ sp->subpid=0;
+- shp->st.trapcom[0] = (comsub==2?NULL:trap);
++ if (comsub==2)
++ {
++ shp->st.trapcom[0] = NULL;
++ if(trap)
++ free((void*)trap);
++ }
++ else
++ shp->st.trapcom[0] = (comsub==2?NULL:trap);
+ shp->savesig = 0;
+ }
+ }
diff --git a/source/ap/ksh93/patches/ksh-20120801-crash.patch b/source/ap/ksh93/patches/ksh-20120801-crash.patch
new file mode 100644
index 000000000..63eda7229
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-crash.patch
@@ -0,0 +1,64 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/jobs.h.crash ksh-20120801/src/cmd/ksh93/include/jobs.h
+--- ksh-20120801/src/cmd/ksh93/include/jobs.h.crash 2014-07-16 17:32:03.570057304 +0200
++++ ksh-20120801/src/cmd/ksh93/include/jobs.h 2014-07-16 17:32:03.600057172 +0200
+@@ -118,6 +118,7 @@ struct jobs
+ char jobcontrol; /* turned on for real job control */
+ char waitsafe; /* wait will not block */
+ char waitall; /* wait for all jobs in pipe */
++ char hack1_waitall;
+ char toclear; /* job table needs clearing */
+ unsigned char *freejobs; /* free jobs numbers */
+ #if SHOPT_COSHELL
+diff -up ksh-20120801/src/cmd/ksh93/sh/jobs.c.crash ksh-20120801/src/cmd/ksh93/sh/jobs.c
+--- ksh-20120801/src/cmd/ksh93/sh/jobs.c.crash 2014-07-16 17:32:03.554057375 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/jobs.c 2014-07-16 17:32:03.600057172 +0200
+@@ -1957,6 +1957,7 @@ again:
+ {
+ count = bp->count;
+ jp = bp->list;
++ jpold = 0;
+ goto again;
+ }
+ if(jp)
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.crash ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.crash 2014-07-16 17:32:03.593057203 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2014-07-16 17:32:03.600057172 +0200
+@@ -492,6 +492,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ struct sh_scoped savst;
+ struct dolnod *argsav=0;
+ int argcnt;
++ int pipefail = 0;
+ memset((char*)sp, 0, sizeof(*sp));
+ sfsync(shp->outpool);
+ sh_sigcheck(shp);
+@@ -541,7 +542,10 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ sp->comsub = shp->comsub;
+ shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
+ if(comsub)
++ {
+ shp->comsub = comsub;
++ job.hack1_waitall=(comsub==1);
++ }
+ sp->shpwdfd=-1;
+ if(!comsub || !shp->subshare)
+ {
+@@ -648,6 +652,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ }
+ else
+ {
++ job.hack1_waitall=0;
+ /* move tmp file to iop and restore sfstdout */
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
+ if(!iop)
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.crash ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.crash 2014-07-16 17:32:03.587057230 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2014-07-16 17:32:03.601057168 +0200
+@@ -2125,7 +2125,7 @@ int sh_exec(register const Shnode_t *t,
+ memset(exitval,0,job.waitall*sizeof(int));
+ }
+ else
+- job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
++ job.waitall |= job.hack1_waitall || !pipejob && sh_isstate(SH_MONITOR);
+ job_lock();
+ nlock++;
+ do
diff --git a/source/ap/ksh93/patches/ksh-20120801-diskfull.patch b/source/ap/ksh93/patches/ksh-20120801-diskfull.patch
new file mode 100644
index 000000000..9d68d9350
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-diskfull.patch
@@ -0,0 +1,20 @@
+--- ksh-20120801/src/cmd/ksh93/sh/main.c 2015-04-17 16:55:57.802048900 -0300
++++ ksh-20120801/src/cmd/ksh93/sh/main.c 2015-04-17 17:10:45.276129709 -0300
+@@ -423,7 +423,7 @@ static void exfile(register Shell_t *shp
+ sfsync(shp->outpool);
+ shp->st.execbrk = shp->st.breakcnt = 0;
+ /* check for return from profile or env file */
+- if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT))
++ if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT || jmpval==SH_JMPERREXIT))
+ {
+ sh_setstate(states);
+ goto done;
+@@ -600,6 +600,8 @@ done:
+ siglongjmp(*shp->jmplist,jmpval);
+ else if(jmpval == SH_JMPEXIT)
+ sh_done(shp,0);
++ else if(jmpval == SH_JMPERREXIT)
++ sh_done(shp,-1);
+ if(fno>0)
+ sh_close(fno);
+ if(shp->st.filename)
diff --git a/source/ap/ksh93/patches/ksh-20120801-emptyarrayinit.patch b/source/ap/ksh93/patches/ksh-20120801-emptyarrayinit.patch
new file mode 100644
index 000000000..c888b319d
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-emptyarrayinit.patch
@@ -0,0 +1,11 @@
+--- ksh-20120801/src/cmd/ksh93/sh/array.c 2014-12-11 16:39:34.253860675 -0200
++++ ksh-20120801/src/cmd/ksh93/sh/array.c 2014-12-11 16:39:40.794857083 -0200
+@@ -1003,7 +1003,7 @@ Namarr_t *nv_setarray(Namval_t *np, void
+ ap->nelem = nelem;
+ ap->fun = fun;
+ nv_onattr(np,NV_ARRAY);
+- if(fp || value)
++ if(fp || (value && value != Empty))
+ {
+ nv_putsub(np, "0", ARRAY_ADD);
+ if(value)
diff --git a/source/ap/ksh93/patches/ksh-20120801-fd2lost.patch b/source/ap/ksh93/patches/ksh-20120801-fd2lost.patch
new file mode 100644
index 000000000..fbb76070e
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-fd2lost.patch
@@ -0,0 +1,64 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/macro.c.orig ksh-20120801/src/cmd/ksh93/sh/macro.c
+--- ksh-20120801/src/cmd/ksh93/sh/macro.c.orig 2013-12-09 13:13:22.153525239 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/macro.c 2013-12-09 13:20:58.144635385 +0100
+@@ -391,7 +391,7 @@ void sh_machere(Shell_t *shp,Sfio_t *inf
+ break;
+ }
+ case S_PAR:
+- comsubst(mp,(Shnode_t*)0,1);
++ comsubst(mp,(Shnode_t*)0,3);
+ break;
+ case S_EOF:
+ if((c=fcfill()) > 0)
+@@ -1165,7 +1165,7 @@ retry1:
+ case S_PAR:
+ if(type)
+ goto nosub;
+- comsubst(mp,(Shnode_t*)0,1);
++ comsubst(mp,(Shnode_t*)0,3);
+ return(1);
+ case S_DIG:
+ var = 0;
+@@ -2152,10 +2152,12 @@ static void comsubst(Mac_t *mp,register
+ mp->ifsp = nv_getval(np);
+ stkset(stkp,savptr,savtop);
+ newlines = 0;
+- if(type/*==3 - don't break `` vs $() */ && mp->shp->spid)
++ if(type==3 && mp->shp->spid)
+ {
+ job_wait(mp->shp->spid);
+- mp->shp->spid = 0;
++ if(mp->shp->pipepid==mp->shp->spid)
++ mp->shp->spid = 0;
++ mp->shp->pipepid = 0;
+ }
+ sfsetbuf(sp,(void*)sp,0);
+ bufsize = sfvalue(sp);
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.anotherfix ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.anotherfix 2014-01-20 14:43:46.410416327 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2014-01-20 14:43:46.444416042 +0100
+@@ -122,7 +122,8 @@ void sh_subtmpfile(Shell_t *shp)
+ else if(errno!=EBADF)
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ /* popping a discipline forces a /tmp file create */
+- sfdisc(sfstdout,SF_POPDISC);
++ if(shp->comsub != 1)
++ sfdisc(sfstdout,SF_POPDISC);
+ if((fd=sffileno(sfstdout))<0)
+ {
+ /* unable to create the /tmp file so use a pipe */
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.anotherfix ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.anotherfix 2014-01-20 14:47:30.527524008 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2014-01-20 14:47:30.563523703 +0100
+@@ -1773,7 +1773,11 @@ int sh_exec(register const Shnode_t *t,
+ if(shp->pipepid)
+ shp->pipepid = parent;
+ else
++ {
+ job_wait(parent);
++ if(parent==shp->spid)
++ shp->spid = 0;
++ }
+ if(shp->topfd > topfd)
+ sh_iorestore(shp,topfd,0);
+ if(usepipe && tsetio && subdup && unpipe)
diff --git a/source/ap/ksh93/patches/ksh-20120801-filecomsubst.patch b/source/ap/ksh93/patches/ksh-20120801-filecomsubst.patch
new file mode 100644
index 000000000..6aa1fea91
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-filecomsubst.patch
@@ -0,0 +1,11 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/io.c.filecombsubst ksh-20120801/src/cmd/ksh93/sh/io.c
+--- ksh-20120801/src/cmd/ksh93/sh/io.c.filecombsubst 2014-02-26 16:15:52.355391420 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/io.c 2014-02-26 16:23:55.588148801 +0100
+@@ -1326,6 +1326,7 @@ int sh_redirect(Shell_t *shp,struct iono
+ if(flag==SH_SHOWME)
+ goto traceit;
+ fd=sh_chkopen(fname);
++ fd=sh_iomovefd(fd);
+ }
+ else if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
diff --git a/source/ap/ksh93/patches/ksh-20120801-forkbomb.patch b/source/ap/ksh93/patches/ksh-20120801-forkbomb.patch
new file mode 100644
index 000000000..7a1a5c169
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-forkbomb.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/fault.c.forkbomb ksh-20120801/src/cmd/ksh93/sh/fault.c
+--- ksh-20120801/src/cmd/ksh93/sh/fault.c.forkbomb 2013-04-30 16:20:40.237490109 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/fault.c 2013-04-30 16:21:49.961068778 +0200
+@@ -519,7 +519,7 @@ void sh_exit(register int xno)
+ if(pp && pp->mode>1)
+ cursig = -1;
+ #ifdef SIGTSTP
+- if(shp->trapnote&SH_SIGTSTP)
++ if((shp->trapnote&SH_SIGTSTP) && job.jobcontrol)
+ {
+ /* ^Z detected by the shell */
+ shp->trapnote = 0;
diff --git a/source/ap/ksh93/patches/ksh-20120801-fununset.patch b/source/ap/ksh93/patches/ksh-20120801-fununset.patch
new file mode 100644
index 000000000..1f5cb17c1
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-fununset.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.fununset ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.fununset 2014-06-16 14:21:09.293513844 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2014-06-16 14:21:09.309513760 +0200
+@@ -3570,7 +3570,7 @@ static void sh_funct(Shell_t *shp,Namval
+ #endif
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ shp->pipepid = pipepid;
+- np->nvalue.rp->running -= 2;
++ if (np->nvalue.rp) np->nvalue.rp->running -= 2;
+ }
+
+ /*
diff --git a/source/ap/ksh93/patches/ksh-20120801-heresub.patch b/source/ap/ksh93/patches/ksh-20120801-heresub.patch
new file mode 100644
index 000000000..880071cd6
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-heresub.patch
@@ -0,0 +1,32 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/lex.c.heresub ksh-20120801/src/cmd/ksh93/sh/lex.c
+--- ksh-20120801/src/cmd/ksh93/sh/lex.c.heresub 2014-05-21 16:48:42.635700984 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/lex.c 2014-05-21 16:48:42.678700772 +0200
+@@ -1557,6 +1557,7 @@ static int comsub(register Lex_t *lp, in
+ {
+ register int n,c,count=1;
+ register int line=lp->sh->inlineno;
++ struct ionod *inheredoc = lp->heredoc;
+ char *first,*cp=fcseek(0),word[5];
+ int off, messages=0, assignok=lp->assignok, csub;
+ struct lexstate save;
+@@ -1683,7 +1684,7 @@ done:
+ lp->lexd.dolparen--;
+ lp->lex = save;
+ lp->assignok = (endchar(lp)==RBRACT?assignok:0);
+- if(lp->heredoc)
++ if(lp->heredoc && !inheredoc)
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
+ return(messages);
+ }
+diff -up ksh-20120801/src/cmd/ksh93/sh/macro.c.heresub ksh-20120801/src/cmd/ksh93/sh/macro.c
+--- ksh-20120801/src/cmd/ksh93/sh/macro.c.heresub 2014-05-21 16:48:42.650700910 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/macro.c 2014-05-21 16:48:42.678700772 +0200
+@@ -2085,7 +2085,7 @@ static void comsubst(Mac_t *mp,register
+ }
+ sfputc(stkp,c);
+ }
+- sfputc(stkp,' ');
++ sfputc(stkp,'\n');
+ c = stktell(stkp);
+ str=stkfreeze(stkp,1);
+ /* disable verbose and don't save in history file */
diff --git a/source/ap/ksh93/patches/ksh-20120801-kshmfix.patch b/source/ap/ksh93/patches/ksh-20120801-kshmfix.patch
new file mode 100644
index 000000000..cc6840666
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-kshmfix.patch
@@ -0,0 +1,66 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/main.c.monintoron ksh-20120801/src/cmd/ksh93/sh/main.c
+--- ksh-20120801/src/cmd/ksh93/sh/main.c.monintoron 2013-05-31 10:15:02.738828102 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/main.c 2013-05-31 10:15:36.057095262 +0200
+@@ -406,10 +406,10 @@ static void exfile(register Shell_t *shp
+ {
+ buff.mode = SH_JMPEXIT;
+ sh_onoption(SH_TRACKALL);
+- sh_offoption(SH_MONITOR);
+ }
+ sh_offstate(SH_INTERACTIVE);
+- sh_offstate(SH_MONITOR);
++ if(sh_isoption(SH_MONITOR))
++ sh_onstate(SH_MONITOR);
+ sh_offstate(SH_HISTORY);
+ sh_offoption(SH_HISTORY);
+ }
+diff -up ksh-20120801/src/cmd/ksh93/sh/jobs.c.orig ksh-20120801/src/cmd/ksh93/sh/jobs.c
+--- ksh-20120801/src/cmd/ksh93/sh/jobs.c.orig 2013-05-31 10:12:28.358590452 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/jobs.c 2013-05-31 10:16:51.203697890 +0200
+@@ -548,7 +548,7 @@ int job_reap(register int sig)
+ {
+ px = job_byjid((int)pw->p_job);
+ for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
+- if(!px)
++ if(!px && sh_isoption(SH_INTERACTIVE))
+ tcsetpgrp(JOBTTY,job.mypid);
+ }
+ #ifndef SHOPT_BGX
+@@ -842,10 +842,11 @@ static void job_set(register struct proc
+
+ static void job_reset(register struct process *pw)
+ {
++ Shell_t *shp = pw->p_shp;
+ /* save the terminal state for current job */
+ #ifdef SIGTSTP
+ job_fgrp(pw,tcgetpgrp(job.fd));
+- if(tcsetpgrp(job.fd,job.mypid) !=0)
++ if(sh_isoption(SH_INTERACTIVE) && tcsetpgrp(job.fd,job.mypid) !=0)
+ return;
+ #endif /* SIGTSTP */
+ /* force the following tty_get() to do a tcgetattr() unless fg */
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.orig ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.orig 2013-05-31 10:12:27.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2013-05-31 10:18:14.650367185 +0200
+@@ -2201,7 +2201,7 @@ int sh_exec(register const Shnode_t *t,
+ }
+ shp->exitval = n;
+ #ifdef SIGTSTP
+- if(!pipejob && sh_isstate(SH_MONITOR))
++ if(!pipejob && sh_isstate(SH_MONITOR) && sh_isoption(SH_INTERACTIVE))
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+ #endif /*SIGTSTP */
+ job.curpgid = savepgid;
+diff -up ksh-20120801/src/cmd/ksh93/edit/edit.c.kshmfix ksh-20120801/src/cmd/ksh93/edit/edit.c
+--- ksh-20120801/src/cmd/ksh93/edit/edit.c.kshmfix 2013-09-23 10:46:57.007256192 +0200
++++ ksh-20120801/src/cmd/ksh93/edit/edit.c 2013-09-23 10:47:43.988937610 +0200
+@@ -1050,7 +1050,7 @@ int ed_getchar(register Edit_t *ep,int m
+ {
+ if(mode<=0 && -c == ep->e_intr)
+ {
+- sh_fault(SIGINT);
++ killpg(getpgrp(),SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+ }
+ if(mode<=0 && ep->sh->st.trap[SH_KEYTRAP])
+
diff --git a/source/ap/ksh93/patches/ksh-20120801-lexfix.patch b/source/ap/ksh93/patches/ksh-20120801-lexfix.patch
new file mode 100644
index 000000000..9150da80d
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-lexfix.patch
@@ -0,0 +1,56 @@
+diff -up ksh-20120801/src/cmd/ksh93/edit/edit.c.trajfiks ksh-20120801/src/cmd/ksh93/edit/edit.c
+--- ksh-20120801/src/cmd/ksh93/edit/edit.c.trajfiks 2012-08-02 00:18:19.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/edit/edit.c 2014-02-06 12:12:11.570942651 +0100
+@@ -53,6 +53,7 @@
+
+ static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
+ static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
++static char *savelex;
+
+
+
+@@ -232,6 +233,8 @@ int tty_set(int fd, int action, struct t
+ void tty_cooked(register int fd)
+ {
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
++ if(ep->sh->st.trap[SH_KEYTRAP] && savelex)
++ memcpy(ep->sh->lex_context,savelex,ep->sh->lexsize);
+ ep->e_keytrap = 0;
+ if(ep->e_raw==0)
+ return;
+@@ -783,6 +786,13 @@ void ed_setup(register Edit_t *ep, int f
+ ep->e_lbuf[n] = *pp++;
+ ep->e_default = 0;
+ }
++ if(ep->sh->st.trap[SH_KEYTRAP])
++ {
++ if(!savelex)
++ savelex = (char*)malloc(shp->lexsize);
++ if(savelex)
++ memcpy(savelex, ep->sh->lex_context, ep->sh->lexsize);
++ }
+ }
+
+ static void ed_putstring(register Edit_t *ep, const char *str)
+diff -up ksh-20120801/src/cmd/ksh93/include/defs.h.trajfiks ksh-20120801/src/cmd/ksh93/include/defs.h
+--- ksh-20120801/src/cmd/ksh93/include/defs.h.trajfiks 2014-02-06 12:18:13.149091836 +0100
++++ ksh-20120801/src/cmd/ksh93/include/defs.h 2014-02-06 12:18:13.175091784 +0100
+@@ -224,6 +224,7 @@ struct shared
+ int xargexit; \
+ int nenv; \
+ mode_t mask; \
++ int lexsize; \
+ Env_t *env; \
+ void *init_context; \
+ void *mac_context; \
+diff -up ksh-20120801/src/cmd/ksh93/sh/lex.c.trajfiks ksh-20120801/src/cmd/ksh93/sh/lex.c
+--- ksh-20120801/src/cmd/ksh93/sh/lex.c.trajfiks 2014-02-06 12:19:13.587950320 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/lex.c 2014-02-06 12:19:13.623950219 +0100
+@@ -268,6 +268,7 @@ Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp
+ {
+ lp = (Lex_t*)newof(0,Lex_t,1,0);
+ lp->sh = sp;
++ sp->lexsize = sizeof(Lex_t);
+ }
+ fcnotify(lex_advance,lp);
+ lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
diff --git a/source/ap/ksh93/patches/ksh-20120801-locking.patch b/source/ap/ksh93/patches/ksh-20120801-locking.patch
new file mode 100644
index 000000000..189d254d5
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-locking.patch
@@ -0,0 +1,26 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/jobs.h.locking ksh-20120801/src/cmd/ksh93/include/jobs.h
+--- ksh-20120801/src/cmd/ksh93/include/jobs.h.locking 2014-06-27 15:51:07.144923719 +0200
++++ ksh-20120801/src/cmd/ksh93/include/jobs.h 2014-06-27 15:52:56.463272276 +0200
+@@ -149,15 +149,18 @@ extern struct jobs job;
+ #define vmbusy() 0
+ #endif
+
+-#define job_lock() (job.in_critical++)
++#define asoincint(p) __sync_fetch_and_add(p,1)
++#define asodecint(p) __sync_fetch_and_sub(p,1)
++
++#define job_lock() asoincint(&job.in_critical)
+ #define job_unlock() \
+ do { \
+ int sig; \
+- if (!--job.in_critical && (sig = job.savesig)) \
++ if (asodecint(&job.in_critical)==1 && (sig = job.savesig)) \
+ { \
+- if (!job.in_critical++ && !vmbusy()) \
++ if (!asoincint(&job.in_critical) && !vmbusy()) \
+ job_reap(sig); \
+- job.in_critical--; \
++ asodecint(&job.in_critical); \
+ } \
+ } while(0)
+
diff --git a/source/ap/ksh93/patches/ksh-20120801-macro.patch b/source/ap/ksh93/patches/ksh-20120801-macro.patch
new file mode 100644
index 000000000..ca8024ef7
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-macro.patch
@@ -0,0 +1,205 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/io.h.macro ksh-20120801/src/cmd/ksh93/include/io.h
+--- ksh-20120801/src/cmd/ksh93/include/io.h.macro 2012-07-18 16:12:38.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/include/io.h 2013-07-04 16:14:05.809595966 +0200
+@@ -81,6 +81,7 @@ extern void sh_iosave(Shell_t *, int,in
+ extern int sh_iovalidfd(Shell_t*, int);
+ extern int sh_inuse(Shell_t*, int);
+ extern void sh_iounsave(Shell_t*);
++extern void iounpipe(Shell_t*);
+ extern int sh_chkopen(const char*);
+ extern int sh_ioaccess(int,int);
+ extern int sh_devtofd(const char*);
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.macro ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.macro 2013-07-04 16:14:05.783595751 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2013-07-04 16:15:46.673432991 +0200
+@@ -171,7 +171,7 @@ void sh_subfork(void)
+ {
+ register struct subshell *sp = subshell_data;
+ Shell_t *shp = sp->shp;
+- int curenv = shp->curenv;
++ int curenv = shp->curenv, comsub=shp->comsub;
+ pid_t pid;
+ char *trap = shp->st.trapcom[0];
+ if(trap)
+@@ -204,7 +204,7 @@ void sh_subfork(void)
+ shp->comsub = 0;
+ SH_SUBSHELLNOD->nvalue.s = 0;
+ sp->subpid=0;
+- shp->st.trapcom[0] = trap;
++ shp->st.trapcom[0] = (comsub==2?NULL:trap);
+ shp->savesig = 0;
+ }
+ }
+@@ -743,7 +743,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ fchdir(shp->pwdfd);
+ }
+ shp->subshare = sp->subshare;
+- shp->comsub = sp->comsub;
+ shp->subdup = sp->subdup;
+ #if SHOPT_COSHELL
+ shp->coshell = sp->coshell;
+@@ -773,7 +772,12 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ if(nsig>0)
+ kill(getpid(),nsig);
+ if(sp->subpid)
++ {
+ job_wait(sp->subpid);
++ if(comsub>1)
++ iounpipe(shp);
++ }
++ shp->comsub = sp->comsub;
+ if(comsub && iop && sp->pipefd<0)
+ sfseek(iop,(off_t)0,SEEK_SET);
+ if(shp->trapnote)
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.macro ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.macro 2013-07-04 16:14:05.800595891 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2013-07-04 16:14:05.810595975 +0200
+@@ -102,11 +102,11 @@ struct funenv
+ * temp file.
+ */
+ static int subpipe[3],subdup,tsetio,usepipe;
+-static void iounpipe(Shell_t*);
++void iounpipe(Shell_t*);
+
+-static int iousepipe(Shell_t *shp)
++int iousepipe(Shell_t *shp)
+ {
+- int i;
++ int fd=sffileno(sfstdout),i,err=errno;
+ if(usepipe)
+ {
+ usepipe++;
+@@ -115,13 +115,18 @@ static int iousepipe(Shell_t *shp)
+ if(sh_rpipe(subpipe) < 0)
+ return(0);
+ usepipe++;
+- fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
+- subpipe[2] = sh_fcntl(1,F_DUPFD,10);
+- fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
++ if(shp->comsub!=1)
++ {
++ subpipe[2] = sh_fcntl(subpipe[1],F_DUPFD,10);
++ sh_close(subpipe[1]);
++ return(1);
++ }
++ subpipe[2] = sh_fcntl(fd,F_dupfd_cloexec,10);
+ shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
+- close(1);
+- fcntl(subpipe[1],F_DUPFD,1);
+- shp->fdstatus[1] = shp->fdstatus[subpipe[1]];
++ while(close(fd)<0 && errno==EINTR)
++ errno = err;
++ fcntl(subpipe[1],F_DUPFD,fd);
++ shp->fdstatus[1] = shp->fdstatus[subpipe[1]]&~IOCLEX;
+ sh_close(subpipe[1]);
+ if(subdup=shp->subdup) for(i=0; i < 10; i++)
+ {
+@@ -135,14 +140,23 @@ static int iousepipe(Shell_t *shp)
+ return(1);
+ }
+
+-static void iounpipe(Shell_t *shp)
++void iounpipe(Shell_t *shp)
+ {
+- int n;
++ int fd=sffileno(sfstdout),n,err=errno;
+ char buff[SF_BUFSIZE];
+- close(1);
+- fcntl(subpipe[2], F_DUPFD, 1);
+- shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
++ if(!usepipe)
++ return;
+ --usepipe;
++ if(shp->comsub>1)
++ {
++ sh_close(subpipe[2]);
++ while(read(subpipe[0],buff,sizeof(buff))>0);
++ goto done;
++ }
++ while(close(fd)<0 && errno==EINTR)
++ errno = err;
++ fcntl(subpipe[2], F_DUPFD, fd);
++ shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
+ if(subdup) for(n=0; n < 10; n++)
+ {
+ if(subdup&(1<<n))
+@@ -174,6 +188,7 @@ static void iounpipe(Shell_t *shp)
+ else if(errno!=EINTR)
+ break;
+ }
++done:
+ sh_close(subpipe[0]);
+ subpipe[0] = -1;
+ tsetio = 0;
+@@ -725,7 +740,7 @@ static void unset_instance(Namval_t *nq,
+ }
+
+ #if SHOPT_COSHELL
+-uintmax_t coused;
++static uintmax_t coused;
+ /*
+ * print out function definition
+ */
+@@ -1619,10 +1634,14 @@ int sh_exec(register const Shnode_t *t,
+ if(shp->subshell)
+ {
+ sh_subtmpfile(shp);
+- if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
+- unpipe=iousepipe(shp);
+ if((type&(FAMP|TFORK))==(FAMP|TFORK))
+- sh_subfork();
++ {
++ if(shp->comsub && !(shp->fdstatus[1]&IONOSEEK))
++ {
++ unpipe = iousepipe(shp);
++ sh_subfork();
++ }
++ }
+ }
+ no_fork = !ntflag && !(type&(FAMP|FPOU)) && !shp->subshell &&
+ !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) &&
+@@ -3495,8 +3514,7 @@ static void sh_funct(Shell_t *shp,Namval
+ struct funenv fun;
+ char *fname = nv_getval(SH_FUNNAMENOD);
+ struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
+- int level, pipepid=shp->pipepid, comsub=shp->comsub;
+- shp->comsub = 0;
++ int level, pipepid=shp->pipepid;
+ shp->pipepid = 0;
+ sh_stats(STAT_FUNCT);
+ if(!lp->hdr.disc)
+@@ -3539,7 +3557,6 @@ static void sh_funct(Shell_t *shp,Namval
+ lp->maxlevel = level;
+ SH_LEVELNOD->nvalue.s = lp->maxlevel;
+ shp->last_root = nv_dict(DOTSHNOD);
+- shp->comsub = comsub;
+ #if 0
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+ #else
+diff -up ksh-20120801/src/cmd/ksh93/sh/macro.c.orig ksh-20120801/src/cmd/ksh93/sh/macro.c
+--- ksh-20120801/src/cmd/ksh93/sh/macro.c.orig 2012-06-29 20:05:47.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/macro.c 2013-08-12 18:06:17.291843164 +0200
+@@ -2152,6 +2152,11 @@ static void comsubst(Mac_t *mp,register
+ mp->ifsp = nv_getval(np);
+ stkset(stkp,savptr,savtop);
+ newlines = 0;
++ if(type/*==3 - don't break `` vs $() */ && mp->shp->spid)
++ {
++ job_wait(mp->shp->spid);
++ mp->shp->spid = 0;
++ }
+ sfsetbuf(sp,(void*)sp,0);
+ bufsize = sfvalue(sp);
+ /* read command substitution output and put on stack or here-doc */
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.orig ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.orig 2013-08-12 18:06:57.567497226 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2013-08-12 18:20:36.443454280 +0200
+@@ -1734,6 +1734,8 @@ int sh_exec(register const Shnode_t *t,
+ nlock--;
+ job_unlock();
+ }
++ if(shp->subshell)
++ shp->spid = parent;
+ if(type&FPCL)
+ sh_close(shp->inpipe[0]);
+ if(type&(FCOOP|FAMP))
diff --git a/source/ap/ksh93/patches/ksh-20120801-manfix4.patch b/source/ap/ksh93/patches/ksh-20120801-manfix4.patch
new file mode 100644
index 000000000..635544518
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-manfix4.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh.1.manfix4 ksh-20120801/src/cmd/ksh93/sh.1
+--- ksh-20120801/src/cmd/ksh93/sh.1.manfix4 2014-05-22 12:04:51.593750721 +0200
++++ ksh-20120801/src/cmd/ksh93/sh.1 2014-05-22 12:05:32.561556452 +0200
+@@ -4147,7 +4147,7 @@ command are ignored if the command is fo
+ .B &
+ and the
+ .B monitor
+-option is not active.
++option is active.
+ Otherwise, signals have the values
+ inherited by the shell from its parent
+ (but see also
diff --git a/source/ap/ksh93/patches/ksh-20120801-memlik.patch b/source/ap/ksh93/patches/ksh-20120801-memlik.patch
new file mode 100644
index 000000000..31f1eb998
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-memlik.patch
@@ -0,0 +1,37 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/array.c.memlik ksh-20120801/src/cmd/ksh93/sh/array.c
+--- ksh-20120801/src/cmd/ksh93/sh/array.c.memlik 2012-06-07 00:00:42.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/array.c 2013-06-11 16:52:47.557123973 +0200
+@@ -1701,7 +1701,11 @@ void *nv_associative(register Namval_t *
+ ap->header.scope = 0;
+ }
+ else
+- dtclose(ap->header.table);
++ {
++ if((ap->header.nelem&ARRAY_MASK)==0 && (ap->cur=nv_search("0",ap->header.table,0)))
++ nv_associative(np,(char*)0,NV_ADELETE);
++ dtclose(ap->header.table);
++ }
+ return((void*)ap);
+ case NV_ANEXT:
+ if(!ap->pos)
+diff -up ksh-20120801/src/cmd/ksh93/sh/name.c.memlik ksh-20120801/src/cmd/ksh93/sh/name.c
+--- ksh-20120801/src/cmd/ksh93/sh/name.c.memlik 2012-07-23 18:21:57.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/name.c 2013-06-11 16:19:41.036648218 +0200
+@@ -2465,6 +2465,8 @@ static void table_unset(Shell_t *shp, re
+ }
+ }
+ npnext = (Namval_t*)dtnext(root,np);
++ if(nv_arrayptr(np))
++ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ _nv_unset(np,flags);
+ nv_delete(np,root,0);
+ }
+@@ -3326,7 +3328,7 @@ int nv_rename(register Namval_t *np, int
+ shp->last_root = last_root;
+ if(flags&NV_MOVE)
+ {
+- if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)))
++ if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && !ap->fun)
+ ap->nelem++;
+ }
+ if((nv_arrayptr(nr) && !arraynr) || nv_isvtree(nr))
diff --git a/source/ap/ksh93/patches/ksh-20120801-memlik3.patch b/source/ap/ksh93/patches/ksh-20120801-memlik3.patch
new file mode 100644
index 000000000..9df57d2ec
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-memlik3.patch
@@ -0,0 +1,76 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/name.h.memlik3 ksh-20120801/src/cmd/ksh93/include/name.h
+--- ksh-20120801/src/cmd/ksh93/include/name.h.memlik3 2012-05-10 18:33:41.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/include/name.h 2014-01-22 14:14:32.774483776 +0100
+@@ -215,7 +215,7 @@ extern Namval_t *nv_mount(Namval_t*, co
+ extern Namval_t *nv_arraychild(Namval_t*, Namval_t*, int);
+ extern int nv_compare(Dt_t*, Void_t*, Void_t*, Dtdisc_t*);
+ extern void nv_outnode(Namval_t*,Sfio_t*, int, int);
+-extern int nv_subsaved(Namval_t*);
++extern int nv_subsaved(Namval_t*,int);
+ extern void nv_typename(Namval_t*, Sfio_t*);
+ extern void nv_newtype(Namval_t*);
+ extern int nv_istable(Namval_t*);
+diff -up ksh-20120801/src/cmd/ksh93/sh/name.c.memlik3 ksh-20120801/src/cmd/ksh93/sh/name.c
+--- ksh-20120801/src/cmd/ksh93/sh/name.c.memlik3 2014-01-22 14:14:32.751483987 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/name.c 2014-01-22 14:14:32.775483767 +0100
+@@ -1297,7 +1297,7 @@ void nv_delete(Namval_t* np, Dt_t *root,
+ {
+ if(dtdelete(root,np))
+ {
+- if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np)))
++ if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np,flags&NV_TABLE)))
+ free((void*)np);
+ }
+ #if 0
+@@ -2461,14 +2461,14 @@ static void table_unset(Shell_t *shp, re
+ {
+ _nv_unset(nq,flags);
+ npnext = (Namval_t*)dtnext(root,nq);
+- nv_delete(nq,root,0);
++ nv_delete(nq,root,NV_TABLE);
+ }
+ }
+ npnext = (Namval_t*)dtnext(root,np);
+ if(nv_arrayptr(np))
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ _nv_unset(np,flags);
+- nv_delete(np,root,0);
++ nv_delete(np,root,NV_TABLE);
+ }
+ }
+
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.memlik3 ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.memlik3 2014-01-22 14:14:32.768483831 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2014-01-22 14:20:50.810236676 +0100
+@@ -218,16 +218,28 @@ void sh_subfork(void)
+ }
+ }
+
+-int nv_subsaved(register Namval_t *np)
++int nv_subsaved(register Namval_t *np,int table)
+ {
+ register struct subshell *sp;
+- register struct Link *lp;
++ register struct Link *lp, *lpprev;
+ for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
+ {
+- for(lp=sp->svar; lp; lp = lp->next)
++ lpprev = 0;
++ for(lp=sp->svar; lp; lpprev=lp, lp=lp->next)
+ {
+ if(lp->node==np)
++ {
++ if(table&NV_TABLE)
++ {
++ if(lpprev)
++ lpprev->next = lp->next;
++ else
++ sp->svar = lp->next;
++ free((void*)np);
++ free((void*)lp);
++ }
+ return(1);
++ }
+ }
+ }
+ return(0);
diff --git a/source/ap/ksh93/patches/ksh-20120801-mlikfiks.patch b/source/ap/ksh93/patches/ksh-20120801-mlikfiks.patch
new file mode 100644
index 000000000..fbf016ae1
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-mlikfiks.patch
@@ -0,0 +1,34 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/lex.c.mlikfiks ksh-20120801/src/cmd/ksh93/sh/lex.c
+--- ksh-20120801/src/cmd/ksh93/sh/lex.c.mlikfiks 2013-07-22 12:45:30.923170264 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/lex.c 2013-07-22 12:46:25.235556905 +0200
+@@ -2465,7 +2465,7 @@ static int alias_exceptf(Sfio_t *iop,int
+ if(dp!=handle)
+ sfdisc(iop,dp);
+ }
+- else if(type==SF_FINAL)
++ else if(type==SF_DPOP || type==SF_FINAL)
+ free((void*)ap);
+ goto done;
+ }
+diff -up ksh-20120801/src/cmd/ksh93/sh/path.c.mlikfiks ksh-20120801/src/cmd/ksh93/sh/path.c
+--- ksh-20120801/src/cmd/ksh93/sh/path.c.mlikfiks 2013-07-22 12:47:23.149990016 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/path.c 2013-07-22 12:48:33.363283877 +0200
+@@ -613,6 +613,7 @@ static void funload(Shell_t *shp,int fno
+ }
+ while((rp=dtnext(shp->fpathdict,rp)) && strcmp(pname,rp->fname)==0);
+ sh_close(fno);
++ free((void*)pname);
+ return;
+ }
+ sh_onstate(SH_NOLOG);
+diff -up ksh-20120801/src/cmd/ksh93/sh/macro.c.aliasfix ksh-20120801/src/cmd/ksh93/sh/macro.c
+--- ksh-20120801/src/cmd/ksh93/sh/macro.c.aliasfix 2013-07-29 15:03:45.841680475 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/macro.c 2013-07-29 15:04:23.871336821 +0200
+@@ -2085,6 +2085,7 @@ static void comsubst(Mac_t *mp,register
+ }
+ sfputc(stkp,c);
+ }
++ sfputc(stkp,' ');
+ c = stktell(stkp);
+ str=stkfreeze(stkp,1);
+ /* disable verbose and don't save in history file */
diff --git a/source/ap/ksh93/patches/ksh-20120801-mtty.patch b/source/ap/ksh93/patches/ksh-20120801-mtty.patch
new file mode 100644
index 000000000..d992a8804
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-mtty.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.mtty ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.mtty 2014-01-22 16:52:06.441608750 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2014-01-22 16:52:06.485608361 +0100
+@@ -3163,7 +3169,7 @@ pid_t _sh_fork(Shell_t *shp,register pid
+ * completed. Make parent the job group id.
+ */
+ if(postid==0)
+- job.curpgid = parent;
++ job.curpgid = job.jobcontrol?parent:getpid();
+ if(job.jobcontrol || (flags&FAMP))
+ {
+ if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
diff --git a/source/ap/ksh93/patches/ksh-20120801-noexeccdfix.patch b/source/ap/ksh93/patches/ksh-20120801-noexeccdfix.patch
new file mode 100644
index 000000000..47128e09b
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-noexeccdfix.patch
@@ -0,0 +1,40 @@
+From b8260293a8ed7849a358291faae7b58f4a05dcc9 Mon Sep 17 00:00:00 2001
+From: Kamil Dudka <kdudka@redhat.com>
+Date: Mon, 10 Nov 2014 18:23:34 +0100
+Subject: [PATCH] Resolves: #1160923 - handle failure of fchdir()
+
+... and chdir()
+---
+ src/cmd/ksh93/bltins/cd_pwd.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c
+index a972da6..c20959c 100644
+--- a/src/cmd/ksh93/bltins/cd_pwd.c
++++ b/src/cmd/ksh93/bltins/cd_pwd.c
+@@ -329,18 +329,20 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
+ if(newdirfd >=0)
+ {
+ /* chdir for directories on HSM/tapeworms may take minutes */
+- if(fchdir(newdirfd) >= 0)
++ if((rval=fchdir(newdirfd)) >= 0)
+ {
+ if(shp->pwdfd >= 0)
+ sh_close(shp->pwdfd);
+ shp->pwdfd=newdirfd;
+ goto success;
+ }
++ else
++ sh_close(newdirfd);
+ }
+ #ifndef O_SEARCH
+ else
+ {
+- if(chdir(dir) >=0)
++ if((rval=chdir(dir)) >=0)
+ {
+ if(shp->pwdfd >= 0)
+ {
+--
+2.1.0
+
diff --git a/source/ap/ksh93/patches/ksh-20120801-nohupfork.patch b/source/ap/ksh93/patches/ksh-20120801-nohupfork.patch
new file mode 100644
index 000000000..20cdeb905
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-nohupfork.patch
@@ -0,0 +1,11 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.nohupfork ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.nohupfork 2015-08-27 14:25:38.925378019 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2015-08-27 14:30:42.267058087 +0200
+@@ -2067,6 +2067,7 @@ int sh_exec(register const Shnode_t *t,
+ {
+ sh_exec(t->par.partre,flags);
+ shp->st.trapcom[0]=0;
++ sh_offoption(SH_INTERACTIVE);
+ sh_done(shp,0);
+ }
+ }
diff --git a/source/ap/ksh93/patches/ksh-20120801-nomulti.patch b/source/ap/ksh93/patches/ksh-20120801-nomulti.patch
new file mode 100644
index 000000000..5d7e7a4e2
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-nomulti.patch
@@ -0,0 +1,11 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.nomulti ksh-20120801/src/cmd/ksh93/sh/init.c
+--- ksh-20120801/src/cmd/ksh93/sh/init.c.nomulti 2013-10-08 20:46:46.202471042 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2013-10-08 20:46:57.912331483 +0200
+@@ -1446,7 +1446,6 @@ Shell_t *sh_init(register int argc,regis
+ #endif /* SHOPT_TIMEOUT */
+ /* initialize jobs table */
+ job_clear();
+- sh_onoption(SH_MULTILINE);
+ if(argc>0)
+ {
+ /* check for restricted shell */
diff --git a/source/ap/ksh93/patches/ksh-20120801-oldenvinit.patch b/source/ap/ksh93/patches/ksh-20120801-oldenvinit.patch
new file mode 100644
index 000000000..8ee086314
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-oldenvinit.patch
@@ -0,0 +1,95 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.fixset ksh-20120801/src/cmd/ksh93/sh/init.c
+--- ksh-20120801/src/cmd/ksh93/sh/init.c.fixset 2014-11-03 15:45:36.510997271 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2014-11-03 16:20:44.398917280 +0100
+@@ -2003,8 +2003,91 @@ static Dt_t *inittree(Shell_t *shp,const
+ * skip over items that are not name-value pairs
+ */
+
++
+ static void env_init(Shell_t *shp)
+ {
++ register char *cp;
++ register Namval_t *np;
++ register char **ep=environ;
++ register char *next=0;
++#ifdef _ENV_H
++ shp->env = env_open(environ,3);
++ env_delete(shp->env,"_");
++#endif
++ if(ep)
++ {
++ while(cp= *ep++)
++ {
++ if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]=='=')
++ next = cp+4;
++ else if(np=nv_open(cp,shp->var_tree,(NV_EXPORT|NV_IDENT|NV_ASSIGN|NV_NOFAIL)))
++ {
++ nv_onattr(np,NV_IMPORT);
++ np->nvenv = cp;
++ nv_close(np);
++ }
++ else /* swap with front */
++ {
++ ep[-1] = environ[shp->nenv];
++ environ[shp->nenv++] = cp;
++ }
++ }
++ while(cp=next)
++ {
++ if(next = strchr(++cp,'='))
++ *next = 0;
++ np = nv_search(cp+2,shp->var_tree,NV_ADD);
++ if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
++ {
++ int flag = *(unsigned char*)cp-' ';
++ int size = *(unsigned char*)(cp+1)-' ';
++ if((flag&NV_INTEGER) && size==0)
++ {
++ /* check for floating*/
++ char *ep,*val = nv_getval(np);
++ strtol(val,&ep,10);
++ if(*ep=='.' || *ep=='e' || *ep=='E')
++ {
++ char *lp;
++ flag |= NV_DOUBLE;
++ if(*ep=='.')
++ {
++ strtol(ep+1,&lp,10);
++ if(*lp)
++ ep = lp;
++ }
++ if(*ep && *ep!='.')
++ {
++ flag |= NV_EXPNOTE;
++ size = ep-val;
++ }
++ else
++ size = strlen(ep);
++ size--;
++ }
++ }
++ nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
++ }
++ else
++ cp += 2;
++ }
++ }
++#ifdef _ENV_H
++ env_delete(shp->env,e_envmarker);
++#endif
++ if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
++ {
++ nv_offattr(PWDNOD,NV_TAGGED);
++ path_pwd(shp,0);
++ }
++ if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
++ sh_onoption(SH_RESTRICTED); /* restricted shell */
++ return;
++}
++
++
++static void env_init_backup(Shell_t *shp)
++{
+ register char *cp;
+ register Namval_t *np,*mp;
+ register char **ep=environ;
diff --git a/source/ap/ksh93/patches/ksh-20120801-retfix.patch b/source/ap/ksh93/patches/ksh-20120801-retfix.patch
new file mode 100644
index 000000000..bcb5b3326
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-retfix.patch
@@ -0,0 +1,20 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.retfix ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.retfix 2014-09-01 13:50:02.956085721 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2014-09-01 13:54:01.104818416 +0200
+@@ -652,6 +652,16 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ }
+ else
+ {
++ if(comsub!=1 && shp->spid)
++ {
++ int c = shp->exitval;
++ job_wait(shp->spid);
++ shp->exitval = c;
++ exitset();
++ if(shp->pipepid==shp->spid)
++ shp->spid = 0;
++ shp->pipepid = 0;
++ }
+ job.hack1_waitall=0;
+ /* move tmp file to iop and restore sfstdout */
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
diff --git a/source/ap/ksh93/patches/rmdirfix.patch b/source/ap/ksh93/patches/ksh-20120801-rmdirfix.patch
index 132de7dba..ae9dfd72d 100644
--- a/source/ap/ksh93/patches/rmdirfix.patch
+++ b/source/ap/ksh93/patches/ksh-20120801-rmdirfix.patch
@@ -69,7 +69,7 @@ diff -up ksh20120801/src/cmd/ksh93/sh/subshell.c.orig ksh20120801/src/cmd/ksh93/
- sp->pwdfd = n;
- if(n<10)
- {
-- sp->pwdfd = fcntl(n,F_DUPFD,10);
+- sp->pwdfd = sh_fcntl(n,F_DUPFD,10);
- close(n);
- }
- if(sp->pwdfd>0)
diff --git a/source/ap/ksh93/patches/ksh-20120801-roundit.patch b/source/ap/ksh93/patches/ksh-20120801-roundit.patch
new file mode 100644
index 000000000..015bc85cd
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-roundit.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/lib/libast/sfio/sfcvt.c.rounditgood ksh-20120801/src/lib/libast/sfio/sfcvt.c
+--- ksh-20120801/src/lib/libast/sfio/sfcvt.c.rounditgood 2014-02-27 16:45:54.630161032 +0100
++++ ksh-20120801/src/lib/libast/sfio/sfcvt.c 2014-02-27 16:45:54.658161205 +0100
+@@ -491,7 +491,7 @@ int format; /* conversion format */
+ *decpt += 1;
+ if(!(format&SFFMT_EFORMAT))
+ { /* add one more 0 for %f precision */
+- ep[-1] = '0';
++ if(ep-sp>1) ep[-1] = '0';
+ ep += 1;
+ }
+ }
diff --git a/source/ap/ksh93/patches/ksh-20120801-sufix.patch b/source/ap/ksh93/patches/ksh-20120801-sufix.patch
new file mode 100644
index 000000000..b820e1cfc
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-sufix.patch
@@ -0,0 +1,11 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/io.c.sufix ksh-20120801/src/cmd/ksh93/sh/io.c
+--- ksh-20120801/src/cmd/ksh93/sh/io.c.sufix 2014-04-08 14:30:14.412343555 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/io.c 2014-04-08 14:31:18.403876587 +0200
+@@ -2144,6 +2144,7 @@ static int io_prompt(Shell_t *shp,Sfio_t
+ }
+ #endif /* TIOCLBIC */
+ cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
++ shp->exitval = 0;
+ for(;c= *cp;cp++)
+ {
+ if(c==HIST_CHAR)
diff --git a/source/ap/ksh93/patches/ksh-20120801-tpstl.patch b/source/ap/ksh93/patches/ksh-20120801-tpstl.patch
new file mode 100644
index 000000000..41e17c87d
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-tpstl.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.tpstl ksh-20120801/src/cmd/ksh93/sh/init.c
+--- ksh-20120801/src/cmd/ksh93/sh/init.c.tpstl 2014-04-03 11:21:25.395547276 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2014-04-03 11:26:03.908867208 +0200
+@@ -332,7 +332,7 @@ static Namfun_t *clone_optindex(Namval_t
+ /* Trap for restricted variables FPATH, PATH, SHELL, ENV */
+ static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+ {
+- Shell_t *shp = nv_shell(np);
++ Shell_t *shp = sh_getinterp();
+ int path_scoped = 0, fpath_scoped=0;
+ Pathcomp_t *pp;
+ char *name = nv_name(np);
diff --git a/source/ap/ksh93/patches/ksh-20120801-trapcom.patch b/source/ap/ksh93/patches/ksh-20120801-trapcom.patch
new file mode 100644
index 000000000..a900b5437
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-trapcom.patch
@@ -0,0 +1,47 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.orig ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.orig 2014-08-23 20:20:24.676186573 -0300
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2014-08-23 20:29:00.772151283 -0300
+@@ -481,12 +481,12 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ {
+ struct subshell sub_data;
+ register struct subshell *sp = &sub_data;
+- int jmpval,nsig=0,duped=0;
++ int jmpval,isig,nsig=0,duped=0;
+ long savecurenv = shp->curenv;
+ int savejobpgid = job.curpgid;
+ int *saveexitval = job.exitval;
+ int16_t subshell;
+- char *savsig;
++ char **savsig;
+ Sfio_t *iop=0;
+ struct checkpt buff;
+ struct sh_scoped savst;
+@@ -561,10 +561,13 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ /* save trap table */
+ shp->st.otrapcom = 0;
+ shp->st.otrap = savst.trap;
+- if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
++ if((nsig=shp->st.trapmax)>0 || shp->st.trapcom[0])
+ {
+- nsig += sizeof(char*);
+- memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
++ ++nsig;
++ savsig = malloc(nsig * sizeof(char*));
++ /* contents of shp->st.st.trapcom may change */
++ for (isig = 0; isig < nsig; ++isig)
++ savsig[isig] = shp->st.trapcom[isig] ? strdup(shp->st.trapcom[isig]) : NULL;
+ /* this nonsense needed for $(trap) */
+ shp->st.otrapcom = (char**)savsig;
+ }
+@@ -729,7 +732,10 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ shp->st.otrap = 0;
+ if(nsig)
+ {
+- memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
++ for (isig = 0; isig < nsig; ++isig)
++ if (shp->st.trapcom[isig])
++ free(shp->st.trapcom[isig]);
++ memcpy((char*)&shp->st.trapcom[0],savsig,nsig*sizeof(char*));
+ free((void*)savsig);
+ }
+ shp->options = sp->options;
diff --git a/source/ap/ksh93/patches/ksh-20120801-xufix.patch b/source/ap/ksh93/patches/ksh-20120801-xufix.patch
new file mode 100644
index 000000000..496e0bf77
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20120801-xufix.patch
@@ -0,0 +1,29 @@
+diff -up ksh-20120801/src/cmd/ksh93/bltins/typeset.c.xufix ksh-20120801/src/cmd/ksh93/bltins/typeset.c
+--- ksh-20120801/src/cmd/ksh93/bltins/typeset.c.xufix 2015-02-03 14:47:23.266022137 +0100
++++ ksh-20120801/src/cmd/ksh93/bltins/typeset.c 2015-02-03 14:47:23.308022046 +0100
+@@ -93,6 +93,8 @@ int b_readonly(int argc,char *argv[],
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ tdata.aflag = '-';
++ /* do not change size */
++ tdata.argnum = -1;
+ while((flag = optget(argv,*command=='e'?sh_optexport:sh_optreadonly))) switch(flag)
+ {
+ case 'p':
+diff -up ksh-20120801/src/cmd/ksh93/sh/name.c.xufix ksh-20120801/src/cmd/ksh93/sh/name.c
+--- ksh-20120801/src/cmd/ksh93/sh/name.c.xufix 2015-02-03 14:47:23.281022105 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/name.c 2015-02-03 14:52:08.768404194 +0100
+@@ -3019,10 +3019,12 @@ void nv_newattr (register Namval_t *np,
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+- if((n^newatts)==NV_EXPORT)
++ if((n^newatts)==NV_EXPORT && size==-1)
+ return;
+ }
+ oldsize = nv_size(np);
++ if (size == -1)
++ size = oldsize;
+ if((size==oldsize|| (n&NV_INTEGER)) && !trans && ((n^newatts)&~NV_NOCHANGE)==0)
+ {
+ if(size)
diff --git a/source/ap/ksh93/patches/ksh-20130613-cdfix4.patch b/source/ap/ksh93/patches/ksh-20130613-cdfix4.patch
new file mode 100644
index 000000000..5b2901750
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20130613-cdfix4.patch
@@ -0,0 +1,15 @@
+diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix4 ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c
+--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix4 2014-08-26 15:24:57.276953822 +0200
++++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2014-08-26 15:25:34.738770361 +0200
+@@ -143,9 +143,9 @@ int sh_diropenat(Shell_t *shp, int dir,
+ }
+
+ /* Move fd to a number > 10 and *register* the fd number with the shell */
+- shfd = sh_fcntl(fd, F_dupfd_cloexec, 10);
++ shfd = fcntl(fd, F_dupfd_cloexec, 10);
+ savederrno=errno;
+- sh_close(fd);
++ close(fd);
+ errno=savederrno;
+ return(shfd);
+ }
diff --git a/source/ap/ksh93/patches/ksh-20130628-longer.patch b/source/ap/ksh93/patches/ksh-20130628-longer.patch
new file mode 100644
index 000000000..4761a3476
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20130628-longer.patch
@@ -0,0 +1,58 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/defs.h.longer ksh-20120801/src/cmd/ksh93/include/defs.h
+--- ksh-20120801/src/cmd/ksh93/include/defs.h.longer 2012-06-25 20:47:47.000000000 +0200
++++ ksh-20120801/src/cmd/ksh93/include/defs.h 2013-07-08 17:33:42.238534376 +0200
+@@ -162,8 +162,8 @@ struct shared
+ Namval_t *prev_table; /* previous table used in nv_open */ \
+ Sfio_t *outpool; /* ouput stream pool */ \
+ long timeout; /* read timeout */ \
+- short curenv; /* current subshell number */ \
+- short jobenv; /* subshell number for jobs */ \
++ long curenv; /* current subshell number */ \
++ long jobenv; /* subshell number for jobs */ \
+ int infd; /* input file descriptor */ \
+ short nextprompt; /* next prompt is PS<nextprompt> */ \
+ short poolfiles; \
+diff -up ksh-20120801/src/cmd/ksh93/include/jobs.h.longer ksh-20120801/src/cmd/ksh93/include/jobs.h
+--- ksh-20120801/src/cmd/ksh93/include/jobs.h.longer 2011-12-19 13:36:37.000000000 +0100
++++ ksh-20120801/src/cmd/ksh93/include/jobs.h 2013-07-08 17:32:52.881124147 +0200
+@@ -87,7 +87,7 @@ struct process
+ unsigned short p_exit; /* exit value or signal number */
+ unsigned short p_exitmin; /* minimum exit value for xargs */
+ unsigned short p_flag; /* flags - see below */
+- int p_env; /* subshell environment number */
++ long p_env; /* subshell environment number */
+ #ifdef JOBS
+ off_t p_name; /* history file offset for command */
+ struct termios p_stty; /* terminal state for job */
+diff -up ksh-20120801/src/cmd/ksh93/sh/jobs.c.longer ksh-20120801/src/cmd/ksh93/sh/jobs.c
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.longer ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.longer 2013-07-08 17:32:52.874124090 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2013-07-08 17:32:52.882124156 +0200
+@@ -98,7 +98,7 @@ static struct subshell
+ #endif /* SHOPT_COSHELL */
+ } *subshell_data;
+
+-static int subenv;
++static long subenv;
+
+
+ /*
+@@ -171,7 +171,8 @@ void sh_subfork(void)
+ {
+ register struct subshell *sp = subshell_data;
+ Shell_t *shp = sp->shp;
+- int curenv = shp->curenv, comsub=shp->comsub;
++ long curenv = shp->curenv;
++ int comsub=shp->comsub;
+ pid_t pid;
+ char *trap = shp->st.trapcom[0];
+ if(trap)
+@@ -461,7 +462,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ struct subshell sub_data;
+ register struct subshell *sp = &sub_data;
+ int jmpval,nsig=0,duped=0;
+- int savecurenv = shp->curenv;
++ long savecurenv = shp->curenv;
+ int savejobpgid = job.curpgid;
+ int *saveexitval = job.exitval;
+ int16_t subshell;
diff --git a/source/ap/ksh93/patches/ksh-20140301-fikspand.patch b/source/ap/ksh93/patches/ksh-20140301-fikspand.patch
new file mode 100644
index 000000000..9899392f4
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20140301-fikspand.patch
@@ -0,0 +1,12 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/expand.c.fikspand ksh-20120801/src/cmd/ksh93/sh/expand.c
+--- ksh-20120801/src/cmd/ksh93/sh/expand.c.fikspand 2010-11-24 05:46:30.000000000 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/expand.c 2014-05-22 12:55:46.252717371 +0200
+@@ -278,6 +278,8 @@ int path_generate(Shell_t *shp,struct ar
+ char comma, range=0;
+ int first, last, incr, count = 0;
+ char tmp[32], end[1];
++ if(!sh_isoption(SH_BRACEEXPAND))
++ return path_expand(shp,todo->argval,arghead);
+ todo->argchn.ap = 0;
+ again:
+ apin = ap = todo;
diff --git a/source/ap/ksh93/patches/ksh-20140415-hokaido.patch b/source/ap/ksh93/patches/ksh-20140415-hokaido.patch
new file mode 100644
index 000000000..5ff69279f
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20140415-hokaido.patch
@@ -0,0 +1,37 @@
+diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.hokaido ksh-20120801/src/cmd/ksh93/sh/xec.c
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c.hokaido 2014-09-18 14:41:57.696756230 +0200
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2014-09-18 14:43:55.439205247 +0200
+@@ -1633,12 +1633,20 @@ int sh_exec(register const Shnode_t *t,
+ #endif /* SHOPT_COSHELL */
+ if(shp->subshell)
+ {
++ int comsubsave = shp->comsub;
++ if(comsubsave==1)
++ shp->comsub = 2;
+ sh_subtmpfile(shp);
++ shp->comsub = comsubsave;
++ if(shp->comsub==1 && (!(shp->fdstatus[1]&IONOSEEK)))
++ unpipe = iousepipe(shp);
++
+ if((type&(FAMP|TFORK))==(FAMP|TFORK))
+ {
+ if(shp->comsub && !(shp->fdstatus[1]&IONOSEEK))
+ {
+- unpipe = iousepipe(shp);
++ if (!unpipe)
++ unpipe = iousepipe(shp);
+ sh_subfork();
+ }
+ }
+@@ -2107,7 +2115,11 @@ int sh_exec(register const Shnode_t *t,
+ job.curjobid = 0;
+ if(shp->subshell)
+ {
++ int comsubsave = shp->comsub;
++ if(comsubsave==1)
++ shp->comsub = 2;
+ sh_subtmpfile(shp);
++ shp->comsub = comsubsave;
+ if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
+ iousepipe(shp);
+ }
diff --git a/source/ap/ksh93/patches/ksh-20140801-arraylen.patch b/source/ap/ksh93/patches/ksh-20140801-arraylen.patch
new file mode 100644
index 000000000..34c9b6bd9
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20140801-arraylen.patch
@@ -0,0 +1,11 @@
+--- ksh-20120801/src/cmd/ksh93/sh/xec.c 2015-04-02 10:55:26.228017873 -0400
++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2015-04-02 10:56:04.099017700 -0400
+@@ -1234,7 +1234,7 @@ int sh_exec(register const Shnode_t *t,
+ if((io||argn))
+ {
+ Shbltin_t *bp=0;
+- static char *argv[1];
++ static char *argv[2];
+ int tflags = 1;
+ if(np && nv_isattr(np,BLT_DCL))
+ tflags |= 2;
diff --git a/source/ap/ksh93/patches/ksh-20140929-safefd.patch b/source/ap/ksh93/patches/ksh-20140929-safefd.patch
new file mode 100644
index 000000000..80db20528
--- /dev/null
+++ b/source/ap/ksh93/patches/ksh-20140929-safefd.patch
@@ -0,0 +1,52 @@
+diff -up ksh-20120801/src/cmd/ksh93/include/io.h.safefd ksh-20120801/src/cmd/ksh93/include/io.h
+--- ksh-20120801/src/cmd/ksh93/include/io.h.safefd 2015-03-03 18:21:40.544732158 +0100
++++ ksh-20120801/src/cmd/ksh93/include/io.h 2015-03-03 18:22:16.284447849 +0100
+@@ -78,6 +78,7 @@ extern void sh_iorestore(Shell_t*,int,i
+ extern Sfio_t *sh_iostream(Shell_t*,int);
+ extern int sh_redirect(Shell_t*,struct ionod*,int);
+ extern void sh_iosave(Shell_t *, int,int,char*);
++extern int safefdnumber(Shell_t* shp, int sfd);
+ extern int sh_iovalidfd(Shell_t*, int);
+ extern int sh_inuse(Shell_t*, int);
+ extern void sh_iounsave(Shell_t*);
+diff -up ksh-20120801/src/cmd/ksh93/sh/io.c.safefd ksh-20120801/src/cmd/ksh93/sh/io.c
+--- ksh-20120801/src/cmd/ksh93/sh/io.c.safefd 2015-03-03 18:21:40.511732421 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/io.c 2015-03-03 18:21:40.544732158 +0100
+@@ -1724,6 +1724,25 @@ void sh_iosave(Shell_t *shp, register in
+ }
+ }
+
++int safefdnumber(Shell_t* shp, int sfd)
++{
++ register int fd;
++
++ while(1)
++ {
++ for(fd=0; fd < shp->topfd; fd++)
++ {
++ if (filemap[fd].save_fd==sfd || filemap[fd].orig_fd==sfd || (fcntl(sfd, F_GETFD) != -1 || errno != EBADF))
++ {
++ sfd++;
++ continue;
++ }
++ }
++ break;
++ }
++ return sfd;
++}
++
+ /*
+ * close all saved file descriptors
+ */
+diff -up ksh-20120801/src/cmd/ksh93/sh/subshell.c.safefd ksh-20120801/src/cmd/ksh93/sh/subshell.c
+--- ksh-20120801/src/cmd/ksh93/sh/subshell.c.safefd 2015-03-03 18:21:40.531732261 +0100
++++ ksh-20120801/src/cmd/ksh93/sh/subshell.c 2015-03-03 18:21:40.544732158 +0100
+@@ -673,7 +673,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
+ }
+ if(iop && sffileno(iop)==1)
+ {
+- int fd=sfsetfd(iop,3);
++ int fd=sfsetfd(iop,safefdnumber(shp,3));
+ if(fd<0)
+ {
+ shp->toomany = 1;