Imported from ../bash-2.0.tar.gz.
[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 SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
32 the shell.  If 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.  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 && signal_object_p (first_arg))
119         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         {
131           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);
137               result = EXECUTION_FAILURE;
138             }
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         }
184     }
185
186   return (result);
187 }
188
189 static void
190 showtrap (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
206 static int
207 display_traps (list)
208      WORD_LIST *list;
209 {
210   int result, i;
211
212   if (list == 0)
213     {
214       for (i = 0; i <= NSIG; i++)
215         showtrap (i);
216       return (EXECUTION_SUCCESS);
217     }
218
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);
232 }