mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-28 17:10:59 +01:00
Sven: 13108: Handle traps synchronously
pws: 13109, 13111: clear up zle display when output produced in trap.
This commit is contained in:
parent
89d480f57d
commit
c292a3ae50
15 changed files with 387 additions and 202 deletions
12
ChangeLog
12
ChangeLog
|
|
@ -1,3 +1,15 @@
|
||||||
|
2000-11-11 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
|
||||||
|
|
||||||
|
* 13109, 13111: Doc/Zsh/mod_zle.yo, Src/Zle/zle_main.c,
|
||||||
|
Src/Zle/zle_thingy.c, Src/signals.c: `zle -I' allows trap code
|
||||||
|
to clear up display when output occurs in a trap.
|
||||||
|
|
||||||
|
* Sven: 13108: Src/Modules/zftp.c, Src/Modules/zpty.c,
|
||||||
|
Src/Zle/zle_main.c, Src/builtin.c, Src/exec.c, Src/init.c,
|
||||||
|
Src/input.c, Src/jobs.c, Src/signals.c, Src/signals.h,
|
||||||
|
Src/utils.c, Src/zsh.h: Execute user traps synchronously if it is
|
||||||
|
unsafe to execute it directly from the signal handler.
|
||||||
|
|
||||||
2000-11-09 Clint Adams <schizo@debian.org>
|
2000-11-09 Clint Adams <schizo@debian.org>
|
||||||
|
|
||||||
* 13125: Completion/User/_mailboxes: evaluate the mailboxes
|
* 13125: Completion/User/_mailboxes: evaluate the mailboxes
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function))
|
||||||
xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
|
xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
|
||||||
xitem(tt(zle) tt(-M) var(string))
|
xitem(tt(zle) tt(-M) var(string))
|
||||||
xitem(tt(zle) tt(-U) var(string))
|
xitem(tt(zle) tt(-U) var(string))
|
||||||
|
xitem(tt(zle) tt(-I))
|
||||||
xitem(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)
|
xitem(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)
|
||||||
item(tt(zle))(
|
item(tt(zle))(
|
||||||
The tt(zle) builtin performs a number of different actions concerning
|
The tt(zle) builtin performs a number of different actions concerning
|
||||||
|
|
@ -263,6 +264,11 @@ cleared.
|
||||||
Note that this option is only useful for widgets that do not exit
|
Note that this option is only useful for widgets that do not exit
|
||||||
immediately after using it because the strings displayed will be erased
|
immediately after using it because the strings displayed will be erased
|
||||||
immediately after return from the widget.
|
immediately after return from the widget.
|
||||||
|
|
||||||
|
This command can safely be called outside user defined widgets; if zle is
|
||||||
|
active, the display will be refreshed, while if zle is not active, the
|
||||||
|
command has no effect. In this case there will usually be no other
|
||||||
|
arguments. The status is zero if zle was active, else one.
|
||||||
)
|
)
|
||||||
item(tt(-M) var(string))(
|
item(tt(-M) var(string))(
|
||||||
As with the tt(-R) option, the var(string) will be displayed below the
|
As with the tt(-R) option, the var(string) will be displayed below the
|
||||||
|
|
@ -281,6 +287,28 @@ the last string pushed onto the stack will be processed first. However,
|
||||||
the characters in each var(string) will be processed in the order in which
|
the characters in each var(string) will be processed in the order in which
|
||||||
they appear in the string.
|
they appear in the string.
|
||||||
)
|
)
|
||||||
|
item(tt(-I))(
|
||||||
|
Unusually, this option is only useful em(outside) ordinary widget functions.
|
||||||
|
It invalidates the current zle display in preparation for output; usually
|
||||||
|
this will be from a trap function. It has no effect if zle is not
|
||||||
|
active. When a trap exits, the shell checks to see if the display needs
|
||||||
|
restoring, hence the following will print output in such a way as not to
|
||||||
|
disturb the line being edited:
|
||||||
|
|
||||||
|
example(TRAPUSR1() {
|
||||||
|
# Invalidate zle display
|
||||||
|
zle -I
|
||||||
|
# Show output
|
||||||
|
print Hello
|
||||||
|
})
|
||||||
|
|
||||||
|
Note that there are better ways of manipulating the display from within zle
|
||||||
|
widgets. In general, the trap function may need to test whether zle is
|
||||||
|
loaded before using this method; if it is not, there is no point in loading
|
||||||
|
it specially since the line editor will not be active.
|
||||||
|
|
||||||
|
The status is zero if zle was active, else one.
|
||||||
|
)
|
||||||
item(var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
|
item(var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
|
||||||
Invoke the specified widget. This can only be done when ZLE is
|
Invoke the specified widget. This can only be done when ZLE is
|
||||||
active; normally this will be within a user-defined widget.
|
active; normally this will be within a user-defined widget.
|
||||||
|
|
|
||||||
|
|
@ -801,7 +801,7 @@ zfgetline(char *ln, int lnsize, int tmout)
|
||||||
cmdbuf[0] = (char)IAC;
|
cmdbuf[0] = (char)IAC;
|
||||||
cmdbuf[1] = (char)DONT;
|
cmdbuf[1] = (char)DONT;
|
||||||
cmdbuf[2] = ch;
|
cmdbuf[2] = ch;
|
||||||
write(zfsess->cfd, cmdbuf, 3);
|
ztrapwrite(zfsess->cfd, cmdbuf, 3);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case DO:
|
case DO:
|
||||||
|
|
@ -811,7 +811,7 @@ zfgetline(char *ln, int lnsize, int tmout)
|
||||||
cmdbuf[0] = (char)IAC;
|
cmdbuf[0] = (char)IAC;
|
||||||
cmdbuf[1] = (char)WONT;
|
cmdbuf[1] = (char)WONT;
|
||||||
cmdbuf[2] = ch;
|
cmdbuf[2] = ch;
|
||||||
write(zfsess->cfd, cmdbuf, 3);
|
ztrapwrite(zfsess->cfd, cmdbuf, 3);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
|
|
@ -996,7 +996,7 @@ zfsendcmd(char *cmd)
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
zfalarm(tmout);
|
zfalarm(tmout);
|
||||||
ret = write(zfsess->cfd, cmd, strlen(cmd));
|
ret = ztrapwrite(zfsess->cfd, cmd, strlen(cmd));
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
|
@ -1470,7 +1470,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!tmout)
|
if (!tmout)
|
||||||
return read(fd, bf, sz);
|
return ztrapread(fd, bf, sz);
|
||||||
|
|
||||||
if (setjmp(zfalrmbuf)) {
|
if (setjmp(zfalrmbuf)) {
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
@ -1479,7 +1479,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
|
||||||
}
|
}
|
||||||
zfalarm(tmout);
|
zfalarm(tmout);
|
||||||
|
|
||||||
ret = read(fd, bf, sz);
|
ret = ztrapread(fd, bf, sz);
|
||||||
|
|
||||||
/* we don't bother turning off the whole alarm mechanism here */
|
/* we don't bother turning off the whole alarm mechanism here */
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
@ -1495,7 +1495,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!tmout)
|
if (!tmout)
|
||||||
return write(fd, bf, sz);
|
return ztrapwrite(fd, bf, sz);
|
||||||
|
|
||||||
if (setjmp(zfalrmbuf)) {
|
if (setjmp(zfalrmbuf)) {
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
@ -1504,7 +1504,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
|
||||||
}
|
}
|
||||||
zfalarm(tmout);
|
zfalarm(tmout);
|
||||||
|
|
||||||
ret = write(fd, bf, sz);
|
ret = ztrapwrite(fd, bf, sz);
|
||||||
|
|
||||||
/* we don't bother turning off the whole alarm mechanism here */
|
/* we don't bother turning off the whole alarm mechanism here */
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
@ -2846,7 +2846,7 @@ zfclose(int leaveparams)
|
||||||
if (!zfnopen) {
|
if (!zfnopen) {
|
||||||
/* Write the final status in case this is a subshell */
|
/* Write the final status in case this is a subshell */
|
||||||
lseek(zfstatfd, zfsessno*sizeof(int), 0);
|
lseek(zfstatfd, zfsessno*sizeof(int), 0);
|
||||||
write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
|
ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
|
||||||
|
|
||||||
close(zfstatfd);
|
close(zfstatfd);
|
||||||
zfstatfd = -1;
|
zfstatfd = -1;
|
||||||
|
|
@ -3123,7 +3123,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||||
/* Get the status in case it was set by a forked process */
|
/* Get the status in case it was set by a forked process */
|
||||||
int oldstatus = zfstatusp[zfsessno];
|
int oldstatus = zfstatusp[zfsessno];
|
||||||
lseek(zfstatfd, 0, 0);
|
lseek(zfstatfd, 0, 0);
|
||||||
read(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
|
ztrapread(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
|
||||||
if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
|
if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
|
||||||
/* got closed in subshell without us knowing */
|
/* got closed in subshell without us knowing */
|
||||||
zcfinish = 2;
|
zcfinish = 2;
|
||||||
|
|
@ -3212,7 +3212,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||||
* but only for the active session.
|
* but only for the active session.
|
||||||
*/
|
*/
|
||||||
lseek(zfstatfd, zfsessno*sizeof(int), 0);
|
lseek(zfstatfd, zfsessno*sizeof(int), 0);
|
||||||
write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
|
ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -536,7 +536,7 @@ ptywritestr(Ptycmd cmd, char *s, int len)
|
||||||
|
|
||||||
for (; !errflag && !breaks && !retflag && !contflag && len;
|
for (; !errflag && !breaks && !retflag && !contflag && len;
|
||||||
len -= written, s += written) {
|
len -= written, s += written) {
|
||||||
if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock &&
|
if ((written = ztrapwrite(cmd->fd, s, len)) < 0 && cmd->nblock &&
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
errno == EWOULDBLOCK
|
errno == EWOULDBLOCK
|
||||||
#else
|
#else
|
||||||
|
|
@ -578,7 +578,7 @@ ptywrite(Ptycmd cmd, char **args, int nonl)
|
||||||
int n;
|
int n;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
while ((n = read(0, buf, BUFSIZ)) > 0)
|
while ((n = ztrapread(0, buf, BUFSIZ)) > 0)
|
||||||
if (ptywritestr(cmd, buf, n))
|
if (ptywritestr(cmd, buf, n))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,11 +313,17 @@ static int
|
||||||
breakread(int fd, char *buf, int n)
|
breakread(int fd, char *buf, int n)
|
||||||
{
|
{
|
||||||
fd_set f;
|
fd_set f;
|
||||||
|
int ret;
|
||||||
|
|
||||||
FD_ZERO(&f);
|
FD_ZERO(&f);
|
||||||
FD_SET(fd, &f);
|
FD_SET(fd, &f);
|
||||||
return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
|
|
||||||
|
ALLOWTRAPS {
|
||||||
|
ret = (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
|
||||||
EOF : read(fd, buf, n));
|
EOF : read(fd, buf, n));
|
||||||
|
} DISALLOWTRAPS;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
# define read breakread
|
# define read breakread
|
||||||
|
|
@ -388,7 +394,7 @@ getkey(int keytmout)
|
||||||
# else
|
# else
|
||||||
ioctl(SHTTY, TCSETA, &ti.tio);
|
ioctl(SHTTY, TCSETA, &ti.tio);
|
||||||
# endif
|
# endif
|
||||||
r = read(SHTTY, &cc, 1);
|
r = ztrapread(SHTTY, &cc, 1);
|
||||||
# ifdef HAVE_TERMIOS_H
|
# ifdef HAVE_TERMIOS_H
|
||||||
tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
|
tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
|
||||||
# else
|
# else
|
||||||
|
|
@ -398,7 +404,10 @@ getkey(int keytmout)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
while ((r = read(SHTTY, &cc, 1)) != 1) {
|
for (;;) {
|
||||||
|
r = ztrapread(SHTTY, &cc, 1);
|
||||||
|
if (r == 1)
|
||||||
|
break;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* The test for IGNOREEOF was added to make zsh ignore ^Ds
|
/* The test for IGNOREEOF was added to make zsh ignore ^Ds
|
||||||
that were typed while commands are running. Unfortuantely
|
that were typed while commands are running. Unfortuantely
|
||||||
|
|
@ -1083,7 +1092,7 @@ zleaftertrap(Hookdef dummy, void *dat)
|
||||||
static struct builtin bintab[] = {
|
static struct builtin bintab[] = {
|
||||||
BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
|
BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
|
||||||
BUILTIN("vared", 0, bin_vared, 1, 7, 0, NULL, NULL),
|
BUILTIN("vared", 0, bin_vared, 1, 7, 0, NULL, NULL),
|
||||||
BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgGcRaU", NULL),
|
BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgGcRaUI", NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The order of the entries in this table has to match the *HOOK
|
/* The order of the entries in this table has to match the *HOOK
|
||||||
|
|
|
||||||
|
|
@ -339,6 +339,7 @@ bin_zle(char *name, char **args, char *ops, int func)
|
||||||
{ 'R', bin_zle_refresh, 0, -1 },
|
{ 'R', bin_zle_refresh, 0, -1 },
|
||||||
{ 'M', bin_zle_mesg, 1, 1 },
|
{ 'M', bin_zle_mesg, 1, 1 },
|
||||||
{ 'U', bin_zle_unget, 1, 1 },
|
{ 'U', bin_zle_unget, 1, 1 },
|
||||||
|
{ 'I', bin_zle_invalidate, 0, 0 },
|
||||||
{ 0, bin_zle_call, 0, -1 },
|
{ 0, bin_zle_call, 0, -1 },
|
||||||
};
|
};
|
||||||
struct opn const *op, *opp;
|
struct opn const *op, *opp;
|
||||||
|
|
@ -396,10 +397,8 @@ bin_zle_refresh(char *name, char **args, char *ops, char func)
|
||||||
char *s = statusline;
|
char *s = statusline;
|
||||||
int sl = statusll, ocl = clearlist;
|
int sl = statusll, ocl = clearlist;
|
||||||
|
|
||||||
if (!zleactive) {
|
if (!zleactive)
|
||||||
zwarnnam(name, "can only be called from widget function", NULL, 0);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
statusline = NULL;
|
statusline = NULL;
|
||||||
statusll = 0;
|
statusll = 0;
|
||||||
if (*args) {
|
if (*args) {
|
||||||
|
|
@ -656,6 +655,17 @@ bin_zle_call(char *name, char **args, char *ops, char func)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_zle_invalidate(char *name, char **args, char *ops, char func)
|
||||||
|
{
|
||||||
|
if (zleactive) {
|
||||||
|
trashzle();
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************/
|
/*******************/
|
||||||
/* initialiasation */
|
/* initialiasation */
|
||||||
/*******************/
|
/*******************/
|
||||||
|
|
|
||||||
|
|
@ -3218,7 +3218,7 @@ zexit(int val, int from_signal)
|
||||||
checkjobs(); /* check if any jobs are running/stopped */
|
checkjobs(); /* check if any jobs are running/stopped */
|
||||||
if (stopmsg) {
|
if (stopmsg) {
|
||||||
stopmsg = 2;
|
stopmsg = 2;
|
||||||
LASTALLOC_RETURN;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_exit++ && from_signal)
|
if (in_exit++ && from_signal)
|
||||||
|
|
@ -3240,7 +3240,7 @@ zexit(int val, int from_signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sigtrapped[SIGEXIT])
|
if (sigtrapped[SIGEXIT])
|
||||||
dotrap(SIGEXIT);
|
dotrap(SIGEXIT, 1);
|
||||||
runhookdef(EXITHOOK, NULL);
|
runhookdef(EXITHOOK, NULL);
|
||||||
if (mypid != getpid())
|
if (mypid != getpid())
|
||||||
_exit(val);
|
_exit(val);
|
||||||
|
|
@ -3486,7 +3486,7 @@ bin_read(char *name, char **args, char *ops, int func)
|
||||||
*bptr = readchar;
|
*bptr = readchar;
|
||||||
val = 1;
|
val = 1;
|
||||||
readchar = -1;
|
readchar = -1;
|
||||||
} else if ((val = read(readfd, bptr, nchars)) <= 0)
|
} else if ((val = ztrapread(readfd, bptr, nchars)) <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* decrement number of characters read from number required */
|
/* decrement number of characters read from number required */
|
||||||
|
|
@ -3500,7 +3500,7 @@ bin_read(char *name, char **args, char *ops, int func)
|
||||||
if (!izle && !ops['u'] && !ops['p']) {
|
if (!izle && !ops['u'] && !ops['p']) {
|
||||||
/* dispose of result appropriately, etc. */
|
/* dispose of result appropriately, etc. */
|
||||||
if (isem)
|
if (isem)
|
||||||
while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
|
while (val > 0 && ztrapread(SHTTY, &d, 1) == 1 && d != '\n');
|
||||||
else
|
else
|
||||||
settyinfo(&shttyinfo);
|
settyinfo(&shttyinfo);
|
||||||
if (haso) {
|
if (haso) {
|
||||||
|
|
@ -3733,6 +3733,7 @@ static int
|
||||||
zread(int izle, int *readchar)
|
zread(int izle, int *readchar)
|
||||||
{
|
{
|
||||||
char cc, retry = 0;
|
char cc, retry = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (izle) {
|
if (izle) {
|
||||||
int c = getkeyptr(0);
|
int c = getkeyptr(0);
|
||||||
|
|
@ -3756,7 +3757,8 @@ zread(int izle, int *readchar)
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* read a character from readfd */
|
/* read a character from readfd */
|
||||||
switch (read(readfd, &cc, 1)) {
|
ret = ztrapread(readfd, &cc, 1);
|
||||||
|
switch (ret) {
|
||||||
case 1:
|
case 1:
|
||||||
/* return the character read */
|
/* return the character read */
|
||||||
return STOUC(cc);
|
return STOUC(cc);
|
||||||
|
|
|
||||||
22
Src/exec.c
22
Src/exec.c
|
|
@ -738,6 +738,7 @@ static int
|
||||||
execsimple(Estate state)
|
execsimple(Estate state)
|
||||||
{
|
{
|
||||||
wordcode code = *state->pc++;
|
wordcode code = *state->pc++;
|
||||||
|
int lv;
|
||||||
|
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return (lastval = 1);
|
return (lastval = 1);
|
||||||
|
|
@ -754,9 +755,13 @@ execsimple(Estate state)
|
||||||
fputc('\n', xtrerr);
|
fputc('\n', xtrerr);
|
||||||
fflush(xtrerr);
|
fflush(xtrerr);
|
||||||
}
|
}
|
||||||
return (lastval = (errflag ? errflag : cmdoutval));
|
lv = (errflag ? errflag : cmdoutval);
|
||||||
} else
|
} else
|
||||||
return (lastval = (execfuncs[code - WC_CURSH])(state, 0));
|
lv = (execfuncs[code - WC_CURSH])(state, 0);
|
||||||
|
|
||||||
|
RUNTRAPS();
|
||||||
|
|
||||||
|
return lastval = lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main routine for executing a list. *
|
/* Main routine for executing a list. *
|
||||||
|
|
@ -887,19 +892,19 @@ sublist_done:
|
||||||
noerrexit = oldnoerrexit;
|
noerrexit = oldnoerrexit;
|
||||||
|
|
||||||
if (sigtrapped[SIGDEBUG])
|
if (sigtrapped[SIGDEBUG])
|
||||||
dotrap(SIGDEBUG);
|
dotrap(SIGDEBUG, 1);
|
||||||
|
|
||||||
/* Check whether we are suppressing traps/errexit *
|
/* Check whether we are suppressing traps/errexit *
|
||||||
* (typically in init scripts) and if we haven't *
|
* (typically in init scripts) and if we haven't *
|
||||||
* already performed them for this sublist. */
|
* already performed them for this sublist. */
|
||||||
if (!noerrexit && !donetrap) {
|
if (!noerrexit && !donetrap) {
|
||||||
if (sigtrapped[SIGZERR] && lastval) {
|
if (sigtrapped[SIGZERR] && lastval) {
|
||||||
dotrap(SIGZERR);
|
dotrap(SIGZERR, 1);
|
||||||
donetrap = 1;
|
donetrap = 1;
|
||||||
}
|
}
|
||||||
if (lastval && isset(ERREXIT)) {
|
if (lastval && isset(ERREXIT)) {
|
||||||
if (sigtrapped[SIGEXIT])
|
if (sigtrapped[SIGEXIT])
|
||||||
dotrap(SIGEXIT);
|
dotrap(SIGEXIT, 1);
|
||||||
if (mypid != getpid())
|
if (mypid != getpid())
|
||||||
_exit(lastval);
|
_exit(lastval);
|
||||||
else
|
else
|
||||||
|
|
@ -1181,9 +1186,10 @@ execpline2(Estate state, wordcode pcode,
|
||||||
else
|
else
|
||||||
list_pipe_text[0] = '\0';
|
list_pipe_text[0] = '\0';
|
||||||
}
|
}
|
||||||
if (WC_PIPE_TYPE(pcode) == WC_PIPE_END)
|
if (WC_PIPE_TYPE(pcode) == WC_PIPE_END) {
|
||||||
execcmd(state, input, output, how, last1 ? 1 : 2);
|
execcmd(state, input, output, how, last1 ? 1 : 2);
|
||||||
else {
|
RUNTRAPS();
|
||||||
|
} else {
|
||||||
int old_list_pipe = list_pipe;
|
int old_list_pipe = list_pipe;
|
||||||
Wordcode next = state->pc + (*state->pc);
|
Wordcode next = state->pc + (*state->pc);
|
||||||
wordcode code;
|
wordcode code;
|
||||||
|
|
@ -1218,12 +1224,14 @@ execpline2(Estate state, wordcode pcode,
|
||||||
entersubsh(how, 2, 0);
|
entersubsh(how, 2, 0);
|
||||||
close(synch[1]);
|
close(synch[1]);
|
||||||
execcmd(state, input, pipes[1], how, 0);
|
execcmd(state, input, pipes[1], how, 0);
|
||||||
|
RUNTRAPS();
|
||||||
_exit(lastval);
|
_exit(lastval);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* otherwise just do the pipeline normally. */
|
/* otherwise just do the pipeline normally. */
|
||||||
subsh_close = pipes[0];
|
subsh_close = pipes[0];
|
||||||
execcmd(state, input, pipes[1], how, 0);
|
execcmd(state, input, pipes[1], how, 0);
|
||||||
|
RUNTRAPS();
|
||||||
}
|
}
|
||||||
zclose(pipes[1]);
|
zclose(pipes[1]);
|
||||||
state->pc = next;
|
state->pc = next;
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ loop(int toplevel, int justonce)
|
||||||
}
|
}
|
||||||
if (isset(SINGLECOMMAND) && toplevel) {
|
if (isset(SINGLECOMMAND) && toplevel) {
|
||||||
if (sigtrapped[SIGEXIT])
|
if (sigtrapped[SIGEXIT])
|
||||||
dotrap(SIGEXIT);
|
dotrap(SIGEXIT, 1);
|
||||||
exit(lastval);
|
exit(lastval);
|
||||||
}
|
}
|
||||||
if (justonce)
|
if (justonce)
|
||||||
|
|
@ -1107,6 +1107,7 @@ fallback_zleread(char *lp, char *rp, int ha)
|
||||||
pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
|
pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
|
||||||
write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
|
write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
|
||||||
free(pptbuf);
|
free(pptbuf);
|
||||||
|
|
||||||
return (unsigned char *)shingetline();
|
return (unsigned char *)shingetline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,9 @@ shingetline(void)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
do {
|
do {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
ALLOWTRAPS {
|
||||||
c = fgetc(bshin);
|
c = fgetc(bshin);
|
||||||
|
} DISALLOWTRAPS;
|
||||||
} while (c < 0 && errno == EINTR);
|
} while (c < 0 && errno == EINTR);
|
||||||
if (c < 0 || c == '\n') {
|
if (c < 0 || c == '\n') {
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ update_job(Job jn)
|
||||||
zrefresh();
|
zrefresh();
|
||||||
}
|
}
|
||||||
if (sigtrapped[SIGCHLD] && job != thisjob)
|
if (sigtrapped[SIGCHLD] && job != thisjob)
|
||||||
dotrap(SIGCHLD);
|
dotrap(SIGCHLD, 0);
|
||||||
|
|
||||||
/* When MONITOR is set, the foreground process runs in a different *
|
/* When MONITOR is set, the foreground process runs in a different *
|
||||||
* process group from the shell, so the shell will not receive *
|
* process group from the shell, so the shell will not receive *
|
||||||
|
|
@ -389,7 +389,7 @@ update_job(Job jn)
|
||||||
|
|
||||||
if (sig == SIGINT || sig == SIGQUIT) {
|
if (sig == SIGINT || sig == SIGQUIT) {
|
||||||
if (sigtrapped[sig]) {
|
if (sigtrapped[sig]) {
|
||||||
dotrap(sig);
|
dotrap(sig, 0);
|
||||||
/* We keep the errflag as set or not by dotrap.
|
/* We keep the errflag as set or not by dotrap.
|
||||||
* This is to fulfil the promise to carry on
|
* This is to fulfil the promise to carry on
|
||||||
* with the jobs if trap returns zero.
|
* with the jobs if trap returns zero.
|
||||||
|
|
@ -878,7 +878,9 @@ waitforpid(pid_t pid)
|
||||||
else
|
else
|
||||||
kill(pid, SIGCONT);
|
kill(pid, SIGCONT);
|
||||||
|
|
||||||
|
ALLOWTRAPS {
|
||||||
child_suspend(SIGINT);
|
child_suspend(SIGINT);
|
||||||
|
} DISALLOWTRAPS;
|
||||||
child_block();
|
child_block();
|
||||||
}
|
}
|
||||||
child_unblock();
|
child_unblock();
|
||||||
|
|
@ -900,7 +902,9 @@ waitjob(int job, int sig)
|
||||||
while (!errflag && jn->stat &&
|
while (!errflag && jn->stat &&
|
||||||
!(jn->stat & STAT_DONE) &&
|
!(jn->stat & STAT_DONE) &&
|
||||||
!(interact && (jn->stat & STAT_STOPPED))) {
|
!(interact && (jn->stat & STAT_STOPPED))) {
|
||||||
|
ALLOWTRAPS {
|
||||||
child_suspend(sig);
|
child_suspend(sig);
|
||||||
|
} DISALLOWTRAPS;
|
||||||
/* Commenting this out makes ^C-ing a job started by a function
|
/* Commenting this out makes ^C-ing a job started by a function
|
||||||
stop the whole function again. But I guess it will stop
|
stop the whole function again. But I guess it will stop
|
||||||
something else from working properly, we have to find out
|
something else from working properly, we have to find out
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ handler(int sig)
|
||||||
|
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
if (sigtrapped[SIGHUP])
|
if (sigtrapped[SIGHUP])
|
||||||
dotrap(SIGHUP);
|
dotrap(SIGHUP, 0);
|
||||||
else {
|
else {
|
||||||
stopmsg = 1;
|
stopmsg = 1;
|
||||||
zexit(SIGHUP, 1);
|
zexit(SIGHUP, 1);
|
||||||
|
|
@ -506,7 +506,7 @@ handler(int sig)
|
||||||
|
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (sigtrapped[SIGINT])
|
if (sigtrapped[SIGINT])
|
||||||
dotrap(SIGINT);
|
dotrap(SIGINT, 0);
|
||||||
else {
|
else {
|
||||||
if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
|
if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
|
||||||
isset(INTERACTIVE) && noerrexit < 0)
|
isset(INTERACTIVE) && noerrexit < 0)
|
||||||
|
|
@ -523,14 +523,14 @@ handler(int sig)
|
||||||
case SIGWINCH:
|
case SIGWINCH:
|
||||||
adjustwinsize(1); /* check window size and adjust */
|
adjustwinsize(1); /* check window size and adjust */
|
||||||
if (sigtrapped[SIGWINCH])
|
if (sigtrapped[SIGWINCH])
|
||||||
dotrap(SIGWINCH);
|
dotrap(SIGWINCH, 0);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case SIGALRM:
|
case SIGALRM:
|
||||||
if (sigtrapped[SIGALRM]) {
|
if (sigtrapped[SIGALRM]) {
|
||||||
int tmout;
|
int tmout;
|
||||||
dotrap(SIGALRM);
|
dotrap(SIGALRM, 0);
|
||||||
|
|
||||||
if ((tmout = getiparam("TMOUT")))
|
if ((tmout = getiparam("TMOUT")))
|
||||||
alarm(tmout); /* reset the alarm */
|
alarm(tmout); /* reset the alarm */
|
||||||
|
|
@ -549,7 +549,7 @@ handler(int sig)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dotrap(sig);
|
dotrap(sig, 0);
|
||||||
break;
|
break;
|
||||||
} /* end of switch(sig) */
|
} /* end of switch(sig) */
|
||||||
|
|
||||||
|
|
@ -907,7 +907,9 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
||||||
* function will test for this, but this way we keep status flags *
|
* function will test for this, but this way we keep status flags *
|
||||||
* intact without working too hard. Special cases (e.g. calling *
|
* intact without working too hard. Special cases (e.g. calling *
|
||||||
* a trap for SIGINT after the error flag was set) are handled *
|
* a trap for SIGINT after the error flag was set) are handled *
|
||||||
* by the calling code. (PWS 1995/06/08). */
|
* by the calling code. (PWS 1995/06/08). *
|
||||||
|
* *
|
||||||
|
* This test is now replicated in dotrap(). */
|
||||||
if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
|
if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -953,15 +955,67 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
||||||
breaks = loops;
|
breaks = loops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If zle was running while the trap was executed, see if we
|
||||||
|
* need to restore the display.
|
||||||
|
*/
|
||||||
|
if (zleactive && resetneeded)
|
||||||
|
zrefresh();
|
||||||
|
|
||||||
if (*sigtr != ZSIG_IGNORED)
|
if (*sigtr != ZSIG_IGNORED)
|
||||||
*sigtr &= ~ZSIG_IGNORED;
|
*sigtr &= ~ZSIG_IGNORED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Standard call to execute a trap for a given signal */
|
/* != 0 if trap handlers can be called immediately */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export int trapsallowed;
|
||||||
|
|
||||||
|
/* Queued traps and allocated length of queue. */
|
||||||
|
|
||||||
|
static int *trapqueue, trapqlen;
|
||||||
|
|
||||||
|
/* Number of used slots in trap queue. */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export int trapqused;
|
||||||
|
|
||||||
|
/* Standard call to execute a trap for a given signal. The second
|
||||||
|
* argument should be zero if we may need to put the trap on the queue
|
||||||
|
* and 1 if it may be called immediately. It should never be set to
|
||||||
|
* anything less than zero, that's used internally. */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
void
|
void
|
||||||
dotrap(int sig)
|
dotrap(int sig, int now)
|
||||||
{
|
{
|
||||||
|
/* Copied from dotrapargs(). */
|
||||||
|
if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (now || trapsallowed) {
|
||||||
|
if (now < 0)
|
||||||
|
RUNTRAPS();
|
||||||
dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
|
dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
|
||||||
|
} else {
|
||||||
|
if (trapqlen == trapqused)
|
||||||
|
trapqueue = (int *) zrealloc(trapqueue, (trapqlen += 32));
|
||||||
|
trapqueue[trapqused++] = sig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export void
|
||||||
|
doqueuedtraps(void)
|
||||||
|
{
|
||||||
|
int sig, ota = trapsallowed;
|
||||||
|
|
||||||
|
trapsallowed = 1;
|
||||||
|
while (trapqused) {
|
||||||
|
trapqused--;
|
||||||
|
sig = *trapqueue;
|
||||||
|
memcpy(trapqueue, trapqueue + 1, trapqused * sizeof(int));
|
||||||
|
dotrap(sig, -1);
|
||||||
|
}
|
||||||
|
trapsallowed = ota;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@
|
||||||
# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0)
|
# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0)
|
||||||
#endif /* ifndef POSIX_SIGNALS */
|
#endif /* ifndef POSIX_SIGNALS */
|
||||||
|
|
||||||
#define child_block() signal_block(signal_mask(SIGCHLD))
|
#define child_block() signal_block(sigchld_mask)
|
||||||
#define child_unblock() signal_unblock(signal_mask(SIGCHLD))
|
#define child_unblock() signal_unblock(sigchld_mask)
|
||||||
#define child_suspend(S) signal_suspend(SIGCHLD, S)
|
#define child_suspend(S) signal_suspend(SIGCHLD, S)
|
||||||
|
|
||||||
/* ignore a signal */
|
/* ignore a signal */
|
||||||
|
|
@ -92,3 +92,34 @@
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/* Make some signal functions faster. */
|
||||||
|
|
||||||
|
#ifdef POSIX_SIGNALS
|
||||||
|
#define signal_block(S) \
|
||||||
|
((dummy_sigset1 = (S)), \
|
||||||
|
sigprocmask(SIG_BLOCK, &dummy_sigset1, &dummy_sigset2), \
|
||||||
|
dummy_sigset2)
|
||||||
|
#else
|
||||||
|
# ifdef BSD_SIGNALS
|
||||||
|
#define signal_block(S) sigblock(S)
|
||||||
|
# else
|
||||||
|
extern sigset_t signal_block _((sigset_t));
|
||||||
|
# endif /* BSD_SIGNALS */
|
||||||
|
#endif /* POSIX_SIGNALS */
|
||||||
|
|
||||||
|
#ifdef POSIX_SIGNALS
|
||||||
|
#define signal_unblock(S) \
|
||||||
|
((dummy_sigset1 = (S)), \
|
||||||
|
sigprocmask(SIG_UNBLOCK, &dummy_sigset1, &dummy_sigset2), \
|
||||||
|
dummy_sigset2)
|
||||||
|
#else
|
||||||
|
extern sigset_t signal_unblock _((sigset_t));
|
||||||
|
#endif /* POSIX_SIGNALS */
|
||||||
|
|
||||||
|
#define RUNTRAPS() do { if (trapqused) doqueuedtraps(); } while (0)
|
||||||
|
#define ALLOWTRAPS do { RUNTRAPS(); trapsallowed++; do
|
||||||
|
#define DISALLOWTRAPS while (0); RUNTRAPS(); trapsallowed--; } while (0)
|
||||||
|
#define ALLOWTRAPS_RETURN(V) \
|
||||||
|
do { RUNTRAPS(); trapsallowed--; return (V); } while (0)
|
||||||
|
|
|
||||||
30
Src/utils.c
30
Src/utils.c
|
|
@ -1417,13 +1417,39 @@ checkrmall(char *s)
|
||||||
return (getquery("ny", 1) == 'y');
|
return (getquery("ny", 1) == 'y');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export int
|
||||||
|
ztrapread(int fd, char *buf, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ALLOWTRAPS {
|
||||||
|
ret = read(fd, buf, len);
|
||||||
|
} DISALLOWTRAPS;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export int
|
||||||
|
ztrapwrite(int fd, char *buf, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ALLOWTRAPS {
|
||||||
|
ret = write(fd, buf, len);
|
||||||
|
} DISALLOWTRAPS;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
read1char(void)
|
read1char(void)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
while (read(SHTTY, &c, 1) != 1) {
|
while (ztrapread(SHTTY, &c, 1) != 1) {
|
||||||
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1440,7 +1466,7 @@ noquery(int purge)
|
||||||
ioctl(SHTTY, FIONREAD, (char *)&val);
|
ioctl(SHTTY, FIONREAD, (char *)&val);
|
||||||
if (purge) {
|
if (purge) {
|
||||||
for (; val; val--)
|
for (; val; val--)
|
||||||
read(SHTTY, &c, 1);
|
ztrapread(SHTTY, &c, 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1627,8 +1627,6 @@ struct heap {
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
# define LASTALLOC_RETURN return
|
|
||||||
|
|
||||||
# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do
|
# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do
|
||||||
# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0);
|
# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue