Line data Source code
1 : /* sig.c - interface for shell signal handlers and signal initialization. */
2 :
3 : /* Copyright (C) 1994-2015 Free Software Foundation, Inc.
4 :
5 : This file is part of GNU Bash, the Bourne Again SHell.
6 :
7 : Bash is free software: you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation, either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : Bash is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "bashtypes.h"
24 :
25 : #if defined (HAVE_UNISTD_H)
26 : # ifdef _MINIX
27 : # include <sys/types.h>
28 : # endif
29 : # include <unistd.h>
30 : #endif
31 :
32 : #include <stdio.h>
33 : #include <signal.h>
34 :
35 : #include "bashintl.h"
36 :
37 : #include "shell.h"
38 : #if defined (JOB_CONTROL)
39 : #include "jobs.h"
40 : #endif /* JOB_CONTROL */
41 : #include "siglist.h"
42 : #include "sig.h"
43 : #include "trap.h"
44 :
45 : #include "builtins/common.h"
46 : #include "builtins/builtext.h"
47 :
48 : #if defined (READLINE)
49 : # include "bashline.h"
50 : # include <readline/readline.h>
51 : #endif
52 :
53 : #if defined (HISTORY)
54 : # include "bashhist.h"
55 : #endif
56 :
57 : extern int last_command_exit_value;
58 : extern int last_command_exit_signal;
59 : extern int return_catch_flag;
60 : extern int running_trap;
61 : extern int loop_level, continuing, breaking, funcnest;
62 : extern int executing_list;
63 : extern int comsub_ignore_return;
64 : extern int parse_and_execute_level, shell_initialized;
65 : #if defined (HISTORY)
66 : extern int history_lines_this_session;
67 : #endif
68 : extern int no_line_editing;
69 : extern int wait_signal_received;
70 : extern int wait_intr_flag;
71 : extern sh_builtin_func_t *this_shell_builtin;
72 :
73 : extern void initialize_siglist ();
74 :
75 : #if !defined (JOB_CONTROL)
76 : extern void initialize_job_signals __P((void));
77 : #endif
78 :
79 : /* Non-zero after SIGINT. */
80 : volatile sig_atomic_t interrupt_state = 0;
81 :
82 : /* Non-zero after SIGWINCH */
83 : volatile sig_atomic_t sigwinch_received = 0;
84 :
85 : /* Non-zero after SIGTERM */
86 : volatile sig_atomic_t sigterm_received = 0;
87 :
88 : /* Set to the value of any terminating signal received. */
89 : volatile sig_atomic_t terminating_signal = 0;
90 :
91 : /* The environment at the top-level R-E loop. We use this in
92 : the case of error return. */
93 : procenv_t top_level;
94 :
95 : #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
96 : /* The signal masks that this shell runs with. */
97 : sigset_t top_level_mask;
98 : #endif /* JOB_CONTROL */
99 :
100 : /* When non-zero, we throw_to_top_level (). */
101 : int interrupt_immediately = 0;
102 :
103 : /* When non-zero, we call the terminating signal handler immediately. */
104 : int terminate_immediately = 0;
105 :
106 : #if defined (SIGWINCH)
107 : static SigHandler *old_winch = (SigHandler *)SIG_DFL;
108 : #endif
109 :
110 : static void initialize_shell_signals __P((void));
111 :
112 : void
113 9143314 : initialize_signals (reinit)
114 : int reinit;
115 : {
116 9143314 : initialize_shell_signals ();
117 9143314 : initialize_job_signals ();
118 : #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
119 : if (reinit == 0)
120 : initialize_siglist ();
121 : #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
122 9143314 : }
123 :
124 : /* A structure describing a signal that terminates the shell if not
125 : caught. The orig_handler member is present so children can reset
126 : these signals back to their original handlers. */
127 : struct termsig {
128 : int signum;
129 : SigHandler *orig_handler;
130 : int orig_flags;
131 : };
132 :
133 : #define NULL_HANDLER (SigHandler *)SIG_DFL
134 :
135 : /* The list of signals that would terminate the shell if not caught.
136 : We catch them, but just so that we can write the history file,
137 : and so forth. */
138 : static struct termsig terminating_signals[] = {
139 : #ifdef SIGHUP
140 : { SIGHUP, NULL_HANDLER, 0 },
141 : #endif
142 :
143 : #ifdef SIGINT
144 : { SIGINT, NULL_HANDLER, 0 },
145 : #endif
146 :
147 : #ifdef SIGILL
148 : { SIGILL, NULL_HANDLER, 0 },
149 : #endif
150 :
151 : #ifdef SIGTRAP
152 : { SIGTRAP, NULL_HANDLER, 0 },
153 : #endif
154 :
155 : #ifdef SIGIOT
156 : { SIGIOT, NULL_HANDLER, 0 },
157 : #endif
158 :
159 : #ifdef SIGDANGER
160 : { SIGDANGER, NULL_HANDLER, 0 },
161 : #endif
162 :
163 : #ifdef SIGEMT
164 : { SIGEMT, NULL_HANDLER, 0 },
165 : #endif
166 :
167 : #ifdef SIGFPE
168 : { SIGFPE, NULL_HANDLER, 0 },
169 : #endif
170 :
171 : #ifdef SIGBUS
172 : { SIGBUS, NULL_HANDLER, 0 },
173 : #endif
174 :
175 : #ifdef SIGSEGV
176 : { SIGSEGV, NULL_HANDLER, 0 },
177 : #endif
178 :
179 : #ifdef SIGSYS
180 : { SIGSYS, NULL_HANDLER, 0 },
181 : #endif
182 :
183 : #ifdef SIGPIPE
184 : { SIGPIPE, NULL_HANDLER, 0 },
185 : #endif
186 :
187 : #ifdef SIGALRM
188 : { SIGALRM, NULL_HANDLER, 0 },
189 : #endif
190 :
191 : #ifdef SIGTERM
192 : { SIGTERM, NULL_HANDLER, 0 },
193 : #endif
194 :
195 : #ifdef SIGXCPU
196 : { SIGXCPU, NULL_HANDLER, 0 },
197 : #endif
198 :
199 : #ifdef SIGXFSZ
200 : { SIGXFSZ, NULL_HANDLER, 0 },
201 : #endif
202 :
203 : #ifdef SIGVTALRM
204 : { SIGVTALRM, NULL_HANDLER, 0 },
205 : #endif
206 :
207 : #if 0
208 : #ifdef SIGPROF
209 : { SIGPROF, NULL_HANDLER, 0 },
210 : #endif
211 : #endif
212 :
213 : #ifdef SIGLOST
214 : { SIGLOST, NULL_HANDLER, 0 },
215 : #endif
216 :
217 : #ifdef SIGUSR1
218 : { SIGUSR1, NULL_HANDLER, 0 },
219 : #endif
220 :
221 : #ifdef SIGUSR2
222 : { SIGUSR2, NULL_HANDLER, 0 },
223 : #endif
224 : };
225 :
226 : #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
227 :
228 : #define XSIG(x) (terminating_signals[x].signum)
229 : #define XHANDLER(x) (terminating_signals[x].orig_handler)
230 : #define XSAFLAGS(x) (terminating_signals[x].orig_flags)
231 :
232 : static int termsigs_initialized = 0;
233 :
234 : /* Initialize signals that will terminate the shell to do some
235 : unwind protection. For non-interactive shells, we only call
236 : this when a trap is defined for EXIT (0) or when trap is run
237 : to display signal dispositions. */
238 : void
239 97 : initialize_terminating_signals ()
240 : {
241 97 : register int i;
242 : #if defined (HAVE_POSIX_SIGNALS)
243 97 : struct sigaction act, oact;
244 : #endif
245 :
246 97 : if (termsigs_initialized)
247 0 : return;
248 :
249 : /* The following code is to avoid an expensive call to
250 : set_signal_handler () for each terminating_signals. Fortunately,
251 : this is possible in Posix. Unfortunately, we have to call signal ()
252 : on non-Posix systems for each signal in terminating_signals. */
253 : #if defined (HAVE_POSIX_SIGNALS)
254 97 : act.sa_handler = termsig_sighandler;
255 97 : act.sa_flags = 0;
256 97 : sigemptyset (&act.sa_mask);
257 97 : sigemptyset (&oact.sa_mask);
258 1746 : for (i = 0; i < TERMSIGS_LENGTH; i++)
259 1649 : sigaddset (&act.sa_mask, XSIG (i));
260 1746 : for (i = 0; i < TERMSIGS_LENGTH; i++)
261 : {
262 : /* If we've already trapped it, don't do anything. */
263 1649 : if (signal_is_trapped (XSIG (i)))
264 : continue;
265 :
266 1649 : sigaction (XSIG (i), &act, &oact);
267 1649 : XHANDLER(i) = oact.sa_handler;
268 1649 : XSAFLAGS(i) = oact.sa_flags;
269 : /* Don't do anything with signals that are ignored at shell entry
270 : if the shell is not interactive. */
271 : /* XXX - should we do this for interactive shells, too? */
272 1649 : if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
273 : {
274 97 : sigaction (XSIG (i), &oact, &act);
275 97 : set_signal_hard_ignored (XSIG (i));
276 : }
277 : #if defined (SIGPROF) && !defined (_MINIX)
278 1649 : if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
279 0 : sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
280 : #endif /* SIGPROF && !_MINIX */
281 : }
282 :
283 : #else /* !HAVE_POSIX_SIGNALS */
284 :
285 : for (i = 0; i < TERMSIGS_LENGTH; i++)
286 : {
287 : /* If we've already trapped it, don't do anything. */
288 : if (signal_is_trapped (XSIG (i)))
289 : continue;
290 :
291 : XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
292 : XSAFLAGS(i) = 0;
293 : /* Don't do anything with signals that are ignored at shell entry
294 : if the shell is not interactive. */
295 : /* XXX - should we do this for interactive shells, too? */
296 : if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
297 : {
298 : signal (XSIG (i), SIG_IGN);
299 : set_signal_hard_ignored (XSIG (i));
300 : }
301 : #ifdef SIGPROF
302 : if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
303 : signal (XSIG (i), XHANDLER (i));
304 : #endif
305 : }
306 :
307 : #endif /* !HAVE_POSIX_SIGNALS */
308 :
309 97 : termsigs_initialized = 1;
310 : }
311 :
312 : static void
313 9143314 : initialize_shell_signals ()
314 : {
315 9143314 : if (interactive)
316 0 : initialize_terminating_signals ();
317 :
318 : #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
319 : /* All shells use the signal mask they inherit, and pass it along
320 : to child processes. Children will never block SIGCHLD, though. */
321 9143314 : sigemptyset (&top_level_mask);
322 9143314 : sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
323 : # if defined (SIGCHLD)
324 9143314 : sigdelset (&top_level_mask, SIGCHLD);
325 : # endif
326 : #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
327 :
328 : /* And, some signals that are specifically ignored by the shell. */
329 9143314 : set_signal_handler (SIGQUIT, SIG_IGN);
330 :
331 9143314 : if (interactive)
332 : {
333 0 : set_signal_handler (SIGINT, sigint_sighandler);
334 0 : get_original_signal (SIGTERM);
335 0 : if (signal_is_hard_ignored (SIGTERM) == 0)
336 0 : set_signal_handler (SIGTERM, sigterm_sighandler);
337 0 : set_sigwinch_handler ();
338 : }
339 9143314 : }
340 :
341 : void
342 7044069 : reset_terminating_signals ()
343 : {
344 7044069 : register int i;
345 : #if defined (HAVE_POSIX_SIGNALS)
346 7044069 : struct sigaction act;
347 : #endif
348 :
349 7044069 : if (termsigs_initialized == 0)
350 7044023 : return;
351 :
352 : #if defined (HAVE_POSIX_SIGNALS)
353 46 : act.sa_flags = 0;
354 46 : sigemptyset (&act.sa_mask);
355 828 : for (i = 0; i < TERMSIGS_LENGTH; i++)
356 : {
357 : /* Skip a signal if it's trapped or handled specially, because the
358 : trap code will restore the correct value. */
359 782 : if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
360 46 : continue;
361 :
362 736 : act.sa_handler = XHANDLER (i);
363 736 : act.sa_flags = XSAFLAGS (i);
364 736 : sigaction (XSIG (i), &act, (struct sigaction *) NULL);
365 : }
366 : #else /* !HAVE_POSIX_SIGNALS */
367 : for (i = 0; i < TERMSIGS_LENGTH; i++)
368 : {
369 : if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
370 : continue;
371 :
372 : signal (XSIG (i), XHANDLER (i));
373 : }
374 : #endif /* !HAVE_POSIX_SIGNALS */
375 :
376 46 : termsigs_initialized = 0;
377 : }
378 : #undef XSIG
379 : #undef XHANDLER
380 :
381 : /* Run some of the cleanups that should be performed when we run
382 : jump_to_top_level from a builtin command context. XXX - might want to
383 : also call reset_parser here. */
384 : void
385 7093 : top_level_cleanup ()
386 : {
387 : /* Clean up string parser environment. */
388 7093 : while (parse_and_execute_level)
389 0 : parse_and_execute_cleanup ();
390 :
391 : #if defined (PROCESS_SUBSTITUTION)
392 7093 : unlink_fifo_list ();
393 : #endif /* PROCESS_SUBSTITUTION */
394 :
395 7093 : run_unwind_protects ();
396 7093 : loop_level = continuing = breaking = funcnest = 0;
397 7093 : executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
398 7093 : }
399 :
400 : /* What to do when we've been interrupted, and it is safe to handle it. */
401 : void
402 0 : throw_to_top_level ()
403 : {
404 0 : int print_newline = 0;
405 :
406 0 : if (interrupt_state)
407 : {
408 0 : if (last_command_exit_value < 128)
409 0 : last_command_exit_value = 128 + SIGINT;
410 0 : print_newline = 1;
411 0 : DELINTERRUPT;
412 : }
413 :
414 0 : if (interrupt_state)
415 0 : return;
416 :
417 0 : last_command_exit_signal = (last_command_exit_value > 128) ?
418 0 : (last_command_exit_value - 128) : 0;
419 0 : last_command_exit_value |= 128;
420 :
421 : /* Run any traps set on SIGINT, mostly for interactive shells */
422 0 : if (signal_is_trapped (SIGINT))
423 0 : run_interrupt_trap (1);
424 :
425 : /* Clean up string parser environment. */
426 0 : while (parse_and_execute_level)
427 0 : parse_and_execute_cleanup ();
428 :
429 0 : if (running_trap > 0)
430 0 : run_trap_cleanup (running_trap - 1);
431 :
432 : #if defined (JOB_CONTROL)
433 0 : give_terminal_to (shell_pgrp, 0);
434 : #endif /* JOB_CONTROL */
435 :
436 : #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
437 : /* This needs to stay because jobs.c:make_child() uses it without resetting
438 : the signal mask. */
439 0 : sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
440 : #endif
441 :
442 0 : reset_parser ();
443 :
444 : #if defined (READLINE)
445 0 : if (interactive)
446 0 : bashline_reset ();
447 : #endif /* READLINE */
448 :
449 : #if defined (PROCESS_SUBSTITUTION)
450 0 : unlink_fifo_list ();
451 : #endif /* PROCESS_SUBSTITUTION */
452 :
453 0 : run_unwind_protects ();
454 0 : loop_level = continuing = breaking = funcnest = 0;
455 0 : executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
456 :
457 0 : if (interactive && print_newline)
458 : {
459 0 : fflush (stdout);
460 0 : fprintf (stderr, "\n");
461 0 : fflush (stderr);
462 : }
463 :
464 : /* An interrupted `wait' command in a script does not exit the script. */
465 0 : if (interactive || (interactive_shell && !shell_initialized) ||
466 0 : (print_newline && signal_is_trapped (SIGINT)))
467 0 : jump_to_top_level (DISCARD);
468 : else
469 0 : jump_to_top_level (EXITPROG);
470 : }
471 :
472 : /* This is just here to isolate the longjmp calls. */
473 : void
474 6875386 : jump_to_top_level (value)
475 : int value;
476 : {
477 6875386 : sh_longjmp (top_level, value);
478 : }
479 :
480 : sighandler
481 0 : termsig_sighandler (sig)
482 : int sig;
483 : {
484 : /* If we get called twice with the same signal before handling it,
485 : terminate right away. */
486 0 : if (
487 : #ifdef SIGHUP
488 0 : sig != SIGHUP &&
489 : #endif
490 : #ifdef SIGINT
491 0 : sig != SIGINT &&
492 : #endif
493 : #ifdef SIGDANGER
494 : sig != SIGDANGER &&
495 : #endif
496 : #ifdef SIGPIPE
497 0 : sig != SIGPIPE &&
498 : #endif
499 : #ifdef SIGALRM
500 0 : sig != SIGALRM &&
501 : #endif
502 : #ifdef SIGTERM
503 : sig != SIGTERM &&
504 : #endif
505 : #ifdef SIGXCPU
506 0 : sig != SIGXCPU &&
507 : #endif
508 : #ifdef SIGXFSZ
509 : sig != SIGXFSZ &&
510 : #endif
511 : #ifdef SIGVTALRM
512 0 : sig != SIGVTALRM &&
513 : #endif
514 : #ifdef SIGLOST
515 : sig != SIGLOST &&
516 : #endif
517 : #ifdef SIGUSR1
518 0 : sig != SIGUSR1 &&
519 : #endif
520 : #ifdef SIGUSR2
521 0 : sig != SIGUSR2 &&
522 : #endif
523 0 : sig == terminating_signal)
524 0 : terminate_immediately = 1;
525 :
526 0 : terminating_signal = sig;
527 :
528 : /* XXX - should this also trigger when interrupt_immediately is set? */
529 0 : if (terminate_immediately)
530 : {
531 : #if defined (HISTORY)
532 : /* XXX - will inhibit history file being written */
533 : # if defined (READLINE)
534 0 : if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
535 : # endif
536 0 : history_lines_this_session = 0;
537 : #endif
538 0 : terminate_immediately = 0;
539 0 : termsig_handler (sig);
540 : }
541 :
542 : #if defined (READLINE)
543 : /* Set the event hook so readline will call it after the signal handlers
544 : finish executing, so if this interrupted character input we can get
545 : quick response. If readline is active or has modified the terminal we
546 : need to set this no matter what the signal is, though the check for
547 : RL_STATE_TERMPREPPED is possibly redundant. */
548 0 : if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
549 0 : bashline_set_event_hook ();
550 : #endif
551 :
552 0 : SIGRETURN (0);
553 : }
554 :
555 : void
556 0 : termsig_handler (sig)
557 : int sig;
558 : {
559 0 : static int handling_termsig = 0;
560 :
561 : /* Simple semaphore to keep this function from being executed multiple
562 : times. Since we no longer are running as a signal handler, we don't
563 : block multiple occurrences of the terminating signals while running. */
564 0 : if (handling_termsig)
565 : return;
566 0 : handling_termsig = 1;
567 0 : terminating_signal = 0; /* keep macro from re-testing true. */
568 :
569 : /* I don't believe this condition ever tests true. */
570 0 : if (sig == SIGINT && signal_is_trapped (SIGINT))
571 0 : run_interrupt_trap (0);
572 :
573 : #if defined (HISTORY)
574 : /* If we don't do something like this, the history will not be saved when
575 : an interactive shell is running in a terminal window that gets closed
576 : with the `close' button. We can't test for RL_STATE_READCMD because
577 : readline no longer handles SIGTERM synchronously. */
578 0 : if (interactive_shell && interactive && (sig == SIGHUP || sig == SIGTERM) && remember_on_history)
579 0 : maybe_save_shell_history ();
580 : #endif /* HISTORY */
581 :
582 0 : if (this_shell_builtin == read_builtin)
583 0 : read_tty_cleanup ();
584 :
585 : #if defined (JOB_CONTROL)
586 0 : if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
587 0 : hangup_all_jobs ();
588 0 : if ((subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB)) == 0)
589 0 : end_job_control ();
590 : #endif /* JOB_CONTROL */
591 :
592 : #if defined (PROCESS_SUBSTITUTION)
593 0 : unlink_fifo_list ();
594 : #endif /* PROCESS_SUBSTITUTION */
595 :
596 : /* Reset execution context */
597 0 : loop_level = continuing = breaking = funcnest = 0;
598 0 : executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
599 :
600 0 : run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
601 0 : set_signal_handler (sig, SIG_DFL);
602 0 : kill (getpid (), sig);
603 : }
604 :
605 : /* What we really do when SIGINT occurs. */
606 : sighandler
607 0 : sigint_sighandler (sig)
608 : int sig;
609 : {
610 : #if defined (MUST_REINSTALL_SIGHANDLERS)
611 : signal (sig, sigint_sighandler);
612 : #endif
613 :
614 : /* interrupt_state needs to be set for the stack of interrupts to work
615 : right. Should it be set unconditionally? */
616 0 : if (interrupt_state == 0)
617 0 : ADDINTERRUPT;
618 :
619 : /* We will get here in interactive shells with job control active; allow
620 : an interactive wait to be interrupted. wait_intr_flag is only set during
621 : the execution of the wait builtin and when wait_intr_buf is valid. */
622 0 : if (wait_intr_flag)
623 : {
624 0 : last_command_exit_value = 128 + sig;
625 0 : wait_signal_received = sig;
626 0 : SIGRETURN (0);
627 : }
628 :
629 0 : if (interrupt_immediately)
630 : {
631 0 : interrupt_immediately = 0;
632 0 : last_command_exit_value = 128 + sig;
633 0 : throw_to_top_level ();
634 : }
635 : #if defined (READLINE)
636 : /* Set the event hook so readline will call it after the signal handlers
637 : finish executing, so if this interrupted character input we can get
638 : quick response. */
639 0 : else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
640 0 : bashline_set_event_hook ();
641 : #endif
642 :
643 : SIGRETURN (0);
644 : }
645 :
646 : #if defined (SIGWINCH)
647 : sighandler
648 0 : sigwinch_sighandler (sig)
649 : int sig;
650 : {
651 : #if defined (MUST_REINSTALL_SIGHANDLERS)
652 : set_signal_handler (SIGWINCH, sigwinch_sighandler);
653 : #endif /* MUST_REINSTALL_SIGHANDLERS */
654 0 : sigwinch_received = 1;
655 0 : SIGRETURN (0);
656 : }
657 : #endif /* SIGWINCH */
658 :
659 : void
660 0 : set_sigwinch_handler ()
661 : {
662 : #if defined (SIGWINCH)
663 0 : old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
664 : #endif
665 0 : }
666 :
667 : void
668 0 : unset_sigwinch_handler ()
669 : {
670 : #if defined (SIGWINCH)
671 0 : set_signal_handler (SIGWINCH, old_winch);
672 : #endif
673 0 : }
674 :
675 : sighandler
676 0 : sigterm_sighandler (sig)
677 : int sig;
678 : {
679 0 : sigterm_received = 1; /* XXX - counter? */
680 0 : SIGRETURN (0);
681 : }
682 :
683 : /* Signal functions used by the rest of the code. */
684 : #if !defined (HAVE_POSIX_SIGNALS)
685 :
686 : /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
687 : sigprocmask (operation, newset, oldset)
688 : int operation, *newset, *oldset;
689 : {
690 : int old, new;
691 :
692 : if (newset)
693 : new = *newset;
694 : else
695 : new = 0;
696 :
697 : switch (operation)
698 : {
699 : case SIG_BLOCK:
700 : old = sigblock (new);
701 : break;
702 :
703 : case SIG_SETMASK:
704 : old = sigsetmask (new);
705 : break;
706 :
707 : default:
708 : internal_error (_("sigprocmask: %d: invalid operation"), operation);
709 : }
710 :
711 : if (oldset)
712 : *oldset = old;
713 : }
714 :
715 : #else
716 :
717 : #if !defined (SA_INTERRUPT)
718 : # define SA_INTERRUPT 0
719 : #endif
720 :
721 : #if !defined (SA_RESTART)
722 : # define SA_RESTART 0
723 : #endif
724 :
725 : SigHandler *
726 184485949 : set_signal_handler (sig, handler)
727 : int sig;
728 : SigHandler *handler;
729 : {
730 184485949 : struct sigaction act, oact;
731 :
732 184485949 : act.sa_handler = handler;
733 184485949 : act.sa_flags = 0;
734 :
735 : /* XXX - bash-4.2 */
736 : /* We don't want a child death to interrupt interruptible system calls, even
737 : if we take the time to reap children */
738 : #if defined (SIGCHLD)
739 184485949 : if (sig == SIGCHLD)
740 34513387 : act.sa_flags |= SA_RESTART; /* XXX */
741 : #endif
742 : /* If we're installing a SIGTERM handler for interactive shells, we want
743 : it to be as close to SIG_IGN as possible. */
744 184485949 : if (sig == SIGTERM && handler == sigterm_sighandler)
745 0 : act.sa_flags |= SA_RESTART; /* XXX */
746 :
747 184485949 : sigemptyset (&act.sa_mask);
748 184485949 : sigemptyset (&oact.sa_mask);
749 184485949 : if (sigaction (sig, &act, &oact) == 0)
750 184485245 : return (oact.sa_handler);
751 : else
752 : return (SIG_DFL);
753 : }
754 : #endif /* HAVE_POSIX_SIGNALS */
|