]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/trap.def
Imported from ../bash-3.2.tar.gz.
[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
0628567a 4Copyright (C) 1987-2006 Free Software Foundation, Inc.
726f6388
JA
5
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
bb70624e 10Software Foundation; either version 2, or (at your option) any later
726f6388
JA
11version.
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
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
726f6388
JA
21
22$PRODUCES trap.c
23
24$BUILTIN trap
25$FUNCTION trap_builtin
eb873671 26$SHORT_DOC trap [-lp] [arg signal_spec ...]
726f6388 27The command ARG is to be read and executed when the shell receives
b80f6443
JA
28signal(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 $$".
726f6388
JA
41$END
42
ccc6cda3
JA
43#include <config.h>
44
45#if defined (HAVE_UNISTD_H)
cce855bc
JA
46# ifdef _MINIX
47# include <sys/types.h>
48# endif
ccc6cda3
JA
49# include <unistd.h>
50#endif
51
52#include "../bashtypes.h"
726f6388 53#include <signal.h>
ccc6cda3
JA
54#include <stdio.h>
55#include "../bashansi.h"
56
726f6388
JA
57#include "../shell.h"
58#include "../trap.h"
59#include "common.h"
ccc6cda3
JA
60#include "bashgetopt.h"
61
f73dda09
JA
62static void showtrap __P((int));
63static int display_traps __P((WORD_LIST *));
726f6388
JA
64
65/* The trap command:
66
67 trap <arg> <signal ...>
68 trap <signal ...>
69 trap -l
ccc6cda3 70 trap -p [sigspec ...]
726f6388
JA
71 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
f73dda09 84extern int posixly_correct;
726f6388 85
ccc6cda3 86int
726f6388
JA
87trap_builtin (list)
88 WORD_LIST *list;
89{
0628567a 90 int list_signal_names, display, result, opt;
726f6388 91
ccc6cda3
JA
92 list_signal_names = display = 0;
93 result = EXECUTION_SUCCESS;
94 reset_internal_getopt ();
95 while ((opt = internal_getopt (list, "lp")) != -1)
726f6388 96 {
ccc6cda3 97 switch (opt)
726f6388 98 {
ccc6cda3 99 case 'l':
726f6388 100 list_signal_names++;
726f6388 101 break;
ccc6cda3
JA
102 case 'p':
103 display++;
104 break;
105 default:
106 builtin_usage ();
726f6388
JA
107 return (EX_USAGE);
108 }
726f6388 109 }
ccc6cda3 110 list = loptend;
726f6388 111
b80f6443
JA
112 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
113
726f6388 114 if (list_signal_names)
ccc6cda3
JA
115 return (display_signal_list ((WORD_LIST *)NULL, 1));
116 else if (display || list == 0)
117 return (display_traps (list));
118 else
726f6388 119 {
ccc6cda3 120 char *first_arg;
eb873671 121 int operation, sig, first_signal;
726f6388 122
ccc6cda3
JA
123 operation = SET;
124 first_arg = list->word->word;
eb873671
JA
125 first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
126
0628567a
JA
127 /* Backwards compatibility. XXX - question about whether or not we
128 should throw an error if an all-digit argument doesn't correspond
129 to a valid signal number (e.g., if it's `50' on a system with only
130 32 signals). */
eb873671
JA
131 if (first_signal)
132 operation = REVERT;
b80f6443
JA
133 /* When in posix mode, the historical behavior of looking for a
134 missing first argument is disabled. To revert to the original
135 signal handling disposition, use `-' as the first argument. */
eb873671 136 else if (posixly_correct == 0 && first_arg && *first_arg &&
b80f6443
JA
137 (*first_arg != '-' || first_arg[1]) &&
138 signal_object_p (first_arg, opt) && list->next == 0)
726f6388
JA
139 operation = REVERT;
140 else
141 {
142 list = list->next;
b80f6443
JA
143 if (list == 0)
144 {
145 builtin_usage ();
146 return (EX_USAGE);
147 }
148 else if (*first_arg == '\0')
726f6388
JA
149 operation = IGNORE;
150 else if (first_arg[0] == '-' && !first_arg[1])
151 operation = REVERT;
152 }
153
154 while (list)
155 {
b80f6443 156 sig = decode_signal (list->word->word, opt);
726f6388
JA
157
158 if (sig == NO_SIG)
159 {
7117c2d2 160 sh_invalidsig (list->word->word);
ccc6cda3 161 result = EXECUTION_FAILURE;
726f6388
JA
162 }
163 else
164 {
165 switch (operation)
166 {
167 case SET:
168 set_signal (sig, first_arg);
169 break;
170
171 case REVERT:
172 restore_default_signal (sig);
173
174 /* Signals that the shell treats specially need special
175 handling. */
176 switch (sig)
177 {
178 case SIGINT:
179 if (interactive)
180 set_signal_handler (SIGINT, sigint_sighandler);
181 else
0628567a 182 set_signal_handler (SIGINT, termsig_sighandler);
726f6388
JA
183 break;
184
185 case SIGQUIT:
186 /* Always ignore SIGQUIT. */
187 set_signal_handler (SIGQUIT, SIG_IGN);
188 break;
189 case SIGTERM:
190#if defined (JOB_CONTROL)
191 case SIGTTIN:
192 case SIGTTOU:
193 case SIGTSTP:
194#endif /* JOB_CONTROL */
195 if (interactive)
196 set_signal_handler (sig, SIG_IGN);
197 break;
198 }
199 break;
200
201 case IGNORE:
202 ignore_signal (sig);
203 break;
204 }
205 }
206 list = list->next;
207 }
726f6388
JA
208 }
209
ccc6cda3
JA
210 return (result);
211}
212
213static void
214showtrap (i)
215 int i;
216{
e8ce775d 217 char *t, *p, *sn;
ccc6cda3
JA
218
219 p = trap_list[i];
ccc6cda3
JA
220 if (p == (char *)DEFAULT_SIG)
221 return;
222
28ef6c31 223 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
e8ce775d
JA
224 sn = signal_name (i);
225 /* Make sure that signals whose names are unknown (for whatever reason)
226 are printed as signal numbers. */
227 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
228 printf ("trap -- %s %d\n", t ? t : "''", i);
28ef6c31
JA
229 else if (posixly_correct)
230 {
231 if (STREQN (sn, "SIG", 3))
232 printf ("trap -- %s %s\n", t ? t : "''", sn+3);
233 else
234 printf ("trap -- %s %s\n", t ? t : "''", sn);
235 }
e8ce775d
JA
236 else
237 printf ("trap -- %s %s\n", t ? t : "''", sn);
238
239 FREE (t);
ccc6cda3 240}
726f6388 241
ccc6cda3
JA
242static int
243display_traps (list)
244 WORD_LIST *list;
245{
246 int result, i;
726f6388 247
ccc6cda3
JA
248 if (list == 0)
249 {
f73dda09 250 for (i = 0; i < BASH_NSIG; i++)
ccc6cda3
JA
251 showtrap (i);
252 return (EXECUTION_SUCCESS);
253 }
726f6388 254
ccc6cda3
JA
255 for (result = EXECUTION_SUCCESS; list; list = list->next)
256 {
b80f6443 257 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
ccc6cda3
JA
258 if (i == NO_SIG)
259 {
7117c2d2 260 sh_invalidsig (list->word->word);
ccc6cda3 261 result = EXECUTION_FAILURE;
ccc6cda3
JA
262 }
263 else
264 showtrap (i);
726f6388 265 }
ccc6cda3
JA
266
267 return (result);
726f6388 268}