blob: 1ecbfbdb2e4628c15767327332c6742c9bfba3ce [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is trap.def, from which is created trap.c.
2It implements the builtin "trap" in Bash.
3
Jari Aaltob80f6442004-07-27 13:29:18 +00004Copyright (C) 1987-2004 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
Jari Aaltobb706242000-03-17 21:46:59 +000010Software Foundation; either version 2, or (at your option) any later
Jari Aalto726f6381996-08-26 18:22:31 +000011version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
Jari Aaltobb706242000-03-17 21:46:59 +000020Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
Jari Aalto726f6381996-08-26 18:22:31 +000021
22$PRODUCES trap.c
23
24$BUILTIN trap
25$FUNCTION trap_builtin
Jari Aaltoeb873672004-11-09 21:37:25 +000026$SHORT_DOC trap [-lp] [arg signal_spec ...]
Jari Aalto726f6381996-08-26 18:22:31 +000027The command ARG is to be read and executed when the shell receives
Jari Aaltob80f6442004-07-27 13:29:18 +000028signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC
29is supplied) or `-', each specified signal is reset to its original
30value. If ARG is the null string each SIGNAL_SPEC is ignored by the
31shell and by the commands it invokes. If a SIGNAL_SPEC is EXIT (0)
32the command ARG is executed on exit from the shell. If a SIGNAL_SPEC
33is DEBUG, ARG is executed after every simple command. If the`-p' option
34is supplied then the trap commands associated with each SIGNAL_SPEC are
35displayed. If no arguments are supplied or if only `-p' is given, trap
36prints the list of commands associated with each signal. Each SIGNAL_SPEC
37is either a signal name in <signal.h> or a signal number. Signal names
38are case insensitive and the SIG prefix is optional. `trap -l' prints
39a list of signal names and their corresponding numbers. Note that a
40signal can be sent to the shell with "kill -signal $$".
Jari Aalto726f6381996-08-26 18:22:31 +000041$END
42
Jari Aaltoccc6cda1996-12-23 17:02:34 +000043#include <config.h>
44
45#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000046# ifdef _MINIX
47# include <sys/types.h>
48# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000049# include <unistd.h>
50#endif
51
52#include "../bashtypes.h"
Jari Aalto726f6381996-08-26 18:22:31 +000053#include <signal.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000054#include <stdio.h>
55#include "../bashansi.h"
56
Jari Aalto726f6381996-08-26 18:22:31 +000057#include "../shell.h"
58#include "../trap.h"
59#include "common.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000060#include "bashgetopt.h"
61
Jari Aaltof73dda02001-11-13 17:56:06 +000062static void showtrap __P((int));
63static int display_traps __P((WORD_LIST *));
Jari Aalto726f6381996-08-26 18:22:31 +000064
65/* The trap command:
66
67 trap <arg> <signal ...>
68 trap <signal ...>
69 trap -l
Jari Aaltoccc6cda1996-12-23 17:02:34 +000070 trap -p [sigspec ...]
Jari Aalto726f6381996-08-26 18:22:31 +000071 trap [--]
72
73 Set things up so that ARG is executed when SIGNAL(s) N is recieved.
74 If ARG is the empty string, then ignore the SIGNAL(s). If there is
75 no ARG, then set the trap for SIGNAL(s) to its original value. Just
76 plain "trap" means to print out the list of commands associated with
77 each signal number. Single arg of "-l" means list the signal names. */
78
79/* Possible operations to perform on the list of signals.*/
80#define SET 0 /* Set this signal to first_arg. */
81#define REVERT 1 /* Revert to this signals original value. */
82#define IGNORE 2 /* Ignore this signal. */
83
Jari Aaltof73dda02001-11-13 17:56:06 +000084extern int posixly_correct;
Jari Aalto726f6381996-08-26 18:22:31 +000085
Jari Aaltoccc6cda1996-12-23 17:02:34 +000086int
Jari Aalto726f6381996-08-26 18:22:31 +000087trap_builtin (list)
88 WORD_LIST *list;
89{
Jari Aaltoeb873672004-11-09 21:37:25 +000090 int list_signal_names, display, result, opt, first_signal;
Jari Aalto726f6381996-08-26 18:22:31 +000091
Jari Aaltoccc6cda1996-12-23 17:02:34 +000092 list_signal_names = display = 0;
93 result = EXECUTION_SUCCESS;
94 reset_internal_getopt ();
95 while ((opt = internal_getopt (list, "lp")) != -1)
Jari Aalto726f6381996-08-26 18:22:31 +000096 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +000097 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +000098 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +000099 case 'l':
Jari Aalto726f6381996-08-26 18:22:31 +0000100 list_signal_names++;
Jari Aalto726f6381996-08-26 18:22:31 +0000101 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000102 case 'p':
103 display++;
104 break;
105 default:
106 builtin_usage ();
Jari Aalto726f6381996-08-26 18:22:31 +0000107 return (EX_USAGE);
108 }
Jari Aalto726f6381996-08-26 18:22:31 +0000109 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000110 list = loptend;
Jari Aalto726f6381996-08-26 18:22:31 +0000111
Jari Aaltob80f6442004-07-27 13:29:18 +0000112 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
113
Jari Aalto726f6381996-08-26 18:22:31 +0000114 if (list_signal_names)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000115 return (display_signal_list ((WORD_LIST *)NULL, 1));
116 else if (display || list == 0)
117 return (display_traps (list));
118 else
Jari Aalto726f6381996-08-26 18:22:31 +0000119 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000120 char *first_arg;
Jari Aaltoeb873672004-11-09 21:37:25 +0000121 int operation, sig, first_signal;
Jari Aalto726f6381996-08-26 18:22:31 +0000122
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000123 operation = SET;
124 first_arg = list->word->word;
Jari Aaltoeb873672004-11-09 21:37:25 +0000125 first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
126
127 /* Backwards compatibility */
128 if (first_signal)
129 operation = REVERT;
Jari Aaltob80f6442004-07-27 13:29:18 +0000130 /* When in posix mode, the historical behavior of looking for a
131 missing first argument is disabled. To revert to the original
132 signal handling disposition, use `-' as the first argument. */
Jari Aaltoeb873672004-11-09 21:37:25 +0000133 else if (posixly_correct == 0 && first_arg && *first_arg &&
Jari Aaltob80f6442004-07-27 13:29:18 +0000134 (*first_arg != '-' || first_arg[1]) &&
135 signal_object_p (first_arg, opt) && list->next == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000136 operation = REVERT;
137 else
138 {
139 list = list->next;
Jari Aaltob80f6442004-07-27 13:29:18 +0000140 if (list == 0)
141 {
142 builtin_usage ();
143 return (EX_USAGE);
144 }
145 else if (*first_arg == '\0')
Jari Aalto726f6381996-08-26 18:22:31 +0000146 operation = IGNORE;
147 else if (first_arg[0] == '-' && !first_arg[1])
148 operation = REVERT;
149 }
150
151 while (list)
152 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000153 sig = decode_signal (list->word->word, opt);
Jari Aalto726f6381996-08-26 18:22:31 +0000154
155 if (sig == NO_SIG)
156 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000157 sh_invalidsig (list->word->word);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000158 result = EXECUTION_FAILURE;
Jari Aalto726f6381996-08-26 18:22:31 +0000159 }
160 else
161 {
162 switch (operation)
163 {
164 case SET:
165 set_signal (sig, first_arg);
166 break;
167
168 case REVERT:
169 restore_default_signal (sig);
170
171 /* Signals that the shell treats specially need special
172 handling. */
173 switch (sig)
174 {
175 case SIGINT:
176 if (interactive)
177 set_signal_handler (SIGINT, sigint_sighandler);
178 else
179 set_signal_handler (SIGINT, termination_unwind_protect);
180 break;
181
182 case SIGQUIT:
183 /* Always ignore SIGQUIT. */
184 set_signal_handler (SIGQUIT, SIG_IGN);
185 break;
186 case SIGTERM:
187#if defined (JOB_CONTROL)
188 case SIGTTIN:
189 case SIGTTOU:
190 case SIGTSTP:
191#endif /* JOB_CONTROL */
192 if (interactive)
193 set_signal_handler (sig, SIG_IGN);
194 break;
195 }
196 break;
197
198 case IGNORE:
199 ignore_signal (sig);
200 break;
201 }
202 }
203 list = list->next;
204 }
Jari Aalto726f6381996-08-26 18:22:31 +0000205 }
206
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000207 return (result);
208}
209
210static void
211showtrap (i)
212 int i;
213{
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000214 char *t, *p, *sn;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000215
216 p = trap_list[i];
217
218 if (p == (char *)DEFAULT_SIG)
219 return;
220
Jari Aalto28ef6c32001-04-06 19:14:31 +0000221 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000222 sn = signal_name (i);
223 /* Make sure that signals whose names are unknown (for whatever reason)
224 are printed as signal numbers. */
225 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
226 printf ("trap -- %s %d\n", t ? t : "''", i);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000227 else if (posixly_correct)
228 {
229 if (STREQN (sn, "SIG", 3))
230 printf ("trap -- %s %s\n", t ? t : "''", sn+3);
231 else
232 printf ("trap -- %s %s\n", t ? t : "''", sn);
233 }
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000234 else
235 printf ("trap -- %s %s\n", t ? t : "''", sn);
236
237 FREE (t);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000238}
239
240static int
241display_traps (list)
242 WORD_LIST *list;
243{
244 int result, i;
245
246 if (list == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000247 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000248 for (i = 0; i < BASH_NSIG; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000249 showtrap (i);
250 return (EXECUTION_SUCCESS);
Jari Aalto726f6381996-08-26 18:22:31 +0000251 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000252
253 for (result = EXECUTION_SUCCESS; list; list = list->next)
254 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000255 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000256 if (i == NO_SIG)
257 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000258 sh_invalidsig (list->word->word);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000259 result = EXECUTION_FAILURE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000260 }
261 else
262 showtrap (i);
263 }
264
265 return (result);
Jari Aalto726f6381996-08-26 18:22:31 +0000266}