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