933bd25a421cd7af77c71431ecc535ecb0af0ee6
[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 2, 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, 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 [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 #  ifdef _MINIX
46 #    include <sys/types.h>
47 #  endif
48 #  include <unistd.h>
49 #endif
50
51 #include "../bashtypes.h"
52 #include <signal.h>
53 #include <stdio.h>
54 #include "../bashansi.h"
55
56 #include "../shell.h"
57 #include "../trap.h"
58 #include "common.h"
59 #include "bashgetopt.h"
60
61 static void showtrap __P((int));
62 static int display_traps __P((WORD_LIST *));
63
64 /* The trap command:
65
66    trap <arg> <signal ...>
67    trap <signal ...>
68    trap -l
69    trap -p [sigspec ...]
70    trap [--]
71
72    Set things up so that ARG is executed when SIGNAL(s) N is recieved.
73    If ARG is the empty string, then ignore the SIGNAL(s).  If there is
74    no ARG, then set the trap for SIGNAL(s) to its original value.  Just
75    plain "trap" means to print out the list of commands associated with
76    each signal number.  Single arg of "-l" means list the signal names. */
77
78 /* Possible operations to perform on the list of signals.*/
79 #define SET 0                   /* Set this signal to first_arg. */
80 #define REVERT 1                /* Revert to this signals original value. */
81 #define IGNORE 2                /* Ignore this signal. */
82
83 extern int posixly_correct;
84
85 int
86 trap_builtin (list)
87      WORD_LIST *list;
88 {
89   int list_signal_names, display, result, opt;
90
91   list_signal_names = display = 0;
92   result = EXECUTION_SUCCESS;
93   reset_internal_getopt ();
94   while ((opt = internal_getopt (list, "lp")) != -1)
95     {
96       switch (opt)
97         {
98         case 'l':
99           list_signal_names++;
100           break;
101         case 'p':
102           display++;
103           break;
104         default:
105           builtin_usage ();
106           return (EX_USAGE);
107         }
108     }
109   list = loptend;
110
111   if (list_signal_names)
112     return (display_signal_list ((WORD_LIST *)NULL, 1));
113   else if (display || list == 0)
114     return (display_traps (list));
115   else
116     {
117       char *first_arg;
118       int operation, sig;
119
120       operation = SET;
121       first_arg = list->word->word;
122       if (first_arg && *first_arg && (*first_arg != '-' || first_arg[1]) &&
123                 signal_object_p (first_arg))
124         operation = REVERT;
125       else
126         {
127           list = list->next;
128           if (*first_arg == '\0')
129             operation = IGNORE;
130           else if (first_arg[0] == '-' && !first_arg[1])
131             operation = REVERT;
132         }
133
134       while (list)
135         {
136           sig = decode_signal (list->word->word);
137
138           if (sig == NO_SIG)
139             {
140               builtin_error ("%s: not a signal specification",
141                              list->word->word);
142               result = EXECUTION_FAILURE;
143             }
144           else
145             {
146               switch (operation)
147                 {
148                   case SET:
149                     set_signal (sig, first_arg);
150                     break;
151
152                   case REVERT:
153                     restore_default_signal (sig);
154
155                     /* Signals that the shell treats specially need special
156                        handling. */
157                     switch (sig)
158                       {
159                       case SIGINT:
160                         if (interactive)
161                           set_signal_handler (SIGINT, sigint_sighandler);
162                         else
163                           set_signal_handler (SIGINT, termination_unwind_protect);
164                         break;
165
166                       case SIGQUIT:
167                         /* Always ignore SIGQUIT. */
168                         set_signal_handler (SIGQUIT, SIG_IGN);
169                         break;
170                       case SIGTERM:
171 #if defined (JOB_CONTROL)
172                       case SIGTTIN:
173                       case SIGTTOU:
174                       case SIGTSTP:
175 #endif /* JOB_CONTROL */
176                         if (interactive)
177                           set_signal_handler (sig, SIG_IGN);
178                         break;
179                       }
180                     break;
181
182                   case IGNORE:
183                     ignore_signal (sig);
184                     break;
185                 }
186             }
187           list = list->next;
188         }
189     }
190
191   return (result);
192 }
193
194 static void
195 showtrap (i)
196      int i;
197 {
198   char *t, *p, *sn;
199
200   p = trap_list[i];
201
202   if (p == (char *)DEFAULT_SIG)
203     return;
204
205   t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
206   sn = signal_name (i);
207   /* Make sure that signals whose names are unknown (for whatever reason)
208      are printed as signal numbers. */
209   if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
210     printf ("trap -- %s %d\n", t ? t : "''", i);
211   else if (posixly_correct)
212     {
213       if (STREQN (sn, "SIG", 3))
214         printf ("trap -- %s %s\n", t ? t : "''", sn+3);
215       else
216         printf ("trap -- %s %s\n", t ? t : "''", sn);
217     }
218   else
219     printf ("trap -- %s %s\n", t ? t : "''", sn);
220
221   FREE (t);
222 }
223
224 static int
225 display_traps (list)
226      WORD_LIST *list;
227 {
228   int result, i;
229
230   if (list == 0)
231     {
232       for (i = 0; i < BASH_NSIG; i++)
233         showtrap (i);
234       return (EXECUTION_SUCCESS);
235     }
236
237   for (result = EXECUTION_SUCCESS; list; list = list->next)
238     {
239       i = decode_signal (list->word->word);
240       if (i == NO_SIG)
241         {
242           result = EXECUTION_FAILURE;
243           builtin_error ("%s: not a signal specification", list->word->word);
244         }
245       else
246         showtrap (i);
247     }
248
249   return (result);
250 }