]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/trap.def
fix for SIGINT in sourced script
[thirdparty/bash.git] / builtins / trap.def
CommitLineData
726f6388
JA
1This file is trap.def, from which is created trap.c.
2It implements the builtin "trap" in Bash.
3
a0c0a00f 4Copyright (C) 1987-2015 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES trap.c
22
23$BUILTIN trap
24$FUNCTION trap_builtin
3185942a
JA
25$SHORT_DOC trap [-lp] [[arg] signal_spec ...]
26Trap signals and other events.
27
28Defines and activates handlers to be run when the shell receives signals
29or other conditions.
30
31ARG is a command to be read and executed when the shell receives the
b80f6443
JA
32signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC
33is supplied) or `-', each specified signal is reset to its original
34value. If ARG is the null string each SIGNAL_SPEC is ignored by the
3185942a
JA
35shell and by the commands it invokes.
36
37If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
495aee44
CR
38a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If
39a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a
40script run by the . or source builtins finishes executing. A SIGNAL_SPEC
41of ERR means to execute ARG each time a command's failure would cause the
42shell to exit when the -e option is enabled.
3185942a
JA
43
44If no arguments are supplied, trap prints the list of commands associated
45with each signal.
46
47Options:
48 -l print a list of signal names and their corresponding numbers
49 -p display the trap commands associated with each SIGNAL_SPEC
50
51Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.
52Signal names are case insensitive and the SIG prefix is optional. A
53signal may be sent to the shell with "kill -signal $$".
54
55Exit Status:
56Returns success unless a SIGSPEC is invalid or an invalid option is given.
726f6388
JA
57$END
58
ccc6cda3
JA
59#include <config.h>
60
61#if defined (HAVE_UNISTD_H)
cce855bc
JA
62# ifdef _MINIX
63# include <sys/types.h>
64# endif
ccc6cda3
JA
65# include <unistd.h>
66#endif
67
68#include "../bashtypes.h"
726f6388 69#include <signal.h>
ccc6cda3
JA
70#include <stdio.h>
71#include "../bashansi.h"
72
726f6388
JA
73#include "../shell.h"
74#include "../trap.h"
75#include "common.h"
ccc6cda3
JA
76#include "bashgetopt.h"
77
f73dda09
JA
78static void showtrap __P((int));
79static int display_traps __P((WORD_LIST *));
726f6388
JA
80
81/* The trap command:
82
83 trap <arg> <signal ...>
84 trap <signal ...>
85 trap -l
ccc6cda3 86 trap -p [sigspec ...]
726f6388
JA
87 trap [--]
88
a0c0a00f 89 Set things up so that ARG is executed when SIGNAL(s) N is received.
726f6388
JA
90 If ARG is the empty string, then ignore the SIGNAL(s). If there is
91 no ARG, then set the trap for SIGNAL(s) to its original value. Just
92 plain "trap" means to print out the list of commands associated with
93 each signal number. Single arg of "-l" means list the signal names. */
94
95/* Possible operations to perform on the list of signals.*/
96#define SET 0 /* Set this signal to first_arg. */
97#define REVERT 1 /* Revert to this signals original value. */
98#define IGNORE 2 /* Ignore this signal. */
99
495aee44 100extern int posixly_correct, subshell_environment;
64447609 101extern int sourcelevel, running_trap;
726f6388 102
ccc6cda3 103int
726f6388
JA
104trap_builtin (list)
105 WORD_LIST *list;
106{
0628567a 107 int list_signal_names, display, result, opt;
726f6388 108
ccc6cda3
JA
109 list_signal_names = display = 0;
110 result = EXECUTION_SUCCESS;
495aee44 111
ccc6cda3
JA
112 reset_internal_getopt ();
113 while ((opt = internal_getopt (list, "lp")) != -1)
726f6388 114 {
ccc6cda3 115 switch (opt)
726f6388 116 {
ccc6cda3 117 case 'l':
726f6388 118 list_signal_names++;
726f6388 119 break;
ccc6cda3
JA
120 case 'p':
121 display++;
122 break;
a0c0a00f 123 CASE_HELPOPT;
ccc6cda3
JA
124 default:
125 builtin_usage ();
726f6388
JA
126 return (EX_USAGE);
127 }
726f6388 128 }
ccc6cda3 129 list = loptend;
726f6388 130
b80f6443
JA
131 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
132
726f6388 133 if (list_signal_names)
3185942a 134 return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
ccc6cda3 135 else if (display || list == 0)
495aee44
CR
136 {
137 initialize_terminating_signals ();
138 get_all_original_signals ();
139 return (sh_chkwrite (display_traps (list)));
140 }
ccc6cda3 141 else
726f6388 142 {
ccc6cda3 143 char *first_arg;
eb873671 144 int operation, sig, first_signal;
726f6388 145
ccc6cda3
JA
146 operation = SET;
147 first_arg = list->word->word;
eb873671
JA
148 first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
149
0628567a
JA
150 /* Backwards compatibility. XXX - question about whether or not we
151 should throw an error if an all-digit argument doesn't correspond
152 to a valid signal number (e.g., if it's `50' on a system with only
153 32 signals). */
eb873671
JA
154 if (first_signal)
155 operation = REVERT;
b80f6443
JA
156 /* When in posix mode, the historical behavior of looking for a
157 missing first argument is disabled. To revert to the original
158 signal handling disposition, use `-' as the first argument. */
eb873671 159 else if (posixly_correct == 0 && first_arg && *first_arg &&
b80f6443
JA
160 (*first_arg != '-' || first_arg[1]) &&
161 signal_object_p (first_arg, opt) && list->next == 0)
726f6388
JA
162 operation = REVERT;
163 else
164 {
165 list = list->next;
b80f6443
JA
166 if (list == 0)
167 {
168 builtin_usage ();
169 return (EX_USAGE);
170 }
171 else if (*first_arg == '\0')
726f6388
JA
172 operation = IGNORE;
173 else if (first_arg[0] == '-' && !first_arg[1])
174 operation = REVERT;
175 }
176
495aee44
CR
177 /* If we're in a command substitution, we haven't freed the trap strings
178 (though we reset the signal handlers). If we're setting a trap to
179 handle a signal here, free the rest of the trap strings since they
180 don't apply any more. */
181 if (subshell_environment & SUBSHELL_RESETTRAP)
182 {
183 free_trap_strings ();
184 subshell_environment &= ~SUBSHELL_RESETTRAP;
185 }
186
726f6388
JA
187 while (list)
188 {
b80f6443 189 sig = decode_signal (list->word->word, opt);
726f6388
JA
190
191 if (sig == NO_SIG)
192 {
7117c2d2 193 sh_invalidsig (list->word->word);
ccc6cda3 194 result = EXECUTION_FAILURE;
726f6388
JA
195 }
196 else
197 {
198 switch (operation)
199 {
200 case SET:
201 set_signal (sig, first_arg);
202 break;
203
204 case REVERT:
205 restore_default_signal (sig);
206
207 /* Signals that the shell treats specially need special
208 handling. */
209 switch (sig)
210 {
211 case SIGINT:
495aee44
CR
212 /* XXX - should we do this if original disposition
213 was SIG_IGN? */
726f6388
JA
214 if (interactive)
215 set_signal_handler (SIGINT, sigint_sighandler);
64447609
CR
216 /* special cases for interactive == 0 */
217 else if (interactive_shell && (sourcelevel||running_trap))
218 set_signal_handler (SIGINT, sigint_sighandler);
726f6388 219 else
0628567a 220 set_signal_handler (SIGINT, termsig_sighandler);
726f6388
JA
221 break;
222
223 case SIGQUIT:
224 /* Always ignore SIGQUIT. */
225 set_signal_handler (SIGQUIT, SIG_IGN);
226 break;
227 case SIGTERM:
228#if defined (JOB_CONTROL)
229 case SIGTTIN:
230 case SIGTTOU:
231 case SIGTSTP:
232#endif /* JOB_CONTROL */
233 if (interactive)
234 set_signal_handler (sig, SIG_IGN);
235 break;
236 }
237 break;
238
239 case IGNORE:
240 ignore_signal (sig);
241 break;
242 }
243 }
244 list = list->next;
245 }
726f6388
JA
246 }
247
ccc6cda3
JA
248 return (result);
249}
250
251static void
252showtrap (i)
253 int i;
254{
e8ce775d 255 char *t, *p, *sn;
ccc6cda3
JA
256
257 p = trap_list[i];
495aee44 258 if (p == (char *)DEFAULT_SIG && signal_is_hard_ignored (i) == 0)
ccc6cda3 259 return;
495aee44
CR
260 else if (signal_is_hard_ignored (i))
261 t = (char *)NULL;
262 else
263 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
ccc6cda3 264
e8ce775d
JA
265 sn = signal_name (i);
266 /* Make sure that signals whose names are unknown (for whatever reason)
267 are printed as signal numbers. */
268 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
269 printf ("trap -- %s %d\n", t ? t : "''", i);
28ef6c31
JA
270 else if (posixly_correct)
271 {
272 if (STREQN (sn, "SIG", 3))
273 printf ("trap -- %s %s\n", t ? t : "''", sn+3);
274 else
275 printf ("trap -- %s %s\n", t ? t : "''", sn);
276 }
e8ce775d
JA
277 else
278 printf ("trap -- %s %s\n", t ? t : "''", sn);
279
280 FREE (t);
ccc6cda3 281}
726f6388 282
ccc6cda3
JA
283static int
284display_traps (list)
285 WORD_LIST *list;
286{
287 int result, i;
726f6388 288
ccc6cda3
JA
289 if (list == 0)
290 {
f73dda09 291 for (i = 0; i < BASH_NSIG; i++)
ccc6cda3
JA
292 showtrap (i);
293 return (EXECUTION_SUCCESS);
294 }
726f6388 295
ccc6cda3
JA
296 for (result = EXECUTION_SUCCESS; list; list = list->next)
297 {
b80f6443 298 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
ccc6cda3
JA
299 if (i == NO_SIG)
300 {
7117c2d2 301 sh_invalidsig (list->word->word);
ccc6cda3 302 result = EXECUTION_FAILURE;
ccc6cda3
JA
303 }
304 else
305 showtrap (i);
726f6388 306 }
ccc6cda3
JA
307
308 return (result);
726f6388 309}