Imported from ../bash-2.05b.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-2002 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               sh_invalidsig (list->word->word);
141               result = EXECUTION_FAILURE;
142             }
143           else
144             {
145               switch (operation)
146                 {
147                   case SET:
148                     set_signal (sig, first_arg);
149                     break;
150
151                   case REVERT:
152                     restore_default_signal (sig);
153
154                     /* Signals that the shell treats specially need special
155                        handling. */
156                     switch (sig)
157                       {
158                       case SIGINT:
159                         if (interactive)
160                           set_signal_handler (SIGINT, sigint_sighandler);
161                         else
162                           set_signal_handler (SIGINT, termination_unwind_protect);
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
193 static void
194 showtrap (i)
195      int i;
196 {
197   char *t, *p, *sn;
198
199   p = trap_list[i];
200
201   if (p == (char *)DEFAULT_SIG)
202     return;
203
204   t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
205   sn = signal_name (i);
206   /* Make sure that signals whose names are unknown (for whatever reason)
207      are printed as signal numbers. */
208   if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
209     printf ("trap -- %s %d\n", t ? t : "''", i);
210   else if (posixly_correct)
211     {
212       if (STREQN (sn, "SIG", 3))
213         printf ("trap -- %s %s\n", t ? t : "''", sn+3);
214       else
215         printf ("trap -- %s %s\n", t ? t : "''", sn);
216     }
217   else
218     printf ("trap -- %s %s\n", t ? t : "''", sn);
219
220   FREE (t);
221 }
222
223 static int
224 display_traps (list)
225      WORD_LIST *list;
226 {
227   int result, i;
228
229   if (list == 0)
230     {
231       for (i = 0; i < BASH_NSIG; i++)
232         showtrap (i);
233       return (EXECUTION_SUCCESS);
234     }
235
236   for (result = EXECUTION_SUCCESS; list; list = list->next)
237     {
238       i = decode_signal (list->word->word);
239       if (i == NO_SIG)
240         {
241           sh_invalidsig (list->word->word);
242           result = EXECUTION_FAILURE;
243         }
244       else
245         showtrap (i);
246     }
247
248   return (result);
249 }