Imported from ../bash-2.05.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 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 int display_traps ();
62
63 /* The trap command:
64
65    trap <arg> <signal ...>
66    trap <signal ...>
67    trap -l
68    trap -p [sigspec ...]
69    trap [--]
70
71    Set things up so that ARG is executed when SIGNAL(s) N is recieved.
72    If ARG is the empty string, then ignore the SIGNAL(s).  If there is
73    no ARG, then set the trap for SIGNAL(s) to its original value.  Just
74    plain "trap" means to print out the list of commands associated with
75    each signal number.  Single arg of "-l" means list the signal names. */
76
77 /* Possible operations to perform on the list of signals.*/
78 #define SET 0                   /* Set this signal to first_arg. */
79 #define REVERT 1                /* Revert to this signals original value. */
80 #define IGNORE 2                /* Ignore this signal. */
81
82 extern int interactive, posixly_correct;
83
84 int
85 trap_builtin (list)
86      WORD_LIST *list;
87 {
88   int list_signal_names, display, result, opt;
89
90   list_signal_names = display = 0;
91   result = EXECUTION_SUCCESS;
92   reset_internal_getopt ();
93   while ((opt = internal_getopt (list, "lp")) != -1)
94     {
95       switch (opt)
96         {
97         case 'l':
98           list_signal_names++;
99           break;
100         case 'p':
101           display++;
102           break;
103         default:
104           builtin_usage ();
105           return (EX_USAGE);
106         }
107     }
108   list = loptend;
109
110   if (list_signal_names)
111     return (display_signal_list ((WORD_LIST *)NULL, 1));
112   else if (display || list == 0)
113     return (display_traps (list));
114   else
115     {
116       char *first_arg;
117       int operation, sig;
118
119       operation = SET;
120       first_arg = list->word->word;
121       if (first_arg && *first_arg && (*first_arg != '-' || first_arg[1]) &&
122                 signal_object_p (first_arg))
123         operation = REVERT;
124       else
125         {
126           list = list->next;
127           if (*first_arg == '\0')
128             operation = IGNORE;
129           else if (first_arg[0] == '-' && !first_arg[1])
130             operation = REVERT;
131         }
132
133       while (list)
134         {
135           sig = decode_signal (list->word->word);
136
137           if (sig == NO_SIG)
138             {
139               builtin_error ("%s: not a signal specification",
140                              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 <= 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           result = EXECUTION_FAILURE;
242           builtin_error ("%s: not a signal specification", list->word->word);
243         }
244       else
245         showtrap (i);
246     }
247
248   return (result);
249 }