long setsignal(int signo, int vforked) { int action; sig_t sigact = SIG_DFL; struct sigaction act, oact; char *t, tsig; if ((t = trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag || minusc || sflag == 0) action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG if (debug) break; #endif /* FALLTHROUGH */ case SIGTERM: if (iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (mflag) action = S_IGN; break; #endif } } t = &sigmode[signo - 1]; tsig = *t; if (tsig == 0) { /* * current setting unknown */ if (!getsigaction(signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return 0; } if (sigact == SIG_IGN) { if (mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { tsig = S_IGN; /* don't hard ignore these */ } else tsig = S_HARD_IGN; } else { tsig = S_RESET; /* force to be set */ } } 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; } if (!vforked) *t = action; act.sa_handler = sigact; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif if(sigaction(signo, &act, &oact) < 0) return (long) SIG_ERR; return (long) oact.sa_handler; }
/* * Set the signal handler for the specified signal. The routine figures * out what it should be set to. */ void setsignal(int signo) { int action; sig_t sigact = SIG_DFL; struct sigaction sa; char *t; if ((t = trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (action == S_DFL) { switch (signo) { case SIGINT: action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG { extern int debug; if (debug) break; } #endif action = S_CATCH; break; case SIGTERM: if (rootshell && iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (rootshell && mflag) action = S_IGN; break; #endif #ifndef NO_HISTORY case SIGWINCH: if (rootshell && iflag) action = S_CATCH; break; #endif } } t = &sigmode[signo]; if (*t == 0) { /* * current setting unknown */ if (!getsigaction(signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return; } if (sigact == SIG_IGN) { if (mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { *t = S_IGN; /* don't hard ignore these */ } else *t = S_HARD_IGN; } else { *t = S_RESET; /* force to be set */ } } if (*t == S_HARD_IGN || *t == action) return; switch (action) { case S_DFL: sigact = SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SIG_IGN; break; } *t = action; sa.sa_handler = sigact; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(signo, &sa, NULL); }
void setsignal(shinstance *psh, int signo, int vforked) { int action; shsig_t sigact = SH_SIG_DFL; char *t, tsig; if ((t = psh->trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (psh->rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag(psh) || psh->minusc || sflag(psh) == 0) action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG if (debug(psh)) break; #endif /* FALLTHROUGH */ case SIGTERM: if (iflag(psh)) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (mflag(psh)) action = S_IGN; break; #endif } } t = &psh->sigmode[signo - 1]; tsig = *t; if (tsig == 0) { /* * current setting unknown */ if (!getsigaction(psh, signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return; } if (sigact == SH_SIG_IGN) { if (mflag(psh) && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { tsig = S_IGN; /* don't hard ignore these */ } else tsig = S_HARD_IGN; } else { tsig = S_RESET; /* force to be set */ } } if (tsig == S_HARD_IGN || tsig == action) return; switch (action) { case S_DFL: sigact = SH_SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SH_SIG_IGN; break; } if (!vforked) *t = action; sh_siginterrupt(psh, signo, 1); sh_signal(psh, signo, sigact); }
sig_t setsignal(int signo, int vforked) { int action; sig_t sigact = SIG_DFL, sig; char *t, tsig; if ((t = trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag || minusc || sflag == 0) action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG if (debug) break; #endif /* FALLTHROUGH */ case SIGTERM: if (iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (mflag) action = S_IGN; break; #endif } } t = &sigmode[signo - 1]; tsig = *t; if (tsig == 0) { /* * current setting unknown */ if (!getsigaction(signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return 0; } if (sigact == SIG_IGN) { /* * POSIX 3.14.13 states that non-interactive shells * should ignore trap commands for signals that were * ignored upon entry, and leaves the behavior * unspecified for interactive shells. On interactive * shells, or if job control is on, and we have a job * control related signal, we allow the trap to work. * * This change allows us to be POSIX compliant, and * at the same time override the default behavior if * we need to by setting the interactive flag. */ if ((mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) || iflag) { tsig = S_IGN; } else tsig = S_HARD_IGN; } else { tsig = S_RESET; /* force to be set */ } } 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; } sig = signal(signo, sigact); if (sig != SIG_ERR) { sigset_t ss; if (!vforked) *t = action; if (action == S_CATCH) (void)siginterrupt(signo, 1); /* * If our parent accidentally blocked signals for * us make sure we unblock them */ (void)sigemptyset(&ss); (void)sigaddset(&ss, signo); (void)sigprocmask(SIG_UNBLOCK, &ss, NULL); } return sig; }
/* * Set the signal handler for the specified signal. The routine figures * out what it should be set to. */ void setsignal(int signo, int vforked) { int action; sig_t sigact = SIG_DFL, sig; char *t, tsig; if ((t = trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; VTRACE(DBG_TRAP, ("setsignal(%d%s) -> %d", signo, vforked ? ", VF" : "", action)); if (rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag || minusc || sflag == 0) action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG if (debug) break; #endif /* FALLTHROUGH */ case SIGTERM: if (rootshell && iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (rootshell && mflag) action = S_IGN; break; #endif } } /* * Never let users futz with SIGCHLD * instead we will give them pseudo SIGCHLD's * when background jobs complete. */ if (signo == SIGCHLD) action = S_DFL; VTRACE(DBG_TRAP, (" -> %d", action)); t = &sigmode[signo]; tsig = *t; if (tsig == 0) { /* * current setting unknown */ if (!getsigaction(signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ VTRACE(DBG_TRAP, (" getsigaction (%d)\n", errno)); return; } VTRACE(DBG_TRAP, (" [%s]%s%s", sigact==SIG_IGN ? "IGN" : sigact==SIG_DFL ? "DFL" : "caught", iflag ? "i" : "", mflag ? "m" : "")); if (sigact == SIG_IGN) { /* * POSIX 3.14.13 states that non-interactive shells * should ignore trap commands for signals that were * ignored upon entry, and leaves the behavior * unspecified for interactive shells. On interactive * shells, or if job control is on, and we have a job * control related signal, we allow the trap to work. * * This change allows us to be POSIX compliant, and * at the same time override the default behavior if * we need to by setting the interactive flag. */ if ((mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) || iflag) { tsig = S_IGN; } else tsig = S_HARD_IGN; } else { tsig = S_RESET; /* force to be set */ } } VTRACE(DBG_TRAP, (" tsig=%d\n", tsig)); if (tsig == S_HARD_IGN || tsig == action) return; switch (action) { case S_DFL: sigact = SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SIG_IGN; break; } sig = signal(signo, sigact); if (sig != SIG_ERR) { sigset_t ss; if (!vforked) *t = action; if (action == S_CATCH) (void)siginterrupt(signo, 1); /* * If our parent accidentally blocked signals for * us make sure we unblock them */ (void)sigemptyset(&ss); (void)sigaddset(&ss, signo); (void)sigprocmask(SIG_UNBLOCK, &ss, NULL); } return; }