Sat Aug 25 14:41:22 2018 UTC ()
Pull up following revision(s) (requested by kre in ticket #987):

	bin/sh/trap.c: revision 1.44

PR bin/36532 (perhaps)

This is more or less the same patch as provided in the PR
(just 11 years later, so changed a bit) by woods@...

Since there is no known way to actually cause the reported crash,
we may never know if this change actually fixes anything.   But
even if it doesn't it certainly cannot hurt.

There is a potential race which could possibly explain the issue
(see commentary in the PR) which is not easy to avoid - if that is
the actual cause, this should provide a defence, if not really a fix.


(martin)
diff -r1.40.2.1 -r1.40.2.2 src/bin/sh/trap.c

cvs diff -r1.40.2.1 -r1.40.2.2 src/bin/sh/trap.c (switch to unified diff)

--- src/bin/sh/trap.c 2017/07/23 14:58:14 1.40.2.1
+++ src/bin/sh/trap.c 2018/08/25 14:41:21 1.40.2.2
@@ -1,596 +1,598 @@ @@ -1,596 +1,598 @@
1/* $NetBSD: trap.c,v 1.40.2.1 2017/07/23 14:58:14 snj Exp $ */ 1/* $NetBSD: trap.c,v 1.40.2.2 2018/08/25 14:41:21 martin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; 38static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
39#else 39#else
40__RCSID("$NetBSD: trap.c,v 1.40.2.1 2017/07/23 14:58:14 snj Exp $"); 40__RCSID("$NetBSD: trap.c,v 1.40.2.2 2018/08/25 14:41:21 martin Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <signal.h> 44#include <signal.h>
45#include <unistd.h> 45#include <unistd.h>
46#include <stdlib.h> 46#include <stdlib.h>
47#include <stdio.h> 47#include <stdio.h>
48 48
49#include "shell.h" 49#include "shell.h"
50#include "main.h" 50#include "main.h"
51#include "nodes.h" /* for other headers */ 51#include "nodes.h" /* for other headers */
52#include "eval.h" 52#include "eval.h"
53#include "jobs.h" 53#include "jobs.h"
54#include "show.h" 54#include "show.h"
55#include "options.h" 55#include "options.h"
56#include "builtins.h" 56#include "builtins.h"
57#include "syntax.h" 57#include "syntax.h"
58#include "output.h" 58#include "output.h"
59#include "memalloc.h" 59#include "memalloc.h"
60#include "error.h" 60#include "error.h"
61#include "trap.h" 61#include "trap.h"
62#include "mystring.h" 62#include "mystring.h"
63#include "var.h" 63#include "var.h"
64 64
65 65
66/* 66/*
67 * Sigmode records the current value of the signal handlers for the various 67 * Sigmode records the current value of the signal handlers for the various
68 * modes. A value of zero means that the current handler is not known. 68 * modes. A value of zero means that the current handler is not known.
69 * S_HARD_IGN indicates that the signal was ignored on entry to the shell, 69 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
70 */ 70 */
71 71
72#define S_DFL 1 /* default signal handling (SIG_DFL) */ 72#define S_DFL 1 /* default signal handling (SIG_DFL) */
73#define S_CATCH 2 /* signal is caught */ 73#define S_CATCH 2 /* signal is caught */
74#define S_IGN 3 /* signal is ignored (SIG_IGN) */ 74#define S_IGN 3 /* signal is ignored (SIG_IGN) */
75#define S_HARD_IGN 4 /* signal is ignored permenantly */ 75#define S_HARD_IGN 4 /* signal is ignored permenantly */
76#define S_RESET 5 /* temporary - to reset a hard ignored sig */ 76#define S_RESET 5 /* temporary - to reset a hard ignored sig */
77 77
78 78
79char *trap[NSIG]; /* trap handler commands */ 79char *trap[NSIG]; /* trap handler commands */
80MKINIT char sigmode[NSIG]; /* current value of signal */ 80MKINIT char sigmode[NSIG]; /* current value of signal */
81static volatile char gotsig[NSIG];/* indicates specified signal received */ 81static volatile char gotsig[NSIG];/* indicates specified signal received */
82volatile int pendingsigs; /* indicates some signal received */ 82volatile int pendingsigs; /* indicates some signal received */
83 83
84static int getsigaction(int, sig_t *); 84static int getsigaction(int, sig_t *);
85STATIC const char *trap_signame(int); 85STATIC const char *trap_signame(int);
86 86
87/* 87/*
88 * return the signal number described by `p' (as a number or a name) 88 * return the signal number described by `p' (as a number or a name)
89 * or -1 if it isn't one 89 * or -1 if it isn't one
90 */ 90 */
91 91
92static int 92static int
93signame_to_signum(const char *p) 93signame_to_signum(const char *p)
94{ 94{
95 int i; 95 int i;
96 96
97 if (is_number(p)) 97 if (is_number(p))
98 return number(p); 98 return number(p);
99 99
100 if (strcasecmp(p, "exit") == 0 ) 100 if (strcasecmp(p, "exit") == 0 )
101 return 0; 101 return 0;
102  102
103 if (strncasecmp(p, "sig", 3) == 0) 103 if (strncasecmp(p, "sig", 3) == 0)
104 p += 3; 104 p += 3;
105 105
106 for (i = 0; i < NSIG; ++i) 106 for (i = 0; i < NSIG; ++i)
107 if (strcasecmp (p, sys_signame[i]) == 0) 107 if (strcasecmp (p, sys_signame[i]) == 0)
108 return i; 108 return i;
109 return -1; 109 return -1;
110} 110}
111 111
112/* 112/*
113 * return the name of a signal used by the "trap" command 113 * return the name of a signal used by the "trap" command
114 */ 114 */
115STATIC const char * 115STATIC const char *
116trap_signame(int signo) 116trap_signame(int signo)
117{ 117{
118 static char nbuf[12]; 118 static char nbuf[12];
119 const char *p = NULL; 119 const char *p = NULL;
120 120
121 if (signo == 0) 121 if (signo == 0)
122 return "EXIT"; 122 return "EXIT";
123 if (signo > 0 && signo < NSIG) 123 if (signo > 0 && signo < NSIG)
124 p = sys_signame[signo]; 124 p = sys_signame[signo];
125 if (p != NULL) 125 if (p != NULL)
126 return p; 126 return p;
127 (void)snprintf(nbuf, sizeof nbuf, "%d", signo); 127 (void)snprintf(nbuf, sizeof nbuf, "%d", signo);
128 return nbuf; 128 return nbuf;
129} 129}
130 130
131/* 131/*
132 * Print a list of valid signal names 132 * Print a list of valid signal names
133 */ 133 */
134static void 134static void
135printsignals(void) 135printsignals(void)
136{ 136{
137 int n; 137 int n;
138 138
139 out1str("EXIT "); 139 out1str("EXIT ");
140 140
141 for (n = 1; n < NSIG; n++) { 141 for (n = 1; n < NSIG; n++) {
142 out1fmt("%s", trap_signame(n)); 142 out1fmt("%s", trap_signame(n));
143 if ((n == NSIG/2) || n == (NSIG - 1)) 143 if ((n == NSIG/2) || n == (NSIG - 1))
144 out1str("\n"); 144 out1str("\n");
145 else 145 else
146 out1c(' '); 146 out1c(' ');
147 } 147 }
148} 148}
149 149
150/* 150/*
151 * The trap builtin. 151 * The trap builtin.
152 */ 152 */
153 153
154int 154int
155trapcmd(int argc, char **argv) 155trapcmd(int argc, char **argv)
156{ 156{
157 char *action; 157 char *action;
158 char **ap; 158 char **ap;
159 int signo; 159 int signo;
160 int errs = 0; 160 int errs = 0;
161 int printonly = 0; 161 int printonly = 0;
162 162
163 ap = argv + 1; 163 ap = argv + 1;
164 164
165 if (argc == 2 && strcmp(*ap, "-l") == 0) { 165 if (argc == 2 && strcmp(*ap, "-l") == 0) {
166 printsignals(); 166 printsignals();
167 return 0; 167 return 0;
168 } 168 }
169 if (argc == 2 && strcmp(*ap, "-") == 0) { 169 if (argc == 2 && strcmp(*ap, "-") == 0) {
170 for (signo = 0; signo < NSIG; signo++) { 170 for (signo = 0; signo < NSIG; signo++) {
171 if (trap[signo] == NULL) 171 if (trap[signo] == NULL)
172 continue; 172 continue;
173 INTOFF; 173 INTOFF;
174 ckfree(trap[signo]); 174 ckfree(trap[signo]);
175 trap[signo] = NULL; 175 trap[signo] = NULL;
176 if (signo != 0) 176 if (signo != 0)
177 setsignal(signo, 0); 177 setsignal(signo, 0);
178 INTON; 178 INTON;
179 } 179 }
180 return 0; 180 return 0;
181 } 181 }
182 if (argc >= 2 && strcmp(*ap, "-p") == 0) { 182 if (argc >= 2 && strcmp(*ap, "-p") == 0) {
183 printonly = 1; 183 printonly = 1;
184 ap++; 184 ap++;
185 argc--; 185 argc--;
186 } 186 }
187 187
188 if (argc > 1 && strcmp(*ap, "--") == 0) { 188 if (argc > 1 && strcmp(*ap, "--") == 0) {
189 argc--; 189 argc--;
190 ap++; 190 ap++;
191 } 191 }
192 192
193 if (argc <= 1) { 193 if (argc <= 1) {
194 int count; 194 int count;
195 195
196 if (printonly) { 196 if (printonly) {
197 for (count = 0, signo = 0 ; signo < NSIG ; signo++) 197 for (count = 0, signo = 0 ; signo < NSIG ; signo++)
198 if (trap[signo] == NULL) { 198 if (trap[signo] == NULL) {
199 if (count == 0) 199 if (count == 0)
200 out1str("trap -- -"); 200 out1str("trap -- -");
201 out1fmt(" %s", trap_signame(signo)); 201 out1fmt(" %s", trap_signame(signo));
202 /* oh! unlucky 13 */ 202 /* oh! unlucky 13 */
203 if (++count >= 13) { 203 if (++count >= 13) {
204 out1str("\n"); 204 out1str("\n");
205 count = 0; 205 count = 0;
206 } 206 }
207 } 207 }
208 if (count) 208 if (count)
209 out1str("\n"); 209 out1str("\n");
210 } 210 }
211 211
212 for (count = 0, signo = 0 ; signo < NSIG ; signo++) 212 for (count = 0, signo = 0 ; signo < NSIG ; signo++)
213 if (trap[signo] != NULL && trap[signo][0] == '\0') { 213 if (trap[signo] != NULL && trap[signo][0] == '\0') {
214 if (count == 0) 214 if (count == 0)
215 out1str("trap -- ''"); 215 out1str("trap -- ''");
216 out1fmt(" %s", trap_signame(signo)); 216 out1fmt(" %s", trap_signame(signo));
217 /* 217 /*
218 * the prefix is 10 bytes, with 4 byte 218 * the prefix is 10 bytes, with 4 byte
219 * signal names (common) we have room in 219 * signal names (common) we have room in
220 * the 70 bytes left on a normal line for 220 * the 70 bytes left on a normal line for
221 * 70/(4+1) signals, that's 14, but to 221 * 70/(4+1) signals, that's 14, but to
222 * allow for the occasional longer sig name 222 * allow for the occasional longer sig name
223 * we output one less... 223 * we output one less...
224 */ 224 */
225 if (++count >= 13) { 225 if (++count >= 13) {
226 out1str("\n"); 226 out1str("\n");
227 count = 0; 227 count = 0;
228 } 228 }
229 } 229 }
230 if (count) 230 if (count)
231 out1str("\n"); 231 out1str("\n");
232 232
233 for (signo = 0 ; signo < NSIG ; signo++) 233 for (signo = 0 ; signo < NSIG ; signo++)
234 if (trap[signo] != NULL && trap[signo][0] != '\0') { 234 if (trap[signo] != NULL && trap[signo][0] != '\0') {
235 out1str("trap -- "); 235 out1str("trap -- ");
236 print_quoted(trap[signo]); 236 print_quoted(trap[signo]);
237 out1fmt(" %s\n", trap_signame(signo)); 237 out1fmt(" %s\n", trap_signame(signo));
238 } 238 }
239 239
240 return 0; 240 return 0;
241 } 241 }
242 242
243 action = NULL; 243 action = NULL;
244 244
245 if (!printonly && !is_number(*ap)) { 245 if (!printonly && !is_number(*ap)) {
246 if ((*ap)[0] == '-' && (*ap)[1] == '\0') 246 if ((*ap)[0] == '-' && (*ap)[1] == '\0')
247 ap++; /* reset to default */ 247 ap++; /* reset to default */
248 else 248 else
249 action = *ap++; /* can be '' for "ignore" */ 249 action = *ap++; /* can be '' for "ignore" */
250 argc--; 250 argc--;
251 } 251 }
252 252
253 if (argc < 2) { /* there must be at least 1 condition */ 253 if (argc < 2) { /* there must be at least 1 condition */
254 out2str("Usage: trap [-l]\n" 254 out2str("Usage: trap [-l]\n"
255 " trap -p [condition ...]\n" 255 " trap -p [condition ...]\n"
256 " trap action condition ...\n" 256 " trap action condition ...\n"
257 " trap N condition ...\n"); 257 " trap N condition ...\n");
258 return 2; 258 return 2;
259 } 259 }
260 260
261 261
262 while (*ap) { 262 while (*ap) {
263 signo = signame_to_signum(*ap); 263 signo = signame_to_signum(*ap);
264 264
265 if (signo < 0 || signo >= NSIG) { 265 if (signo < 0 || signo >= NSIG) {
266 /* This is not a fatal error, so sayeth posix */ 266 /* This is not a fatal error, so sayeth posix */
267 outfmt(out2, "trap: '%s' bad condition\n", *ap); 267 outfmt(out2, "trap: '%s' bad condition\n", *ap);
268 errs = 1; 268 errs = 1;
269 ap++; 269 ap++;
270 continue; 270 continue;
271 } 271 }
272 ap++; 272 ap++;
273 273
274 if (printonly) { 274 if (printonly) {
275 out1str("trap -- "); 275 out1str("trap -- ");
276 if (trap[signo] == NULL) 276 if (trap[signo] == NULL)
277 out1str("-"); 277 out1str("-");
278 else 278 else
279 print_quoted(trap[signo]); 279 print_quoted(trap[signo]);
280 out1fmt(" %s\n", trap_signame(signo)); 280 out1fmt(" %s\n", trap_signame(signo));
281 continue; 281 continue;
282 } 282 }
283 283
284 INTOFF; 284 INTOFF;
285 if (action) 285 if (action)
286 action = savestr(action); 286 action = savestr(action);
287 287
288 if (trap[signo]) 288 if (trap[signo])
289 ckfree(trap[signo]); 289 ckfree(trap[signo]);
290 290
291 trap[signo] = action; 291 trap[signo] = action;
292 292
293 if (signo != 0) 293 if (signo != 0)
294 setsignal(signo, 0); 294 setsignal(signo, 0);
295 INTON; 295 INTON;
296 } 296 }
297 return errs; 297 return errs;
298} 298}
299 299
300 300
301 301
302/* 302/*
303 * Clear traps on a fork or vfork. 303 * Clear traps on a fork or vfork.
304 * Takes one arg vfork, to tell it to not be destructive of 304 * Takes one arg vfork, to tell it to not be destructive of
305 * the parents variables. 305 * the parents variables.
306 */ 306 */
307 307
308void 308void
309clear_traps(int vforked) 309clear_traps(int vforked)
310{ 310{
311 char **tp; 311 char **tp;
312 312
313 for (tp = trap ; tp < &trap[NSIG] ; tp++) { 313 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
314 if (*tp && **tp) { /* trap not NULL or SIG_IGN */ 314 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
315 INTOFF; 315 INTOFF;
316 if (!vforked) { 316 if (!vforked) {
317 ckfree(*tp); 317 ckfree(*tp);
318 *tp = NULL; 318 *tp = NULL;
319 } 319 }
320 if (tp != &trap[0]) 320 if (tp != &trap[0])
321 setsignal(tp - trap, vforked); 321 setsignal(tp - trap, vforked);
322 INTON; 322 INTON;
323 } 323 }
324 } 324 }
325} 325}
326 326
327 327
328 328
329/* 329/*
330 * Set the signal handler for the specified signal. The routine figures 330 * Set the signal handler for the specified signal. The routine figures
331 * out what it should be set to. 331 * out what it should be set to.
332 */ 332 */
333 333
334sig_t 334sig_t
335setsignal(int signo, int vforked) 335setsignal(int signo, int vforked)
336{ 336{
337 int action; 337 int action;
338 sig_t sigact = SIG_DFL, sig; 338 sig_t sigact = SIG_DFL, sig;
339 char *t, tsig; 339 char *t, tsig;
340 340
341 if ((t = trap[signo]) == NULL) 341 if ((t = trap[signo]) == NULL)
342 action = S_DFL; 342 action = S_DFL;
343 else if (*t != '\0') 343 else if (*t != '\0')
344 action = S_CATCH; 344 action = S_CATCH;
345 else 345 else
346 action = S_IGN; 346 action = S_IGN;
347 if (rootshell && !vforked && action == S_DFL) { 347 if (rootshell && !vforked && action == S_DFL) {
348 switch (signo) { 348 switch (signo) {
349 case SIGINT: 349 case SIGINT:
350 if (iflag || minusc || sflag == 0) 350 if (iflag || minusc || sflag == 0)
351 action = S_CATCH; 351 action = S_CATCH;
352 break; 352 break;
353 case SIGQUIT: 353 case SIGQUIT:
354#ifdef DEBUG 354#ifdef DEBUG
355 if (debug) 355 if (debug)
356 break; 356 break;
357#endif 357#endif
358 /* FALLTHROUGH */ 358 /* FALLTHROUGH */
359 case SIGTERM: 359 case SIGTERM:
360 if (iflag) 360 if (iflag)
361 action = S_IGN; 361 action = S_IGN;
362 break; 362 break;
363#if JOBS 363#if JOBS
364 case SIGTSTP: 364 case SIGTSTP:
365 case SIGTTOU: 365 case SIGTTOU:
366 if (mflag) 366 if (mflag)
367 action = S_IGN; 367 action = S_IGN;
368 break; 368 break;
369#endif 369#endif
370 } 370 }
371 } 371 }
372 372
373 t = &sigmode[signo - 1]; 373 t = &sigmode[signo - 1];
374 tsig = *t; 374 tsig = *t;
375 if (tsig == 0) { 375 if (tsig == 0) {
376 /* 376 /*
377 * current setting unknown 377 * current setting unknown
378 */ 378 */
379 if (!getsigaction(signo, &sigact)) { 379 if (!getsigaction(signo, &sigact)) {
380 /* 380 /*
381 * Pretend it worked; maybe we should give a warning 381 * Pretend it worked; maybe we should give a warning
382 * here, but other shells don't. We don't alter 382 * here, but other shells don't. We don't alter
383 * sigmode, so that we retry every time. 383 * sigmode, so that we retry every time.
384 */ 384 */
385 return 0; 385 return 0;
386 } 386 }
387 if (sigact == SIG_IGN) { 387 if (sigact == SIG_IGN) {
388 /* 388 /*
389 * POSIX 3.14.13 states that non-interactive shells 389 * POSIX 3.14.13 states that non-interactive shells
390 * should ignore trap commands for signals that were 390 * should ignore trap commands for signals that were
391 * ignored upon entry, and leaves the behavior 391 * ignored upon entry, and leaves the behavior
392 * unspecified for interactive shells. On interactive 392 * unspecified for interactive shells. On interactive
393 * shells, or if job control is on, and we have a job 393 * shells, or if job control is on, and we have a job
394 * control related signal, we allow the trap to work. 394 * control related signal, we allow the trap to work.
395 * 395 *
396 * This change allows us to be POSIX compliant, and 396 * This change allows us to be POSIX compliant, and
397 * at the same time override the default behavior if 397 * at the same time override the default behavior if
398 * we need to by setting the interactive flag. 398 * we need to by setting the interactive flag.
399 */ 399 */
400 if ((mflag && (signo == SIGTSTP || 400 if ((mflag && (signo == SIGTSTP ||
401 signo == SIGTTIN || signo == SIGTTOU)) || iflag) { 401 signo == SIGTTIN || signo == SIGTTOU)) || iflag) {
402 tsig = S_IGN; 402 tsig = S_IGN;
403 } else 403 } else
404 tsig = S_HARD_IGN; 404 tsig = S_HARD_IGN;
405 } else { 405 } else {
406 tsig = S_RESET; /* force to be set */ 406 tsig = S_RESET; /* force to be set */
407 } 407 }
408 } 408 }
409 if (tsig == S_HARD_IGN || tsig == action) 409 if (tsig == S_HARD_IGN || tsig == action)
410 return 0; 410 return 0;
411 switch (action) { 411 switch (action) {
412 case S_DFL: sigact = SIG_DFL; break; 412 case S_DFL: sigact = SIG_DFL; break;
413 case S_CATCH: sigact = onsig; break; 413 case S_CATCH: sigact = onsig; break;
414 case S_IGN: sigact = SIG_IGN; break; 414 case S_IGN: sigact = SIG_IGN; break;
415 } 415 }
416 sig = signal(signo, sigact); 416 sig = signal(signo, sigact);
417 if (sig != SIG_ERR) { 417 if (sig != SIG_ERR) {
418 sigset_t ss; 418 sigset_t ss;
419 if (!vforked) 419 if (!vforked)
420 *t = action; 420 *t = action;
421 if (action == S_CATCH) 421 if (action == S_CATCH)
422 (void)siginterrupt(signo, 1); 422 (void)siginterrupt(signo, 1);
423 /* 423 /*
424 * If our parent accidentally blocked signals for 424 * If our parent accidentally blocked signals for
425 * us make sure we unblock them 425 * us make sure we unblock them
426 */ 426 */
427 (void)sigemptyset(&ss); 427 (void)sigemptyset(&ss);
428 (void)sigaddset(&ss, signo); 428 (void)sigaddset(&ss, signo);
429 (void)sigprocmask(SIG_UNBLOCK, &ss, NULL); 429 (void)sigprocmask(SIG_UNBLOCK, &ss, NULL);
430 } 430 }
431 return sig; 431 return sig;
432} 432}
433 433
434/* 434/*
435 * Return the current setting for sig w/o changing it. 435 * Return the current setting for sig w/o changing it.
436 */ 436 */
437static int 437static int
438getsigaction(int signo, sig_t *sigact) 438getsigaction(int signo, sig_t *sigact)
439{ 439{
440 struct sigaction sa; 440 struct sigaction sa;
441 441
442 if (sigaction(signo, (struct sigaction *)0, &sa) == -1) 442 if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
443 return 0; 443 return 0;
444 *sigact = (sig_t) sa.sa_handler; 444 *sigact = (sig_t) sa.sa_handler;
445 return 1; 445 return 1;
446} 446}
447 447
448/* 448/*
449 * Ignore a signal. 449 * Ignore a signal.
450 */ 450 */
451 451
452void 452void
453ignoresig(int signo, int vforked) 453ignoresig(int signo, int vforked)
454{ 454{
455 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { 455 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
456 signal(signo, SIG_IGN); 456 signal(signo, SIG_IGN);
457 } 457 }
458 if (!vforked) 458 if (!vforked)
459 sigmode[signo - 1] = S_HARD_IGN; 459 sigmode[signo - 1] = S_HARD_IGN;
460} 460}
461 461
462 462
463#ifdef mkinit 463#ifdef mkinit
464INCLUDE <signal.h> 464INCLUDE <signal.h>
465INCLUDE "trap.h" 465INCLUDE "trap.h"
466 466
467SHELLPROC { 467SHELLPROC {
468 char *sm; 468 char *sm;
469 469
470 clear_traps(0); 470 clear_traps(0);
471 for (sm = sigmode ; sm < sigmode + NSIG ; sm++) { 471 for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
472 if (*sm == S_IGN) 472 if (*sm == S_IGN)
473 *sm = S_HARD_IGN; 473 *sm = S_HARD_IGN;
474 } 474 }
475} 475}
476#endif 476#endif
477 477
478 478
479 479
480/* 480/*
481 * Signal handler. 481 * Signal handler.
482 */ 482 */
483 483
484void 484void
485onsig(int signo) 485onsig(int signo)
486{ 486{
487 CTRACE(DBG_SIG, ("Signal %d, had: pending %d, gotsig[%d]=%d\n", 487 CTRACE(DBG_SIG, ("Signal %d, had: pending %d, gotsig[%d]=%d\n",
488 signo, pendingsigs, signo, gotsig[signo])); 488 signo, pendingsigs, signo, gotsig[signo]));
489 489
490 signal(signo, onsig); 490 signal(signo, onsig);
491 if (signo == SIGINT && trap[SIGINT] == NULL) { 491 if (signo == SIGINT && trap[SIGINT] == NULL) {
492 onint(); 492 onint();
493 return; 493 return;
494 } 494 }
495 gotsig[signo] = 1; 495 gotsig[signo] = 1;
496 pendingsigs++; 496 pendingsigs++;
497} 497}
498 498
499 499
500 500
501/* 501/*
502 * Called to execute a trap. Perhaps we should avoid entering new trap 502 * Called to execute a trap. Perhaps we should avoid entering new trap
503 * handlers while we are executing a trap handler. 503 * handlers while we are executing a trap handler.
504 */ 504 */
505 505
506void 506void
507dotrap(void) 507dotrap(void)
508{ 508{
509 int i; 509 int i;
510 int savestatus; 510 int savestatus;
511 char *tr; 511 char *tr;
512 512
513 for (;;) { 513 for (;;) {
514 for (i = 1 ; ; i++) { 514 for (i = 1 ; ; i++) {
515 if (i >= NSIG) { 515 if (i >= NSIG) {
516 pendingsigs = 0; 516 pendingsigs = 0;
517 return; 517 return;
518 } 518 }
519 if (gotsig[i]) 519 if (gotsig[i])
520 break; 520 break;
521 } 521 }
522 gotsig[i] = 0; 522 gotsig[i] = 0;
523 savestatus=exitstatus; 523 savestatus=exitstatus;
524 CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: \"%s\"\n", i, 524 CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: \"%s\"\n", i,
525 trap[i] ? trap[i] : "-NULL-")); 525 trap[i] ? trap[i] : "-NULL-"));
526 tr = savestr(trap[i]); /* trap code may free trap[i] */ 526 if ((tr = trap[i]) != NULL) {
527 evalstring(tr, 0); 527 tr = savestr(tr); /* trap code may free trap[i] */
528 ckfree(tr); 528 evalstring(tr, 0);
 529 ckfree(tr);
 530 }
529 exitstatus=savestatus; 531 exitstatus=savestatus;
530 } 532 }
531} 533}
532 534
533int 535int
534lastsig(void) 536lastsig(void)
535{ 537{
536 int i; 538 int i;
537 539
538 for (i = NSIG; --i > 0; ) 540 for (i = NSIG; --i > 0; )
539 if (gotsig[i]) 541 if (gotsig[i])
540 return i; 542 return i;
541 return SIGINT; /* XXX */ 543 return SIGINT; /* XXX */
542} 544}
543 545
544/* 546/*
545 * Controls whether the shell is interactive or not. 547 * Controls whether the shell is interactive or not.
546 */ 548 */
547 549
548 550
549void 551void
550setinteractive(int on) 552setinteractive(int on)
551{ 553{
552 static int is_interactive; 554 static int is_interactive;
553 555
554 if (on == is_interactive) 556 if (on == is_interactive)
555 return; 557 return;
556 setsignal(SIGINT, 0); 558 setsignal(SIGINT, 0);
557 setsignal(SIGQUIT, 0); 559 setsignal(SIGQUIT, 0);
558 setsignal(SIGTERM, 0); 560 setsignal(SIGTERM, 0);
559 is_interactive = on; 561 is_interactive = on;
560} 562}
561 563
562 564
563 565
564/* 566/*
565 * Called to exit the shell. 567 * Called to exit the shell.
566 */ 568 */
567 569
568void 570void
569exitshell(int status) 571exitshell(int status)
570{ 572{
571 struct jmploc loc1, loc2; 573 struct jmploc loc1, loc2;
572 char *p; 574 char *p;
573 575
574 CTRACE(DBG_ERRS|DBG_PROCS|DBG_CMDS|DBG_TRAP, 576 CTRACE(DBG_ERRS|DBG_PROCS|DBG_CMDS|DBG_TRAP,
575 ("pid %d, exitshell(%d)\n", getpid(), status)); 577 ("pid %d, exitshell(%d)\n", getpid(), status));
576 578
577 if (setjmp(loc1.loc)) { 579 if (setjmp(loc1.loc)) {
578 goto l1; 580 goto l1;
579 } 581 }
580 if (setjmp(loc2.loc)) { 582 if (setjmp(loc2.loc)) {
581 goto l2; 583 goto l2;
582 } 584 }
583 handler = &loc1; 585 handler = &loc1;
584 if ((p = trap[0]) != NULL && *p != '\0') { 586 if ((p = trap[0]) != NULL && *p != '\0') {
585 trap[0] = NULL; 587 trap[0] = NULL;
586 VTRACE(DBG_TRAP, ("exit trap: \"%s\"\n", p)); 588 VTRACE(DBG_TRAP, ("exit trap: \"%s\"\n", p));
587 evalstring(p, 0); 589 evalstring(p, 0);
588 } 590 }
589 l1: handler = &loc2; /* probably unnecessary */ 591 l1: handler = &loc2; /* probably unnecessary */
590 flushall(); 592 flushall();
591#if JOBS 593#if JOBS
592 setjobctl(0); 594 setjobctl(0);
593#endif 595#endif
594 l2: _exit(status); 596 l2: _exit(status);
595 /* NOTREACHED */ 597 /* NOTREACHED */
596} 598}