| Fix for bnc#814135, bnc#808449, and bnc#838475 | - 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= 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<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<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<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<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 * 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<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: