diff options
Diffstat (limited to 'Src/exec.c')
-rw-r--r-- | Src/exec.c | 424 |
1 files changed, 214 insertions, 210 deletions
diff --git a/Src/exec.c b/Src/exec.c index 109a04a26..c0ee527b7 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -176,7 +176,8 @@ mod_export int sfcontext; /**/ struct execstack *exstack; -/* Stack with names of functions currently active. */ +/* Stack with names of function calls, 'source' calls, and 'eval' calls + * currently active. */ /**/ mod_export Funcstack funcstack; @@ -1363,7 +1364,8 @@ sublist_done: * we hit execcmd on the way down. We're now * on the way back up, so don't restore it. */ - noerrexit = (oldnoerrexit == 2) ? 0 : oldnoerrexit; + if (oldnoerrexit != 2) + noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) { /* @@ -2288,7 +2290,7 @@ addvars(Estate state, Wordcode pc, int addflags) if (vl && htok) { prefork(vl, (isstr ? (PREFORK_SINGLE|PREFORK_ASSIGN) : - PREFORK_ASSIGN)); + PREFORK_ASSIGN), NULL); if (errflag) { state->pc = opc; return; @@ -2414,7 +2416,7 @@ void execsubst(LinkList strs) { if (strs) { - prefork(strs, esprefork); + prefork(strs, esprefork, NULL); if (esglob && !errflag) { LinkList ostrs = strs; globlist(strs, 0); @@ -2719,7 +2721,7 @@ execcmd(Estate state, int input, int output, int how, int last1) /* Do prefork substitutions */ esprefork = (assign || isset(MAGICEQUALSUBST)) ? PREFORK_TYPESET : 0; if (args && htok) - prefork(args, esprefork); + prefork(args, esprefork, NULL); if (type == WC_SIMPLE || type == WC_TYPESET) { int unglobbed = 0; @@ -3556,7 +3558,7 @@ execcmd(Estate state, int input, int output, int how, int last1) */ /* Unused dummy value for name */ (void)ecgetstr(state, EC_DUPTOK, &htok); - prefork(&svl, PREFORK_TYPESET); + prefork(&svl, PREFORK_TYPESET, NULL); if (errflag) { state->pc = opc; break; @@ -3582,7 +3584,7 @@ execcmd(Estate state, int input, int output, int how, int last1) } continue; } - prefork(&svl, PREFORK_SINGLE); + prefork(&svl, PREFORK_SINGLE, NULL); name = empty(&svl) ? "" : (char *)getdata(firstnode(&svl)); } @@ -3598,7 +3600,9 @@ execcmd(Estate state, int input, int output, int how, int last1) } else { if (htok) { init_list1(svl, val); - prefork(&svl, PREFORK_SINGLE|PREFORK_ASSIGN); + prefork(&svl, + PREFORK_SINGLE|PREFORK_ASSIGN, + NULL); if (errflag) { state->pc = opc; break; @@ -3620,7 +3624,7 @@ execcmd(Estate state, int input, int output, int how, int last1) EC_DUPTOK, &htok); if (asg->value.array) { - prefork(asg->value.array, PREFORK_ASSIGN); + prefork(asg->value.array, PREFORK_ASSIGN, NULL); if (errflag) { state->pc = opc; break; @@ -5065,230 +5069,230 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif + Heap funcheap; queue_signals(); /* Lots of memory and global state changes coming */ - pushheap(); + NEWHEAPS(funcheap) { + oargv0 = NULL; + obreaks = breaks; + ocontflag = contflag; + oloops = loops; + if (trap_state == TRAP_STATE_PRIMED) + trap_return--; + oldlastval = lastval; + oldnumpipestats = numpipestats; + if (noreturnval) { + /* + * Easiest to use the heap here since we're bracketed + * immediately by a pushheap/popheap pair. + */ + size_t bytes = sizeof(int)*numpipestats; + oldpipestats = (int *)zhalloc(bytes); + memcpy(oldpipestats, pipestats, bytes); + } - oargv0 = NULL; - obreaks = breaks; - ocontflag = contflag; - oloops = loops; - if (trap_state == TRAP_STATE_PRIMED) - trap_return--; - oldlastval = lastval; - oldnumpipestats = numpipestats; - if (noreturnval) { - /* - * Easiest to use the heap here since we're bracketed - * immediately by a pushheap/popheap pair. - */ - size_t bytes = sizeof(int)*numpipestats; - oldpipestats = (int *)zhalloc(bytes); - memcpy(oldpipestats, pipestats, bytes); - } + starttrapscope(); + startpatternscope(); + + pptab = pparams; + if (!(flags & PM_UNDEFINED)) + scriptname = dupstring(name); + oldzoptind = zoptind; + oldoptcind = optcind; + if (!isset(POSIXBUILTINS)) { + zoptind = 1; + optcind = 0; + } - starttrapscope(); - startpatternscope(); - - pptab = pparams; - if (!(flags & PM_UNDEFINED)) - scriptname = dupstring(name); - oldzoptind = zoptind; - oldoptcind = optcind; - if (!isset(POSIXBUILTINS)) { - zoptind = 1; - optcind = 0; - } + /* We need to save the current options even if LOCALOPTIONS is * + * not currently set. That's because if it gets set in the * + * function we need to restore the original options on exit. */ + memcpy(saveopts, opts, sizeof(opts)); + saveemulation = emulation; + save_sticky = sticky; - /* We need to save the current options even if LOCALOPTIONS is * - * not currently set. That's because if it gets set in the * - * function we need to restore the original options on exit. */ - memcpy(saveopts, opts, sizeof(opts)); - saveemulation = emulation; - save_sticky = sticky; + if (sticky_emulation_differs(shfunc->sticky)) { + /* + * Function is marked for sticky emulation. + * Enable it now. + * + * We deliberately do not do this if the sticky emulation + * in effect is the same as that requested. This enables + * option setting naturally within emulation environments. + * Note that a difference in EMULATE_FULLY (emulate with + * or without -R) counts as a different environment. + * + * This propagates the sticky emulation to subfunctions. + */ + sticky = sticky_emulation_dup(shfunc->sticky, 1); + emulation = sticky->emulation; + restore_sticky = 1; + installemulation(emulation, opts); + if (sticky->n_on_opts) { + OptIndex *onptr; + for (onptr = sticky->on_opts; + onptr < sticky->on_opts + sticky->n_on_opts; + onptr++) + opts[*onptr] = 1; + } + if (sticky->n_off_opts) { + OptIndex *offptr; + for (offptr = sticky->off_opts; + offptr < sticky->off_opts + sticky->n_off_opts; + offptr++) + opts[*offptr] = 0; + } + /* All emulations start with pattern disables clear */ + clearpatterndisables(); + } else + restore_sticky = 0; - if (sticky_emulation_differs(shfunc->sticky)) { + if (flags & (PM_TAGGED|PM_TAGGED_LOCAL)) + opts[XTRACE] = 1; + else if (oflags & PM_TAGGED_LOCAL) + opts[XTRACE] = 0; + ooflags = oflags; /* - * Function is marked for sticky emulation. - * Enable it now. - * - * We deliberately do not do this if the sticky emulation - * in effect is the same as that requested. This enables - * option setting naturally within emulation environments. - * Note that a difference in EMULATE_FULLY (emulate with - * or without -R) counts as a different environment. - * - * This propagates the sticky emulation to subfunctions. + * oflags is static, because we compare it on the next recursive + * call. Hence also we maintain ooflags for restoring the previous + * value of oflags after the call. */ - sticky = sticky_emulation_dup(shfunc->sticky, 1); - emulation = sticky->emulation; - restore_sticky = 1; - installemulation(emulation, opts); - if (sticky->n_on_opts) { - OptIndex *onptr; - for (onptr = sticky->on_opts; - onptr < sticky->on_opts + sticky->n_on_opts; - onptr++) - opts[*onptr] = 1; - } - if (sticky->n_off_opts) { - OptIndex *offptr; - for (offptr = sticky->off_opts; - offptr < sticky->off_opts + sticky->n_off_opts; - offptr++) - opts[*offptr] = 0; - } - /* All emulations start with pattern disables clear */ - clearpatterndisables(); - } else - restore_sticky = 0; - - if (flags & (PM_TAGGED|PM_TAGGED_LOCAL)) - opts[XTRACE] = 1; - else if (oflags & PM_TAGGED_LOCAL) - opts[XTRACE] = 0; - ooflags = oflags; - /* - * oflags is static, because we compare it on the next recursive - * call. Hence also we maintain ooflags for restoring the previous - * value of oflags after the call. - */ - oflags = flags; - opts[PRINTEXITVALUE] = 0; - if (doshargs) { - LinkNode node; - - node = firstnode(doshargs); - pparams = x = (char **) zshcalloc(((sizeof *x) * - (1 + countlinknodes(doshargs)))); - if (isset(FUNCTIONARGZERO)) { - oargv0 = argzero; - argzero = ztrdup(getdata(node)); - } - /* first node contains name regardless of option */ - node = node->next; - for (; node; node = node->next, x++) - *x = ztrdup(getdata(node)); - } else { - pparams = (char **) zshcalloc(sizeof *pparams); - if (isset(FUNCTIONARGZERO)) { - oargv0 = argzero; - argzero = ztrdup(argzero); + oflags = flags; + opts[PRINTEXITVALUE] = 0; + if (doshargs) { + LinkNode node; + + node = firstnode(doshargs); + pparams = x = (char **) zshcalloc(((sizeof *x) * + (1 + countlinknodes(doshargs)))); + if (isset(FUNCTIONARGZERO)) { + oargv0 = argzero; + argzero = ztrdup(getdata(node)); + } + /* first node contains name regardless of option */ + node = node->next; + for (; node; node = node->next, x++) + *x = ztrdup(getdata(node)); + } else { + pparams = (char **) zshcalloc(sizeof *pparams); + if (isset(FUNCTIONARGZERO)) { + oargv0 = argzero; + argzero = ztrdup(argzero); + } } - } #ifdef MAX_FUNCTION_DEPTH - if(++funcdepth > MAX_FUNCTION_DEPTH) - { - zerr("maximum nested function level reached"); - goto undoshfunc; - } + if(++funcdepth > MAX_FUNCTION_DEPTH) + { + zerr("maximum nested function level reached"); + goto undoshfunc; + } #endif - fstack.name = dupstring(name); - /* - * The caller is whatever is immediately before on the stack, - * unless we're at the top, in which case it's the script - * or interactive shell name. - */ - fstack.caller = funcstack ? funcstack->name : - dupstring(oargv0 ? oargv0 : argzero); - fstack.lineno = lineno; - fstack.prev = funcstack; - fstack.tp = FS_FUNC; - funcstack = &fstack; - - fstack.flineno = shfunc->lineno; - fstack.filename = dupstring(shfunc->filename); - - prog = shfunc->funcdef; - if (prog->flags & EF_RUN) { - Shfunc shf; + fstack.name = dupstring(name); + /* + * The caller is whatever is immediately before on the stack, + * unless we're at the top, in which case it's the script + * or interactive shell name. + */ + fstack.caller = funcstack ? funcstack->name : + dupstring(oargv0 ? oargv0 : argzero); + fstack.lineno = lineno; + fstack.prev = funcstack; + fstack.tp = FS_FUNC; + funcstack = &fstack; - prog->flags &= ~EF_RUN; + fstack.flineno = shfunc->lineno; + fstack.filename = dupstring(shfunc->filename); - runshfunc(prog, NULL, fstack.name); + prog = shfunc->funcdef; + if (prog->flags & EF_RUN) { + Shfunc shf; - if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, - (name = fname)))) { - zwarn("%s: function not defined by file", name); - if (noreturnval) - errflag |= ERRFLAG_ERROR; - else - lastval = 1; - goto doneshfunc; + prog->flags &= ~EF_RUN; + + runshfunc(prog, NULL, fstack.name); + + if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, + (name = fname)))) { + zwarn("%s: function not defined by file", name); + if (noreturnval) + errflag |= ERRFLAG_ERROR; + else + lastval = 1; + goto doneshfunc; + } + prog = shf->funcdef; } - prog = shf->funcdef; - } - runshfunc(prog, wrappers, fstack.name); - doneshfunc: - funcstack = fstack.prev; + runshfunc(prog, wrappers, fstack.name); + doneshfunc: + funcstack = fstack.prev; #ifdef MAX_FUNCTION_DEPTH - undoshfunc: - --funcdepth; + undoshfunc: + --funcdepth; #endif - if (retflag) { - retflag = 0; - breaks = obreaks; - } - freearray(pparams); - if (oargv0) { - zsfree(argzero); - argzero = oargv0; - } - pparams = pptab; - if (!isset(POSIXBUILTINS)) { - zoptind = oldzoptind; - optcind = oldoptcind; - } - scriptname = oldscriptname; - oflags = ooflags; + if (retflag) { + retflag = 0; + breaks = obreaks; + } + freearray(pparams); + if (oargv0) { + zsfree(argzero); + argzero = oargv0; + } + pparams = pptab; + if (!isset(POSIXBUILTINS)) { + zoptind = oldzoptind; + optcind = oldoptcind; + } + scriptname = oldscriptname; + oflags = ooflags; - endpatternscope(); /* before restoring old LOCALPATTERNS */ + endpatternscope(); /* before restoring old LOCALPATTERNS */ - if (restore_sticky) { - /* - * If we switched to an emulation environment just for - * this function, we interpret the option and emulation - * switch as being a firewall between environments. - */ - memcpy(opts, saveopts, sizeof(opts)); - emulation = saveemulation; - sticky = save_sticky; - } else if (isset(LOCALOPTIONS)) { - /* restore all shell options except PRIVILEGED and RESTRICTED */ - saveopts[PRIVILEGED] = opts[PRIVILEGED]; - saveopts[RESTRICTED] = opts[RESTRICTED]; - memcpy(opts, saveopts, sizeof(opts)); - emulation = saveemulation; - } else { - /* just restore a couple. */ - opts[XTRACE] = saveopts[XTRACE]; - opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE]; - opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; - opts[LOCALLOOPS] = saveopts[LOCALLOOPS]; - } + if (restore_sticky) { + /* + * If we switched to an emulation environment just for + * this function, we interpret the option and emulation + * switch as being a firewall between environments. + */ + memcpy(opts, saveopts, sizeof(opts)); + emulation = saveemulation; + sticky = save_sticky; + } else if (isset(LOCALOPTIONS)) { + /* restore all shell options except PRIVILEGED and RESTRICTED */ + saveopts[PRIVILEGED] = opts[PRIVILEGED]; + saveopts[RESTRICTED] = opts[RESTRICTED]; + memcpy(opts, saveopts, sizeof(opts)); + emulation = saveemulation; + } else { + /* just restore a couple. */ + opts[XTRACE] = saveopts[XTRACE]; + opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE]; + opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; + opts[LOCALLOOPS] = saveopts[LOCALLOOPS]; + } - if (opts[LOCALLOOPS]) { - if (contflag) - zwarn("`continue' active at end of function scope"); - if (breaks) - zwarn("`break' active at end of function scope"); - breaks = obreaks; - contflag = ocontflag; - loops = oloops; - } + if (opts[LOCALLOOPS]) { + if (contflag) + zwarn("`continue' active at end of function scope"); + if (breaks) + zwarn("`break' active at end of function scope"); + breaks = obreaks; + contflag = ocontflag; + loops = oloops; + } - endtrapscope(); + endtrapscope(); - if (trap_state == TRAP_STATE_PRIMED) - trap_return++; - ret = lastval; - if (noreturnval) { - lastval = oldlastval; - numpipestats = oldnumpipestats; - memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats); - } - popheap(); + if (trap_state == TRAP_STATE_PRIMED) + trap_return++; + ret = lastval; + if (noreturnval) { + lastval = oldlastval; + numpipestats = oldnumpipestats; + memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats); + } + } OLDHEAPS; unqueue_signals(); |