source: vendor/bash/3.1/builtins/trap.def

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 6.8 KB
Line 
1This file is trap.def, from which is created trap.c.
2It implements the builtin "trap" in Bash.
3
4Copyright (C) 1987-2005 Free Software Foundation, Inc.
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
10Software Foundation; either version 2, or (at your option) any later
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
20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22$PRODUCES trap.c
23
24$BUILTIN trap
25$FUNCTION trap_builtin
26$SHORT_DOC trap [-lp] [arg signal_spec ...]
27The command ARG is to be read and executed when the shell receives
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 $$".
41$END
42
43#include <config.h>
44
45#if defined (HAVE_UNISTD_H)
46# ifdef _MINIX
47# include <sys/types.h>
48# endif
49# include <unistd.h>
50#endif
51
52#include "../bashtypes.h"
53#include <signal.h>
54#include <stdio.h>
55#include "../bashansi.h"
56
57#include "../shell.h"
58#include "../trap.h"
59#include "common.h"
60#include "bashgetopt.h"
61
62static void showtrap __P((int));
63static int display_traps __P((WORD_LIST *));
64
65/* The trap command:
66
67 trap <arg> <signal ...>
68 trap <signal ...>
69 trap -l
70 trap -p [sigspec ...]
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
84extern int posixly_correct;
85
86int
87trap_builtin (list)
88 WORD_LIST *list;
89{
90 int list_signal_names, display, result, opt, first_signal;
91
92 list_signal_names = display = 0;
93 result = EXECUTION_SUCCESS;
94 reset_internal_getopt ();
95 while ((opt = internal_getopt (list, "lp")) != -1)
96 {
97 switch (opt)
98 {
99 case 'l':
100 list_signal_names++;
101 break;
102 case 'p':
103 display++;
104 break;
105 default:
106 builtin_usage ();
107 return (EX_USAGE);
108 }
109 }
110 list = loptend;
111
112 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
113
114 if (list_signal_names)
115 return (display_signal_list ((WORD_LIST *)NULL, 1));
116 else if (display || list == 0)
117 return (display_traps (list));
118 else
119 {
120 char *first_arg;
121 int operation, sig, first_signal;
122
123 operation = SET;
124 first_arg = list->word->word;
125 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;
130 /* 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. */
133 else if (posixly_correct == 0 && first_arg && *first_arg &&
134 (*first_arg != '-' || first_arg[1]) &&
135 signal_object_p (first_arg, opt) && list->next == 0)
136 operation = REVERT;
137 else
138 {
139 list = list->next;
140 if (list == 0)
141 {
142 builtin_usage ();
143 return (EX_USAGE);
144 }
145 else if (*first_arg == '\0')
146 operation = IGNORE;
147 else if (first_arg[0] == '-' && !first_arg[1])
148 operation = REVERT;
149 }
150
151 while (list)
152 {
153 sig = decode_signal (list->word->word, opt);
154
155 if (sig == NO_SIG)
156 {
157 sh_invalidsig (list->word->word);
158 result = EXECUTION_FAILURE;
159 }
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 }
205 }
206
207 return (result);
208}
209
210static void
211showtrap (i)
212 int i;
213{
214 char *t, *p, *sn;
215
216 p = trap_list[i];
217 if (p == (char *)DEFAULT_SIG)
218 return;
219
220 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
221 sn = signal_name (i);
222 /* Make sure that signals whose names are unknown (for whatever reason)
223 are printed as signal numbers. */
224 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
225 printf ("trap -- %s %d\n", t ? t : "''", i);
226 else if (posixly_correct)
227 {
228 if (STREQN (sn, "SIG", 3))
229 printf ("trap -- %s %s\n", t ? t : "''", sn+3);
230 else
231 printf ("trap -- %s %s\n", t ? t : "''", sn);
232 }
233 else
234 printf ("trap -- %s %s\n", t ? t : "''", sn);
235
236 FREE (t);
237}
238
239static int
240display_traps (list)
241 WORD_LIST *list;
242{
243 int result, i;
244
245 if (list == 0)
246 {
247 for (i = 0; i < BASH_NSIG; i++)
248 showtrap (i);
249 return (EXECUTION_SUCCESS);
250 }
251
252 for (result = EXECUTION_SUCCESS; list; list = list->next)
253 {
254 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
255 if (i == NO_SIG)
256 {
257 sh_invalidsig (list->word->word);
258 result = EXECUTION_FAILURE;
259 }
260 else
261 showtrap (i);
262 }
263
264 return (result);
265}
Note: See TracBrowser for help on using the repository browser.