2d5daca7c60c290a57503e62efedb77bde4b4ae0
[platform/upstream/bash.git] / builtins / trap.def
1 This file is trap.def, from which is created trap.c.
2 It implements the builtin "trap" in Bash.
3
4 Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING.  If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES trap.c
23
24 $BUILTIN trap
25 $FUNCTION trap_builtin
26 $SHORT_DOC trap [arg] [signal_spec ...] or trap -l
27 The command ARG is to be read and executed when the shell receives
28 signal(s) SIGNAL_SPEC.  If ARG is absent all specified signals are
29 reset to their original values.  If ARG is the null string each
30 SIGNAL_SPEC is ignored by the shell and by the commands it invokes.
31 If a SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
32 the shell.  If a SIGNAL_SPEC is DEBUG, ARG is executed after every
33 command.  If ARG is `-p' then the trap commands associated with
34 each SIGNAL_SPEC are displayed.  If no arguments are supplied or if
35 only `-p' is given, trap prints the list of commands associated with
36 each signal number.  Each SIGNAL_SPEC is either a signal name in <signal.h>
37 or a signal number.  `trap -l' prints a list of signal names and their
38 corresponding numbers.  Note that a signal can be sent to the shell
39 with "kill -signal $$".
40 $END
41
42 #include <config.h>
43
44 #if defined (HAVE_UNISTD_H)
45 #  include <unistd.h>
46 #endif
47
48 #include "../bashtypes.h"
49 #include <signal.h>
50 #include <stdio.h>
51 #include "../bashansi.h"
52
53 #include "../shell.h"
54 #include "../trap.h"
55 #include "common.h"
56 #include "bashgetopt.h"
57
58 static int display_traps ();
59
60 /* The trap command:
61
62    trap <arg> <signal ...>
63    trap <signal ...>
64    trap -l
65    trap -p [sigspec ...]
66    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
79 extern int interactive;
80
81 int
82 trap_builtin (list)
83      WORD_LIST *list;
84 {
85   int list_signal_names, display, result, opt;
86
87   list_signal_names = display = 0;
88   result = EXECUTION_SUCCESS;
89   reset_internal_getopt ();
90   while ((opt = internal_getopt (list, "lp")) != -1)
91     {
92       switch (opt)
93         {
94         case 'l':
95           list_signal_names++;
96           break;
97         case 'p':
98           display++;
99           break;
100         default:
101           builtin_usage ();
102           return (EX_USAGE);
103         }
104     }
105   list = loptend;
106
107   if (list_signal_names)
108     return (display_signal_list ((WORD_LIST *)NULL, 1));
109   else if (display || list == 0)
110     return (display_traps (list));
111   else
112     {
113       char *first_arg;
114       int operation, sig;
115
116       operation = SET;
117       first_arg = list->word->word;
118       if (first_arg && *first_arg && (*first_arg != '-' || first_arg[1]) &&
119                 signal_object_p (first_arg))
120         operation = REVERT;
121       else
122         {
123           list = list->next;
124           if (*first_arg == '\0')
125             operation = IGNORE;
126           else if (first_arg[0] == '-' && !first_arg[1])
127             operation = REVERT;
128         }
129
130       while (list)
131         {
132           sig = decode_signal (list->word->word);
133
134           if (sig == NO_SIG)
135             {
136               builtin_error ("%s: not a signal specification",
137                              list->word->word);
138               result = EXECUTION_FAILURE;
139             }
140           else
141             {
142               switch (operation)
143                 {
144                   case SET:
145                     set_signal (sig, first_arg);
146                     break;
147
148                   case REVERT:
149                     restore_default_signal (sig);
150
151                     /* Signals that the shell treats specially need special
152                        handling. */
153                     switch (sig)
154                       {
155                       case SIGINT:
156                         if (interactive)
157                           set_signal_handler (SIGINT, sigint_sighandler);
158                         else
159                           set_signal_handler (SIGINT, termination_unwind_protect);
160                         break;
161
162                       case SIGQUIT:
163                         /* Always ignore SIGQUIT. */
164                         set_signal_handler (SIGQUIT, SIG_IGN);
165                         break;
166                       case SIGTERM:
167 #if defined (JOB_CONTROL)
168                       case SIGTTIN:
169                       case SIGTTOU:
170                       case SIGTSTP:
171 #endif /* JOB_CONTROL */
172                         if (interactive)
173                           set_signal_handler (sig, SIG_IGN);
174                         break;
175                       }
176                     break;
177
178                   case IGNORE:
179                     ignore_signal (sig);
180                     break;
181                 }
182             }
183           list = list->next;
184         }
185     }
186
187   return (result);
188 }
189
190 static void
191 showtrap (i)
192      int i;
193 {
194   char *t, *p;
195
196   p = trap_list[i];
197
198   if (p == (char *)DEFAULT_SIG)
199     return;
200
201   t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
202   printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
203   if (t)
204     free (t);
205 }
206
207 static int
208 display_traps (list)
209      WORD_LIST *list;
210 {
211   int result, i;
212
213   if (list == 0)
214     {
215       for (i = 0; i <= NSIG; i++)
216         showtrap (i);
217       return (EXECUTION_SUCCESS);
218     }
219
220   for (result = EXECUTION_SUCCESS; list; list = list->next)
221     {
222       i = decode_signal (list->word->word);
223       if (i == NO_SIG)
224         {
225           result = EXECUTION_FAILURE;
226           builtin_error ("%s: not a signal specification", list->word->word);
227         }
228       else
229         showtrap (i);
230     }
231
232   return (result);
233 }