From 839a72de105b1f52f8c24d25212f1721f4870d6c Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 31 Aug 2014 13:53:25 -0700 Subject: 33077: SHTTY = -1 when closing it in closem() --- Src/exec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Src/exec.c') diff --git a/Src/exec.c b/Src/exec.c index 5ad957f98..bf50d0f32 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3569,8 +3569,11 @@ closem(int how) for (i = 10; i <= max_zsh_fd; i++) if (fdtable[i] != FDT_UNUSED && - (how == FDT_UNUSED || fdtable[i] == how)) + (how == FDT_UNUSED || fdtable[i] == how)) { + if (i == SHTTY) + SHTTY = -1; zclose(i); + } } /* convert here document into a here string */ -- cgit v1.2.3 From a3b1e3ffb1765943aef4a1d74f66ffe5f899ac02 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 3 Sep 2014 08:46:56 -0700 Subject: 33100: check $fd more rigorously in "exec {fd}<&-" --- ChangeLog | 2 ++ Src/exec.c | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'Src/exec.c') diff --git a/ChangeLog b/ChangeLog index 09d39cd0d..5041d171f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2014-09-03 Barton E. Schaefer + * 33100: Src/exec.c: check $fd more rigorously in "exec {fd}<&-" + * 33088: Completion/Base/Widget/_complete_debug: indentation in $PS4 2014-09-01 Peter Stephenson diff --git a/Src/exec.c b/Src/exec.c index bf50d0f32..fb2739acc 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3050,7 +3050,7 @@ execcmd(Estate state, int input, int output, int how, int last1) break; case REDIR_CLOSE: if (fn->varid) { - char *s = fn->varid; + char *s = fn->varid, *t; struct value vbuf; Value v; int bad = 0; @@ -3060,13 +3060,25 @@ execcmd(Estate state, int input, int output, int how, int last1) } else if (v->pm->node.flags & PM_READONLY) { bad = 2; } else { - fn->fd1 = (int)getintvalue(v); + s = getstrvalue(v); if (errflag) bad = 1; - else if (fn->fd1 <= max_zsh_fd) { - if (fn->fd1 >= 10 && - fdtable[fn->fd1] == FDT_INTERNAL) - bad = 3; + else { + fn->fd1 = zstrtol(s, &t, 0); + if (s == t) + bad = 1; + else if (*t) { + /* Check for base#number format */ + if (*t == '#' && *s != '0') + fn->fd1 = zstrtol(s = t+1, &t, fn->fd1); + if (s == t || *t) + bad = 1; + } + if (!bad && fn->fd1 <= max_zsh_fd) { + if (fn->fd1 >= 10 && + fdtable[fn->fd1] == FDT_INTERNAL) + bad = 3; + } } } if (bad) { -- cgit v1.2.3 From 60e31a45b0c015d42e9dc8ca2c991930c3f7fd66 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 29 Sep 2014 08:59:31 -0700 Subject: 33268: interactive shells treat SIGPIPE like SIGHUP if and only if SHTTY is disconnected --- ChangeLog | 5 +++++ Src/exec.c | 2 ++ Src/init.c | 1 + Src/signals.c | 13 +++++++++++++ 4 files changed, 21 insertions(+) (limited to 'Src/exec.c') diff --git a/ChangeLog b/ChangeLog index b89f90015..3cccf62ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-09-28 Barton E. Schaefer + + * 33268: Src/exec.c, Src/init.c, Src/signals.c: interactive shells + treat SIGPIPE like SIGHUP if and only if SHTTY is disconnected + 2014-09-27 Barton E. Schaefer * 33256: Src/prompt.c: fix prompttrunc() counting of %{ %} spans diff --git a/Src/exec.c b/Src/exec.c index fb2739acc..fbd309580 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1005,6 +1005,8 @@ entersubsh(int flags) signal_default(SIGTERM); if (!(sigtrapped[SIGINT] & ZSIG_IGNORED)) signal_default(SIGINT); + if (!(sigtrapped[SIGPIPE])) + signal_default(SIGPIPE); } if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED)) signal_default(SIGQUIT); diff --git a/Src/init.c b/Src/init.c index 40f46a804..6d005dce7 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1134,6 +1134,7 @@ init_signals(void) winch_block(); /* See utils.c:preprompt() */ #endif if (interact) { + install_handler(SIGPIPE); install_handler(SIGALRM); signal_ignore(SIGTERM); } diff --git a/Src/signals.c b/Src/signals.c index cb2b58161..84a2609e5 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -594,6 +594,17 @@ zhandler(int sig) wait_for_processes(); break; + case SIGPIPE: + if (!handletrap(SIGPIPE)) { + if (!interact) + _exit(SIGPIPE); + else if (!isatty(SHTTY)) { + stopmsg = 1; + zexit(SIGPIPE, 1); + } + } + break; + case SIGHUP: if (!handletrap(SIGHUP)) { stopmsg = 1; @@ -897,6 +908,8 @@ removetrap(int sig) noholdintr(); } else if (sig == SIGHUP) install_handler(sig); + else if (sig == SIGPIPE && interact && !forklevel) + install_handler(sig); else if (sig && sig <= SIGCOUNT && #ifdef SIGWINCH sig != SIGWINCH && -- cgit v1.2.3 From cf6b0f5663e798c8d4303697115230ac4469baca Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 29 Sep 2014 21:02:59 +0100 Subject: 33285: apply function definition redirections at execution --- ChangeLog | 6 ++++ NEWS | 7 +++++ Src/exec.c | 77 ++++++++++++++++++++++++++++++++++++++++++--- Src/hashtable.c | 15 +++++++-- Src/parse.c | 87 +++++++++++++++++++++++++++++++++++++++++++++------ Src/signals.c | 2 +- Src/zsh.h | 1 + Test/A04redirect.ztst | 38 +++++++++++++++++++++- 8 files changed, 216 insertions(+), 17 deletions(-) (limited to 'Src/exec.c') diff --git a/ChangeLog b/ChangeLog index e9d167310..7fa84fb86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-09-29 Peter Stephenson + + * 33285: NEWS, Src/exec.c, Src/hashtable.c, Src/parse.c, + Src/signals.c, Src/zsh.h, Test/A04redirect.ztst: redirections in + function definitions are applied at execution not definition. + 2014-09-29 Frank Terbeck * 33277: Functions/VCS_Info/VCS_INFO_reposub: Fix diff --git a/NEWS b/NEWS index 7dc134e68..bf8969b26 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,13 @@ Changes since 5.0.0 Also, the value of $pipestatus is now updated when a job stops, not just when it exits. +- Redirections applied to function definitions take effect when the + function is executed, not when it is defined. Other shells already + work this way. For example, + fn() { echo hello } >~/logfile + Running fn writes "hello" to logfile. In older versions of the shell + it would create an empty file at the point of definition. + Changes between 4.2 and 5.0.0 ----------------------------- diff --git a/Src/exec.c b/Src/exec.c index fb2739acc..1c2a9044c 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -198,7 +198,8 @@ static char *blank_env[] = { NULL }; /* Execution functions. */ static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = { - execcursh, exectime, execfuncdef, execfor, execselect, + execcursh, exectime, NULL /* execfuncdef handled specially */, + execfor, execselect, execwhile, execrepeat, execcase, execif, execcond, execarith, execautofn, exectry }; @@ -1116,8 +1117,11 @@ execsimple(Estate state) fflush(xtrerr); } lv = (errflag ? errflag : cmdoutval); - } else + } else if (code == WC_FUNCDEF) { + lv = execfuncdef(state, NULL); + } else { lv = (execfuncs[code - WC_CURSH])(state, 0); + } thisjob = otj; @@ -2790,6 +2794,42 @@ execcmd(Estate state, int input, int output, int how, int last1) return; } + if (type == WC_FUNCDEF) { + /* + * The first word of a function definition is a list of + * names. If this is empty, we're doing an anonymous function: + * in that case redirections are handled normally. + * If not, it's a function definition: then we don't do + * redirections here but pass in the list of redirections to + * be stored for recall with the function. + */ + if (*state->pc != 0) { + /* Nonymous, don't do redirections here */ + redir = NULL; + } + } else if (is_shfunc) { + Shfunc shf = (Shfunc)hn; + /* + * A function definition may have a list of additional + * redirections to apply, so retrieve it. + */ + if (shf->redir) { + struct estate s; + LinkList redir2; + + s.prog = shf->redir; + s.pc = shf->redir->prog; + s.strs = shf->redir->strs; + redir2 = ecgetredirs(&s); + if (!redir) + redir = redir2; + else { + while (nonempty(redir2)) + addlinknode(redir, ugetnode(redir2)); + } + } + } + if (type == WC_SIMPLE && !nullexec) { char *s; char trycd = (isset(AUTOCD) && isset(SHINSTDIN) && @@ -3238,7 +3278,33 @@ execcmd(Estate state, int input, int output, int how, int last1) flags |= ESUB_REVERTPGRP; entersubsh(flags); } - if (type >= WC_CURSH) { + if (type == WC_FUNCDEF) { + Eprog redir_prog; + if (!redir && wc_code(*beg) == WC_REDIR) { + /* + * We're not using a redirection from the currently + * parsed environment, which is what we'd do for an + * anonymous function, but there are redirections we + * should store with the new function. + */ + struct estate s; + + s.prog = state->prog; + s.pc = beg; + s.strs = state->prog->strs; + + /* + * The copy uses the wordcode parsing area, so save and + * restore state. + */ + lexsave(); + redir_prog = eccopyredirs(&s); + lexrestore(); + } else + redir_prog = NULL; + + lastval = execfuncdef(state, redir_prog); + } else if (type >= WC_CURSH) { if (last1 == 1) do_exec = 1; lastval = (execfuncs[type - WC_CURSH])(state, do_exec); @@ -4235,7 +4301,7 @@ exectime(Estate state, UNUSED(int do_exec)) /**/ static int -execfuncdef(Estate state, UNUSED(int do_exec)) +execfuncdef(Estate state, Eprog redir_prog) { Shfunc shf; char *s = NULL; @@ -4305,6 +4371,7 @@ execfuncdef(Estate state, UNUSED(int do_exec)) shf->node.flags = 0; shf->filename = ztrdup(scriptfilename); shf->lineno = lineno; + shf->redir = redir_prog; shfunc_set_sticky(shf); if (!names) { @@ -4335,6 +4402,8 @@ execfuncdef(Estate state, UNUSED(int do_exec)) ret = lastval; freeeprog(shf->funcdef); + if (shf->redir) /* shouldn't be */ + freeeprog(shf->redir); zsfree(shf->filename); zfree(shf, sizeof(*shf)); break; diff --git a/Src/hashtable.c b/Src/hashtable.c index ef187927b..7a430629d 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -887,6 +887,8 @@ freeshfuncnode(HashNode hn) zsfree(shf->node.nam); if (shf->funcdef) freeeprog(shf->funcdef); + if (shf->redir) + freeeprog(shf->redir); zsfree(shf->filename); if (shf->sticky) { if (shf->sticky->n_on_opts) @@ -954,10 +956,19 @@ printshfuncnode(HashNode hn, int printflags) printf(" \"$@\""); } } - printf("\n}\n"); + printf("\n}"); } else { - printf(" () { }\n"); + printf(" () { }"); } + if (f->redir) { + t = getpermtext(f->redir, NULL, 1); + if (t) { + zputs(t, stdout); + zsfree(t); + } + } + + putchar('\n'); } /**************************************/ diff --git a/Src/parse.c b/Src/parse.c index 3633417fe..6cba05082 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -375,6 +375,8 @@ init_parse(void) /* Build eprog. */ +/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */ + static void copy_ecstr(Eccstr s, char *p) { @@ -386,24 +388,25 @@ copy_ecstr(Eccstr s, char *p) } static Eprog -bld_eprog(void) +bld_eprog(int heap) { Eprog ret; int l; ecadd(WCB_END()); - ret = (Eprog) zhalloc(sizeof(*ret)); + ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret)); ret->len = ((ecnpats * sizeof(Patprog)) + (ecused * sizeof(wordcode)) + ecsoffs); ret->npats = ecnpats; - ret->nref = -1; /* Eprog is on the heap */ - ret->pats = (Patprog *) zhalloc(ret->len); + ret->nref = heap ? -1 : 1; + ret->pats = heap ? (Patprog *) zhalloc(ret->len) : + (Patprog *) zshcalloc(ret->len); ret->prog = (Wordcode) (ret->pats + ecnpats); ret->strs = (char *) (ret->prog + ecused); ret->shf = NULL; - ret->flags = EF_HEAP; + ret->flags = heap ? EF_HEAP : EF_REAL; ret->dump = NULL; for (l = 0; l < ecnpats; l++) ret->pats[l] = dummy_patprog1; @@ -455,7 +458,7 @@ parse_event(void) clear_hdocs(); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /**/ @@ -534,7 +537,7 @@ parse_list(void) yyerror(0); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /* @@ -553,7 +556,7 @@ parse_cond(void) clear_hdocs(); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /* This adds a list wordcode. The important bit about this is that it also @@ -2554,6 +2557,73 @@ ecgetredirs(Estate s) return ret; } +/* + * Copy the consecutive set of redirections in the state at s. + * Return NULL if none, else an Eprog consisting only of the + * redirections from permanently allocated memory. + * + * s is left in the state ready for whatever follows the redirections. + */ + +/**/ +Eprog +eccopyredirs(Estate s) +{ + Wordcode pc = s->pc; + wordcode code = *pc; + int ncode, ncodes = 0, r, type; + + if (wc_code(code) != WC_REDIR) + return NULL; + + init_parse(); + + while (wc_code(code) == WC_REDIR) { + type = WC_REDIR_TYPE(code); + + DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH, + "unexpanded here document"); + + if (WC_REDIR_FROM_HEREDOC(code)) + ncode = 5; + else + ncode = 3; + if (WC_REDIR_VARID(code)) + ncode++; + pc += ncode; + ncodes += ncode; + code = *pc; + } + r = ecused; + ecispace(r, ncodes); + + code = *s->pc; + while (wc_code(code) == WC_REDIR) { + s->pc++; + + ecbuf[r++] = code; + /* fd1 */ + ecbuf[r++] = *s->pc++; + /* name or HERE string */ + /* No DUP needed as we'll copy into Eprog immediately below */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + if (WC_REDIR_FROM_HEREDOC(code)) + { + /* terminator, raw */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + /* terminator, munged */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + } + if (WC_REDIR_VARID(code)) + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + + code = *s->pc; + } + + /* bld_eprog() appends a useful WC_END marker */ + return bld_eprog(0); +} + /**/ mod_export struct eprog dummy_eprog; @@ -3546,4 +3616,3 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func) } return ret; } - diff --git a/Src/signals.c b/Src/signals.c index cb2b58161..74a39e5fb 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -752,7 +752,7 @@ dosavetrap(int sig, int level) Shfunc shf, newshf = NULL; if ((shf = (Shfunc)gettrapnode(sig, 1))) { /* Copy the node for saving */ - newshf = (Shfunc) zalloc(sizeof(*newshf)); + newshf = (Shfunc) zshcalloc(sizeof(*newshf)); newshf->node.nam = ztrdup(shf->node.nam); newshf->node.flags = shf->node.flags; newshf->funcdef = dupeprog(shf->funcdef, 0); diff --git a/Src/zsh.h b/Src/zsh.h index 8f56fa265..d284c7aa7 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1139,6 +1139,7 @@ struct shfunc { char *filename; /* Name of file located in */ zlong lineno; /* line number in above file */ Eprog funcdef; /* function definition */ + Eprog redir; /* redirections to apply */ Emulation_options sticky; /* sticky emulation definitions, if any */ }; diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index 7ad02db3b..436ae59cd 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -54,7 +54,7 @@ 0:Here-documents stripping tabs >barbar - cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" + cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" # # tabs again. sorry about the max miller. Here's a funny thing. Here is a funny thing. I went home last night. There's a funny thing. @@ -455,3 +455,39 @@ [input1 + () { + local var + read var + print I just read $var + } output1 + print Nothing output yet + cat output1 +0:anonymous function redirections are applied immediately +>Nothing output yet +>I just read any old rubbish + + redirfn() { + local var + read var + print I want to tell you about $var + print Also, this might be an error >&2 + } output2 2>&1 + print something I heard on the radio >input2 + redirfn + print No output until after this + cat output2 +0:redirections with normal function definition +>No output until after this +>I want to tell you about something I heard on the radio +>Also, this might be an error + + which redirfn +0:text output of function with redirections +>redirfn () { +> local var +> read var +> print I want to tell you about $var +> print Also, this might be an error >&2 +>} < input2 > output2 2>&1 -- cgit v1.2.3 From 8cb67e721b3f02779bf4cf0d6a368f67c49c11f8 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 29 Sep 2014 21:31:37 +0100 Subject: 33286: handle redirections for multiply named functions --- ChangeLog | 3 +++ Src/exec.c | 17 ++++++++++++++++- Test/A04redirect.ztst | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'Src/exec.c') diff --git a/ChangeLog b/ChangeLog index 7fa84fb86..b8bbbdea8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2014-09-29 Peter Stephenson + * 33286: Src/exec.c, Test/A04redirect.ztst: handle redirections + for multiple named functions. + * 33285: NEWS, Src/exec.c, Src/hashtable.c, Src/parse.c, Src/signals.c, Src/zsh.h, Test/A04redirect.ztst: redirections in function definitions are applied at execution not definition. diff --git a/Src/exec.c b/Src/exec.c index 1c2a9044c..cedadc86a 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4306,6 +4306,7 @@ execfuncdef(Estate state, Eprog redir_prog) Shfunc shf; char *s = NULL; int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0; + int nfunc = 0; Wordcode beg = state->pc, end; Eprog prog; Patprog *pp; @@ -4330,6 +4331,8 @@ execfuncdef(Estate state, Eprog redir_prog) } } + DPUTS(!names && redir_prog, + "Passing redirection to anon function definition."); while (!names || (s = (char *) ugetnode(names))) { if (!names) { prog = (Eprog) zhalloc(sizeof(*prog)); @@ -4371,7 +4374,15 @@ execfuncdef(Estate state, Eprog redir_prog) shf->node.flags = 0; shf->filename = ztrdup(scriptfilename); shf->lineno = lineno; - shf->redir = redir_prog; + /* + * redir_prog is permanently allocated --- but if + * this function has multiple names we need an additional + * one. + */ + if (nfunc++ && redir_prog) + shf->redir = dupeprog(redir_prog, 0); + else + shf->redir = redir_prog; shfunc_set_sticky(shf); if (!names) { @@ -4427,6 +4438,10 @@ execfuncdef(Estate state, Eprog redir_prog) shfunctab->addnode(shfunctab, ztrdup(s), shf); } } + if (!nfunc && redir_prog) { + /* For completeness, shouldn't happen */ + freeeprog(redir_prog); + } state->pc = end; return ret; } diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index 436ae59cd..6c38a3194 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -491,3 +491,19 @@ > print I want to tell you about $var > print Also, this might be an error >&2 >} < input2 > output2 2>&1 + + 1func 2func 3func() { print Ich heisse $0 } >output3 + for i in 1 2 3; do + f=${i}func + print Running $f + $f + cat output3 + unfunction $f + done +0:multiply named functions with redirection +>Running 1func +>Ich heisse 1func +>Running 2func +>Ich heisse 2func +>Running 3func +>Ich heisse 3func -- cgit v1.2.3 From f16813792ecefce25f0cd19ad2806eb229b0799f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 2 Oct 2014 16:15:10 +0100 Subject: 33325: fix ksh autoloads with redirections on function definitions --- ChangeLog | 5 +++ Src/exec.c | 82 ++++++++++++++++++++++++++++++++++++++------------ Test/A05execution.ztst | 13 ++++++++ 3 files changed, 81 insertions(+), 19 deletions(-) (limited to 'Src/exec.c') diff --git a/ChangeLog b/ChangeLog index 8f6e73736..fd17e025a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-10-02 Peter Stephenson + + * 33325: Src/exec.c, Test/A05execution.ztst: fix ksh autoloads + with redirections on functiond definitions. + 2014-10-01 Barton E. Schaefer * 33319: Doc/Zsh/grammar.yo: fix parens in example from 33312 diff --git a/Src/exec.c b/Src/exec.c index 10f71dab6..a5452e56e 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2789,13 +2789,6 @@ execcmd(Estate state, int input, int output, int how, int last1) errflag = 1; } - if (errflag) { - lastval = 1; - if (oautocont >= 0) - opts[AUTOCONTINUE] = oautocont; - return; - } - if (type == WC_FUNCDEF) { /* * The first word of a function definition is a list of @@ -2809,8 +2802,24 @@ execcmd(Estate state, int input, int output, int how, int last1) /* Nonymous, don't do redirections here */ redir = NULL; } - } else if (is_shfunc) { - Shfunc shf = (Shfunc)hn; + } else if (is_shfunc || type == WC_AUTOFN) { + Shfunc shf; + if (is_shfunc) + shf = (Shfunc)hn; + else { + shf = loadautofn(state->prog->shf, 1, 0); + if (shf) + state->prog->shf = shf; + else { + /* + * This doesn't set errflag, so just return now. + */ + lastval = 1; + if (oautocont >= 0) + opts[AUTOCONTINUE] = oautocont; + return; + } + } /* * A function definition may have a list of additional * redirections to apply, so retrieve it. @@ -2832,6 +2841,13 @@ execcmd(Estate state, int input, int output, int how, int last1) } } + if (errflag) { + lastval = 1; + if (oautocont >= 0) + opts[AUTOCONTINUE] = oautocont; + return; + } + if (type == WC_SIMPLE && !nullexec) { char *s; char trycd = (isset(AUTOCD) && isset(SHINSTDIN) && @@ -3306,10 +3322,18 @@ execcmd(Estate state, int input, int output, int how, int last1) redir_prog = NULL; lastval = execfuncdef(state, redir_prog); - } else if (type >= WC_CURSH) { + } + else if (type >= WC_CURSH) { if (last1 == 1) do_exec = 1; - lastval = (execfuncs[type - WC_CURSH])(state, do_exec); + if (type == WC_AUTOFN) { + /* + * We pre-loaded this to get any redirs. + * So we execuate a simplified function here. + */ + lastval = execautofn_basic(state, do_exec); + } else + lastval = (execfuncs[type - WC_CURSH])(state, do_exec); } else if (is_builtin || is_shfunc) { LinkList restorelist = 0, removelist = 0; /* builtin or shell function */ @@ -4540,21 +4564,28 @@ execshfunc(Shfunc shf, LinkList args) deletefilelist(last_file_list, 0); } -/* Function to execute the special type of command that represents an * - * autoloaded shell function. The command structure tells us which * - * function it is. This function is actually called as part of the * - * execution of the autoloaded function itself, so when the function * - * has been autoloaded, its list is just run with no frills. */ +/* + * Function to execute the special type of command that represents an + * autoloaded shell function. The command structure tells us which + * function it is. This function is actually called as part of the + * execution of the autoloaded function itself, so when the function + * has been autoloaded, its list is just run with no frills. + * + * There are two cases because if we are doing all-singing, all-dancing + * non-simple code we load the shell function early in execcmd() (the + * action also present in the non-basic version) to check if + * there are redirections that need to be handled at that point. + * Then we call execautofn_basic() to do the rest. + */ /**/ static int -execautofn(Estate state, UNUSED(int do_exec)) +execautofn_basic(Estate state, UNUSED(int do_exec)) { Shfunc shf; char *oldscriptname, *oldscriptfilename; - if (!(shf = loadautofn(state->prog->shf, 1, 0))) - return 1; + shf = state->prog->shf; /* * Probably we didn't know the filename where this function was @@ -4573,6 +4604,19 @@ execautofn(Estate state, UNUSED(int do_exec)) return lastval; } +/**/ +static int +execautofn(Estate state, UNUSED(int do_exec)) +{ + Shfunc shf; + + if (!(shf = loadautofn(state->prog->shf, 1, 0))) + return 1; + + state->prog->shf = shf; + return execautofn_basic(state, 0); +} + /**/ Shfunc loadautofn(Shfunc shf, int fksh, int autol) diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst index df6d7bc06..8d256ff84 100644 --- a/Test/A05execution.ztst +++ b/Test/A05execution.ztst @@ -216,3 +216,16 @@ F:This similar test was triggering a reproducible failure with pipestatus. >done F:This test checks for a file descriptor leak that could cause the left F:side of a pipe to block on write after the right side has exited + + print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir + autoload -Uk autoload_redir + autoload_redir + print No output yet + cat autoload.log + functions autoload_redir +0: +>No output yet +>Autoloaded ksh style +>autoload_redir () { +> print Autoloaded ksh style +>} > autoload.log -- cgit v1.2.3 From 49a3086bb67575435251c70ee598e2fd406ef055 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Mon, 6 Oct 2014 20:33:47 +0200 Subject: 33365: avoid buffer overflow for very long fds in >& fd syntax --- Src/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/exec.c') diff --git a/Src/exec.c b/Src/exec.c index a5452e56e..d0fadd69a 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3201,7 +3201,7 @@ execcmd(Estate state, int input, int output, int how, int last1) fil = movefd(dup(fd)); } if (fil == -1) { - char fdstr[4]; + char fdstr[DIGBUFSIZE]; closemnodes(mfds); fixfds(save); -- cgit v1.2.3