Do not exit on SIGINT in non-interactive shells, fixes PR 1206,
i.e. this makes emacs usable from system(3). Programs called from shellscripts are now required to exit with proper signal status. That means, they have to kill themself. Exiting with faked numerical exit code is not sufficient. Exit with proper signal status if script exits on signal. Make the wait builtin interruptable, both with and without traps set. Use volatile sig_atomic_t where (and only where) appropriate. (Almost) fix printing of newlines on SIGINT. Make traps setable from trap handlers. This is needed for shellscripts that catch SIGINT for cleanup work but intend to exit on it, hance have to kill themself from a trap handler. I.e. mkdep. While I'm at it, make it -Wall clean. -Wall is not enabled in Makefile, since vararg warnx() macro calls in usr.bin/printf/printf.c are not -Wall-able. PR: 1206 Obtained from: Basic SIGINT fix from Bruce Evans
This commit is contained in:
parent
f3d290b0b5
commit
8a3c521f04
@ -88,12 +88,12 @@ expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: arith.y,v 1.6 1997/02/22 13:58:21 peter Exp $
|
||||
* $Id: arith.y,v 1.7 1998/05/18 06:43:27 charnier Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
#include "error.h"
|
||||
@ -103,6 +103,9 @@ static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
char *arith_buf, *arith_startbuf;
|
||||
extern void arith_lex_reset();
|
||||
|
||||
int yyparse(void);
|
||||
int yylex(void);
|
||||
|
||||
int
|
||||
arith(s)
|
||||
char *s;
|
||||
|
@ -34,12 +34,12 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: arith_lex.l,v 1.9 1997/02/22 13:58:21 peter Exp $
|
||||
* $Id: arith_lex.l,v 1.10 1998/05/18 06:43:28 charnier Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include "y.tab.h"
|
||||
|
@ -39,7 +39,7 @@
|
||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: error.c,v 1.10 1998/05/18 06:43:32 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@ -52,6 +52,7 @@ static const char rcsid[] =
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "show.h"
|
||||
#include "trap.h"
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@ -62,9 +63,9 @@ static const char rcsid[] =
|
||||
*/
|
||||
|
||||
struct jmploc *handler;
|
||||
int exception;
|
||||
volatile int suppressint;
|
||||
volatile int intpending;
|
||||
volatile sig_atomic_t exception;
|
||||
int suppressint;
|
||||
volatile sig_atomic_t intpending;
|
||||
char *commandname;
|
||||
|
||||
|
||||
@ -90,29 +91,43 @@ exraise(e)
|
||||
/*
|
||||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
||||
* there is a short period after a fork before the signal handlers are
|
||||
* set to the appropriate value for the child. (The test for iflag is
|
||||
* just defensive programming.)
|
||||
* this routine is not called.) Supressint is nonzero when interrupts
|
||||
* are held using the INTOFF macro. If SIGINTs are not suppressed and
|
||||
* the shell is not a root shell, then we want to be terminated if we
|
||||
* get here, as if we were terminated directly by a SIGINT. Arrange for
|
||||
* this here.
|
||||
*/
|
||||
|
||||
void
|
||||
onint() {
|
||||
sigset_t sigset;
|
||||
|
||||
if (suppressint) {
|
||||
/* The !in_dotrap is save. The only way we can arrive here with
|
||||
* in_dotrap set is that a trap handler set SIGINT to default
|
||||
* and killed itself.
|
||||
*/
|
||||
|
||||
if (suppressint && !in_dotrap) {
|
||||
intpending++;
|
||||
return;
|
||||
}
|
||||
intpending = 0;
|
||||
sigemptyset(&sigset);
|
||||
sigprocmask(SIG_SETMASK, &sigset, NULL);
|
||||
out2str("\n");
|
||||
|
||||
/* This doesn't seem to be needed. Note that main emit a newline
|
||||
* as well.
|
||||
*/
|
||||
#if 0
|
||||
if (tcgetpgrp(0) == getpid())
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
#endif
|
||||
if (rootshell && iflag)
|
||||
exraise(EXINT);
|
||||
else
|
||||
_exit(128 + SIGINT);
|
||||
else {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||
* $Id$
|
||||
* $Id: error.h,v 1.7 1997/02/22 13:58:23 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -57,6 +57,7 @@
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
struct jmploc {
|
||||
jmp_buf loc;
|
||||
@ -79,8 +80,8 @@ extern int exception;
|
||||
* more fun than worrying about efficiency and portability. :-))
|
||||
*/
|
||||
|
||||
extern volatile int suppressint;
|
||||
extern volatile int intpending;
|
||||
extern volatile sig_atomic_t suppressint;
|
||||
extern volatile sig_atomic_t intpending;
|
||||
extern char *commandname; /* name of command--printed on error */
|
||||
|
||||
#define INTOFF suppressint++
|
||||
|
@ -39,7 +39,7 @@
|
||||
static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: jobs.c,v 1.20 1998/05/18 06:43:47 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <fcntl.h>
|
||||
@ -87,6 +87,8 @@ MKINIT pid_t backgndpid = -1; /* pid of last background process */
|
||||
int initialpgrp; /* pgrp of shell on invocation */
|
||||
int curjob; /* current job */
|
||||
#endif
|
||||
int in_waitcmd = 0; /* Are we in waitcmd? */
|
||||
volatile sig_atomic_t breakwaitcmd = 0; /* Should wait be terminated? */
|
||||
|
||||
#if JOBS
|
||||
STATIC void restartjob __P((struct job *));
|
||||
@ -95,7 +97,7 @@ STATIC void freejob __P((struct job *));
|
||||
STATIC struct job *getjob __P((char *));
|
||||
STATIC int dowait __P((int, struct job *));
|
||||
#if SYSV
|
||||
STATIC int onsigchild __P((void));
|
||||
STATIC volatile int onsigchild __P((void));
|
||||
#endif
|
||||
STATIC int waitproc __P((int, int *));
|
||||
STATIC void cmdtxt __P((union node *));
|
||||
@ -385,7 +387,10 @@ waitcmd(argc, argv)
|
||||
} else {
|
||||
job = NULL;
|
||||
}
|
||||
for (;;) { /* loop until process terminated or stopped */
|
||||
in_waitcmd++;
|
||||
do { /* loop until process terminated or stopped or SIGINT is
|
||||
* received
|
||||
*/
|
||||
if (job != NULL) {
|
||||
if (job->state) {
|
||||
status = job->ps[job->nprocs - 1].status;
|
||||
@ -410,8 +415,11 @@ waitcmd(argc, argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
dowait(1, (struct job *)NULL);
|
||||
}
|
||||
} while (dowait(1, (struct job *)NULL) != -1);
|
||||
in_waitcmd--;
|
||||
|
||||
/* Not reachable */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -727,9 +735,12 @@ waitforjob(jp)
|
||||
st = WTERMSIG(status) + 128;
|
||||
if (! JOBS || jp->state == JOBDONE)
|
||||
freejob(jp);
|
||||
CLEAR_PENDING_INT;
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
|
||||
kill(getpid(), SIGINT);
|
||||
if (int_pending()) {
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
|
||||
kill(getpid(), SIGINT);
|
||||
else
|
||||
CLEAR_PENDING_INT;
|
||||
}
|
||||
INTON;
|
||||
return st;
|
||||
}
|
||||
@ -759,7 +770,11 @@ dowait(block, job)
|
||||
do {
|
||||
pid = waitproc(block, &status);
|
||||
TRACE(("wait returns %d, status=%d\n", pid, status));
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
} while (pid == -1 && errno == EINTR && breakwaitcmd == 0);
|
||||
if (breakwaitcmd != 0) {
|
||||
breakwaitcmd = 0;
|
||||
return -1;
|
||||
}
|
||||
if (pid <= 0)
|
||||
return pid;
|
||||
INTOFF;
|
||||
@ -867,7 +882,7 @@ dowait(block, job)
|
||||
*/
|
||||
|
||||
#ifdef SYSV
|
||||
STATIC int gotsigchild;
|
||||
STATIC sig_atomic_t gotsigchild;
|
||||
|
||||
STATIC int onsigchild() {
|
||||
gotsigchild = 1;
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||
* $Id: jobs.h,v 1.5 1997/02/22 13:58:29 peter Exp $
|
||||
* $Id: jobs.h,v 1.6 1997/08/18 02:53:20 steve Exp $
|
||||
*/
|
||||
|
||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||
@ -42,6 +42,7 @@
|
||||
#define FORK_BG 1
|
||||
#define FORK_NOJOB 2
|
||||
|
||||
#include <signal.h> /* For sig_atomic_t */
|
||||
|
||||
/*
|
||||
* A job structure contains information about a job. A job is either a
|
||||
@ -77,6 +78,8 @@ struct job {
|
||||
|
||||
extern pid_t backgndpid; /* pid of last background process */
|
||||
extern int job_warning; /* user was warned about stopped jobs */
|
||||
extern int in_waitcmd; /* Are we in wait? */
|
||||
extern volatile sig_atomic_t breakwaitcmd; /* Should wait be terminated? */
|
||||
|
||||
void setjobctl __P((int));
|
||||
int fgcmd __P((int, char **));
|
||||
|
@ -39,13 +39,14 @@
|
||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: miscbltin.c,v 1.15 1998/05/18 06:43:58 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Miscelaneous builtins.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* strtol() */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -39,7 +39,7 @@
|
||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: trap.c,v 1.11 1998/05/18 06:44:22 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <signal.h>
|
||||
@ -75,9 +75,11 @@ static const char rcsid[] =
|
||||
|
||||
|
||||
MKINIT char sigmode[NSIG]; /* current value of signal */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
int in_dotrap = 0; /* Do we execute in a trap handler? */
|
||||
static char *trap[NSIG]; /* trap handler commands */
|
||||
static char gotsig[NSIG]; /* indicates specified signal received */
|
||||
static volatile sig_atomic_t gotsig[NSIG];
|
||||
/* indicates specified signal received */
|
||||
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
|
||||
|
||||
static int getsigaction __P((int, sig_t *));
|
||||
@ -221,11 +223,10 @@ setsignal(signo)
|
||||
action = S_CATCH;
|
||||
else
|
||||
action = S_IGN;
|
||||
if (rootshell && action == S_DFL) {
|
||||
if (action == S_DFL) {
|
||||
switch (signo) {
|
||||
case SIGINT:
|
||||
if (iflag)
|
||||
action = S_CATCH;
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#ifdef DEBUG
|
||||
@ -236,15 +237,16 @@ setsignal(signo)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
action = S_IGN;
|
||||
break;
|
||||
case SIGTERM:
|
||||
if (iflag)
|
||||
if (rootshell && iflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#if JOBS
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
if (mflag)
|
||||
if (rootshell && mflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#endif
|
||||
@ -356,6 +358,10 @@ onsig(signo)
|
||||
if (signo != SIGCHLD || !ignore_sigchld)
|
||||
gotsig[signo] = 1;
|
||||
pendingsigs++;
|
||||
if (signo == SIGINT && in_waitcmd != 0) {
|
||||
dotrap();
|
||||
breakwaitcmd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -369,6 +375,7 @@ dotrap()
|
||||
int i;
|
||||
int savestatus;
|
||||
|
||||
in_dotrap++;
|
||||
for (;;) {
|
||||
for (i = 1; i < NSIG; i++) {
|
||||
if (gotsig[i]) {
|
||||
@ -392,6 +399,7 @@ dotrap()
|
||||
if (i >= NSIG)
|
||||
break;
|
||||
}
|
||||
in_dotrap--;
|
||||
pendingsigs = 0;
|
||||
}
|
||||
|
||||
@ -403,7 +411,7 @@ void
|
||||
setinteractive(on)
|
||||
int on;
|
||||
{
|
||||
static int is_interactive = 0;
|
||||
static int is_interactive = -1;
|
||||
|
||||
if (on == is_interactive)
|
||||
return;
|
||||
|
@ -34,10 +34,11 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||
* $Id: trap.h,v 1.6 1997/02/22 13:58:47 peter Exp $
|
||||
* $Id: trap.h,v 1.7 1997/11/10 11:32:24 bde Exp $
|
||||
*/
|
||||
|
||||
extern int pendingsigs;
|
||||
extern int in_dotrap;
|
||||
|
||||
int trapcmd __P((int, char **));
|
||||
void clear_traps __P((void));
|
||||
|
Loading…
Reference in New Issue
Block a user