File ksh93-fdstatus.dif of Package ksh

| Fix for bnc#814135, bnc#808449, and bnc#835885
| - crash in bestreclaim() after traversing a memory block with a very large size (ksh)
| - set -k does not work properly with ksh-93t-13.17 and higher
| - Problem after update of ksh from ksh-93u-0.14.1 to ksh-93u-0.22.1
| This is a backport from the beta version ksh93v-2013-08-29
--- src/cmd/ksh93/bltins/read.c
+++ src/cmd/ksh93/bltins/read.c	2013-09-17 15:01:33.000000000 +0000
@@ -280,24 +280,25 @@ int sh_readline(register Shell_t *shp,ch
 	if(size || (flags>>D_FLAG))	/* delimiter not new-line or fixed size read */
 	{
 		if((shp->fdstatus[fd]&IOTTY) && !keytrap)
-			tty_raw(fd,1);
+			tty_raw(sffileno(iop),1);
 		if(!(flags&(N_FLAG|NN_FLAG)))
 		{
 			delim = ((unsigned)flags)>>D_FLAG;
 			ep->e_nttyparm.c_cc[VEOL] = delim;
 			ep->e_nttyparm.c_lflag |= ISIG;
-			tty_set(fd,TCSADRAIN,&ep->e_nttyparm);
+			tty_set(sffileno(iop),TCSADRAIN,&ep->e_nttyparm);
 		}
 #if defined(__linux__)
 		else if ((shp->fdstatus[fd]&(IOTTY|IONOSEEK))==0)
 		{
 			struct stat st;
-			if ((fstat(fd, &st) == 0) && S_ISFIFO(st.st_mode))
+			int fn = sffileno(iop);
+			if ((fstat(fn, &st) == 0) && S_ISFIFO(st.st_mode))
 			{
 				int fdflg;
-				if (((fdflg = fcntl(fd, F_GETFL)) != -1) && !(fdflg & O_NONBLOCK))
-					fcntl(fd, F_SETFL, fdflg|O_NONBLOCK);
-				shp->fdstatus[fd] |= IONOSEEK;
+				if (((fdflg = fcntl(fn, F_GETFL)) != -1) && !(fdflg & O_NONBLOCK))
+					fcntl(fn, F_SETFL, fdflg|O_NONBLOCK);
+				shp->fdstatus[fn] |= IONOSEEK;
 			}
 		}
 #endif
@@ -342,7 +343,7 @@ int sh_readline(register Shell_t *shp,ch
 		size = nv_size(np);
 	}
 	was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
-	if(fd==0)
+	if(sffileno(iop)==0)
 		was_share = (sfset(iop,SF_SHARE,shp->redir0!=2)&SF_SHARE)!=0;
 	if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
 	{
@@ -366,7 +367,7 @@ int sh_readline(register Shell_t *shp,ch
 		else
 			end = var + sizeof(buf) - 1;
 		up = cur = var;
-		if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
+		if((sfset(iop,SF_SHARE,1)&SF_SHARE) && sffileno(iop)!=0)
 			was_share = 1;
 		if(size==0)
 		{
@@ -473,7 +474,7 @@ int sh_readline(register Shell_t *shp,ch
 			timerdel(timeslot);
 		if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
 		{
-			if((c==size) && np->nvalue.cp && !nv_isarray(np))
+			if((c==size) && np->nvalue.cp && !nv_isarray(np) && !np->nvfun)
 				memcpy((char*)np->nvalue.cp,var,c);
 			else
 			{
@@ -819,7 +820,7 @@ done:
 		sfset(iop,SF_SHARE,0);
 	nv_close(np);
 	if((shp->fdstatus[fd]&IOTTY) && !keytrap)
-		tty_cooked(fd);
+		tty_cooked(sffileno(iop));
 	if(flags&S_FLAG)
 		hist_flush(shp->gd->hist_ptr);
 	if(jmpval > 1)
--- src/cmd/ksh93/bltins/trap.c
+++ src/cmd/ksh93/bltins/trap.c	2013-09-17 14:37:19.000000000 +0000
@@ -116,8 +116,7 @@ int	b_trap(int argc,char *argv[],Shbltin
 					continue;
 				}
 				shp->st.otrap = 0;
-				if(shp->st.trap[sig])
-					free(shp->st.trap[sig]);
+				arg = shp->st.trap[sig];
 				shp->st.trap[sig] = 0;
 				if(!clear && *action)
 					shp->st.trap[sig] = strdup(action);
@@ -128,6 +127,8 @@ int	b_trap(int argc,char *argv[],Shbltin
 					else
 						shp->trapnote = 0;
 				}
+				if(arg)
+					free(arg);
 				continue;
 			}
 			if(sig>shp->gd->sigmax)
--- src/cmd/ksh93/bltins/typeset.c
+++ src/cmd/ksh93/bltins/typeset.c	2013-09-13 16:26:49.000000000 +0000
@@ -533,6 +533,7 @@ static int     setall(char **argv,regist
 	char *last = 0;
 	int nvflags=(flag&(NV_ARRAY|NV_NOARRAY|NV_VARNAME|NV_IDENT|NV_ASSIGN|NV_STATIC|NV_MOVE));
 	int r=0, ref=0, comvar=(flag&NV_COMVAR),iarray=(flag&NV_IARRAY);
+	size_t len;
 	Shell_t *shp =tp->sh;
 	if(!shp->prefix)
 	{
@@ -579,7 +580,7 @@ static int     setall(char **argv,regist
 						np = sh_fsearch(shp,name,NV_ADD|HASH_NOSCOPE);
 					else
 #endif /* SHOPT_NAMESPACE */
-					np = nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
+					np = nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
 				}
 				else 
 				{
@@ -640,7 +641,10 @@ static int     setall(char **argv,regist
 				path_alias(np,path_absolute(shp,nv_name(np),NIL(Pathcomp_t*)));
 				continue;
 			}
-			np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&(NV_REF|NV_NOADD)==NV_REF))?NV_FARRAY:0));
+			if(shp->nodelist && (len=strlen(name)) && name[len-1]=='@')
+				np = *shp->nodelist++;
+			else
+				np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&(NV_REF|NV_NOADD)==NV_REF))?NV_FARRAY:0));
 			if(!np)
 				continue;
 			if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
@@ -676,7 +680,7 @@ static int     setall(char **argv,regist
 			}
 			if(!nv_isarray(np) && !strchr(name,'=') && !(shp->envlist  && nv_onlist(shp->envlist,name)))
 			{
-				if(comvar || (shp->last_root==shp->var_tree && (tp->tp || (!shp->st.real_fun && (nvflags&NV_STATIC)) || (!(flag&(NV_EXPORT|NV_RDONLY)) && nv_isattr(np,(NV_EXPORT|NV_IMPORT))==(NV_EXPORT|NV_IMPORT)))))
+				if(comvar || (shp->last_root==shp->var_tree && ((tp->tp && tp->tp!=nv_type(np)) || (!shp->st.real_fun && (nvflags&NV_STATIC)) || (!(flag&(NV_EXPORT|NV_RDONLY)) && nv_isattr(np,(NV_EXPORT|NV_IMPORT))==(NV_EXPORT|NV_IMPORT)))))
 {
 				if((flag&(NV_HOST|NV_INTEGER))!=NV_HOST)
 					_nv_unset(np,0);
@@ -1168,14 +1172,14 @@ static int unall(int argc, char **argv,
 	{
 		name = sh_optunalias;
 		if(shp->subshell)
-			troot = sh_subaliastree(0);
+			troot = sh_subaliastree(shp,0);
 	}
 	else
 		name = sh_optunset;
 	while(r = optget(argv,name)) switch(r)
 	{
 		case 'f':
-			troot = sh_subfuntree(1);
+			troot = sh_subfuntree(shp,1);
 			break;
 		case 'a':
 			all=1;
--- src/cmd/ksh93/edit/edit.c
+++ src/cmd/ksh93/edit/edit.c	2013-09-16 13:04:37.000000000 +0000
@@ -1414,12 +1414,12 @@ int	ed_internal(const char *src, genchar
 int	ed_external(const genchar *src, char *dest)
 {
 	register genchar wc;
-	register int c,size;
 	register char *dp = dest;
 	char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
 	if((char*)src == dp)
 	{
-		char buffer[MAXLINE*sizeof(genchar)];
+		int c;
+		char buffer[MAXLINE*sizeof(genchar)] = "";
 		c = ed_external(src,buffer);
 
 #ifdef _lib_wcscpy
@@ -1431,6 +1431,7 @@ int	ed_external(const genchar *src, char
 	}
 	while((wc = *src++) && dp<dpmax)
 	{
+		ssize_t size;
 		if((size = mbconv(dp, wc)) < 0)
 		{
 			/* copy the character as is */
--- src/cmd/ksh93/edit/history.c
+++ src/cmd/ksh93/edit/history.c	2013-09-13 12:00:30.000000000 +0000
@@ -153,7 +153,7 @@ static History_t *hist_ptr;
 		int n;
 		if((n = fcntl(acctfd, F_DUPFD, 10)) >= 0)
 		{
-			close(acctfd);
+			sh_close(acctfd);
 			acctfd = n;
 		}
 	}
@@ -203,7 +203,7 @@ static int sh_checkaudit(History_t *hp,
 	}
 	while(*cp==';' ||  *cp==' ');
 done:
-	close(fd);
+	sh_close(fd);
 	return(r);
 	
 }
@@ -272,14 +272,14 @@ retry:
 		int n;
 		if((n=fcntl(fd,F_DUPFD,10))>=0)
 		{
-			close(fd);
+			sh_close(fd);
 			fd=n;
 		}
 	}
 	/* make sure that file has history file format */
 	if(hsize && hist_check(fd))
 	{
-		close(fd);
+		sh_close(fd);
 		hsize = 0;
 		if(unlink(cp)>=0)
 			goto retry;
@@ -308,7 +308,7 @@ retry:
 	for(histmask=16;histmask <= maxlines; histmask <<=1 );
 	if(!(hp=new_of(History_t,(--histmask)*sizeof(off_t))))
 	{
-		close(fd);
+		sh_close(fd);
 		return(0);
 	}
 	shgd->hist_ptr = hist_ptr = hp;
@@ -425,7 +425,7 @@ void hist_close(register History_t *hp)
 #if SHOPT_ACCTFILE
 	if(acctfd)
 	{
-		close(acctfd);
+		sh_close(acctfd);
 		acctfd = 0;
 	}
 #endif /* SHOPT_ACCTFILE */
@@ -470,7 +470,7 @@ static History_t* hist_trim(History_t *h
 		/* The unlink can fail on windows 95 */
 		int fd;
 		char *last, *name=hist_old->histname;
-		close(sffileno(hist_old->histfp));
+		sh_close(sffileno(hist_old->histfp));
 		tmpname = (char*)malloc(strlen(name)+14);
 		if(last = strrchr(name,'/'))
 		{
@@ -736,7 +736,7 @@ again:
 				hist_marker(buff,hp->histind);
 				write(fd,(char*)hist_stamp,2);
 				write(fd,buff,HIST_MARKSZ);
-				close(fd);
+				sh_close(fd);
 			}
 		}
 		last = 0;
@@ -1195,7 +1195,7 @@ static int hist_exceptf(Sfio_t* fp, int
 		if(errno==ENOSPC || hp->histwfail++ >= 10)
 			return(0);
 		/* write failure could be NFS problem, try to re-open */
-		close(oldfd=sffileno(fp));
+		sh_close(oldfd=sffileno(fp));
 		if((newfd=open(hp->histname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) >= 0)
 		{
 			if(fcntl(newfd, F_DUPFD, oldfd) !=oldfd)
--- src/cmd/ksh93/include/defs.h
+++ src/cmd/ksh93/include/defs.h	2013-09-13 14:19:35.000000000 +0000
@@ -160,6 +160,7 @@ struct shared
 	Namval_t	*namespace;	/* current active namespace*/ \
 	Namval_t	*last_table;	/* last table used in last nv_open  */ \
 	Namval_t	*prev_table;	/* previous table used in nv_open  */ \
+	Namval_t	**nodelist;	/* for decl commands */ \
 	Sfio_t		*outpool;	/* ouput stream pool */ \
 	long		timeout;	/* read timeout */ \
 	short		curenv;		/* current subshell number */ \
@@ -182,6 +183,8 @@ struct shared
 	pid_t		spid; 		/* subshell process id */ \
 	pid_t		pipepid; \
 	pid_t		outpipepid; \
+	pid_t		*procsub;	/* pids for >() argument */ \
+	int		nprocsub;	/* number of pids in procsub */ \
 	int		topfd; \
 	int		savesig; \
 	unsigned char	*sigflag;	/* pointer to signal states */ \
@@ -423,10 +426,10 @@ extern void		sh_printopts(Shopt_t,int,Sh
 extern int 		sh_readline(Shell_t*,char**,volatile int,int,ssize_t,long);
 extern Sfio_t		*sh_sfeval(char*[]);
 extern void		sh_setmatch(Shell_t*,const char*,int,int,int[],int);
-extern Dt_t		*sh_subaliastree(int);
+extern Dt_t		*sh_subaliastree(Shell_t*,int);
 extern void             sh_scope(Shell_t*, struct argnod*, int);
 extern Namval_t		*sh_scoped(Shell_t*, Namval_t*);
-extern Dt_t		*sh_subfuntree(int);
+extern Dt_t		*sh_subfuntree(Shell_t*,int);
 extern void		sh_subjobcheck(pid_t);
 extern int		sh_subsavefd(int);
 extern void		sh_subtmpfile(Shell_t*);
--- src/cmd/ksh93/include/io.h
+++ src/cmd/ksh93/include/io.h	2013-09-09 16:35:27.000000000 +0000
@@ -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	sh_iounpipe(Shell_t*);
 extern int	sh_chkopen(const char*);
 extern int	sh_ioaccess(int,int);
 extern int	sh_devtofd(const char*);
--- src/cmd/ksh93/include/jobs.h
+++ src/cmd/ksh93/include/jobs.h	2013-09-16 13:36:02.000000000 +0000
@@ -103,6 +103,7 @@ struct jobs
 	pid_t		mypid;		/* process id of shell */
 	pid_t		mypgid;		/* process group id of shell */
 	pid_t		mytgid;		/* terminal group id of shell */
+	pid_t		lastpost;	/* last job posted */
 	int		curjobid;
 	unsigned int	in_critical;	/* >0 => in critical region */
 	int		savesig;	/* active signal */
@@ -152,11 +153,11 @@ extern struct jobs job;
 #define job_lock()	(job.in_critical++)
 #define job_unlock()	\
 	do { \
-		int	sig; \
-		if (!--job.in_critical && (sig = job.savesig)) \
+		int	_sig; \
+		if (!--job.in_critical && (_sig = job.savesig)) \
 		{ \
 			if (!job.in_critical++ && !vmbusy()) \
-				job_reap(sig); \
+				job_reap(_sig); \
 			job.in_critical--; \
 		} \
 	} while(0)
--- src/cmd/ksh93/include/name.h
+++ src/cmd/ksh93/include/name.h	2013-09-11 13:02:16.000000000 +0000
@@ -124,6 +124,7 @@ struct Ufunction
 #define NV_PARAM	NV_NODISC	/* expansion use positional params */
 
 /* This following are for use with nodes which are not name-values */
+#define NV_DECL		0x20000000
 #define NV_TYPE		0x1000000
 #define NV_STATIC	0x2000000
 #define NV_COMVAR	0x4000000
@@ -190,7 +191,7 @@ extern int		nv_aimax(Namval_t*);
 extern int		nv_atypeindex(Namval_t*, const char*);
 extern int		nv_setnotify(Namval_t*,char **);
 extern int		nv_unsetnotify(Namval_t*,char **);
-extern void		nv_setlist(struct argnod*, int, Namval_t*);
+extern Namval_t		**nv_setlist(struct argnod*, int, Namval_t*);
 extern struct argnod*	nv_onlist(struct argnod*, const char*);
 extern void 		nv_optimize(Namval_t*);
 extern void		nv_outname(Sfio_t*,char*, int);
--- src/cmd/ksh93/sh/args.c
+++ src/cmd/ksh93/sh/args.c	2013-09-12 14:17:44.000000000 +0000
@@ -32,6 +32,7 @@
 #include	"builtins.h"
 #include	"terminal.h"
 #include	"edit.h"
+#include	"jobs.h"
 #include	"FEATURE/poll"
 #if SHOPT_KIA
 #   include	"shlex.h"
@@ -57,6 +58,7 @@
 #define PRINT		2
 
 static	char		*null;
+static	pid_t		*procsub; 
 
 /* The following order is determined by sh_optset */
 static  const char optksh[] =  PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
@@ -717,6 +719,7 @@ char **sh_argbuild(Shell_t *shp,int *nar
 			return(ap->dolval+ap->dolbot);
 		}
 		shp->lastpath = 0;
+		procsub = shp->procsub;
 		*nargs = 0;
 		if(ac)
 		{
@@ -737,6 +740,8 @@ char **sh_argbuild(Shell_t *shp,int *nar
 			}
 			argp = arghead;
 		}
+		if(procsub)
+			*procsub = 0;
 	}
 	{
 		register char	**comargn;
@@ -782,8 +787,9 @@ struct argnod *sh_argprocsub(Shell_t *sh
 {
 	/* argument of the form <(cmd) or >(cmd) */
 	register struct argnod *ap;
-	int monitor, fd, pv[3];
+	int nn, monitor, fd, pv[3];
 	int subshell = shp->subshell;
+	pid_t pid0;
 	ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
 	ap->argflag |= ARG_MAKE;
 	ap->argflag &= ~ARG_RAW;
@@ -794,18 +800,33 @@ struct argnod *sh_argprocsub(Shell_t *sh
 	sfwrite(shp->stk,e_devfdNN,8);
 	pv[2] = 0;
 	sh_pipe(pv);
+	sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
 #else
 	pv[0] = -1;
 	shp->fifo = pathtemp(0,0,0,"ksh.fifo",0);
 	mkfifo(shp->fifo,S_IRUSR|S_IWUSR);
 	sfputr(shp->stk,shp->fifo,0);
 #endif /* SHOPT_DEVFD */
-	sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
 	ap = (struct argnod*)stkfreeze(shp->stk,0);
 	shp->inpipe = shp->outpipe = 0;
 	if(monitor = (sh_isstate(SH_MONITOR)!=0))
 		sh_offstate(SH_MONITOR);
 	shp->subshell = 0;
+#if SHOPT_DEVFD
+	fcntl(pv[fd],F_SETFD,0);
+	shp->fdstatus[pv[fd]] &= ~IOCLEX;
+#endif /* SHOPT_DEVFD */
+	pid0=shp->procsub?*shp->procsub:0; 
+	if(!shp->procsub)
+		shp->procsub = procsub = newof(0,pid_t,shp->nprocsub=4,0);
+	else if((nn=procsub-shp->procsub) >= shp->nprocsub)
+	{
+		shp->nprocsub += 3;
+		shp->procsub = newof(shp->procsub,pid_t,shp->nprocsub,0);
+		procsub = shp->procsub + nn;
+	}
+	if(pid0)
+		*shp->procsub = 0;
 	if(fd)
 	{
 		shp->inpipe = pv;
@@ -816,11 +837,14 @@ struct argnod *sh_argprocsub(Shell_t *sh
 		shp->outpipe = pv;
 		sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
 	}
+	if(pid0)
+		*shp->procsub = pid0;
+	*procsub++ = job.lastpost;
 	shp->subshell = subshell;
 	if(monitor)
 		sh_onstate(SH_MONITOR);
 #if SHOPT_DEVFD
-	close(pv[1-fd]);
+	sh_close(pv[1-fd]);
 	sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
 #else
 	free(shp->fifo);
--- src/cmd/ksh93/sh/arith.c
+++ src/cmd/ksh93/sh/arith.c	2013-09-13 13:44:25.000000000 +0000
@@ -180,7 +180,10 @@ static Namval_t *scope(register Namval_t
 			{
 				ap = nv_arrayptr(np);
 				if(ap && !ap->table)
+				{
 					ap->table = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(ap->table,shp,1);
+				}
 				if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
 					nq->nvenv = (char*)np;
 				if(nq && nv_isnull(nq))
--- src/cmd/ksh93/sh/array.c
+++ src/cmd/ksh93/sh/array.c	2013-09-13 14:11:55.000000000 +0000
@@ -79,6 +79,7 @@ struct assoc_array
 
 static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags)
 {
+	Shell_t	*shp = sh_getinterp();
 	Namarr_t *aq;
 #if SHOPT_FIXEDARRAY
 	struct fixed_array *fp;
@@ -95,6 +96,7 @@ static Namarr_t *array_scope(Namval_t *n
 	if(is_associative(aq))
 	{
 		aq->scope = (void*)dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(aq->scope,shp,1);
 		dtview((Dt_t*)aq->scope,aq->table);
 		aq->table = (Dt_t*)aq->scope;
 		return(aq);
@@ -271,6 +273,7 @@ int nv_arrayisset(Namval_t *np, Namarr_t
  */
 static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
 {
+	Shell_t	*shp=sh_getinterp();
 	register struct index_array *ap = (struct index_array*)arp;
 	register union Value	*up;
 	Namval_t		*mp;
@@ -373,7 +376,10 @@ static Namval_t *array_find(Namval_t *np
 		{
 			char *cp;
 			if(!ap->header.table)
+			{
 				ap->header.table = dtopen(&_Nvdisc,Dtoset);
+				dtuserdata(ap->header.table,shp,1);
+			}
 			sfprintf(sh.strbuf,"%d",ap->cur);
 			cp = sfstruse(sh.strbuf);
 			mp = nv_search(cp, ap->header.table, NV_ADD);
@@ -402,6 +408,7 @@ static Namval_t *array_find(Namval_t *np
 #if SHOPT_TYPEDEF
 int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
 {
+	Shell_t		*shp = sh_getinterp();
 	Namval_t	*nq;
 	char		*av[2];
 	int		rdonly = nv_isattr(np,NV_RDONLY);
@@ -410,7 +417,10 @@ int nv_arraysettype(Namval_t *np, Namval
 	av[1] = 0;
 	sh.last_table = 0;
 	if(!ap->table)
+	{
 		ap->table = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(ap->table,shp,1);
+	}
 	if(nq = nv_search(sub, ap->table, NV_ADD))
 	{
 		if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0)
@@ -485,6 +495,7 @@ static Namfun_t *array_clone(Namval_t *n
 	if(ap->table)
 	{
 		ap->table = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(ap->table,shp,1);
 		if(ap->scope && !(flags&NV_COMVAR))
 		{
 			ap->scope = ap->table;
@@ -854,7 +865,9 @@ static struct index_array *array_grow(Na
 			np->nvalue.cp=0;
 		if(nv_hasdisc(np,&array_disc) || (nv_type(np) && nv_isvtree(np)))
 		{
+			Shell_t *shp = sh_getinterp();
 			ap->header.table = dtopen(&_Nvdisc,Dtoset);
+			dtuserdata(ap->header.table,shp,1);
 			mp = nv_search("0", ap->header.table,NV_ADD);
 			if(mp && nv_isnull(mp))
 			{
@@ -1169,6 +1182,7 @@ int nv_nextsub(Namval_t *np)
  */
 Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
 {
+	Shell_t *shp = sh_getinterp();
 	register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
 	register int size = (mode&ARRAY_MASK);
 #if SHOPT_FIXEDARRAY
@@ -1180,7 +1194,6 @@ Namval_t *nv_putsub(Namval_t *np,registe
 	{
 		if(sp)
 		{
-			Shell_t	*shp = sh_getinterp();
 			if(ap && ap->xp && !strmatch(sp,"+([0-9])"))
 			{
 				Namval_t *mp = nv_namptr(ap->xp,0);
@@ -1258,7 +1271,10 @@ Namval_t *nv_putsub(Namval_t *np,registe
 					char *cp;
 					Namval_t *mp;
 					if(!ap->header.table)
+					{
 						ap->header.table = dtopen(&_Nvdisc,Dtoset);
+						dtuserdata(ap->header.table,shp,1);
+					}
 					sfprintf(sh.strbuf,"%d",ap->cur);
 					cp = sfstruse(sh.strbuf);
 					mp = nv_search(cp, ap->header.table, NV_ADD);
@@ -1666,6 +1682,7 @@ int nv_aimax(register Namval_t* np)
  */
 void *nv_associative(register Namval_t *np,const char *sp,int mode)
 {
+	Shell_t	*shp = sh_getinterp();
 	register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np);
 	register int type;
 	switch(mode)
@@ -1674,6 +1691,7 @@ void *nv_associative(register Namval_t *
 		if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array)))
 		{
 			ap->header.table = dtopen(&_Nvdisc,Dtoset);
+			dtuserdata(ap->header.table,shp,1);
 			ap->cur = 0;
 			ap->pos = 0;
 			ap->header.hdr.disc = &array_disc;
@@ -1742,7 +1760,6 @@ void *nv_associative(register Namval_t *
 	    case NV_ANAME:
 		if(ap->cur)
 		{
-			Shell_t *shp = sh_getinterp();
 			if(!shp->instance && nv_isnull(ap->cur))
 				return(NIL(void*));
 			return((void*)ap->cur->nvname);
--- src/cmd/ksh93/sh/fault.c
+++ src/cmd/ksh93/sh/fault.c	2013-09-12 14:14:49.000000000 +0000
@@ -518,6 +518,8 @@ void sh_exit(register int xno)
 		shp->exitval |= (sig=shp->lastsig);
 	if(pp && pp->mode>1)
 		cursig = -1;
+	if(shp->procsub)
+		*shp->procsub = 0;
 #ifdef SIGTSTP
 	if(shp->trapnote&SH_SIGTSTP)
 	{
--- src/cmd/ksh93/sh/init.c
+++ src/cmd/ksh93/sh/init.c	2013-09-13 13:52:48.000000000 +0000
@@ -1909,9 +1909,13 @@ static Init_t *nv_init(Shell_t *shp)
 	(OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
 	/* set up the seconds clock */
 	shp->alias_tree = inittree(shp,shtab_aliases);
+	dtuserdata(shp->alias_tree,shp,1);
 	shp->track_tree = dtopen(&_Nvdisc,Dtset);
+	dtuserdata(shp->track_tree,shp,1);
 	shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
+	dtuserdata(shp->bltin_tree,shp,1);
 	shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(shp->fun_tree,shp,1);
 	dtview(shp->fun_tree,shp->bltin_tree);
 	nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
 	nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
@@ -1954,6 +1958,7 @@ static Dt_t *inittree(Shell_t *shp,const
 		nbltins = n;
 	}
 	base_treep = treep = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(treep,shp,1);
 	treep->user = (void*)shp;
 	for(tp=name_vals;*tp->sh_name;tp++,np++)
 	{
--- src/cmd/ksh93/sh/io.c
+++ src/cmd/ksh93/sh/io.c	2013-09-17 17:08:41.000000000 +0000
@@ -39,6 +39,7 @@
 #include	"shnodes.h"
 #include	"history.h"
 #include	"edit.h"
+#include	"builtins.h"
 #include	"timeout.h"
 #include	"FEATURE/externs"
 #include	"FEATURE/dynamic"
@@ -453,6 +454,8 @@ void sh_ioinit(Shell_t *shp)
 	sfnotify(sftrack);
 	sh_iostream(shp,0);
 	sh_iostream(shp,1);
+	/* sh_iostream(shp,2); --- ksh93u+ 2012-08-01 does not have a (io)vex to
+	   restore sfstderr and close file descriptors */
 	/* all write steams are in the same pool and share outbuff */
 	shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw");  /* pool identifier */
 	shp->outbuff = (char*)malloc(IOBSIZE+4);
@@ -536,8 +539,12 @@ Sfio_t *sh_iostream(Shell_t *shp, regist
 	}
 	if(status&IOREAD)
 	{
-		if(!(bp = (char *)malloc(IOBSIZE+1)))
+		if(shp->bltinfun && shp->bltinfun!=b_read && shp->bltindata.bnode && !nv_isattr(shp->bltindata.bnode,BLT_SPC))
+			bp = 0;
+		else if(!(bp = (char *)malloc(IOBSIZE+1)))
 			return(NIL(Sfio_t*));
+		if(bp)
+			bp[IOBSIZE]=0;
 		flags |= SF_READ;
 		if(!(status&IOWRITE))
 			flags &= ~SF_WRITE;
@@ -550,7 +557,8 @@ Sfio_t *sh_iostream(Shell_t *shp, regist
 	{
 		if(status&IOTTY)
 			sfset(iop,SF_LINE|SF_WCWIDTH,1);
-		sfsetbuf(iop, bp, IOBSIZE);
+		if(bp)
+			sfsetbuf(iop, bp, IOBSIZE);
 	}
 	else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
 		return(NIL(Sfio_t*));
@@ -964,7 +972,7 @@ int	sh_pipe(register int pv[])
 	while ((r=bind (pv[out], (struct sockaddr *) &sin, slen)) == -1 && errno==EADDRINUSE);
 	if(r<0 ||  listen(pv[out],5) <0)
 	{
-		close(pv[out]);
+		sh_close(pv[out]);
 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
 	}
 	fcntl(pv[out],F_SETFD,FD_CLOEXEC);
@@ -1079,7 +1087,7 @@ static char *io_usename(char *name, int
 		if((fd = sh_open(name,O_RDONLY,0)) >= 0)
 		{
 			r = fstat(fd,&statb);
-			close(fd);
+			sh_close(fd);
 			if(r)
 				return(0);
 			if(!S_ISREG(statb.st_mode))
@@ -1144,6 +1152,7 @@ int	sh_redirect(Shell_t *shp,struct iono
 	char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
 	Namval_t *np=0;
 	int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
+	Sfio_t		*sp;
 
 	if(flag==2)
 		clexec = 1;
@@ -1245,16 +1254,35 @@ int	sh_redirect(Shell_t *shp,struct iono
 			{
 				int dupfd,toclose= -1;
 				io_op[2] = '&';
-				if((fd=fname[0])>='0' && fd<='9')
+				if((fd=fname[0])>='0' && (fd=='{' || fd<='9'))
 				{
 					char *number = fname;
-					dupfd = strtol(fname,&number,10);
+					int f;
+					if(fd=='{')
+					{
+						np = 0;
+						if(number=strchr(fname,'}'))
+						{
+							*number = 0;
+							np = nv_open(fname+1,shp->var_tree,NV_NOASSIGN|NV_VARNAME|NV_NOFAIL);
+							*number++ = '}';
+						}
+						if(!np)
+						{
+							message = e_file;
+							goto fail;
+						}
+						dupfd = nv_getnum(np);
+						np = 0;
+					}
+					else
+						dupfd = strtol(fname,&number,10);
 					if(*number=='-')
 					{
 						toclose = dupfd;
 						number++;
 					}
-					if(*number || dupfd > IOUFD)
+					if(*number)
 					{
 						message = e_file;
 						goto fail;
@@ -1267,8 +1295,23 @@ int	sh_redirect(Shell_t *shp,struct iono
 							shp->subdup |= 1<<fn;
 						dupfd = sffileno(sfstdout);
 					}
-					else if(shp->sftable[dupfd])
+					else if(sp=shp->sftable[dupfd])
+					{
+						char *tmpname;
+						if((sfset(sp,0,0)&SF_STRING) && (tmpname = pathtemp(NiL ,NiL,NiL,"sf",&f)))
+						{
+							Sfoff_t last = sfseek(sp,(Sfoff_t)0,SEEK_END);
+				
+							unlink(tmpname);
+							free(tmpname);
+							write(f, sp->_data, (size_t)last);
+							lseek(f,(Sfoff_t)0,SEEK_SET);
+
+							sfclose(sp);
+							sp = sfnew(sp,NULL,-1,f,SF_READ);
+						}
 						sfsync(shp->sftable[dupfd]);
+					}
 					if(dupfd!=1 && fn < 10)
 						shp->subdup &= ~(1<<fn);
 				}
@@ -1293,11 +1336,25 @@ int	sh_redirect(Shell_t *shp,struct iono
 				}
 				if(flag==SH_SHOWME)
 					goto traceit;
-				if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
+				if((sp=shp->sftable[dupfd]) && sfset(sp,0,0)&SF_STRING)
+				{
+					char *cp;
+					Sfoff_t	off = sftell(sp);
+					sfset(sp,SF_MALLOC,0);
+					cp = sfsetbuf(sp,(char*)sp,0);
+					sfset(sp,SF_MALLOC,1);
+					r = (int)(sfseek(sp,(Sfoff_t)0,SEEK_END)-off);
+					sfseek(sp,off,SEEK_SET);
+					fd = shp->gd->lim.open_max-1;
+					shp->sftable[fd] = sfnew(NIL(Sfio_t*),cp,r,-1,SF_READ|SF_STRING);
+					shp->fdstatus[fd] = shp->fdstatus[dupfd];
+				}
+				else if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
 					goto fail;
 				if(fd>= shp->gd->lim.open_max)
 					sh_iovalidfd(shp,fd);
-				sh_iocheckfd(shp,dupfd);
+				if(!shp->sftable[dupfd])
+					sh_iocheckfd(shp,dupfd);
 				shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
 				if(toclose<0 && shp->fdstatus[fd]&IOREAD)
 					shp->fdstatus[fd] |= IODUP;
@@ -1496,7 +1553,8 @@ int	sh_redirect(Shell_t *shp,struct iono
 					if(fn>9 || !(shp->inuse_bits&(1<<fn)))
 						io_preserve(shp,shp->sftable[fn],fn);
 				}
-				sh_close(fn);
+				if(!(iof&IODOC))
+					sh_close(fn);
 			}
 			if(flag==3)
 				return(fd);
@@ -1531,7 +1589,24 @@ int	sh_redirect(Shell_t *shp,struct iono
 						shp->inuse_bits |= (1<<fn);
 				}
 			}
-			if(fd >2 && clexec)
+			else if(iof&IODOC)
+			{
+				Sfio_t *sp = &_Sfstderr;
+				if(fn==1)
+					sp = &_Sfstdout;
+				else if(fn==0)
+					sp = &_Sfstdin;
+				shp->sftable[fn] = shp->sftable[-1];
+				shp->fdstatus[fn] = shp->fdstatus[-1];
+				if(fn <=2)
+				{
+					sfswap(shp->sftable[fn],sp);
+					shp->sftable[fn] = sp;
+				}
+				shp->fdptrs[fn] = 0;
+				shp->sftable[-1] = 0;
+			}
+			if(fd >2 && clexec && !(shp->fdstatus[fd]&IOCLEX))
 			{
 				fcntl(fd,F_SETFD,FD_CLOEXEC);
 				shp->fdstatus[fd] |= IOCLEX;
@@ -2059,9 +2134,11 @@ int sh_iocheckfd(Shell_t *shp, register
 	if(!(n&(IOSEEK|IONOSEEK)))
 	{
 		struct stat statb;
+		Sfio_t *sp = shp->sftable[fd];
 		/* /dev/null check is a workaround for select bug */
 		static ino_t null_ino;
 		static dev_t null_dev;
+		shp->sftable[fd] = 0;
 		if(null_ino==0 && stat(e_devnull,&statb) >=0)
 		{
 			null_ino = statb.st_ino;
@@ -2097,6 +2174,7 @@ int sh_iocheckfd(Shell_t *shp, register
 			n |= IONOSEEK;
 		else
 			n |= IOSEEK;
+		shp->sftable[fd] = sp;
 	}
 	if(fd==0)
 		n &= ~IOWRITE;
@@ -2143,6 +2221,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)
--- src/cmd/ksh93/sh/jobs.c
+++ src/cmd/ksh93/sh/jobs.c	2013-09-16 14:18:07.000000000 +0000
@@ -424,6 +424,8 @@ int job_reap(register int sig)
 		}
 		if(pid<=0)
 			break;
+		if(pid==shp->spid)
+			shp->spid = 0;
 		if(wstat==0)
 			job_chksave(pid);
 		flags |= WNOHANG;
@@ -520,7 +522,12 @@ int job_reap(register int sig)
 				{
 					shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
 					if(sig==0)
+					{
+						int c = job.in_critical;
+						job.in_critical = 0;
 						job_chldtrap(shp,shp->st.trapcom[SIGCHLD],0);
+						job.in_critical = c;
+					}
 					else
 						shp->trapnote |= SH_SIGTRAP;
 				}
@@ -1313,6 +1320,7 @@ int job_post(Shell_t *shp,pid_t pid, pid
 		return(0);
 	}
 	job_lock();
+	job.lastpost = pid;
 #ifdef SHOPT_BGX
 	if(join==1)
 	{
@@ -1635,9 +1643,21 @@ int	job_wait(register pid_t pid)
 	if(intr && shp->trapnote)
 		shp->exitval = 1;
 	pwfg = 0;
-	job_unlock();
 	if(pid==1)
+	{
+		if(nochild)
+		{
+			for(pw=job.pwlist; pw; pw=px)
+			{
+				px = pw->p_nxtjob;
+				pw->p_flag |= P_DONE;
+				job_unpost(pw,1);
+			}
+		}
+		job_unlock();
 		return(nochild);
+	}
+	job_unlock();
 	exitset();
 	if(pid==0)
 		goto done;
@@ -1800,7 +1820,7 @@ static struct process *job_unpost(regist
 #endif /* DEBUG */
 	pwtop = pw = job_byjid((int)pwtop->p_job);
 #ifdef SHOPT_BGX
-	if(pw->p_flag&P_BG) 
+	if(!pw || pw->p_flag&P_BG) 
 		return(pw);
 #endif /* SHOPT_BGX */
 	for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc);
--- src/cmd/ksh93/sh/lex.c
+++ src/cmd/ksh93/sh/lex.c	2013-09-13 19:12:25.000000000 +0000
@@ -556,7 +556,7 @@ int sh_lex(Lex_t* lp)
 							lp->lexd.docword=1;
 						else if(n==LPAREN)
 						{
-							if(lp->lex.intest)
+							if(lp->lex.intest || lp->comp_assign)
 								return(c);
 							lp->lexd.nest=1;
 							lp->lastline = shp->inlineno;
--- src/cmd/ksh93/sh/macro.c
+++ src/cmd/ksh93/sh/macro.c	2013-09-13 18:46:30.000000000 +0000
@@ -392,7 +392,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)
@@ -1166,7 +1166,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;
@@ -1349,7 +1349,7 @@ retry1:
 					ap = nv_arrayptr(np=nq);
 				if(ap)
 				{
-					nv_putsub(np,v,ARRAY_SCAN);
+					np = nv_putsub(np,v,ARRAY_SCAN);
 					v = stkptr(stkp,mp->dotdot);
 					dolmax =1;
 					if(array_assoc(ap))
@@ -2077,6 +2077,18 @@ static void comsubst(Mac_t *mp,register
 			fcrestore(&save);
 			return;
 		}
+		else if(type==2 && t && (t->tre.tretyp&COMMSK)==0 && t->com.comarg)
+		{
+			Namval_t *np;
+			str = NULL;
+			if(!(t->com.comtyp&COMSCAN))
+			{
+				struct dolnod *ap = (struct dolnod*)t->com.comarg;
+				str = ap->dolval[ap->dolbot];
+			}
+			else if(t->com.comarg->argflag&ARG_RAW)
+				str = t->com.comarg->argval;
+		}
 	}
 	else
 	{
@@ -2158,10 +2170,22 @@ static void comsubst(Mac_t *mp,register
 	mp->ifsp = nv_getval(np);
 	stkset(stkp,savptr,savtop);
 	newlines = 0;
-	sfsetbuf(sp,(void*)sp,0);
-	bufsize = sfvalue(sp);
+	if(type==3 && mp->shp->spid)
+	{
+		c = mp->shp->exitval;
+		job_wait(mp->shp->spid);
+		if(mp->shp->exitval==ERROR_NOENT)
+		{
+			mp->shp->exitval = c;
+			mp->shp->savexit=mp->shp->exitval;
+		}
+		if(mp->shp->pipepid==mp->shp->spid)
+			mp->shp->spid = 0;
+		mp->shp->pipepid = 0;
+	}
 	/* read command substitution output and put on stack or here-doc */
 	sfpool(sp, NIL(Sfio_t*), SF_WRITE);
+	sfset(sp, SF_WRITE|SF_PUBLIC|SF_SHARE,0);
 	sh_offstate(SH_INTERACTIVE);
 	if((foff = sfseek(sp,(Sfoff_t)0,SEEK_END)) > 0)
 	{
@@ -2170,6 +2194,8 @@ static void comsubst(Mac_t *mp,register
 		stkseek(stkp,soff+foff+64);
 		stkseek(stkp,soff);
 	}
+	if(foff > IOBSIZE)
+		sfsetbuf(sp,NULL,SF_UNBOUND);
 	while((str=(char*)sfreserve(sp,SF_UNBOUND,0)) && (c=bufsize=sfvalue(sp))>0)
 	{
 #if SHOPT_CRNL
@@ -2291,6 +2317,13 @@ static void mac_copy(register Mac_t *mp,
 	Stk_t			*stkp=mp->shp->stk;
 	int			oldpat = mp->pattern;
 	nopat = (mp->quote||(mp->assign==1)||mp->arith);
+	if(size>512)
+	{
+		/* pre-allocate to improve performance */
+		c = stktell(stkp);
+		stkseek(stkp,c+size+(size>>4));
+		stkseek(stkp,c);
+	}
 	if(mp->zeros)
 	{
 		/* prevent leading 0's from becomming octal constants */
@@ -2742,7 +2775,10 @@ static char *sh_tilde(Shell_t *shp,regis
 skip:
 #endif /* _WINIX */
 	if(!logins_tree)
+	{
 		logins_tree = dtopen(&_Nvdisc,Dtbag);
+		dtuserdata(logins_tree,shp,1);
+	}
 	if(np=nv_search(string,logins_tree,NV_ADD))
 	{
 		c = shp->subshell;
--- src/cmd/ksh93/sh/main.c
+++ src/cmd/ksh93/sh/main.c	2013-09-13 12:07:49.000000000 +0000
@@ -309,7 +309,7 @@ int sh_main(int ac, char *av[], Shinit_f
 					int isdir = 0;
 					if((fdin=sh_open(name,O_RDONLY,0))>=0 &&(fstat(fdin,&statb)<0 || S_ISDIR(statb.st_mode)))
 					{
-						close(fdin);
+						sh_close(fdin);
 						isdir = 1;
 						fdin = -1;
 					}
--- src/cmd/ksh93/sh/name.c
+++ src/cmd/ksh93/sh/name.c	2013-09-16 16:00:12.000000000 +0000
@@ -291,7 +291,7 @@ struct argnod *nv_onlist(struct argnod *
  * Perform parameter assignment for a linked list of parameters
  * <flags> contains attributes for the parameters
  */
-void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
+Namval_t ** nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
 {
 	Shell_t		*shp = sh_getinterp();
 	register char	*cp;
@@ -301,7 +301,7 @@ void nv_setlist(register struct argnod *
 	int		traceon = (sh_isoption(SH_XTRACE)!=0);
 	int		array = (flags&(NV_ARRAY|NV_IARRAY));
 	Namarr_t	*ap;
-	Namval_t	node;
+	Namval_t	node, **nodelist=0, **nlp=0;
 	struct Namref	nr;
 #if SHOPT_TYPEDEF
 	int		maketype = flags&NV_TYPE;
@@ -330,6 +330,15 @@ void nv_setlist(register struct argnod *
 	}
 	else
 		shp->prefix_root = shp->first_root = 0;
+	if(flags&NV_DECL)
+	{
+		struct argnod *ap;
+		int n=0;
+		for(ap=arg;ap; ap=ap->argnxt.ap)
+			n++;
+		nlp = nodelist = (Namval_t**)stakalloc((n+1)*sizeof(Namval_t*));
+		nodelist[n] = 0;
+	}
 	for(;arg; arg=arg->argnxt.ap)
 	{
 		shp->used_pos = 0;
@@ -421,6 +430,8 @@ void nv_setlist(register struct argnod *
 					if(array&NV_ARRAY)
 					{
 						nv_setarray(np,nv_associative);
+						if(typ)
+							nv_settype(np,typ,0);
 					}
 					else
 					{
@@ -436,7 +447,7 @@ void nv_setlist(register struct argnod *
 #endif /* SHOPT_TYPEDEF */
 				}
 				/* check for array assignment */
-				if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && ((array&NV_IARRAY) || !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))))
+				if((tp->tre.tretyp&COMMSK)==TCOM && tp->com.comarg && !tp->com.comset && ((array&NV_IARRAY) || !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))))
 				{
 					int argc;
 					Dt_t	*last_root = shp->last_root;
@@ -509,6 +520,7 @@ void nv_setlist(register struct argnod *
 							if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE))
 								nv_setarray(np,nv_associative);
 						}
+						shp->typeinit = 0;
 						nv_setlist(tp->com.comset,flags&~NV_STATIC,0);
 						shp->prefix = prefix;
 						if(tp->com.comset->argval[1]!='[')
@@ -682,6 +694,7 @@ void nv_setlist(register struct argnod *
 		}
 #endif /* SHOPT_TYPEDEF */
 	}
+	return(nodelist);
 }
 
 /*
@@ -821,6 +834,7 @@ Namval_t *nv_create(const char *name,  D
 				{
 					Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
 					rp->sdict = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(rp->sdict,shp,1);
 					dtview(rp->sdict,dp);
 					dtview(shp->var_tree,rp->sdict);
 				}
@@ -1170,7 +1184,10 @@ Namval_t *nv_create(const char *name,  D
 								ap = nv_arrayptr(np);
 							}
 							if(n && ap && !ap->table)
+							{
 								ap->table = dtopen(&_Nvdisc,Dtoset);
+								dtuserdata(ap->table,shp,1);
+							}
 							if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
 								nq->nvenv = (char*)np;
 							if(nq && nv_isnull(nq))
@@ -1288,8 +1305,9 @@ void nv_delete(Namval_t* np, Dt_t *root,
 				if(rp->sub)
 					free(rp->sub);
 				rp->sub = 0;
-				rp = dtdelete(Refdict,(void*)rp);
-				rp->np = &NullNode;
+				rp = dtremove(Refdict,(void*)rp);
+				if(rp)
+					rp->np = &NullNode;
 			}
 		}
 	}
@@ -1341,10 +1359,12 @@ Namval_t *nv_open(const char *name, Dt_t
 	struct Cache_entry	*xp;
 #endif
 	
-	sh_stats(STAT_NVOPEN);
 	memset(&fun,0,sizeof(fun));
 	shp->openmatch = 0;
 	shp->last_table = 0;
+	if(!name)
+		return(0);
+	sh_stats(STAT_NVOPEN);
 	if(!root)
 		root = shp->var_tree;
 	shp->last_root = root;
@@ -1391,7 +1411,7 @@ Namval_t *nv_open(const char *name, Dt_t
 		while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
 			(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
 		if(shp->subshell && c=='=')
-			root = sh_subaliastree(1);
+			root = sh_subaliastree(shp,1);
 		if(c= *--cp)
 			*cp = 0;
 		np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 
@@ -2350,6 +2370,7 @@ void sh_scope(Shell_t *shp, struct argno
 		newroot = nv_dict(shp->namespace);
 #endif /* SHOPT_NAMESPACE */
 	newscope = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(newscope,shp,1);
 	if(envlist)
 	{
 		dtview(newscope,(Dt_t*)shp->var_tree);
@@ -2465,6 +2486,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);
 	}
@@ -2533,7 +2556,7 @@ void	_nv_unset(register Namval_t *np,int
 				}
 				dtclose(rp->sdict);
 			}
-			stakdelete(slp->slptr);
+			sfclose(slp->slptr);
 			free((void*)np->nvalue.ip);
 			np->nvalue.ip = 0;
 		}
@@ -2547,9 +2570,11 @@ void	_nv_unset(register Namval_t *np,int
 		/* This function contains disc */
 		if(!nv_local)
 		{
+			Dt_t *last_root = shp->last_root;
 			nv_local=1;
 			nv_putv(np,NIL(char*),flags,np->nvfun);
 			nv_local=0;
+			shp->last_root = last_root;
 			return;
 		}
 		/* called from disc, assign the actual value */
@@ -2570,7 +2595,7 @@ void	_nv_unset(register Namval_t *np,int
 	{
 
 		if(np->nvalue.nrp->root)
-			dtdelete(Refdict,(void*)np->nvalue.nrp);
+			dtremove(Refdict,(void*)np->nvalue.nrp);
 		if(np->nvalue.nrp->sub)
 			free(np->nvalue.nrp->sub);
 		free((void*)np->nvalue.nrp);
@@ -3334,7 +3359,10 @@ int nv_rename(register Namval_t *np, int
 		if(ap=nv_arrayptr(np))
 		{
 			if(!ap->table)
+			{
 				ap->table = dtopen(&_Nvdisc,Dtoset);
+				dtuserdata(ap->table,shp,1);
+			}
 			if(ap->table)
 				mp = nv_search(nv_getsub(np),ap->table,NV_ADD);
 			nv_arraychild(np,mp,0);
@@ -3569,7 +3597,7 @@ void nv_unref(register Namval_t *np)
 	{
 		if(np->nvalue.nrp->sub)
 			free(np->nvalue.nrp->sub);
-		dtdelete(Refdict,(void*)np->nvalue.nrp);
+		dtremove(Refdict,(void*)np->nvalue.nrp);
 	}
 	free((void*)np->nvalue.nrp);
 	np->nvalue.cp = strdup(nv_name(nq));
--- src/cmd/ksh93/sh/nvdisc.c
+++ src/cmd/ksh93/sh/nvdisc.c	2013-09-13 14:34:31.000000000 +0000
@@ -246,6 +246,7 @@ static void chktfree(register Namval_t *
  */
 static void	assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
 {
+	Shell_t		*shp = sh_getinterp();
 	int		type = (flags&NV_APPEND)?APPEND:ASSIGN;
 	register	struct vardisc *vp = (struct vardisc*)handle;
 	register	Namval_t *nq =  vp->disc[type];
@@ -330,7 +331,7 @@ static void	assign(Namval_t *np,const ch
 	}
 	else if(!nq || !isblocked(bp,type))
 	{
-		Dt_t *root = sh_subfuntree(1);
+		Dt_t *root = sh_subfuntree(shp,1);
 		int n;
 		Namarr_t *ap;
 		block(bp,type);
@@ -1225,7 +1226,10 @@ Namval_t *sh_addbuiltin(const char *path
 			if(np->nvenv)
 				dtdelete(sh.bltin_tree,np);
 			if(extra == (void*)1)
+			{
+				dtdelete(sh.bltin_tree,np);
 				return(0);
+			}
 			np = 0;
 		}
 		break;
@@ -1296,6 +1300,7 @@ static Namfun_t *clone_table(Namval_t* n
 	Dt_t		*oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
 	if(!nroot)
 		return(0);
+	dtuserdata(nroot,dtuserdata(oroot,0,0),1);
 	memcpy((void*)ntp,(void*)fp,sizeof(struct table));
 	ntp->dict = nroot;
 	ntp->parent = nv_lastdict();
@@ -1437,6 +1442,7 @@ Namval_t *nv_mount(Namval_t *np, const c
 {
 	Namval_t *mp, *pp;
 	struct table *tp;
+	dtuserdata(dict,sh_getinterp(),1);
 	if(nv_hasdisc(np,&table_disc))
 		pp = np;
 	else
@@ -1493,6 +1499,6 @@ Namval_t *sh_fsearch(Shell_t *shp, const
 	sfputr(stkp,nv_name(shp->namespace),'.');
 	sfputr(stkp,fname,0);
 	fname = stkptr(stkp,offset);
-	return(nv_search(fname,sh_subfuntree(add&NV_ADD),add));
+	return(nv_search(fname,sh_subfuntree(shp,add&NV_ADD),add));
 }
 #endif /* SHOPT_NAMESPACE */
--- src/cmd/ksh93/sh/nvtree.c
+++ src/cmd/ksh93/sh/nvtree.c	2013-09-16 15:37:34.000000000 +0000
@@ -144,8 +144,9 @@ static  Namfun_t *nextdisc(Namval_t *np)
 
 void *nv_diropen(Namval_t *np,const char *name)
 {
-	char *next,*last;
-	int c,len=strlen(name);
+	const char *last;
+	char *next;
+	size_t c,len=strlen(name);
 	struct nvdir *save, *dp = new_of(struct nvdir,len+1);
 	Namval_t *nq=0,fake;
 	Namfun_t *nfp=0;
@@ -160,7 +161,10 @@ void *nv_diropen(Namval_t *np,const char
 	dp->len = len;
 	dp->root = sh.last_root?sh.last_root:sh.var_tree;
 #if 1
-	while(1)
+	last = &name[len];
+	if(!np)
+		np = nv_search(name,dp->root,0);
+	if(!np || !nv_isvtree(np)) while(1)
 	{
 		dp->table = sh.last_table;
 		sh.last_table = 0;
@@ -188,7 +192,7 @@ void *nv_diropen(Namval_t *np,const char
 		{
 			char *cp = nv_name(dp->hp);
 			c = strlen(cp);
-			if(memcmp(name,cp,c) || name[c]!='[')
+			if(strncmp(name,cp,c) || name[c]!='[')
 				dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
 			else
 			{
@@ -266,7 +270,7 @@ static Namval_t *nextnode(struct nvdir *
 {
 	if(dp->nextnode)
 		return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
-	if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
+	if(dp->len && strncmp(dp->data, dp->hp->nvname, dp->len))
 		return(0);
 	return((Namval_t*)dtnext(dp->root,dp->hp));
 }
@@ -311,7 +315,7 @@ char *nv_dirnext(void *dir)
 					dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
 			}
 			sh.last_table = last_table;
-			if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
+			if(!dp->len || strncmp(cp,dp->data,dp->len)==0)
 			{
 				if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
 					nfp = 0;
@@ -703,6 +707,7 @@ static void outval(char *name, const cha
 	if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
 	{
 		wp->shp->last_table = last_table;
+		wp->flags &= ~NV_COMVAR;
 		return;
 	}
 	if(!wp->out)
@@ -739,8 +744,20 @@ static void outval(char *name, const cha
 				break;
 		}
 		if(!xp)
+		{
+			if(nv_type(np) || !(wp->flags&NV_COMVAR))
+			{
+				wp->flags &= ~NV_COMVAR;
+				return;
+			}
+			if(wp->indent>0)
+				sfnputc(wp->out,'\t',wp->indent);
+			nv_attribute(np,wp->out,"typeset",' ');
+			sfputr(wp->out,name,wp->indent>0?'\n':-1);
 			return;
+		}
 	}
+	wp->flags &= ~NV_COMVAR;
 	if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
 		return;
 	if(special || (nv_isarray(np) && nv_arrayptr(np)))
@@ -927,6 +944,17 @@ static char **genvalue(char **argv, cons
 			}
 			else
 			{
+				if(n && *cp &&  cp[-1]!='.' && cp[-1]!='[')
+					break;
+				if(outfile && wp->indent<0 && (wp->flags&NV_COMVAR))
+					sfputc(outfile,';');
+				wp->flags |= NV_COMVAR;
+				if(argv[1])
+				{
+					ssize_t r = (cp-argv[0]) + strlen(cp);
+					if(argv[1][r]=='.' && strncmp(argv[0],argv[1],r)==0)
+						wp->flags &= ~NV_COMVAR;
+				}
 				outval(cp,arg,wp);
 				if(wp->array)
 				{
@@ -943,6 +971,7 @@ static char **genvalue(char **argv, cons
 		wp->nofollow = 0;
 	}
 	wp->array = 0;
+	wp->flags &= ~NV_COMVAR;
 	if(outfile)
 	{
 		int c = prefix[m-1];
@@ -1031,9 +1060,18 @@ static char *walk_tree(register Namval_t
 			shp->var_tree = dp;
 			if(nq && mq)
 			{
+				register struct nvdir *odir=0,*dp = (struct nvdir*)dir;
+				if(dp->table==nq)
+				{
+					dp = dp->prev;
+					odir = dir;
+					dir = dp;
+				}
 				nv_clone(nq,mq,flags|NV_RAW);
 				if(flags&NV_MOVE)
 					nv_delete(nq,walk.root,0);
+				if(odir)
+					free(odir);
 			}
 			continue;
 		}
--- src/cmd/ksh93/sh/nvtype.c
+++ src/cmd/ksh93/sh/nvtype.c	2013-09-17 13:37:34.000000000 +0000
@@ -484,7 +484,10 @@ static Namfun_t *clone_type(Namval_t* np
 		}
 	}
 	if(nv_isattr(mp,NV_BINARY))
+	{
 		mp->nvalue.cp = dp->data;
+		nv_onattr(mp,NV_NOFREE);
+	}
 	if(pp->strsize<0)
 		dp->strsize = -pp->strsize;
 	return(&dp->fun);
--- src/cmd/ksh93/sh/parse.c
+++ src/cmd/ksh93/sh/parse.c	2013-09-13 16:21:49.000000000 +0000
@@ -1722,6 +1722,7 @@ static struct ionod	*inout(Lex_t *lexp,s
 	lexp->digits=0;
 	iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
 	iop->iodelim = 0;
+	iop->iosize = 0;
 	if(token=sh_lex(lexp))
 	{
 		if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub) 
--- src/cmd/ksh93/sh/path.c
+++ src/cmd/ksh93/sh/path.c	2013-09-17 13:49:01.000000000 +0000
@@ -592,7 +592,7 @@ static void funload(Shell_t *shp,int fno
 	pname = path_fullname(shp,stakptr(PATH_OFFSET));
 	if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
 	{
-		Dt_t	*funtree = sh_subfuntree(1);
+		Dt_t	*funtree = sh_subfuntree(shp,1);
 		while(1)
 		{
 			rpfirst = dtprev(shp->fpathdict,rp);
@@ -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);
@@ -868,15 +869,15 @@ Pathcomp_t *path_absolute(Shell_t *shp,r
 		if(isfun && f>=0 && (cp = strrchr(name,'.')))
 		{
 			*cp = 0;
-			if(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
+			if(nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
 				f = -1;
 			*cp = '.';
 		}
 		if(isfun && f>=0)
 		{
-			nv_onattr(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
+			nv_onattr(nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
 			funload(shp,f,name);
-			close(f);
+			sh_close(f);
 			f = -1;
 			return(0);
 		}
@@ -1408,7 +1409,7 @@ static void exscript(Shell_t *shp,regist
 		sabuf.ac_etime = compress( (time_t)(after-before));
 		fd = open( SHACCT , O_WRONLY | O_APPEND | O_CREAT,RW_ALL);
 		write(fd, (const char*)&sabuf, sizeof( sabuf ));
-		close( fd);
+		sh_close( fd);
 	}
     }
  
--- src/cmd/ksh93/sh/streval.c
+++ src/cmd/ksh93/sh/streval.c	2013-09-17 15:21:23.000000000 +0000
@@ -165,14 +165,11 @@ Sfdouble_t	arith_exec(Arith_t *ep)
 	Math_f fun;
 	struct lval node;
 	Shell_t	*shp = ep->shp;
+	memset(&node,0,sizeof(node));
 	node.shp = shp;
 	node.emode = ep->emode;
 	node.expr = ep->expr;
 	node.elen = ep->elen;
-	node.value = 0;
-	node.nosub = 0;
-	node.ptr = 0;
-	node.eflag = 0;
 	if(level++ >=MAXLEVEL)
 	{
 		arith_error(e_recursive,ep->expr,ep->emode);
--- src/cmd/ksh93/sh/subshell.c
+++ src/cmd/ksh93/sh/subshell.c	2013-09-17 15:12:00.000000000 +0000
@@ -122,23 +122,26 @@ 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)
 		{
+			int err=errno;
 			fcntl(fd,F_SETFD,FD_CLOEXEC);
 			shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
-			close(1);
+			while(close(1)<0 && errno==EINTR)
+				errno = err;
 		}
 		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 */
 			int fds[3];
 			Sfoff_t off;
 			fds[2] = 0;
-			sh_pipe(fds);
+			sh_rpipe(fds);
 			sp->pipefd = fds[0];
 			sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
 			/* write the data to the pipe */
@@ -180,7 +183,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)
@@ -213,7 +216,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;
 	}
 }
@@ -337,7 +340,7 @@ static void nv_restore(struct subshell *
 		}
 		nv_setsize(mp,nv_size(np));
 		if(!(flags&NV_MINIMAL))
-			mp->nvenv = np->nvenv;
+			mp->nvenv = nv_isnull(mp)?0:np->nvenv;
 		if(!nofree)
 			mp->nvfun = np->nvfun;
 		if(nv_isattr(np,NV_IDENT))
@@ -379,7 +382,7 @@ static void nv_restore(struct subshell *
  * return pointer to alias tree
  * create new one if in a subshell and one doesn't exist and create is non-zero
  */
-Dt_t *sh_subaliastree(int create)
+Dt_t *sh_subaliastree(Shell_t *shp,int create)
 {
 	register struct subshell *sp = subshell_data;
 	if(!sp || sp->shp->curenv==0)
@@ -387,6 +390,7 @@ Dt_t *sh_subaliastree(int create)
 	if(!sp->salias && create)
 	{
 		sp->salias = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(sp->salias,shp,1);
 		dtview(sp->salias,sp->shp->alias_tree);
 		sp->shp->alias_tree = sp->salias;
 	}
@@ -397,7 +401,7 @@ Dt_t *sh_subaliastree(int create)
  * return pointer to function tree
  * create new one if in a subshell and one doesn't exist and create is non-zero
  */
-Dt_t *sh_subfuntree(int create)
+Dt_t *sh_subfuntree(Shell_t *shp,int create)
 {
 	register struct subshell *sp = subshell_data;
 	if(!sp || sp->shp->curenv==0)
@@ -405,6 +409,7 @@ Dt_t *sh_subfuntree(int create)
 	if(!sp->sfun && create)
 	{
 		sp->sfun = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(sp->sfun,shp,1);
 		dtview(sp->sfun,sp->shp->fun_tree);
 		sp->shp->fun_tree = sp->sfun;
 	}
@@ -492,6 +497,8 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 		subenv = 0;
 	}
 	shp->curenv = ++subenv;
+	if(shp->curenv<=0)
+		shp->curenv = subenv = 1;
 	savst = shp->st;
 	sh_pushcontext(shp,&buff,SH_JMPSUB);
 	subshell = shp->subshell+1;
@@ -506,6 +513,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 	sp->options = shp->options;
 	sp->jobs = job_subsave();
 	sp->subdup = shp->subdup;
+	shp->subdup = 0;
 #if SHOPT_COSHELL
 	sp->coshell = shp->coshell;
 	shp->coshell = 0;
@@ -528,7 +536,9 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 		job.curpgid = 0;
 	sp->subshare = shp->subshare;
 	sp->comsub = shp->comsub;
-	shp->subshare = comsub==2 ||  (comsub==1 && sh_isoption(SH_SUBSHARE));
+	shp->subshare = comsub==2 ||  (comsub && sh_isoption(SH_SUBSHARE));
+	if(!shp->subshare)
+		sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
 	if(comsub)
 		shp->comsub = comsub;
 	if(!comsub || !shp->subshare)
@@ -602,7 +612,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 			sp->tmpfd = -1;
 			sp->pipefd = -1;
 			/* use sftmp() file for standard output */
-			if(!(iop = sftmp(PIPE_BUF)))
+			if(!(iop = sftmp(comsub==1?PIPE_BUF:IOBSIZE)))
 			{
 				sfswap(sp->saveout,sfstdout);
 				errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
@@ -688,19 +698,27 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 			}
 			sfset(iop,SF_READ,1);
 		}
-		sfswap(sp->saveout,sfstdout);
+		if(sp->saveout)
+			sfswap(sp->saveout,sfstdout);
+		else
+			sfstdout = &_Sfstdout;
 		/*  check if standard output was preserved */
 		if(sp->tmpfd>=0)
 		{
-			close(1);
+			int err=errno;
+			while(close(1)<0 && errno==EINTR)
+				errno = err;
 			if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
 				duped++;
 			sh_close(sp->tmpfd);
 		}
 		shp->fdstatus[1] = sp->fdstatus;
 	}
-	path_delete((Pathcomp_t*)shp->pathlist);
-	shp->pathlist = (void*)sp->pathlist;
+	if(!shp->subshare)
+	{
+		path_delete((Pathcomp_t*)shp->pathlist);
+		shp->pathlist = (void*)sp->pathlist;
+	}
 	job_subrestore(sp->jobs);
 	shp->jobenv = savecurenv;
 	job.curpgid = savejobpgid;
@@ -776,7 +794,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
 		shp->coutpipe = sp->coutpipe;
 	}
 	shp->subshare = sp->subshare;
-	shp->comsub = sp->comsub;
 	shp->subdup = sp->subdup;
 #if SHOPT_COSHELL
 	shp->coshell = sp->coshell;
@@ -806,7 +823,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)
+			sh_iounpipe(shp);
+	}
+	shp->comsub = sp->comsub;
 	if(comsub && iop && sp->pipefd<0)
 		sfseek(iop,(off_t)0,SEEK_SET);
 	if(shp->trapnote)
--- src/cmd/ksh93/sh/xec.c
+++ src/cmd/ksh93/sh/xec.c	2013-09-13 18:27:02.000000000 +0000
@@ -102,26 +102,30 @@ struct funenv
  * temp file.
  */
 static int      subpipe[3],subdup,tsetio,usepipe;
-static void iounpipe(Shell_t*);
 
 static int iousepipe(Shell_t *shp)
 {
-	int i;
+	int fd=sffileno(sfstdout),i,err=errno;
 	if(usepipe)
 	{
 		usepipe++;
-		iounpipe(shp);
+		sh_iounpipe(shp);
 	}
 	if(sh_rpipe(subpipe) < 0)
 		return(0);
 	usepipe++;
-	fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
-	subpipe[2] = 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 +139,23 @@ static int iousepipe(Shell_t *shp)
 	return(1);
 }
 
-static void iounpipe(Shell_t *shp)
+void sh_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 +187,7 @@ static void iounpipe(Shell_t *shp)
 		else if(errno!=EINTR)
 			break;
 	}
+done:
 	sh_close(subpipe[0]);
 	subpipe[0] = -1;
 	tsetio = 0;
@@ -748,20 +762,20 @@ static void *sh_coinit(Shell_t *shp,char
 {
 	struct cosh	*csp = job.colist;
 	const char 	*name = argv?argv[0]:0;
-	int  		id, open=1;
+	int  		id, xopen=1;
 	if(!name)
 		return(0);
 	if(*name=='-')
 	{
 		name++;
-		open=0;
+		xopen=0;
 	}
 	nv_open(name,shp->var_tree,NV_IDENT|NV_NOADD);
 	while(csp)
 	{
 		if(strcmp(name,csp->name)==0)
 		{
-			if(open)
+			if(xopen)
 			{
 				coattr(csp->coshell,argv[1]);
 				return((void*)csp);
@@ -771,7 +785,7 @@ static void *sh_coinit(Shell_t *shp,char
 		}
 		csp = csp->next;
 	}
-	if(!open)
+	if(!xopen)
 		errormsg(SH_DICT,ERROR_exit(1),"%s: unknown namespace",name);
 	environ[0][2]=0;
 	csp = newof(0,struct cosh,1,strlen(name)+1);
@@ -898,13 +912,14 @@ static int sh_coexec(Shell_t *shp,const
 #if SHOPT_FILESCAN
     static Sfio_t *openstream(Shell_t *shp, struct ionod *iop, int *save)
     {
-	int savein, fd = sh_redirect(shp,iop,3);
+	int err=errno,savein, fd = sh_redirect(shp,iop,3);
 	Sfio_t	*sp;
 	savein = dup(0);
 	if(fd==0)
 		fd = savein;
 	sp = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
-	close(0);
+	while(close(0)<0 && errno==EINTR)
+		errno = err;
 	open(e_devnull,O_RDONLY);
 	shp->offsets[0] = -1;
 	shp->offsets[1] = 0;
@@ -1207,7 +1222,9 @@ int sh_exec(register const Shnode_t *t,
 					if(OPTIMIZE)
 						flgs |= NV_TAGGED;
 #endif
-					nv_setlist(argp,flgs,tp);
+					if (np && nv_isattr(np,BLT_DCL))
+						flgs |= NV_DECL;
+					shp->nodelist = nv_setlist(argp,flgs,tp);
 					if(np==shp->typeinit)
 						shp->typeinit = 0;
 					shp->envlist = argp;
@@ -1570,7 +1587,7 @@ int sh_exec(register const Shnode_t *t,
 						unset_instance(nq,&node,&nr,mode);
 					sh_funstaks(slp->slchild,-1);
 					stakdelete(slp->slptr);
-					if(jmpval > SH_JMPFUN)
+					if(jmpval > SH_JMPFUN || (io && jmpval>SH_JMPIO))
 						siglongjmp(*shp->jmplist,jmpval);
 					goto setexit;
 				}
@@ -1597,10 +1614,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]) &&
@@ -1676,7 +1697,7 @@ int sh_exec(register const Shnode_t *t,
 				if(parent<0)
 				{
 					if(shp->comsub==1 && usepipe && unpipe)
-						iounpipe(shp);
+						sh_iounpipe(shp);
 					break;
 				}
 #else
@@ -1693,7 +1714,7 @@ int sh_exec(register const Shnode_t *t,
 				if(parent<0)
 				{
 					if(shp->comsub==1 && usepipe && unpipe)
-						iounpipe(shp);
+						sh_iounpipe(shp);
 					break;
 				}
 #else
@@ -1715,6 +1736,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))
@@ -1733,8 +1756,8 @@ int sh_exec(register const Shnode_t *t,
 						job_wait(parent);
 					if(shp->topfd > topfd)
 						sh_iorestore(shp,topfd,0);
-					if(usepipe && tsetio &&  subdup && unpipe)
-						iounpipe(shp);
+					if(usepipe && tsetio &&  subdup)
+						sh_iounpipe(shp);
 					if(!sh_isoption(SH_MONITOR))
 					{
 						shp->trapnote &= ~SH_SIGIGNORE;
@@ -1906,8 +1929,8 @@ int sh_exec(register const Shnode_t *t,
 			{
 				was_interactive = sh_isstate(SH_INTERACTIVE);
 				sh_offstate(SH_INTERACTIVE);
-				sh_iosave(shp,0,shp->topfd,(char*)0);
 				shp->pipepid = simple;
+				sh_iosave(shp,0,shp->topfd,(char*)0);
 				sh_iorenumber(shp,shp->inpipe[0],0);
 				/*
 				 * if read end of pipe is a simple command
@@ -1924,7 +1947,7 @@ int sh_exec(register const Shnode_t *t,
 			jmpval = sigsetjmp(buffp->buff,0);
 			if(jmpval==0)
 			{
-				if(shp->comsub==1)
+				if(shp->comsub)
 					tsetio = 1;
 				sh_redirect(shp,t->fork.forkio,execflg);
 				(t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
@@ -1953,8 +1976,8 @@ int sh_exec(register const Shnode_t *t,
 					if(type || !sh_isoption(SH_PIPEFAIL))
 						shp->exitval = type;
 				}
-				if(shp->comsub==1 && usepipe)
-					iounpipe(shp);
+				if(shp->comsub==1 && usepipe && unpipe)
+					sh_iounpipe(shp);
 				shp->pipepid = 0;
 				shp->st.ioset = 0;
 				if(simple && was_errexit)
@@ -2179,7 +2202,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_isstate(SH_INTERACTIVE))
 				tcsetpgrp(JOBTTY,shp->gd->pid);
 #endif /*SIGTSTP */
 			job.curpgid = savepgid;
@@ -2320,7 +2343,10 @@ int sh_exec(register const Shnode_t *t,
 					nv_putsub(np,NIL(char*),0L);
 				nv_putval(np,cp,0);
 				if(nameref)
+				{
 					nv_setref(np,(Dt_t*)0,NV_VARNAME);
+					nv_onattr(np,NV_TABLE);
+				}
 				if(trap=shp->st.trap[SH_DEBUGTRAP])
 				{
 					av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
@@ -2352,6 +2378,8 @@ int sh_exec(register const Shnode_t *t,
 				if(shp->st.breakcnt<0)
 					shp->st.execbrk = (++shp->st.breakcnt !=0);
 			}
+			if(nameref)
+				nv_offattr(np,NV_TABLE);
 #if SHOPT_OPTIMIZE
 		endfor:
 			sh_popcontext(shp,buffp);
@@ -2466,8 +2494,10 @@ int sh_exec(register const Shnode_t *t,
 #if SHOPT_FILESCAN
 			if(iop)
 			{
+				int err=errno;
 				sfclose(iop);
-				close(0);
+				while(close(0)<0 && errno==EINTR)
+					errno = err;
 				dup(savein);
 				shp->cur_line = 0;
 			}
@@ -2688,6 +2718,7 @@ int sh_exec(register const Shnode_t *t,
 				else
 				{
 					root = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(root,shp,1);
 					nv_mount(np, (char*)0, root);
 					np->nvalue.cp = Empty;
 					dtview(root,shp->var_base);
@@ -2729,7 +2760,7 @@ int sh_exec(register const Shnode_t *t,
 				np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
 			if(!np)
 #endif /* SHOPT_NAMESPACE */
-			np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
+			np = nv_open(fname,sh_subfuntree(shp,1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
 			if(npv)
 			{
 				if(!shp->mktype)
@@ -2745,7 +2776,7 @@ int sh_exec(register const Shnode_t *t,
 				stakdelete(slp->slptr);
 				if(rp->sdict)
 				{
-					Namval_t *mp, *nq;
+					Namval_t *nq;
 					shp->last_root = rp->sdict;
 					for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
 					{
@@ -2799,7 +2830,8 @@ int sh_exec(register const Shnode_t *t,
 					rp->np = np;
 					if(!shp->fpathdict)
 						shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
-					if(shp->fpathdict) {
+					if(shp->fpathdict)
+					{
 						dtuserdata(shp->fpathdict,shp,1);
 						dtinsert(shp->fpathdict,rp);
 					}
@@ -2909,6 +2941,15 @@ int sh_exec(register const Shnode_t *t,
 			break;
 		    }
 		}
+		if(shp->procsub && *shp->procsub)
+		{
+			pid_t pid, *procsub;
+			int exitval = shp->exitval;
+			for(procsub=shp->procsub;pid=*procsub;procsub++)
+				job_wait(pid);
+			*shp->procsub = 0;
+			shp->exitval = exitval;
+		}
 		if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
 			t && echeck) 
 			sh_chktrap(shp);
@@ -3165,7 +3206,7 @@ pid_t _sh_fork(Shell_t *shp,register pid
 			{
 				if(shp->topfd > restorefd)
 					sh_iorestore(shp,restorefd,0);
-				iounpipe(shp);
+				sh_iounpipe(shp);
 			}
 		}
 		return(parent);
@@ -3477,8 +3518,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)
@@ -3521,7 +3561,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
@@ -3626,11 +3665,11 @@ 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);
-				close(outfd);
+				sh_close(outfd);
 			        shp->fdstatus[outfd] = IOCLOSE;
 				shp->cpipe[1] = fd;
 			}
@@ -3719,7 +3758,7 @@ static int run_subshell(Shell_t *shp,con
 	if(!shp->gd->shpath)
 		shp->gd->shpath = pathshell();
 	pid = spawnveg(shp->shpath,arglist,envlist,grp);
-	close(fd);
+	sh_close(fd);
 	for(i=3; i < 10; i++)
 	{
 		if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
@@ -4000,7 +4039,7 @@ static pid_t sh_ntfork(Shell_t *shp,cons
 				shp->gd->shpath = pathshell();
 			spawnpid = path_spawn(shp,shp->gd->shpath,&argv[-1],arge,pp,(grp<<1)|1);
 			if(fd>=0)
-				close(fd);
+				sh_close(fd);
 			argv[0] = argv[-1];
 		}
 	fail:
openSUSE Build Service is sponsored by