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