diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 5e2b951d80d9..4195255c7cd0 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -1,4 +1,4 @@ -/* $NetBSD: eval.c,v 1.51 2000/02/09 20:26:53 christos Exp $ */ +/* $NetBSD: eval.c,v 1.52 2000/05/13 20:50:14 elric Exp $ */ /*- * Copyright (c) 1993 @@ -41,10 +41,13 @@ #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #else -__RCSID("$NetBSD: eval.c,v 1.51 2000/02/09 20:26:53 christos Exp $"); +__RCSID("$NetBSD: eval.c,v 1.52 2000/05/13 20:50:14 elric Exp $"); #endif #endif /* not lint */ +#include +#include +#include #include #include @@ -52,6 +55,7 @@ __RCSID("$NetBSD: eval.c,v 1.51 2000/02/09 20:26:53 christos Exp $"); * Evaluate a command. */ +#include "main.h" #include "shell.h" #include "nodes.h" #include "syntax.h" @@ -588,6 +592,7 @@ out: } +int vforked = 0; /* * Execute a simple command. @@ -627,6 +632,7 @@ evalcommand(cmd, flags, backcmd) (void) &flags; #endif + vforked = 0; /* First expand the arguments. */ TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(&smark); @@ -736,8 +742,62 @@ evalcommand(cmd, flags, backcmd) if (pipe(pip) < 0) error("Pipe call failed"); } - if (forkshell(jp, cmd, mode) != 0) - goto parent; /* at end of routine */ +#ifdef DO_SHAREDVFORK + /* It is essential that if DO_SHAREDVFORK is defined that the + * child's address space is actually shared with the parent as + * we rely on this. + */ + if (cmdentry.cmdtype == CMDNORMAL) { + pid_t pid; + + INTOFF; + vforked = 1; + switch (pid = vfork()) { + case -1: + TRACE(("Vfork failed, errno=%d", errno)); + INTON; + error("Cannot vfork"); + break; + case 0: + /* Make sure that exceptions only unwind to + * after the vfork(2) + */ + if (setjmp(jmploc.loc)) { + if (exception == EXSHELLPROC) { + /* We can't progress with the vfork, + * so, set vforked = 2 so the parent + * knows, and _exit(); + */ + vforked = 2; + _exit(0); + } else { + _exit(exerrno); + } + } + savehandler = handler; + handler = &jmploc; + forkchild(jp, cmd, mode, vforked); + break; + default: + handler = savehandler; /* restore from vfork(2) */ + if (vforked == 2) { + vforked = 0; + waitpid(pid, NULL, 0); + /* We need to progress in a normal fork fashion */ + goto normal_fork; + } + vforked = 0; + forkparent(jp, cmd, mode, pid); + goto parent; + } + } else { +normal_fork: +#endif + if (forkshell(jp, cmd, mode) != 0) + goto parent; /* at end of routine */ +#ifdef DO_SHAREDVFORK + } +#endif if (flags & EV_BACKCMD) { FORCEINTON; close(pip[0]); @@ -862,12 +922,12 @@ cmddone: #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif - clearredir(); - redirect(cmd->ncmd.redirect, 0); + clearredir(vforked?REDIR_VFORK:0); + redirect(cmd->ncmd.redirect, vforked?REDIR_VFORK:0); for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); envp = environment(); - shellexec(argv, envp, pathval(), cmdentry.u.index); + shellexec(argv, envp, pathval(), cmdentry.u.index, vforked); } goto out; @@ -892,7 +952,6 @@ out: } - /* * Search for a command. This is called before we fork so that the * location of the command will be available in the parent as well as @@ -1022,7 +1081,7 @@ execcmd(argc, argv) optschanged(); for (sp = cmdenviron; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); - shellexec(argv + 1, environment(), pathval(), 0); + shellexec(argv + 1, environment(), pathval(), 0, 0); } return 0; } diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 59ebb0b1f8a6..a4a7a946544e 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: exec.c,v 1.27 1999/07/09 03:05:49 christos Exp $ */ +/* $NetBSD: exec.c,v 1.28 2000/05/13 20:50:14 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,15 +41,17 @@ #if 0 static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; #else -__RCSID("$NetBSD: exec.c,v 1.27 1999/07/09 03:05:49 christos Exp $"); +__RCSID("$NetBSD: exec.c,v 1.28 2000/05/13 20:50:14 elric Exp $"); #endif #endif /* not lint */ #include #include +#include #include #include #include +#include #include /* @@ -102,7 +104,7 @@ STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ int exerrno = 0; /* Last exec error */ -STATIC void tryexec __P((char *, char **, char **)); +STATIC void tryexec __P((char *, char **, char **, int)); STATIC void execinterp __P((char **, char **)); STATIC void printentry __P((struct tblentry *, int)); STATIC void clearcmdentry __P((int)); @@ -117,22 +119,23 @@ STATIC void delete_cmd_entry __P((void)); */ void -shellexec(argv, envp, path, idx) +shellexec(argv, envp, path, idx, vforked) char **argv, **envp; const char *path; int idx; + int vforked; { char *cmdname; int e; if (strchr(argv[0], '/') != NULL) { - tryexec(argv[0], argv, envp); + tryexec(argv[0], argv, envp, vforked); e = errno; } else { e = ENOENT; while ((cmdname = padvance(&path, argv[0])) != NULL) { if (--idx < 0 && pathopt == NULL) { - tryexec(cmdname, argv, envp); + tryexec(cmdname, argv, envp, vforked); if (errno != ENOENT && errno != ENOTDIR) e = errno; } @@ -158,10 +161,11 @@ shellexec(argv, envp, path, idx) STATIC void -tryexec(cmd, argv, envp) +tryexec(cmd, argv, envp, vforked) char *cmd; char **argv; char **envp; + int vforked; { int e; #ifndef BSD @@ -177,6 +181,13 @@ tryexec(cmd, argv, envp) #endif e = errno; if (e == ENOEXEC) { + if (vforked) { + /* We are currently vfork(2)ed, so raise an + * exception, and evalcommand will try again + * with a normal fork(2). + */ + exraise(EXSHELLPROC); + } initshellproc(); setinputfile(cmd, 0); commandname = arg0 = savestr(argv[0]); diff --git a/bin/sh/exec.h b/bin/sh/exec.h index 3c0394951a42..ddfc1fcd31e7 100644 --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: exec.h,v 1.15 1999/07/09 03:05:50 christos Exp $ */ +/* $NetBSD: exec.h,v 1.16 2000/05/13 20:50:14 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -60,7 +60,7 @@ struct cmdentry { extern const char *pathopt; /* set by padvance */ extern int exerrno; /* last exec error */ -void shellexec __P((char **, char **, const char *, int)) +void shellexec __P((char **, char **, const char *, int, int)) __attribute__((noreturn)); char *padvance __P((const char **, const char *)); int hashcmd __P((int, char **)); diff --git a/bin/sh/input.c b/bin/sh/input.c index f119f1ac9138..c44c2c0771a7 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -1,4 +1,4 @@ -/* $NetBSD: input.c,v 1.32 1999/07/09 03:05:50 christos Exp $ */ +/* $NetBSD: input.c,v 1.33 2000/05/13 20:50:14 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; #else -__RCSID("$NetBSD: input.c,v 1.32 1999/07/09 03:05:50 christos Exp $"); +__RCSID("$NetBSD: input.c,v 1.33 2000/05/13 20:50:14 elric Exp $"); #endif #endif /* not lint */ @@ -506,10 +506,22 @@ popallfiles() { /* * Close the file(s) that the shell is reading commands from. Called * after a fork is done. + * + * Takes one arg, vfork, which tells it to not modify its global vars + * as it is still running in the parent. */ void -closescript() { +closescript(int vforked) { + if (vforked) { + struct parsefile *pf; + + for (pf=parsefile; pf != &basepf; pf=pf->prev) + close(pf->fd); + if (parsefile->fd > 0) + close(parsefile->fd); + return; + } popallfiles(); if (parsefile->fd > 0) { close(parsefile->fd); diff --git a/bin/sh/input.h b/bin/sh/input.h index 93f9ecfcf8e6..b45ec3f0d8ae 100644 --- a/bin/sh/input.h +++ b/bin/sh/input.h @@ -1,4 +1,4 @@ -/* $NetBSD: input.h,v 1.10 1999/07/09 03:05:50 christos Exp $ */ +/* $NetBSD: input.h,v 1.11 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -61,6 +61,6 @@ void setinputfd __P((int, int)); void setinputstring __P((char *, int)); void popfile __P((void)); void popallfiles __P((void)); -void closescript __P((void)); +void closescript __P((int)); #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer()) diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 3f8f04b2d823..63240f5f0967 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -1,4 +1,4 @@ -/* $NetBSD: jobs.c,v 1.32 1999/08/31 08:58:47 mycroft Exp $ */ +/* $NetBSD: jobs.c,v 1.33 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: jobs.c,v 1.32 1999/08/31 08:58:47 mycroft Exp $"); +__RCSID("$NetBSD: jobs.c,v 1.33 2000/05/13 20:50:15 elric Exp $"); #endif #endif /* not lint */ @@ -149,9 +149,9 @@ setjobctl(on) return; } #endif - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); + setsignal(SIGTSTP, 0); + setsignal(SIGTTOU, 0); + setsignal(SIGTTIN, 0); setpgid(0, rootpid); #ifdef OLD_TTY_DRIVER ioctl(2, TIOCSPGRP, (char *)&rootpid); @@ -165,9 +165,9 @@ setjobctl(on) #else tcsetpgrp(2, initialpgrp); #endif - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); + setsignal(SIGTSTP, 0); + setsignal(SIGTTOU, 0); + setsignal(SIGTTIN, 0); } jobctl = on; } @@ -574,81 +574,33 @@ forkshell(jp, n, mode) { int pid; int pgrp; - const char *devnull = _PATH_DEVNULL; - const char *nullerr = "Can't open %s"; TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, mode)); INTOFF; - pid = fork(); - if (pid == -1) { + switch (pid = fork()) { + case -1: TRACE(("Fork failed, errno=%d\n", errno)); INTON; error("Cannot fork"); + break; + case 0: + forkchild(jp, n, mode, 0); + return 0; + default: + return forkparent(jp, n, mode, pid); } - if (pid == 0) { - struct job *p; - int wasroot; - int i; +} - TRACE(("Child shell %d\n", getpid())); - wasroot = rootshell; - rootshell = 0; - for (i = njobs, p = jobtab ; --i >= 0 ; p++) - if (p->used) - freejob(p); - closescript(); - INTON; - clear_traps(); -#if JOBS - jobctl = 0; /* do job control only in root shell */ - if (wasroot && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = getpid(); - else - pgrp = jp->ps[0].pid; - setpgid(0, pgrp); - if (mode == FORK_FG) { - /*** this causes superfluous TIOCSPGRPS ***/ -#ifdef OLD_TTY_DRIVER - if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) - error("TIOCSPGRP failed, errno=%d", errno); -#else - if (tcsetpgrp(2, pgrp) < 0) - error("tcsetpgrp failed, errno=%d", errno); -#endif - } - setsignal(SIGTSTP); - setsignal(SIGTTOU); - } else if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#else - if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#endif - if (wasroot && iflag) { - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); - } - return pid; - } +int +forkparent(jp, n, mode, pid) + union node *n; + struct job *jp; + int mode; + pid_t pid; +{ + int pgrp; + if (rootshell && mode != FORK_NOJOB && mflag) { if (jp == NULL || jp->nprocs == 0) pgrp = pid; @@ -671,6 +623,81 @@ forkshell(jp, n, mode) return pid; } +void +forkchild(jp, n, mode, vforked) + union node *n; + struct job *jp; + int mode; + int vforked; +{ + struct job *p; + int wasroot; + int i; + int pgrp; + const char *devnull = _PATH_DEVNULL; + const char *nullerr = "Can't open %s"; + + TRACE(("Child shell %d\n", getpid())); + wasroot = rootshell; + if (!vforked) { + rootshell = 0; + for (i = njobs, p = jobtab ; --i >= 0 ; p++) + if (p->used) + freejob(p); + } + closescript(vforked); + INTON; + clear_traps(vforked); +#if JOBS + if (!vforked) + jobctl = 0; /* do job control only in root shell */ + if (wasroot && mode != FORK_NOJOB && mflag) { + if (jp == NULL || jp->nprocs == 0) + pgrp = getpid(); + else + pgrp = jp->ps[0].pid; + setpgid(0, pgrp); + if (mode == FORK_FG) { + /*** this causes superfluous TIOCSPGRPS ***/ +#ifdef OLD_TTY_DRIVER + if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) + error("TIOCSPGRP failed, errno=%d", errno); +#else + if (tcsetpgrp(2, pgrp) < 0) + error("tcsetpgrp failed, errno=%d", errno); +#endif + } + setsignal(SIGTSTP, vforked); + setsignal(SIGTTOU, vforked); + } else if (mode == FORK_BG) { + ignoresig(SIGINT, vforked); + ignoresig(SIGQUIT, vforked); + if ((jp == NULL || jp->nprocs == 0) && + ! fd0_redirected_p ()) { + close(0); + if (open(devnull, O_RDONLY) != 0) + error(nullerr, devnull); + } + } +#else + if (mode == FORK_BG) { + ignoresig(SIGINT, vforked); + ignoresig(SIGQUIT, vforked); + if ((jp == NULL || jp->nprocs == 0) && + ! fd0_redirected_p ()) { + close(0); + if (open(devnull, O_RDONLY) != 0) + error(nullerr, devnull); + } + } +#endif + if (wasroot && iflag) { + setsignal(SIGINT, vforked); + setsignal(SIGQUIT, vforked); + setsignal(SIGTERM, vforked); + } +} + /* diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index d5ec14530e3e..4a26ee9f6656 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -1,4 +1,4 @@ -/* $NetBSD: jobs.h,v 1.9 1997/10/15 13:23:10 christos Exp $ */ +/* $NetBSD: jobs.h,v 1.10 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -88,6 +88,8 @@ int waitcmd __P((int, char **)); int jobidcmd __P((int, char **)); struct job *makejob __P((union node *, int)); int forkshell __P((struct job *, union node *, int)); +void forkchild __P((struct job *jp, union node *n, int mode, int vfork)); +int forkparent __P((struct job *jp, union node *n, int mode, pid_t pid)); int waitforjob __P((struct job *)); int stoppedjobs __P((void)); char *commandtext __P((union node *)); diff --git a/bin/sh/main.c b/bin/sh/main.c index 20e44967f31f..5804b237f1f0 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.36 2000/04/14 05:54:20 simonb Exp $ */ +/* $NetBSD: main.c,v 1.37 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -46,7 +46,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\ #if 0 static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95"; #else -__RCSID("$NetBSD: main.c,v 1.36 2000/04/14 05:54:20 simonb Exp $"); +__RCSID("$NetBSD: main.c,v 1.37 2000/05/13 20:50:15 elric Exp $"); #endif #endif /* not lint */ @@ -205,7 +205,7 @@ state3: int i; for (i = 0; i < SIGSSIZE; i++) - setsignal(sigs[i]); + setsignal(sigs[i], 0); } if (minusc) diff --git a/bin/sh/redir.c b/bin/sh/redir.c index f79d8f0881c4..3a782de314ac 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -1,4 +1,4 @@ -/* $NetBSD: redir.c,v 1.20 1999/02/04 16:17:39 christos Exp $ */ +/* $NetBSD: redir.c,v 1.21 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: redir.c,v 1.20 1999/02/04 16:17:39 christos Exp $"); +__RCSID("$NetBSD: redir.c,v 1.21 2000/05/13 20:50:15 elric Exp $"); #endif #endif /* not lint */ @@ -120,6 +120,9 @@ redirect(redir, flags) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { + /* We don't have to worry about REDIR_VFORK here, as + * flags & REDIR_PUSH is never true if REDIR_VFORK is set. + */ sv = ckmalloc(sizeof (struct redirtab)); for (i = 0 ; i < 10 ; i++) sv->renamed[i] = EMPTY; @@ -335,7 +338,7 @@ RESET { } SHELLPROC { - clearredir(); + clearredir(0); } #endif @@ -351,7 +354,9 @@ fd0_redirected_p () { */ void -clearredir() { +clearredir(vforked) + int vforked; +{ struct redirtab *rp; int i; @@ -360,7 +365,8 @@ clearredir() { if (rp->renamed[i] >= 0) { close(rp->renamed[i]); } - rp->renamed[i] = EMPTY; + if (!vforked) + rp->renamed[i] = EMPTY; } } } diff --git a/bin/sh/redir.h b/bin/sh/redir.h index 44eecc76c59f..553d69e30d39 100644 --- a/bin/sh/redir.h +++ b/bin/sh/redir.h @@ -1,4 +1,4 @@ -/* $NetBSD: redir.h,v 1.10 1996/10/16 15:45:18 christos Exp $ */ +/* $NetBSD: redir.h,v 1.11 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,11 +41,12 @@ /* flags passed to redirect */ #define REDIR_PUSH 01 /* save previous values of file descriptors */ #define REDIR_BACKQ 02 /* save the command output in memory */ +#define REDIR_VFORK 04 /* running under vfork(2), be careful */ union node; void redirect __P((union node *, int)); void popredir __P((void)); int fd0_redirected_p __P((void)); -void clearredir __P((void)); +void clearredir __P((int)); int copyfd __P((int, int)); diff --git a/bin/sh/shell.h b/bin/sh/shell.h index 95012d1ee288..b6f269947ed4 100644 --- a/bin/sh/shell.h +++ b/bin/sh/shell.h @@ -1,4 +1,4 @@ -/* $NetBSD: shell.h,v 1.10 1996/10/16 15:21:49 christos Exp $ */ +/* $NetBSD: shell.h,v 1.11 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -46,6 +46,8 @@ * define SYSV if you are running under System V. * define DEBUG=1 to compile in debugging (set global "debug" to turn on) * define DEBUG=2 to compile in and turn on debugging. + * define DO_SHAREDVFORK to indicate that vfork(2) shares its address + * with its parent. * * When debugging is on, debugging info will be written to $HOME/trace and * a quit signal will generate a core dump. @@ -57,6 +59,12 @@ #define BSD 1 #endif +#ifndef DO_SHAREDVFORK +#if __NetBSD_Version__ >= 104000000 +#define DO_SHAREDVFORK +#endif +#endif + #ifdef __STDC__ typedef void *pointer; #ifndef NULL diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 13e62f3a3ec2..9087caca051f 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.22 2000/01/27 23:39:41 christos Exp $ */ +/* $NetBSD: trap.c,v 1.23 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; #else -__RCSID("$NetBSD: trap.c,v 1.22 2000/01/27 23:39:41 christos Exp $"); +__RCSID("$NetBSD: trap.c,v 1.23 2000/05/13 20:50:15 elric Exp $"); #endif #endif /* not lint */ @@ -121,7 +121,7 @@ trapcmd(argc, argv) ckfree(trap[signo]); trap[signo] = action; if (signo != 0) - setsignal(signo); + setsignal(signo, 0); INTON; ap++; } @@ -131,20 +131,26 @@ trapcmd(argc, argv) /* - * Clear traps on a fork. + * Clear traps on a fork or vfork. + * Takes one arg vfork, to tell it to not be destructive of + * the parents variables. */ void -clear_traps() { +clear_traps(vforked) + int vforked; +{ char **tp; for (tp = trap ; tp <= &trap[NSIG] ; tp++) { if (*tp && **tp) { /* trap not NULL or SIG_IGN */ INTOFF; - ckfree(*tp); - *tp = NULL; + if (!vforked) { + ckfree(*tp); + *tp = NULL; + } if (tp != &trap[0]) - setsignal(tp - trap); + setsignal(tp - trap, vforked); INTON; } } @@ -158,12 +164,13 @@ clear_traps() { */ long -setsignal(signo) +setsignal(signo, vforked) int signo; + int vforked; { int action; sig_t sigact = SIG_DFL; - char *t; + char *t, tsig; if ((t = trap[signo]) == NULL) action = S_DFL; @@ -171,7 +178,7 @@ setsignal(signo) action = S_CATCH; else action = S_IGN; - if (rootshell && action == S_DFL) { + if (rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag || minusc || sflag == 0) @@ -202,7 +209,8 @@ setsignal(signo) } t = &sigmode[signo - 1]; - if (*t == 0) { + tsig = *t; + if (tsig == 0) { /* * current setting unknown */ @@ -217,21 +225,22 @@ setsignal(signo) if (sigact == SIG_IGN) { if (mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { - *t = S_IGN; /* don't hard ignore these */ + tsig = S_IGN; /* don't hard ignore these */ } else - *t = S_HARD_IGN; + tsig = S_HARD_IGN; } else { - *t = S_RESET; /* force to be set */ + tsig = S_RESET; /* force to be set */ } } - if (*t == S_HARD_IGN || *t == action) + if (tsig == S_HARD_IGN || tsig == action) return 0; switch (action) { case S_DFL: sigact = SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SIG_IGN; break; } - *t = action; + if (!vforked) + *t = action; siginterrupt(signo, 1); return (long)signal(signo, sigact); } @@ -257,13 +266,15 @@ getsigaction(signo, sigact) */ void -ignoresig(signo) +ignoresig(signo, vforked) int signo; + int vforked; { if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { signal(signo, SIG_IGN); } - sigmode[signo - 1] = S_HARD_IGN; + if (!vforked) + sigmode[signo - 1] = S_HARD_IGN; } @@ -274,7 +285,7 @@ INCLUDE "trap.h" SHELLPROC { char *sm; - clear_traps(); + clear_traps(0); for (sm = sigmode ; sm < sigmode + NSIG ; sm++) { if (*sm == S_IGN) *sm = S_HARD_IGN; @@ -344,9 +355,9 @@ setinteractive(on) if (on == is_interactive) return; - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); + setsignal(SIGINT, 0); + setsignal(SIGQUIT, 0); + setsignal(SIGTERM, 0); is_interactive = on; } diff --git a/bin/sh/trap.h b/bin/sh/trap.h index 6eff5c7d507a..4f82ed08b1e2 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -1,4 +1,4 @@ -/* $NetBSD: trap.h,v 1.12 1998/07/28 11:41:58 mycroft Exp $ */ +/* $NetBSD: trap.h,v 1.13 2000/05/13 20:50:15 elric Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,9 +41,9 @@ extern int pendingsigs; int trapcmd __P((int, char **)); -void clear_traps __P((void)); -long setsignal __P((int)); -void ignoresig __P((int)); +void clear_traps __P((int)); +long setsignal __P((int, int)); +void ignoresig __P((int, int)); void onsig __P((int)); void dotrap __P((void)); void setinteractive __P((int));