mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-03 10:21:46 +02:00
33876: etc.: Separate errors and keyboards interrupts
Combination of 12 commits from interrupt_abort branch. Basic strategy is to introduce bits to errflag and to set and reset them separately. Remove interrupt status on return to main keymap. Turn off ERRFLAG_INT for always block. Restore bit thereafter: we probably need a new variable in order to allow user interrupts to be reset in the always block. Add TRY_BLOCK_INTERRUPT This works the same as TRY_BLOCK_ERROR, but for a SIGINT, too. Ensure propagation of SIGINT from exited job. If received by foreground job, shell uses ERRFLAG_INT, not ERRFLAG_ERROR, to set the new state. Reset errflag before precmd() Add always block in _main_completion to fix ZLS_COLORS Ensures we get the right state of $ZLS_COLORS at the end of _main_complete even if there's an interrupt. However, the "right state" is a bit messy as it depends on styles.
This commit is contained in:
parent
247f7548dc
commit
d067ebcacd
31 changed files with 315 additions and 134 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2014-12-11 Peter Stephenson <p.stephenson@samsung.com>
|
||||
|
||||
* 33876: etc.: Completion/Base/Core/_main_complete,
|
||||
Doc/Zsh/params.yo, Src/Modules/zpty.c, Src/Modules/zutil.c,
|
||||
Src/Zle/compcore.c, Src/Zle/compctl.c, Src/Zle/compresult.c,
|
||||
Src/Zle/textobjects.c, Src/Zle/zle_hist.c, Src/Zle/zle_keymap.c,
|
||||
Src/Zle/zle_main.c, Src/Zle/zle_misc.c, Src/Zle/zle_tricky.c,
|
||||
Src/Zle/zle_utils.c, Src/builtin.c, Src/exec.c, Src/glob.c,
|
||||
Src/hist.c, Src/init.c, Src/input.c, Src/jobs.c, Src/lex.c,
|
||||
Src/loop.c, Src/params.c, Src/parse.c, Src/prompt.c,
|
||||
Src/signals.c, Src/subst.c, Src/utils.c, Src/zsh.h: Separate
|
||||
shell errors and user interrupt flags into different bits of
|
||||
errflag: ERRFLAG_ERROR and ERRFLAG_INT. Various
|
||||
rationalisations to make keyboard interrupts work smoothly.
|
||||
Work done on interrupt_abort branch.
|
||||
|
||||
2014-12-10 Mikael Magnusson <mikachu@gmail.com>
|
||||
|
||||
* 33948: Completion/Unix/Command/_getent,
|
||||
|
@ -612,7 +628,7 @@
|
|||
* 33354: Src/jobs.c, Test/A05execution.ztst: when backgrounding
|
||||
a pipeline, close all pipe descriptors in the parent; add test
|
||||
for both this and 33345+33346
|
||||
|
||||
|
||||
2014-10-03 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 33346: Src/parse.c: another bit of the 33345 repair
|
||||
|
@ -2083,7 +2099,7 @@
|
|||
2013-12-20 Barton E. Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 32172; Test/A05execution.ztst: regression test for 32171
|
||||
|
||||
|
||||
* 32171: Src/exec.c: fix leaked pipe descriptor that could
|
||||
deadlock a pipeline from a complex shell construct or function
|
||||
into an external command
|
||||
|
|
|
@ -43,6 +43,8 @@ local -a precommands
|
|||
|
||||
typeset -U _lastdescr _comp_ignore _comp_colors
|
||||
|
||||
{
|
||||
|
||||
[[ -z "$curcontext" ]] && curcontext=:::
|
||||
|
||||
zstyle -s ":completion:${curcontext}:" insert-tab tmp || tmp=yes
|
||||
|
@ -349,17 +351,20 @@ fi
|
|||
( "$_comp_force_list" = ?* && nm -ge _comp_force_list ) ]] &&
|
||||
compstate[list]="${compstate[list]//messages} force"
|
||||
|
||||
if [[ "$compstate[old_list]" = keep ]]; then
|
||||
if [[ $_saved_colors_set = 1 ]]; then
|
||||
ZLS_COLORS="$_saved_colors"
|
||||
} always {
|
||||
# Stuff we always do to clean up.
|
||||
if [[ "$compstate[old_list]" = keep ]]; then
|
||||
if [[ $_saved_colors_set = 1 ]]; then
|
||||
ZLS_COLORS="$_saved_colors"
|
||||
else
|
||||
unset ZLS_COLORS
|
||||
fi
|
||||
elif (( $#_comp_colors )); then
|
||||
ZLS_COLORS="${(j.:.)_comp_colors}"
|
||||
else
|
||||
unset ZLS_COLORS
|
||||
fi
|
||||
elif (( $#_comp_colors )); then
|
||||
ZLS_COLORS="${(j.:.)_comp_colors}"
|
||||
else
|
||||
unset ZLS_COLORS
|
||||
fi
|
||||
}
|
||||
|
||||
# Now call the post-functions.
|
||||
|
||||
|
|
|
@ -754,6 +754,17 @@ It may be reset, clearing the error condition. See
|
|||
ifzman(em(Complex Commands) in zmanref(zshmisc))\
|
||||
ifnzman(noderef(Complex Commands))
|
||||
)
|
||||
vindex(TRY_BLOCK_INTERRUPT)
|
||||
item(tt(TRY_BLOCK_INTERRUPT) <S>)(
|
||||
This variable works in a similar way to tt(TRY_BLOCK_ERROR), but
|
||||
represents the status of an interrupt from the signal SIGINT, which
|
||||
typically comes from the keyboard when the user types tt(^C). If set to
|
||||
0, any such interrupt will be reset; otherwise, the interrupt is
|
||||
propagated after the tt(always) block.
|
||||
|
||||
Note that it is possible that an interrupt arrives during the execution
|
||||
of the tt(always) block; this interrupt is also propagated.
|
||||
)
|
||||
vindex(TTY)
|
||||
item(tt(TTY))(
|
||||
The name of the tty associated with the shell, if any.
|
||||
|
|
|
@ -308,7 +308,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
|
|||
|
||||
prog = parse_string(zjoin(args, ' ', 1), 0);
|
||||
if (!prog) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
scriptname = oscriptname;
|
||||
ineval = oineval;
|
||||
return 1;
|
||||
|
|
|
@ -301,7 +301,8 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval)
|
|||
int ef = errflag;
|
||||
|
||||
eprog = parse_string(zjoin(vals, ' ', 1), 0);
|
||||
errflag = ef;
|
||||
/* Keep any user interrupt error status */
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
|
||||
if (!eprog)
|
||||
{
|
||||
|
@ -394,10 +395,11 @@ evalstyle(Stypat p)
|
|||
unsetparam("reply");
|
||||
execode(p->eval, 1, 0, "style");
|
||||
if (errflag) {
|
||||
errflag = ef;
|
||||
/* Keep any user interrupt error status */
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
return NULL;
|
||||
}
|
||||
errflag = ef;
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
|
||||
queue_signals();
|
||||
if ((ret = getaparam("reply")))
|
||||
|
|
|
@ -1671,7 +1671,7 @@ set_comp_sep(void)
|
|||
noaliases = ona;
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
noerrs = ne;
|
||||
lexrestore();
|
||||
wb = owb;
|
||||
|
|
|
@ -1879,7 +1879,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat)
|
|||
if (!m || !(m = m->next))
|
||||
break;
|
||||
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
}
|
||||
redup(osi, 0);
|
||||
dat->lst = 1;
|
||||
|
@ -2121,7 +2121,7 @@ getreal(char *str)
|
|||
if (!errflag && nonempty(l) &&
|
||||
((char *) peekfirst(l)) && ((char *) peekfirst(l))[0])
|
||||
return dupstring(peekfirst(l));
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
|
||||
return dupstring(str);
|
||||
}
|
||||
|
@ -2599,7 +2599,7 @@ makecomplistlist(Compctl cc, char *s, int incmd, int compadd)
|
|||
makecomplistflags(cc, s, incmd, compadd);
|
||||
|
||||
/* Reset some information variables for the next try. */
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
offs = oloffs;
|
||||
wb = owb;
|
||||
we = owe;
|
||||
|
@ -2847,7 +2847,7 @@ sep_comp_string(char *ss, char *s, int noffs)
|
|||
noaliases = ona;
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
noerrs = ne;
|
||||
lexrestore();
|
||||
wb = owb;
|
||||
|
@ -3725,7 +3725,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
noaliases = ona;
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
lexrestore();
|
||||
/* Fine, now do full expansion. */
|
||||
prefork(foo, 0);
|
||||
|
|
|
@ -1092,7 +1092,7 @@ do_single(Cmatch m)
|
|||
noerrs = 1;
|
||||
parsestr(p);
|
||||
singsub(&p);
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
noerrs = ne;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -275,7 +275,7 @@ selectargument(UNUSED(char **args))
|
|||
noaliases = ona;
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
noerrs = ne;
|
||||
lexrestore();
|
||||
zlemetacs = ocs;
|
||||
|
|
|
@ -853,8 +853,10 @@ pushlineoredit(char **args)
|
|||
free(zhline);
|
||||
}
|
||||
ret = pushline(args);
|
||||
if (!isfirstln)
|
||||
errflag = done = 1;
|
||||
if (!isfirstln) {
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
done = 1;
|
||||
}
|
||||
clearlist = 1;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -504,6 +504,16 @@ mod_export void
|
|||
selectlocalmap(Keymap m)
|
||||
{
|
||||
localkeymap = m;
|
||||
if (!m)
|
||||
{
|
||||
/*
|
||||
* No local keymap; so we are returning to the global map. If
|
||||
* the user ^Ced in the local map, they probably just want to go
|
||||
* back to normal editing. So remove the interrupt error
|
||||
* status.
|
||||
*/
|
||||
errflag &= ~ERRFLAG_INT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reopen the currently selected keymap, in case it got deleted. This *
|
||||
|
|
|
@ -744,7 +744,7 @@ raw_getbyte(long do_keytmout, char *cptr)
|
|||
}
|
||||
if (errflag) {
|
||||
/* No sensible way of handling errors here */
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
/*
|
||||
* Paranoia: don't run the hooks again this
|
||||
* time.
|
||||
|
@ -882,7 +882,7 @@ getbyte(long do_keytmout, int *timeout)
|
|||
die = 0;
|
||||
if (!errflag && !retflag && !breaks && !exit_pending)
|
||||
continue;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
breaks = obreaks;
|
||||
errno = old_errno;
|
||||
return lastchar = EOF;
|
||||
|
@ -1075,7 +1075,7 @@ zlecore(void)
|
|||
DECCS();
|
||||
handleundo();
|
||||
} else {
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
|
@ -1233,6 +1233,10 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
|
|||
|
||||
zleactive = 1;
|
||||
resetneeded = 1;
|
||||
/*
|
||||
* Start of the main zle read.
|
||||
* Fully reset error conditions, including user interrupt.
|
||||
*/
|
||||
errflag = retflag = 0;
|
||||
lastcol = -1;
|
||||
initmodifier(&zmod);
|
||||
|
@ -1658,7 +1662,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func))
|
|||
}
|
||||
if (!t || errflag) {
|
||||
/* error in editing */
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
breaks = obreaks;
|
||||
if (t)
|
||||
zsfree(t);
|
||||
|
@ -1778,7 +1782,7 @@ recursiveedit(UNUSED(char **args))
|
|||
zrefresh();
|
||||
zlecore();
|
||||
|
||||
locerror = errflag;
|
||||
locerror = errflag ? 1 : 0;
|
||||
errflag = done = eofsent = 0;
|
||||
|
||||
return locerror;
|
||||
|
|
|
@ -1041,7 +1041,7 @@ copyprevshellword(UNUSED(char **args))
|
|||
int
|
||||
sendbreak(UNUSED(char **args))
|
||||
{
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -829,7 +829,7 @@ docomplete(int lst)
|
|||
if (olst == COMP_EXPAND_COMPLETE &&
|
||||
!strcmp(ol, zlemetaline)) {
|
||||
zlemetacs = ocs;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
|
||||
if (!compfunc) {
|
||||
char *p;
|
||||
|
@ -877,6 +877,19 @@ docomplete(int lst)
|
|||
|
||||
active = 0;
|
||||
makecommaspecial(0);
|
||||
|
||||
/*
|
||||
* As a special case, we reset user interrupts here.
|
||||
* That's because completion is an intensive piece of
|
||||
* computation that the user might want to interrupt separately
|
||||
* from anything else going on. If they do, they probably
|
||||
* want to keep the line edit buffer intact.
|
||||
*
|
||||
* There's a race here that the user might hit ^C just
|
||||
* after completion exited anyway, but that's inevitable.
|
||||
*/
|
||||
errflag &= ~ERRFLAG_INT;
|
||||
|
||||
return dat[1];
|
||||
}
|
||||
|
||||
|
@ -1394,7 +1407,8 @@ get_comp_string(void)
|
|||
}
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = lexflags = 0;
|
||||
lexflags = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
if (parbegin != -1) {
|
||||
/* We are in command or process substitution if we are not in
|
||||
* a $((...)). */
|
||||
|
@ -2917,7 +2931,7 @@ getcurcmd(void)
|
|||
popheap();
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
unmetafy_line();
|
||||
lexrestore();
|
||||
|
||||
|
|
|
@ -1715,7 +1715,8 @@ zlecallhook(char *name, char *arg)
|
|||
execzlefunc(thingy, args, 1);
|
||||
unrefthingy(thingy);
|
||||
|
||||
errflag = saverrflag;
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = saverrflag | (errflag & ERRFLAG_INT);
|
||||
retflag = savretflag;
|
||||
}
|
||||
|
||||
|
|
|
@ -422,7 +422,7 @@ execbuiltin(LinkList args, Builtin bn)
|
|||
argc -= argv - argarr;
|
||||
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3136,7 +3136,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
|
|||
}
|
||||
}
|
||||
returnval = errflag;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
} else {
|
||||
zerrnam(name, "%s: invalid element for unset", s);
|
||||
returnval = 1;
|
||||
|
@ -4242,7 +4242,7 @@ bin_print(char *name, char **args, Options ops, int func)
|
|||
if (*argp) {
|
||||
width = (int)mathevali(*argp++);
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
@ -4272,7 +4272,7 @@ bin_print(char *name, char **args, Options ops, int func)
|
|||
if (*argp) {
|
||||
prec = (int)mathevali(*argp++);
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
@ -4452,7 +4452,7 @@ bin_print(char *name, char **args, Options ops, int func)
|
|||
zlongval = (curarg) ? mathevali(curarg) : 0;
|
||||
if (errflag) {
|
||||
zlongval = 0;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
ret = 1;
|
||||
}
|
||||
print_val(zlongval)
|
||||
|
@ -4481,7 +4481,7 @@ bin_print(char *name, char **args, Options ops, int func)
|
|||
} else doubleval = 0;
|
||||
if (errflag) {
|
||||
doubleval = 0;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
ret = 1;
|
||||
}
|
||||
print_val(doubleval)
|
||||
|
@ -4494,7 +4494,7 @@ bin_print(char *name, char **args, Options ops, int func)
|
|||
zulongval = (curarg) ? mathevali(curarg) : 0;
|
||||
if (errflag) {
|
||||
zulongval = 0;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
ret = 1;
|
||||
}
|
||||
print_val(zulongval)
|
||||
|
@ -4871,7 +4871,7 @@ zexit(int val, int from_where)
|
|||
in_exit = -1;
|
||||
/*
|
||||
* We want to do all remaining processing regardless of preceding
|
||||
* errors.
|
||||
* errors, even user interrupts.
|
||||
*/
|
||||
errflag = 0;
|
||||
|
||||
|
@ -5074,7 +5074,7 @@ eval(char **argv)
|
|||
if (fpushed)
|
||||
funcstack = funcstack->prev;
|
||||
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
scriptname = oscriptname;
|
||||
ineval = oineval;
|
||||
|
||||
|
@ -6101,7 +6101,7 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func)
|
|||
condlex = zshlex;
|
||||
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
lexrestore();
|
||||
return 1;
|
||||
}
|
||||
|
@ -6278,7 +6278,7 @@ bin_let(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int func))
|
|||
while (*argv)
|
||||
val = matheval(*argv++);
|
||||
/* Errors in math evaluation in let are non-fatal. */
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
/* should test for fabs(val.u.d) < epsilon? */
|
||||
return (val.type == MN_INTEGER) ? val.u.l == 0 : val.u.d == 0.0;
|
||||
}
|
||||
|
|
56
Src/exec.c
56
Src/exec.c
|
@ -59,7 +59,7 @@ mod_export int noerrs;
|
|||
/**/
|
||||
int nohistsave;
|
||||
|
||||
/* error/break flag */
|
||||
/* error flag: bits from enum errflag_bits */
|
||||
|
||||
/**/
|
||||
mod_export int errflag;
|
||||
|
@ -1601,7 +1601,8 @@ execpline(Estate state, wordcode slcode, int how, int last1)
|
|||
(killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1);
|
||||
list_pipe_pid = pid;
|
||||
list_pipe_start = bgtime;
|
||||
nowait = errflag = 1;
|
||||
nowait = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
breaks = loops;
|
||||
close(synch[1]);
|
||||
read_loop(synch[0], &dummy, 1);
|
||||
|
@ -1634,7 +1635,10 @@ execpline(Estate state, wordcode slcode, int how, int last1)
|
|||
list_pipe_child = 1;
|
||||
opts[INTERACTIVE] = 0;
|
||||
if (errbrk_saved) {
|
||||
errflag = prev_errflag;
|
||||
/*
|
||||
* Keep any user interrupt bit in errflag.
|
||||
*/
|
||||
errflag = prev_errflag | (errflag & ERRFLAG_INT);
|
||||
breaks = prev_breaks;
|
||||
}
|
||||
break;
|
||||
|
@ -1719,12 +1723,14 @@ execpline2(Estate state, wordcode pcode,
|
|||
|
||||
if (pipe(synch) < 0) {
|
||||
zerr("pipe failed: %e", errno);
|
||||
lastval = errflag = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
} else if ((pid = zfork(&bgtime)) == -1) {
|
||||
close(synch[0]);
|
||||
close(synch[1]);
|
||||
lastval = errflag = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
} else if (pid) {
|
||||
char dummy, *text;
|
||||
|
@ -2560,7 +2566,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
while (next && *next == '-' && strlen(next) >= 2) {
|
||||
if (!firstnode(args)) {
|
||||
zerr("exec requires a command to execute");
|
||||
errflag = lastval = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
goto done;
|
||||
}
|
||||
uremnode(args, firstnode(args));
|
||||
|
@ -2577,12 +2584,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
} else {
|
||||
if (!firstnode(args)) {
|
||||
zerr("exec requires a command to execute");
|
||||
errflag = lastval = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (!nextnode(firstnode(args))) {
|
||||
zerr("exec flag -a requires a parameter");
|
||||
errflag = lastval = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
goto done;
|
||||
}
|
||||
exec_argv0 = (char *)
|
||||
|
@ -2598,7 +2607,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
break;
|
||||
default:
|
||||
zerr("unknown exec flag -%c", *cmdopt);
|
||||
errflag = lastval = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2661,7 +2671,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
} else if (!nullcmd || !*nullcmd || opts[CSHNULLCMD] ||
|
||||
(cflags & BINF_PREFIX)) {
|
||||
zerr("redirection with no command");
|
||||
errflag = lastval = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
} else if (!nullcmd || !*nullcmd || opts[SHNULLCMD]) {
|
||||
if (!args)
|
||||
|
@ -2691,7 +2702,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
if (varspc)
|
||||
addvars(state, varspc, 0);
|
||||
if (errflag)
|
||||
lastval = errflag;
|
||||
lastval = 1;
|
||||
else
|
||||
lastval = cmdoutval;
|
||||
if (isset(XTRACE)) {
|
||||
|
@ -2795,7 +2806,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
}
|
||||
}
|
||||
if (!nextnode(firstnode(args)))
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
|
||||
if (type == WC_FUNCDEF) {
|
||||
|
@ -2940,7 +2951,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
} else if ((pid = zfork(&bgtime)) == -1) {
|
||||
close(synch[0]);
|
||||
close(synch[1]);
|
||||
lastval = errflag = 1;
|
||||
lastval = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
goto fatal;
|
||||
}
|
||||
if (pid) {
|
||||
|
@ -3529,7 +3541,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
else
|
||||
exit(1);
|
||||
}
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
}
|
||||
if (newxtrerr) {
|
||||
|
@ -3759,8 +3771,10 @@ gethere(char **strp, int typ)
|
|||
|
||||
parsestr(buf);
|
||||
|
||||
if (!errflag)
|
||||
errflag = ef;
|
||||
if (!errflag) {
|
||||
/* Retain any user interrupt error */
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
}
|
||||
}
|
||||
s = dupstring(buf);
|
||||
zfree(buf, bsiz);
|
||||
|
@ -3854,7 +3868,7 @@ getoutput(char *cmd, int qt)
|
|||
return readoutput(stream, qt);
|
||||
}
|
||||
if (mpipe(pipes) < 0) {
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
cmdoutpid = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3864,7 +3878,7 @@ getoutput(char *cmd, int qt)
|
|||
/* fork error */
|
||||
zclose(pipes[0]);
|
||||
zclose(pipes[1]);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
cmdoutpid = 0;
|
||||
child_unblock();
|
||||
return NULL;
|
||||
|
@ -4274,7 +4288,7 @@ execcond(Estate state, UNUSED(int do_exec))
|
|||
* into a shell error.
|
||||
*/
|
||||
if (stat == 2)
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
cmdpop();
|
||||
if (isset(XTRACE)) {
|
||||
fprintf(xtrerr, " ]]\n");
|
||||
|
@ -4314,7 +4328,7 @@ execarith(Estate state, UNUSED(int do_exec))
|
|||
fflush(xtrerr);
|
||||
}
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
return 2;
|
||||
}
|
||||
/* should test for fabs(val.u.d) < epsilon? */
|
||||
|
@ -4932,7 +4946,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
|
|||
(name = fname)))) {
|
||||
zwarn("%s: function not defined by file", name);
|
||||
if (noreturnval)
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
else
|
||||
lastval = 1;
|
||||
goto doneshfunc;
|
||||
|
|
12
Src/glob.c
12
Src/glob.c
|
@ -682,7 +682,7 @@ parsecomplist(char *instr)
|
|||
/* Now get the next path component if there is one. */
|
||||
l1 = (Complist) zhalloc(sizeof *l1);
|
||||
if ((l1->next = parsecomplist(instr)) == NULL) {
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL);
|
||||
|
@ -728,7 +728,7 @@ parsecomplist(char *instr)
|
|||
return (ef && !l1->next) ? NULL : l1;
|
||||
}
|
||||
}
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1790,7 +1790,7 @@ zglob(LinkList list, LinkNode np, int nountok)
|
|||
insertlinknode(list, node, ostr);
|
||||
return;
|
||||
}
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
zerr("bad pattern: %s", ostr);
|
||||
return;
|
||||
}
|
||||
|
@ -1873,7 +1873,8 @@ zglob(LinkList list, LinkNode np, int nountok)
|
|||
tmpptr->sortstrs[iexec] = tmpptr->name;
|
||||
}
|
||||
|
||||
errflag = ef;
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
lastval = lv;
|
||||
} else {
|
||||
/* Failed, let's be safe */
|
||||
|
@ -3733,7 +3734,8 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str)
|
|||
execode(prog, 1, 0, "globqual");
|
||||
|
||||
ret = lastval;
|
||||
errflag = ef;
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = ef | (errflag & ERRFLAG_INT);
|
||||
lastval = lv;
|
||||
|
||||
if (!(inserts = getaparam("reply")) &&
|
||||
|
|
10
Src/hist.c
10
Src/hist.c
|
@ -287,7 +287,8 @@ ihgetc(void)
|
|||
c = histsubchar(c);
|
||||
if (c < 0) {
|
||||
/* bad expansion */
|
||||
errflag = lexstop = 1;
|
||||
lexstop = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
@ -721,7 +722,7 @@ histsubchar(int c)
|
|||
noerrs = 1;
|
||||
parse_subst_string(sline);
|
||||
noerrs = one;
|
||||
errflag = oef;
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
remnulargs(sline);
|
||||
untokenize(sline);
|
||||
}
|
||||
|
@ -880,7 +881,8 @@ hbegin(int dohist)
|
|||
char *hf;
|
||||
|
||||
isfirstln = isfirstch = 1;
|
||||
errflag = histdone = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
histdone = 0;
|
||||
if (!dohist)
|
||||
stophist = 2;
|
||||
else if (dohist != 2)
|
||||
|
@ -3182,7 +3184,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
|
|||
noaliases = ona;
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
nocomments = onc;
|
||||
noerrs = ne;
|
||||
lexrestore();
|
||||
|
|
29
Src/init.c
29
Src/init.c
|
@ -118,11 +118,24 @@ loop(int toplevel, int justonce)
|
|||
if (interact && toplevel) {
|
||||
int hstop = stophist;
|
||||
stophist = 3;
|
||||
/*
|
||||
* Reset all errors including the interrupt error status
|
||||
* immediately, so preprompt runs regardless of what
|
||||
* just happened. We'll reset again below as a
|
||||
* precaution to ensure we get back to the command line
|
||||
* no matter what.
|
||||
*/
|
||||
errflag = 0;
|
||||
preprompt();
|
||||
if (stophist != 3)
|
||||
hbegin(1);
|
||||
else
|
||||
stophist = hstop;
|
||||
/*
|
||||
* Reset all errors, including user interupts.
|
||||
* This is what allows ^C in an interactive shell
|
||||
* to return us to the command line.
|
||||
*/
|
||||
errflag = 0;
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +191,15 @@ loop(int toplevel, int justonce)
|
|||
|
||||
/* The only permanent storage is from getpermtext() */
|
||||
zsfree(cmdstr);
|
||||
errflag = 0;
|
||||
/*
|
||||
* Note this does *not* remove a user interrupt error
|
||||
* condition, even though we're at the top level loop:
|
||||
* that would be inconsistent with the case where
|
||||
* we didn't execute a preexec function. This is
|
||||
* an implementation detail that an interrupting user
|
||||
* does't care about.
|
||||
*/
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
}
|
||||
if (stopmsg) /* unset 'you have stopped jobs' flag */
|
||||
stopmsg--;
|
||||
|
@ -689,7 +710,7 @@ init_term(void)
|
|||
{
|
||||
if (isset(INTERACTIVE))
|
||||
zerr("can't find terminal definition for %s", term);
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
termflags |= TERM_BAD;
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -1336,7 +1357,7 @@ source(char *s)
|
|||
|
||||
if (prog) {
|
||||
pushheap();
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
execode(prog, 1, 0, "filecode");
|
||||
popheap();
|
||||
if (errflag)
|
||||
|
@ -1379,7 +1400,7 @@ source(char *s)
|
|||
lineno = oldlineno; /* our current lineno */
|
||||
loops = oloops; /* the # of nested loops we are in */
|
||||
dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
if (!exit_pending)
|
||||
retflag = 0;
|
||||
scriptname = old_scriptname;
|
||||
|
|
|
@ -291,7 +291,8 @@ inputline(void)
|
|||
}
|
||||
if (errflag) {
|
||||
free(ingetcline);
|
||||
return lexstop = errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return lexstop = 1;
|
||||
}
|
||||
if (isset(VERBOSE)) {
|
||||
/* Output the whole line read so far. */
|
||||
|
|
23
Src/jobs.c
23
Src/jobs.c
|
@ -509,7 +509,7 @@ update_job(Job jn)
|
|||
prev_errflag = errflag;
|
||||
}
|
||||
breaks = loops;
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_INT;
|
||||
inerrflush();
|
||||
}
|
||||
} else {
|
||||
|
@ -526,7 +526,7 @@ update_job(Job jn)
|
|||
prev_errflag = errflag;
|
||||
}
|
||||
breaks = loops;
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_INT;
|
||||
inerrflush();
|
||||
}
|
||||
if (somestopped && jn->stat & STAT_SUPERJOB)
|
||||
|
@ -581,7 +581,7 @@ update_job(Job jn)
|
|||
breaks = loops;
|
||||
} else {
|
||||
breaks = loops;
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_INT;
|
||||
}
|
||||
check_cursh_sig(sig);
|
||||
}
|
||||
|
@ -1444,12 +1444,19 @@ zwaitjob(int job, int wait_cmd)
|
|||
restore_queue_signals(q);
|
||||
return 128 + last_signal;
|
||||
}
|
||||
/* Commenting this out makes ^C-ing a job started by a function
|
||||
stop the whole function again. But I guess it will stop
|
||||
something else from working properly, we have to find out
|
||||
what this might be. --oberon
|
||||
/* Commenting this out makes ^C-ing a job started by a function
|
||||
stop the whole function again. But I guess it will stop
|
||||
something else from working properly, we have to find out
|
||||
what this might be. --oberon
|
||||
|
||||
When attempting to separate errors and interrupts, we
|
||||
assumed because of the previous comment it would be OK
|
||||
to remove ERRFLAG_ERROR and leave ERRFLAG_INT set, since
|
||||
that's the one related to ^C. But that doesn't work.
|
||||
There's something more here we don't understand. --pws
|
||||
|
||||
errflag = 0; */
|
||||
|
||||
errflag = 0; */
|
||||
if (subsh) {
|
||||
killjb(jn, SIGCONT);
|
||||
jn->stat &= ~STAT_STOPPED;
|
||||
|
|
|
@ -385,7 +385,7 @@ lexrestore(void)
|
|||
ecnfunc = ln->ecnfunc;
|
||||
hlinesz = ln->hlinesz;
|
||||
toklineno = ln->toklineno;
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
free(ln);
|
||||
|
||||
unqueue_signals();
|
||||
|
@ -1737,7 +1737,8 @@ parse_subst_string(char *s)
|
|||
inpop();
|
||||
DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty.");
|
||||
lexrestore();
|
||||
errflag = err;
|
||||
/* Keep any interrupt error status */
|
||||
errflag = err | (errflag & ERRFLAG_INT);
|
||||
if (ctok == LEXERR) {
|
||||
untokenize(s);
|
||||
return 1;
|
||||
|
|
28
Src/loop.c
28
Src/loop.c
|
@ -259,7 +259,8 @@ execselect(Estate state, UNUSED(int do_exec))
|
|||
0, ZLCON_SELECT);
|
||||
if (errflag)
|
||||
str = NULL;
|
||||
errflag = oef;
|
||||
/* Keep any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
} else {
|
||||
str = promptexpand(prompt3, 0, NULL, NULL, NULL);
|
||||
zputs(str, stderr);
|
||||
|
@ -632,6 +633,14 @@ execcase(Estate state, int do_exec)
|
|||
zlong
|
||||
try_errflag = -1;
|
||||
|
||||
/**
|
||||
* Corresponding interrupt error status form `try' block.
|
||||
*/
|
||||
|
||||
/**/
|
||||
zlong
|
||||
try_interrupt = -1;
|
||||
|
||||
/**/
|
||||
zlong
|
||||
try_tryflag = 0;
|
||||
|
@ -643,7 +652,7 @@ exectry(Estate state, int do_exec)
|
|||
Wordcode end, always;
|
||||
int endval;
|
||||
int save_retflag, save_breaks, save_contflag;
|
||||
zlong save_try_errflag, save_try_tryflag;
|
||||
zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
|
||||
|
||||
end = state->pc + WC_TRY_SKIP(state->pc[-1]);
|
||||
always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
|
||||
|
@ -670,7 +679,10 @@ exectry(Estate state, int do_exec)
|
|||
|
||||
/* The always clause. */
|
||||
save_try_errflag = try_errflag;
|
||||
try_errflag = (zlong)errflag;
|
||||
save_try_interrupt = try_interrupt;
|
||||
try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
|
||||
try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0);
|
||||
/* We need to reset all errors to allow the block to execute */
|
||||
errflag = 0;
|
||||
save_retflag = retflag;
|
||||
retflag = 0;
|
||||
|
@ -682,8 +694,16 @@ exectry(Estate state, int do_exec)
|
|||
state->pc = always;
|
||||
execlist(state, 1, do_exec);
|
||||
|
||||
errflag = try_errflag ? 1 : 0;
|
||||
if (try_errflag)
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
else
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
if (try_interrupt)
|
||||
errflag |= ERRFLAG_INT;
|
||||
else
|
||||
errflag &= ~ERRFLAG_INT;
|
||||
try_errflag = save_try_errflag;
|
||||
try_interrupt = save_try_interrupt;
|
||||
if (!retflag)
|
||||
retflag = save_retflag;
|
||||
if (!breaks)
|
||||
|
|
13
Src/params.c
13
Src/params.c
|
@ -331,6 +331,7 @@ IPDEF5("SHLVL", &shlvl, varinteger_gsu),
|
|||
#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
|
||||
IPDEF6("OPTIND", &zoptind, varinteger_gsu),
|
||||
IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
|
||||
IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu),
|
||||
|
||||
#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
|
||||
#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
|
||||
|
@ -2654,7 +2655,7 @@ assignsparam(char *s, char *val, int flags)
|
|||
if (!isident(s)) {
|
||||
zerr("not an identifier: %s", s);
|
||||
zsfree(val);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
queue_signals();
|
||||
|
@ -2783,7 +2784,7 @@ assignaparam(char *s, char **val, int flags)
|
|||
if (!isident(s)) {
|
||||
zerr("not an identifier: %s", s);
|
||||
freearray(val);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
queue_signals();
|
||||
|
@ -2799,7 +2800,7 @@ assignaparam(char *s, char **val, int flags)
|
|||
zerr("%s: attempt to set slice of associative array",
|
||||
v->pm->node.nam);
|
||||
freearray(val);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
v = NULL;
|
||||
|
@ -2870,13 +2871,13 @@ sethparam(char *s, char **val)
|
|||
if (!isident(s)) {
|
||||
zerr("not an identifier: %s", s);
|
||||
freearray(val);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
if (strchr(s, '[')) {
|
||||
freearray(val);
|
||||
zerr("nested associative arrays not yet supported");
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
if (unset(EXECOPT))
|
||||
|
@ -2916,7 +2917,7 @@ setnparam(char *s, mnumber val)
|
|||
|
||||
if (!isident(s)) {
|
||||
zerr("not an identifier: %s", s);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
if (unset(EXECOPT))
|
||||
|
|
31
Src/parse.c
31
Src/parse.c
|
@ -71,13 +71,14 @@ struct heredocs *hdocs;
|
|||
|
||||
#define YYERROR(O) { tok = LEXERR; ecused = (O); return 0; }
|
||||
#define YYERRORV(O) { tok = LEXERR; ecused = (O); return; }
|
||||
#define COND_ERROR(X,Y) do { \
|
||||
zwarn(X,Y); \
|
||||
herrflush(); \
|
||||
if (noerrs != 2) \
|
||||
errflag = 1; \
|
||||
YYERROR(ecused) \
|
||||
} while(0)
|
||||
#define COND_ERROR(X,Y) \
|
||||
do { \
|
||||
zwarn(X,Y); \
|
||||
herrflush(); \
|
||||
if (noerrs != 2) \
|
||||
errflag |= ERRFLAG_ERROR; \
|
||||
YYERROR(ecused) \
|
||||
} while(0)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -506,7 +507,7 @@ par_event(void)
|
|||
yyerror(1);
|
||||
herrflush();
|
||||
if (noerrs != 2)
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
ecused--;
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -2339,7 +2340,7 @@ yyerror(int noerr)
|
|||
zwarn("parse error");
|
||||
}
|
||||
if (!noerr && noerrs != 2)
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3031,7 +3032,7 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
|
|||
file = metafy(file, flen, META_REALLOC);
|
||||
|
||||
if (!(prog = parse_string(file, 1)) || errflag) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
zfree(file, flen);
|
||||
zwarnnam(nam, "can't read file: %s", *files);
|
||||
|
@ -3141,7 +3142,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
|
|||
for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
|
||||
if (cur_add_func(nam, (Shfunc) hn, lnames, progs,
|
||||
&hlen, &tlen, what)) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
unlink(dump);
|
||||
return 1;
|
||||
|
@ -3166,7 +3167,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
|
|||
pattry(pprog, hn->nam) &&
|
||||
cur_add_func(nam, (Shfunc) hn, lnames, progs,
|
||||
&hlen, &tlen, what)) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
unlink(dump);
|
||||
return 1;
|
||||
|
@ -3177,13 +3178,13 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
|
|||
if (errflag ||
|
||||
!(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
|
||||
zwarnnam(nam, "unknown function: %s", *names);
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
unlink(dump);
|
||||
return 1;
|
||||
}
|
||||
if (cur_add_func(nam, shf, lnames, progs, &hlen, &tlen, what)) {
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
unlink(dump);
|
||||
return 1;
|
||||
|
@ -3192,7 +3193,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
|
|||
}
|
||||
if (empty(progs)) {
|
||||
zwarnnam(nam, "no functions");
|
||||
errflag = 0;
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
close(dfd);
|
||||
unlink(dump);
|
||||
return 1;
|
||||
|
|
|
@ -192,8 +192,11 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
|
|||
if (*s == Nularg && s[1] == '\0')
|
||||
*s = '\0';
|
||||
|
||||
/* Ignore errors and status change in prompt substitution */
|
||||
errflag = olderr;
|
||||
/*
|
||||
* Ignore errors and status change in prompt substitution.
|
||||
* However, keep any user interrupt error that occurred.
|
||||
*/
|
||||
errflag = olderr | (errflag & ERRFLAG_INT);
|
||||
lastval = oldval;
|
||||
}
|
||||
|
||||
|
|
|
@ -619,7 +619,7 @@ zhandler(int sig)
|
|||
zexit(SIGINT, 1);
|
||||
if (list_pipe || chline || simple_pline) {
|
||||
breaks = loops;
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_INT;
|
||||
inerrflush();
|
||||
check_cursh_sig(SIGINT);
|
||||
}
|
||||
|
@ -640,6 +640,11 @@ zhandler(int sig)
|
|||
if (idle >= 0 && idle < tmout)
|
||||
alarm(tmout - idle);
|
||||
else {
|
||||
/*
|
||||
* We want to exit now.
|
||||
* Cancel all errors, including a user interrupt
|
||||
* which is now redundant.
|
||||
*/
|
||||
errflag = noerrs = 0;
|
||||
zwarn("timeout");
|
||||
stopmsg = 1;
|
||||
|
@ -1267,7 +1272,18 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
|||
!(isfunc && new_trap_return == 0)) {
|
||||
if (isfunc) {
|
||||
breaks = loops;
|
||||
errflag = 1;
|
||||
/*
|
||||
* For SIGINT we behave the same as the default behaviour
|
||||
* i.e. we set the error bit indicating an interrupt.
|
||||
* We do this with SIGQUIT, too, even though we don't
|
||||
* handle SIGQUIT by default. That's to try to make
|
||||
* it behave a bit more like its normal behaviour when
|
||||
* the trap handler has told us that's what it wants.
|
||||
*/
|
||||
if (sig == SIGINT || sig == SIGQUIT)
|
||||
errflag |= ERRFLAG_INT;
|
||||
else
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
lastval = new_trap_return;
|
||||
/* return triggered */
|
||||
|
@ -1282,8 +1298,12 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
|||
*/
|
||||
lastval = olastval;
|
||||
}
|
||||
if (try_tryflag)
|
||||
errflag = traperr;
|
||||
if (try_tryflag) {
|
||||
if (traperr)
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
else
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
}
|
||||
breaks += obreaks;
|
||||
/* return not triggered: restore old flag */
|
||||
retflag = oretflag;
|
||||
|
|
27
Src/subst.c
27
Src/subst.c
|
@ -2822,7 +2822,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
|
|||
haserr = parse_subst_string(s);
|
||||
noerrs = one;
|
||||
if (!quoteerr) {
|
||||
errflag = oef;
|
||||
/* Retain user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
if (haserr)
|
||||
shtokenize(s);
|
||||
} else if (haserr || errflag) {
|
||||
|
@ -3249,8 +3250,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
|
|||
haserr = 1;
|
||||
}
|
||||
noerrs = one;
|
||||
if (!quoteerr)
|
||||
errflag = oef;
|
||||
if (!quoteerr) {
|
||||
/* Retain user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
}
|
||||
if (haserr || errflag)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3483,8 +3486,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
|
|||
untokenize(*ap);
|
||||
}
|
||||
noerrs = one;
|
||||
if (!quoteerr)
|
||||
errflag = oef;
|
||||
if (!quoteerr) {
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
}
|
||||
else if (haserr || errflag) {
|
||||
zerr("parse error in parameter value");
|
||||
return NULL;
|
||||
|
@ -3516,8 +3521,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
|
|||
noerrs = 1;
|
||||
haserr = parse_subst_string(val);
|
||||
noerrs = one;
|
||||
if (!quoteerr)
|
||||
errflag = oef;
|
||||
if (!quoteerr) {
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
}
|
||||
else if (haserr || errflag) {
|
||||
zerr("parse error in parameter value");
|
||||
return NULL;
|
||||
|
@ -4086,7 +4093,8 @@ modify(char **str, char **ptr)
|
|||
noerrs = 1;
|
||||
parse_subst_string(copy);
|
||||
noerrs = one;
|
||||
errflag = oef;
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
remnulargs(copy);
|
||||
untokenize(copy);
|
||||
}
|
||||
|
@ -4161,7 +4169,8 @@ modify(char **str, char **ptr)
|
|||
noerrs = 1;
|
||||
parse_subst_string(*str);
|
||||
noerrs = one;
|
||||
errflag = oef;
|
||||
/* Retain any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
remnulargs(*str);
|
||||
untokenize(*str);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ VA_DCL
|
|||
|
||||
if (errflag || noerrs) {
|
||||
if (noerrs < 2)
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ VA_DCL
|
|||
VA_GET_ARG(ap, fmt, const char *);
|
||||
zwarning(NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -181,7 +181,7 @@ VA_DCL
|
|||
VA_GET_ARG(ap, fmt, const char *);
|
||||
zwarning(cmd, fmt, ap);
|
||||
va_end(ap);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -330,7 +330,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
|
|||
num = va_arg(ap, int);
|
||||
if (num == EINTR) {
|
||||
fputs("interrupt\n", file);
|
||||
errflag = 1;
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return;
|
||||
}
|
||||
errmsg = strerror(num);
|
||||
|
|
14
Src/zsh.h
14
Src/zsh.h
|
@ -2623,6 +2623,20 @@ enum trap_state {
|
|||
#define IN_EVAL_TRAP() \
|
||||
(intrap && !trapisfunc && traplocallevel == locallevel)
|
||||
|
||||
/*
|
||||
* Bits in the errflag variable.
|
||||
*/
|
||||
enum errflag_bits {
|
||||
/*
|
||||
* Standard internal error bit.
|
||||
*/
|
||||
ERRFLAG_ERROR = 1,
|
||||
/*
|
||||
* User interrupt.
|
||||
*/
|
||||
ERRFLAG_INT = 2
|
||||
};
|
||||
|
||||
/***********/
|
||||
/* Sorting */
|
||||
/***********/
|
||||
|
|
Loading…
Reference in a new issue