Imported from ../bash-3.0.tar.gz.
[platform/upstream/bash.git] / sig.c
1 /* sig.c - interface for shell signal handlers and signal initialization. */
2
3 /* Copyright (C) 1994 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 it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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
47 #if defined (READLINE)
48 #  include "bashline.h"
49 #endif
50
51 #if defined (HISTORY)
52 #  include "bashhist.h"
53 #endif
54
55 extern int last_command_exit_value;
56 extern int last_command_exit_signal;
57 extern int return_catch_flag;
58 extern int loop_level, continuing, breaking;
59 extern int parse_and_execute_level, shell_initialized;
60
61 /* Non-zero after SIGINT. */
62 int interrupt_state;
63
64 /* The environment at the top-level R-E loop.  We use this in
65    the case of error return. */
66 procenv_t top_level;
67
68 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
69 /* The signal masks that this shell runs with. */
70 sigset_t top_level_mask;
71 #endif /* JOB_CONTROL */
72
73 /* When non-zero, we throw_to_top_level (). */
74 int interrupt_immediately = 0;
75
76 static void initialize_shell_signals __P((void));
77
78 void
79 initialize_signals (reinit)
80      int reinit;
81 {
82   initialize_shell_signals ();
83   initialize_job_signals ();
84 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
85   if (reinit == 0)
86     initialize_siglist ();
87 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
88 }
89
90 /* A structure describing a signal that terminates the shell if not
91    caught.  The orig_handler member is present so children can reset
92    these signals back to their original handlers. */
93 struct termsig {
94      int signum;
95      SigHandler *orig_handler;
96 };
97
98 #define NULL_HANDLER (SigHandler *)SIG_DFL
99
100 /* The list of signals that would terminate the shell if not caught.
101    We catch them, but just so that we can write the history file,
102    and so forth. */
103 static struct termsig terminating_signals[] = {
104 #ifdef SIGHUP
105 {  SIGHUP, NULL_HANDLER },
106 #endif
107
108 #ifdef SIGINT
109 {  SIGINT, NULL_HANDLER },
110 #endif
111
112 #ifdef SIGILL
113 {  SIGILL, NULL_HANDLER },
114 #endif
115
116 #ifdef SIGTRAP
117 {  SIGTRAP, NULL_HANDLER },
118 #endif
119
120 #ifdef SIGIOT
121 {  SIGIOT, NULL_HANDLER },
122 #endif
123
124 #ifdef SIGDANGER
125 {  SIGDANGER, NULL_HANDLER },
126 #endif
127
128 #ifdef SIGEMT
129 {  SIGEMT, NULL_HANDLER },
130 #endif
131
132 #ifdef SIGFPE
133 {  SIGFPE, NULL_HANDLER },
134 #endif
135
136 #ifdef SIGBUS
137 {  SIGBUS, NULL_HANDLER },
138 #endif
139
140 #ifdef SIGSEGV
141 {  SIGSEGV, NULL_HANDLER },
142 #endif
143
144 #ifdef SIGSYS
145 {  SIGSYS, NULL_HANDLER },
146 #endif
147
148 #ifdef SIGPIPE
149 {  SIGPIPE, NULL_HANDLER },
150 #endif
151
152 #ifdef SIGALRM
153 {  SIGALRM, NULL_HANDLER },
154 #endif
155
156 #ifdef SIGTERM
157 {  SIGTERM, NULL_HANDLER },
158 #endif
159
160 #ifdef SIGXCPU
161 {  SIGXCPU, NULL_HANDLER },
162 #endif
163
164 #ifdef SIGXFSZ
165 {  SIGXFSZ, NULL_HANDLER },
166 #endif
167
168 #ifdef SIGVTALRM
169 {  SIGVTALRM, NULL_HANDLER },
170 #endif
171
172 #if 0
173 #ifdef SIGPROF
174 {  SIGPROF, NULL_HANDLER },
175 #endif
176 #endif
177
178 #ifdef SIGLOST
179 {  SIGLOST, NULL_HANDLER },
180 #endif
181
182 #ifdef SIGUSR1
183 {  SIGUSR1, NULL_HANDLER },
184 #endif
185
186 #ifdef SIGUSR2
187 {  SIGUSR2, NULL_HANDLER },
188 #endif
189 };
190
191 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
192
193 #define XSIG(x) (terminating_signals[x].signum)
194 #define XHANDLER(x) (terminating_signals[x].orig_handler)
195
196 static int termsigs_initialized = 0;
197
198 /* Initialize signals that will terminate the shell to do some
199    unwind protection.  For non-interactive shells, we only call
200    this when a trap is defined for EXIT (0). */
201 void
202 initialize_terminating_signals ()
203 {
204   register int i;
205 #if defined (HAVE_POSIX_SIGNALS)
206   struct sigaction act, oact;
207 #endif
208
209   if (termsigs_initialized)
210     return;
211
212   /* The following code is to avoid an expensive call to
213      set_signal_handler () for each terminating_signals.  Fortunately,
214      this is possible in Posix.  Unfortunately, we have to call signal ()
215      on non-Posix systems for each signal in terminating_signals. */
216 #if defined (HAVE_POSIX_SIGNALS)
217   act.sa_handler = termination_unwind_protect;
218   act.sa_flags = 0;
219   sigemptyset (&act.sa_mask);
220   sigemptyset (&oact.sa_mask);
221   for (i = 0; i < TERMSIGS_LENGTH; i++)
222     sigaddset (&act.sa_mask, XSIG (i));
223   for (i = 0; i < TERMSIGS_LENGTH; i++)
224     {
225       /* If we've already trapped it, don't do anything. */
226       if (signal_is_trapped (XSIG (i)))
227         continue;
228
229       sigaction (XSIG (i), &act, &oact);
230       XHANDLER(i) = oact.sa_handler;
231       /* Don't do anything with signals that are ignored at shell entry
232          if the shell is not interactive. */
233       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
234         {
235           sigaction (XSIG (i), &oact, &act);
236           set_signal_ignored (XSIG (i));
237         }
238 #if defined (SIGPROF) && !defined (_MINIX)
239       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
240         sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
241 #endif /* SIGPROF && !_MINIX */
242     }
243
244 #else /* !HAVE_POSIX_SIGNALS */
245
246   for (i = 0; i < TERMSIGS_LENGTH; i++)
247     {
248       /* If we've already trapped it, don't do anything. */
249       if (signal_is_trapped (XSIG (i)))
250         continue;
251
252       XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
253       /* Don't do anything with signals that are ignored at shell entry
254          if the shell is not interactive. */
255       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
256         {
257           signal (XSIG (i), SIG_IGN);
258           set_signal_ignored (XSIG (i));
259         }
260 #ifdef SIGPROF
261       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
262         signal (XSIG (i), XHANDLER (i));
263 #endif
264     }
265
266 #endif /* !HAVE_POSIX_SIGNALS */
267
268   termsigs_initialized = 1;
269 }
270
271 static void
272 initialize_shell_signals ()
273 {
274   if (interactive)
275     initialize_terminating_signals ();
276
277 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
278   /* All shells use the signal mask they inherit, and pass it along
279      to child processes.  Children will never block SIGCHLD, though. */
280   sigemptyset (&top_level_mask);
281   sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
282 #  if defined (SIGCHLD)
283   sigdelset (&top_level_mask, SIGCHLD);
284 #  endif
285 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
286
287   /* And, some signals that are specifically ignored by the shell. */
288   set_signal_handler (SIGQUIT, SIG_IGN);
289
290   if (interactive)
291     {
292       set_signal_handler (SIGINT, sigint_sighandler);
293       set_signal_handler (SIGTERM, SIG_IGN);
294     }
295 }
296
297 void
298 reset_terminating_signals ()
299 {
300   register int i;
301 #if defined (HAVE_POSIX_SIGNALS)
302   struct sigaction act;
303 #endif
304
305   if (termsigs_initialized == 0)
306     return;
307
308 #if defined (HAVE_POSIX_SIGNALS)
309   act.sa_flags = 0;
310   sigemptyset (&act.sa_mask);
311   for (i = 0; i < TERMSIGS_LENGTH; i++)
312     {
313       /* Skip a signal if it's trapped or handled specially, because the
314          trap code will restore the correct value. */
315       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
316         continue;
317
318       act.sa_handler = XHANDLER (i);
319       sigaction (XSIG (i), &act, (struct sigaction *) NULL);
320     }
321 #else /* !HAVE_POSIX_SIGNALS */
322   for (i = 0; i < TERMSIGS_LENGTH; i++)
323     {
324       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
325         continue;
326
327       signal (XSIG (i), XHANDLER (i));
328     }
329 #endif /* !HAVE_POSIX_SIGNALS */
330 }
331 #undef XSIG
332 #undef XHANDLER
333
334 /* What to do when we've been interrupted, and it is safe to handle it. */
335 void
336 throw_to_top_level ()
337 {
338   int print_newline = 0;
339
340   if (interrupt_state)
341     {
342       print_newline = 1;
343       DELINTERRUPT;
344     }
345
346   if (interrupt_state)
347     return;
348
349   last_command_exit_signal = (last_command_exit_value > 128) ?
350                                 (last_command_exit_value - 128) : 0;
351   last_command_exit_value |= 128;
352
353   /* Run any traps set on SIGINT. */
354   run_interrupt_trap ();
355
356   /* Cleanup string parser environment. */
357   while (parse_and_execute_level)
358     parse_and_execute_cleanup ();
359
360 #if defined (JOB_CONTROL)
361   give_terminal_to (shell_pgrp, 0);
362 #endif /* JOB_CONTROL */
363
364 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
365   /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
366   sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
367 #endif
368
369   reset_parser ();
370
371 #if defined (READLINE)
372   if (interactive)
373     bashline_reinitialize ();
374 #endif /* READLINE */
375
376 #if defined (PROCESS_SUBSTITUTION)
377   unlink_fifo_list ();
378 #endif /* PROCESS_SUBSTITUTION */
379
380   run_unwind_protects ();
381   loop_level = continuing = breaking = 0;
382   return_catch_flag = 0;
383
384   if (interactive && print_newline)
385     {
386       fflush (stdout);
387       fprintf (stderr, "\n");
388       fflush (stderr);
389     }
390
391   /* An interrupted `wait' command in a script does not exit the script. */
392   if (interactive || (interactive_shell && !shell_initialized) ||
393       (print_newline && signal_is_trapped (SIGINT)))
394     jump_to_top_level (DISCARD);
395   else
396     jump_to_top_level (EXITPROG);
397 }
398
399 /* This is just here to isolate the longjmp calls. */
400 void
401 jump_to_top_level (value)
402      int value;
403 {
404   longjmp (top_level, value);
405 }
406
407 sighandler
408 termination_unwind_protect (sig)
409      int sig;
410 {
411   if (sig == SIGINT && signal_is_trapped (SIGINT))
412     run_interrupt_trap ();
413
414 #if defined (HISTORY)
415   if (interactive_shell && sig != SIGABRT)
416     maybe_save_shell_history ();
417 #endif /* HISTORY */
418
419 #if defined (JOB_CONTROL)
420   if (interactive && sig == SIGHUP)
421     hangup_all_jobs ();
422   end_job_control ();
423 #endif /* JOB_CONTROL */
424
425 #if defined (PROCESS_SUBSTITUTION)
426   unlink_fifo_list ();
427 #endif /* PROCESS_SUBSTITUTION */
428
429   run_exit_trap ();
430   set_signal_handler (sig, SIG_DFL);
431   kill (getpid (), sig);
432
433   SIGRETURN (0);
434 }
435
436 /* What we really do when SIGINT occurs. */
437 sighandler
438 sigint_sighandler (sig)
439      int sig;
440 {
441 #if defined (MUST_REINSTALL_SIGHANDLERS)
442   signal (sig, sigint_sighandler);
443 #endif
444
445   /* interrupt_state needs to be set for the stack of interrupts to work
446      right.  Should it be set unconditionally? */
447   if (interrupt_state == 0)
448     ADDINTERRUPT;
449
450   if (interrupt_immediately)
451     {
452       interrupt_immediately = 0;
453       throw_to_top_level ();
454     }
455
456   SIGRETURN (0);
457 }
458
459 /* Signal functions used by the rest of the code. */
460 #if !defined (HAVE_POSIX_SIGNALS)
461
462 #if defined (JOB_CONTROL)
463 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
464 sigprocmask (operation, newset, oldset)
465      int operation, *newset, *oldset;
466 {
467   int old, new;
468
469   if (newset)
470     new = *newset;
471   else
472     new = 0;
473
474   switch (operation)
475     {
476     case SIG_BLOCK:
477       old = sigblock (new);
478       break;
479
480     case SIG_SETMASK:
481       sigsetmask (new);
482       break;
483
484     default:
485       internal_error (_("sigprocmask: %d: invalid operation"), operation);
486     }
487
488   if (oldset)
489     *oldset = old;
490 }
491 #endif /* JOB_CONTROL */
492
493 #else
494
495 #if !defined (SA_INTERRUPT)
496 #  define SA_INTERRUPT 0
497 #endif
498
499 #if !defined (SA_RESTART)
500 #  define SA_RESTART 0
501 #endif
502
503 SigHandler *
504 set_signal_handler (sig, handler)
505      int sig;
506      SigHandler *handler;
507 {
508   struct sigaction act, oact;
509
510   act.sa_handler = handler;
511   act.sa_flags = 0;
512 #if 0
513   if (sig == SIGALRM)
514     act.sa_flags |= SA_INTERRUPT;       /* XXX */
515   else
516     act.sa_flags |= SA_RESTART;         /* XXX */
517 #endif
518   sigemptyset (&act.sa_mask);
519   sigemptyset (&oact.sa_mask);
520   sigaction (sig, &act, &oact);
521   return (oact.sa_handler);
522 }
523 #endif /* HAVE_POSIX_SIGNALS */