blob: f6a8ee483e1fb80ccaa2d2c0097c107d73d5ac54 [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
4Copyright (C) 1987, 1989, 1991 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22$PRODUCES trap.c
23
24$BUILTIN trap
25$FUNCTION trap_builtin
Jari Aaltoccc6cda1996-12-23 17:02:34 +000026$SHORT_DOC trap [arg] [signal_spec] or trap -l
Jari Aalto726f6381996-08-26 18:22:31 +000027The command ARG is to be read and executed when the shell receives
28signal(s) SIGNAL_SPEC. If ARG is absent all specified signals are
Jari Aaltoccc6cda1996-12-23 17:02:34 +000029reset to their original values. If ARG is the null string each
30SIGNAL_SPEC is ignored by the shell and by the commands it invokes.
31If SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
32the shell. If SIGNAL_SPEC is DEBUG, ARG is executed after every
33command. If ARG is `-p' then the trap commands associated with
34each SIGNAL_SPEC are displayed. If no arguments are supplied or if
35only `-p' is given, trap prints the list of commands associated with
36each signal number. SIGNAL_SPEC is either a signal name in <signal.h>
37or a signal number. `trap -l' prints a list of signal names and their
38corresponding numbers. Note that a signal can be sent to the shell
39with "kill -signal $$".
Jari Aalto726f6381996-08-26 18:22:31 +000040$END
41
Jari Aaltoccc6cda1996-12-23 17:02:34 +000042#include <config.h>
43
44#if defined (HAVE_UNISTD_H)
45# include <unistd.h>
46#endif
47
48#include "../bashtypes.h"
Jari Aalto726f6381996-08-26 18:22:31 +000049#include <signal.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000050#include <stdio.h>
51#include "../bashansi.h"
52
Jari Aalto726f6381996-08-26 18:22:31 +000053#include "../shell.h"
54#include "../trap.h"
55#include "common.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000056#include "bashgetopt.h"
57
58static int display_traps ();
Jari Aalto726f6381996-08-26 18:22:31 +000059
60/* The trap command:
61
62 trap <arg> <signal ...>
63 trap <signal ...>
64 trap -l
Jari Aaltoccc6cda1996-12-23 17:02:34 +000065 trap -p [sigspec ...]
Jari Aalto726f6381996-08-26 18:22:31 +000066 trap [--]
67
68 Set things up so that ARG is executed when SIGNAL(s) N is recieved.
69 If ARG is the empty string, then ignore the SIGNAL(s). If there is
70 no ARG, then set the trap for SIGNAL(s) to its original value. Just
71 plain "trap" means to print out the list of commands associated with
72 each signal number. Single arg of "-l" means list the signal names. */
73
74/* Possible operations to perform on the list of signals.*/
75#define SET 0 /* Set this signal to first_arg. */
76#define REVERT 1 /* Revert to this signals original value. */
77#define IGNORE 2 /* Ignore this signal. */
78
79extern int interactive;
80
Jari Aaltoccc6cda1996-12-23 17:02:34 +000081int
Jari Aalto726f6381996-08-26 18:22:31 +000082trap_builtin (list)
83 WORD_LIST *list;
84{
Jari Aaltoccc6cda1996-12-23 17:02:34 +000085 int list_signal_names, display, result, opt;
Jari Aalto726f6381996-08-26 18:22:31 +000086
Jari Aaltoccc6cda1996-12-23 17:02:34 +000087 list_signal_names = display = 0;
88 result = EXECUTION_SUCCESS;
89 reset_internal_getopt ();
90 while ((opt = internal_getopt (list, "lp")) != -1)
Jari Aalto726f6381996-08-26 18:22:31 +000091 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +000092 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +000093 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +000094 case 'l':
Jari Aalto726f6381996-08-26 18:22:31 +000095 list_signal_names++;
Jari Aalto726f6381996-08-26 18:22:31 +000096 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000097 case 'p':
98 display++;
99 break;
100 default:
101 builtin_usage ();
Jari Aalto726f6381996-08-26 18:22:31 +0000102 return (EX_USAGE);
103 }
Jari Aalto726f6381996-08-26 18:22:31 +0000104 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000105 list = loptend;
Jari Aalto726f6381996-08-26 18:22:31 +0000106
107 if (list_signal_names)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000108 return (display_signal_list ((WORD_LIST *)NULL, 1));
109 else if (display || list == 0)
110 return (display_traps (list));
111 else
Jari Aalto726f6381996-08-26 18:22:31 +0000112 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000113 char *first_arg;
114 int operation, sig;
Jari Aalto726f6381996-08-26 18:22:31 +0000115
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000116 operation = SET;
117 first_arg = list->word->word;
118 if (first_arg && *first_arg && signal_object_p (first_arg))
Jari Aalto726f6381996-08-26 18:22:31 +0000119 operation = REVERT;
120 else
121 {
122 list = list->next;
123 if (*first_arg == '\0')
124 operation = IGNORE;
125 else if (first_arg[0] == '-' && !first_arg[1])
126 operation = REVERT;
127 }
128
129 while (list)
130 {
Jari Aalto726f6381996-08-26 18:22:31 +0000131 sig = decode_signal (list->word->word);
132
133 if (sig == NO_SIG)
134 {
135 builtin_error ("%s: not a signal specification",
136 list->word->word);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000137 result = EXECUTION_FAILURE;
Jari Aalto726f6381996-08-26 18:22:31 +0000138 }
139 else
140 {
141 switch (operation)
142 {
143 case SET:
144 set_signal (sig, first_arg);
145 break;
146
147 case REVERT:
148 restore_default_signal (sig);
149
150 /* Signals that the shell treats specially need special
151 handling. */
152 switch (sig)
153 {
154 case SIGINT:
155 if (interactive)
156 set_signal_handler (SIGINT, sigint_sighandler);
157 else
158 set_signal_handler (SIGINT, termination_unwind_protect);
159 break;
160
161 case SIGQUIT:
162 /* Always ignore SIGQUIT. */
163 set_signal_handler (SIGQUIT, SIG_IGN);
164 break;
165 case SIGTERM:
166#if defined (JOB_CONTROL)
167 case SIGTTIN:
168 case SIGTTOU:
169 case SIGTSTP:
170#endif /* JOB_CONTROL */
171 if (interactive)
172 set_signal_handler (sig, SIG_IGN);
173 break;
174 }
175 break;
176
177 case IGNORE:
178 ignore_signal (sig);
179 break;
180 }
181 }
182 list = list->next;
183 }
Jari Aalto726f6381996-08-26 18:22:31 +0000184 }
185
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000186 return (result);
187}
188
189static void
190showtrap (i)
191 int i;
192{
193 char *t, *p;
194
195 p = trap_list[i];
196
197 if (p == (char *)DEFAULT_SIG)
198 return;
199
200 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
201 printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
202 if (t)
203 free (t);
204}
205
206static int
207display_traps (list)
208 WORD_LIST *list;
209{
210 int result, i;
211
212 if (list == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000213 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000214 for (i = 0; i <= NSIG; i++)
215 showtrap (i);
216 return (EXECUTION_SUCCESS);
Jari Aalto726f6381996-08-26 18:22:31 +0000217 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000218
219 for (result = EXECUTION_SUCCESS; list; list = list->next)
220 {
221 i = decode_signal (list->word->word);
222 if (i == NO_SIG)
223 {
224 result = EXECUTION_FAILURE;
225 builtin_error ("%s: not a signal specification", list->word->word);
226 }
227 else
228 showtrap (i);
229 }
230
231 return (result);
Jari Aalto726f6381996-08-26 18:22:31 +0000232}