blob: 6008899d4245a5c64785b33cf73a3e2aa58b785d [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* trap.c, created from trap.def. */
2#line 22 "./trap.def"
3
4#line 58 "./trap.def"
5
6#include <config.h>
7
8#if defined (HAVE_UNISTD_H)
9# ifdef _MINIX
10# include <sys/types.h>
11# endif
12# include <unistd.h>
13#endif
14
15#include "../bashtypes.h"
16#include <signal.h>
17#include <stdio.h>
18#include "../bashansi.h"
19
20#include "../shell.h"
21#include "../trap.h"
22#include "common.h"
23#include "bashgetopt.h"
24
25static void showtrap __P((int));
26static int display_traps __P((WORD_LIST *));
27
28/* The trap command:
29
30 trap <arg> <signal ...>
31 trap <signal ...>
32 trap -l
33 trap -p [sigspec ...]
34 trap [--]
35
36 Set things up so that ARG is executed when SIGNAL(s) N is recieved.
37 If ARG is the empty string, then ignore the SIGNAL(s). If there is
38 no ARG, then set the trap for SIGNAL(s) to its original value. Just
39 plain "trap" means to print out the list of commands associated with
40 each signal number. Single arg of "-l" means list the signal names. */
41
42/* Possible operations to perform on the list of signals.*/
43#define SET 0 /* Set this signal to first_arg. */
44#define REVERT 1 /* Revert to this signals original value. */
45#define IGNORE 2 /* Ignore this signal. */
46
47extern int posixly_correct, subshell_environment;
48
49int
50trap_builtin (list)
51 WORD_LIST *list;
52{
53 int list_signal_names, display, result, opt;
54
55 list_signal_names = display = 0;
56 result = EXECUTION_SUCCESS;
57
58 reset_internal_getopt ();
59 while ((opt = internal_getopt (list, "lp")) != -1)
60 {
61 switch (opt)
62 {
63 case 'l':
64 list_signal_names++;
65 break;
66 case 'p':
67 display++;
68 break;
69 default:
70 builtin_usage ();
71 return (EX_USAGE);
72 }
73 }
74 list = loptend;
75
76 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
77
78 if (list_signal_names)
79 return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
80 else if (display || list == 0)
81 {
82 initialize_terminating_signals ();
83 get_all_original_signals ();
84 return (sh_chkwrite (display_traps (list)));
85 }
86 else
87 {
88 char *first_arg;
89 int operation, sig, first_signal;
90
91 operation = SET;
92 first_arg = list->word->word;
93 first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
94
95 /* Backwards compatibility. XXX - question about whether or not we
96 should throw an error if an all-digit argument doesn't correspond
97 to a valid signal number (e.g., if it's `50' on a system with only
98 32 signals). */
99 if (first_signal)
100 operation = REVERT;
101 /* When in posix mode, the historical behavior of looking for a
102 missing first argument is disabled. To revert to the original
103 signal handling disposition, use `-' as the first argument. */
104 else if (posixly_correct == 0 && first_arg && *first_arg &&
105 (*first_arg != '-' || first_arg[1]) &&
106 signal_object_p (first_arg, opt) && list->next == 0)
107 operation = REVERT;
108 else
109 {
110 list = list->next;
111 if (list == 0)
112 {
113 builtin_usage ();
114 return (EX_USAGE);
115 }
116 else if (*first_arg == '\0')
117 operation = IGNORE;
118 else if (first_arg[0] == '-' && !first_arg[1])
119 operation = REVERT;
120 }
121
122 /* If we're in a command substitution, we haven't freed the trap strings
123 (though we reset the signal handlers). If we're setting a trap to
124 handle a signal here, free the rest of the trap strings since they
125 don't apply any more. */
126 if (subshell_environment & SUBSHELL_RESETTRAP)
127 {
128 free_trap_strings ();
129 subshell_environment &= ~SUBSHELL_RESETTRAP;
130 }
131
132 while (list)
133 {
134 sig = decode_signal (list->word->word, opt);
135
136 if (sig == NO_SIG)
137 {
138 sh_invalidsig (list->word->word);
139 result = EXECUTION_FAILURE;
140 }
141 else
142 {
143 switch (operation)
144 {
145 case SET:
146 set_signal (sig, first_arg);
147 break;
148
149 case REVERT:
150 restore_default_signal (sig);
151
152 /* Signals that the shell treats specially need special
153 handling. */
154 switch (sig)
155 {
156 case SIGINT:
157 /* XXX - should we do this if original disposition
158 was SIG_IGN? */
159 if (interactive)
160 set_signal_handler (SIGINT, sigint_sighandler);
161 else
162 set_signal_handler (SIGINT, termsig_sighandler);
163 break;
164
165 case SIGQUIT:
166 /* Always ignore SIGQUIT. */
167 set_signal_handler (SIGQUIT, SIG_IGN);
168 break;
169 case SIGTERM:
170#if defined (JOB_CONTROL)
171 case SIGTTIN:
172 case SIGTTOU:
173 case SIGTSTP:
174#endif /* JOB_CONTROL */
175 if (interactive)
176 set_signal_handler (sig, SIG_IGN);
177 break;
178 }
179 break;
180
181 case IGNORE:
182 ignore_signal (sig);
183 break;
184 }
185 }
186 list = list->next;
187 }
188 }
189
190 return (result);
191}
192
193static void
194showtrap (i)
195 int i;
196{
197 char *t, *p, *sn;
198
199 p = trap_list[i];
200 if (p == (char *)DEFAULT_SIG && signal_is_hard_ignored (i) == 0)
201 return;
202 else if (signal_is_hard_ignored (i))
203 t = (char *)NULL;
204 else
205 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
206
207 sn = signal_name (i);
208 /* Make sure that signals whose names are unknown (for whatever reason)
209 are printed as signal numbers. */
210 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
211 printf ("trap -- %s %d\n", t ? t : "''", i);
212 else if (posixly_correct)
213 {
214 if (STREQN (sn, "SIG", 3))
215 printf ("trap -- %s %s\n", t ? t : "''", sn+3);
216 else
217 printf ("trap -- %s %s\n", t ? t : "''", sn);
218 }
219 else
220 printf ("trap -- %s %s\n", t ? t : "''", sn);
221
222 FREE (t);
223}
224
225static int
226display_traps (list)
227 WORD_LIST *list;
228{
229 int result, i;
230
231 if (list == 0)
232 {
233 for (i = 0; i < BASH_NSIG; i++)
234 showtrap (i);
235 return (EXECUTION_SUCCESS);
236 }
237
238 for (result = EXECUTION_SUCCESS; list; list = list->next)
239 {
240 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
241 if (i == NO_SIG)
242 {
243 sh_invalidsig (list->word->word);
244 result = EXECUTION_FAILURE;
245 }
246 else
247 showtrap (i);
248 }
249
250 return (result);
251}