| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 1 | This file is trap.def, from which is created trap.c. |
| 2 | It implements the builtin "trap" in Bash. |
| 3 | |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 4 | Copyright (C) 1987-2004 Free Software Foundation, Inc. |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 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 |
| Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 10 | Software Foundation; either version 2, or (at your option) any later |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 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 |
| Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 21 | |
| 22 | $PRODUCES trap.c |
| 23 | |
| 24 | $BUILTIN trap |
| 25 | $FUNCTION trap_builtin |
| Jari Aalto | eb87367 | 2004-11-09 21:37:25 +0000 | [diff] [blame^] | 26 | $SHORT_DOC trap [-lp] [arg signal_spec ...] |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 27 | The command ARG is to be read and executed when the shell receives |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 28 | signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC |
| 29 | is supplied) or `-', each specified signal is reset to its original |
| 30 | value. If ARG is the null string each SIGNAL_SPEC is ignored by the |
| 31 | shell and by the commands it invokes. If a SIGNAL_SPEC is EXIT (0) |
| 32 | the command ARG is executed on exit from the shell. If a SIGNAL_SPEC |
| 33 | is DEBUG, ARG is executed after every simple command. If the`-p' option |
| 34 | is supplied then the trap commands associated with each SIGNAL_SPEC are |
| 35 | displayed. If no arguments are supplied or if only `-p' is given, trap |
| 36 | prints the list of commands associated with each signal. Each SIGNAL_SPEC |
| 37 | is either a signal name in <signal.h> or a signal number. Signal names |
| 38 | are case insensitive and the SIG prefix is optional. `trap -l' prints |
| 39 | a list of signal names and their corresponding numbers. Note that a |
| 40 | signal can be sent to the shell with "kill -signal $$". |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 41 | $END |
| 42 | |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 43 | #include <config.h> |
| 44 | |
| 45 | #if defined (HAVE_UNISTD_H) |
| Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 46 | # ifdef _MINIX |
| 47 | # include <sys/types.h> |
| 48 | # endif |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 49 | # include <unistd.h> |
| 50 | #endif |
| 51 | |
| 52 | #include "../bashtypes.h" |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 53 | #include <signal.h> |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 54 | #include <stdio.h> |
| 55 | #include "../bashansi.h" |
| 56 | |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 57 | #include "../shell.h" |
| 58 | #include "../trap.h" |
| 59 | #include "common.h" |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 60 | #include "bashgetopt.h" |
| 61 | |
| Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 62 | static void showtrap __P((int)); |
| 63 | static int display_traps __P((WORD_LIST *)); |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 64 | |
| 65 | /* The trap command: |
| 66 | |
| 67 | trap <arg> <signal ...> |
| 68 | trap <signal ...> |
| 69 | trap -l |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 70 | trap -p [sigspec ...] |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 71 | trap [--] |
| 72 | |
| 73 | Set things up so that ARG is executed when SIGNAL(s) N is recieved. |
| 74 | If ARG is the empty string, then ignore the SIGNAL(s). If there is |
| 75 | no ARG, then set the trap for SIGNAL(s) to its original value. Just |
| 76 | plain "trap" means to print out the list of commands associated with |
| 77 | each signal number. Single arg of "-l" means list the signal names. */ |
| 78 | |
| 79 | /* Possible operations to perform on the list of signals.*/ |
| 80 | #define SET 0 /* Set this signal to first_arg. */ |
| 81 | #define REVERT 1 /* Revert to this signals original value. */ |
| 82 | #define IGNORE 2 /* Ignore this signal. */ |
| 83 | |
| Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 84 | extern int posixly_correct; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 85 | |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 86 | int |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 87 | trap_builtin (list) |
| 88 | WORD_LIST *list; |
| 89 | { |
| Jari Aalto | eb87367 | 2004-11-09 21:37:25 +0000 | [diff] [blame^] | 90 | int list_signal_names, display, result, opt, first_signal; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 91 | |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 92 | list_signal_names = display = 0; |
| 93 | result = EXECUTION_SUCCESS; |
| 94 | reset_internal_getopt (); |
| 95 | while ((opt = internal_getopt (list, "lp")) != -1) |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 96 | { |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 97 | switch (opt) |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 98 | { |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 99 | case 'l': |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 100 | list_signal_names++; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 101 | break; |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 102 | case 'p': |
| 103 | display++; |
| 104 | break; |
| 105 | default: |
| 106 | builtin_usage (); |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 107 | return (EX_USAGE); |
| 108 | } |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 109 | } |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 110 | list = loptend; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 111 | |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 112 | opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */ |
| 113 | |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 114 | if (list_signal_names) |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 115 | return (display_signal_list ((WORD_LIST *)NULL, 1)); |
| 116 | else if (display || list == 0) |
| 117 | return (display_traps (list)); |
| 118 | else |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 119 | { |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 120 | char *first_arg; |
| Jari Aalto | eb87367 | 2004-11-09 21:37:25 +0000 | [diff] [blame^] | 121 | int operation, sig, first_signal; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 122 | |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 123 | operation = SET; |
| 124 | first_arg = list->word->word; |
| Jari Aalto | eb87367 | 2004-11-09 21:37:25 +0000 | [diff] [blame^] | 125 | first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt); |
| 126 | |
| 127 | /* Backwards compatibility */ |
| 128 | if (first_signal) |
| 129 | operation = REVERT; |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 130 | /* When in posix mode, the historical behavior of looking for a |
| 131 | missing first argument is disabled. To revert to the original |
| 132 | signal handling disposition, use `-' as the first argument. */ |
| Jari Aalto | eb87367 | 2004-11-09 21:37:25 +0000 | [diff] [blame^] | 133 | else if (posixly_correct == 0 && first_arg && *first_arg && |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 134 | (*first_arg != '-' || first_arg[1]) && |
| 135 | signal_object_p (first_arg, opt) && list->next == 0) |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 136 | operation = REVERT; |
| 137 | else |
| 138 | { |
| 139 | list = list->next; |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 140 | if (list == 0) |
| 141 | { |
| 142 | builtin_usage (); |
| 143 | return (EX_USAGE); |
| 144 | } |
| 145 | else if (*first_arg == '\0') |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 146 | operation = IGNORE; |
| 147 | else if (first_arg[0] == '-' && !first_arg[1]) |
| 148 | operation = REVERT; |
| 149 | } |
| 150 | |
| 151 | while (list) |
| 152 | { |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 153 | sig = decode_signal (list->word->word, opt); |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 154 | |
| 155 | if (sig == NO_SIG) |
| 156 | { |
| Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 157 | sh_invalidsig (list->word->word); |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 158 | result = EXECUTION_FAILURE; |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 159 | } |
| 160 | else |
| 161 | { |
| 162 | switch (operation) |
| 163 | { |
| 164 | case SET: |
| 165 | set_signal (sig, first_arg); |
| 166 | break; |
| 167 | |
| 168 | case REVERT: |
| 169 | restore_default_signal (sig); |
| 170 | |
| 171 | /* Signals that the shell treats specially need special |
| 172 | handling. */ |
| 173 | switch (sig) |
| 174 | { |
| 175 | case SIGINT: |
| 176 | if (interactive) |
| 177 | set_signal_handler (SIGINT, sigint_sighandler); |
| 178 | else |
| 179 | set_signal_handler (SIGINT, termination_unwind_protect); |
| 180 | break; |
| 181 | |
| 182 | case SIGQUIT: |
| 183 | /* Always ignore SIGQUIT. */ |
| 184 | set_signal_handler (SIGQUIT, SIG_IGN); |
| 185 | break; |
| 186 | case SIGTERM: |
| 187 | #if defined (JOB_CONTROL) |
| 188 | case SIGTTIN: |
| 189 | case SIGTTOU: |
| 190 | case SIGTSTP: |
| 191 | #endif /* JOB_CONTROL */ |
| 192 | if (interactive) |
| 193 | set_signal_handler (sig, SIG_IGN); |
| 194 | break; |
| 195 | } |
| 196 | break; |
| 197 | |
| 198 | case IGNORE: |
| 199 | ignore_signal (sig); |
| 200 | break; |
| 201 | } |
| 202 | } |
| 203 | list = list->next; |
| 204 | } |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 205 | } |
| 206 | |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 207 | return (result); |
| 208 | } |
| 209 | |
| 210 | static void |
| 211 | showtrap (i) |
| 212 | int i; |
| 213 | { |
| Jari Aalto | e8ce775 | 1997-09-22 20:22:27 +0000 | [diff] [blame] | 214 | char *t, *p, *sn; |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 215 | |
| 216 | p = trap_list[i]; |
| 217 | |
| 218 | if (p == (char *)DEFAULT_SIG) |
| 219 | return; |
| 220 | |
| Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 221 | t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p); |
| Jari Aalto | e8ce775 | 1997-09-22 20:22:27 +0000 | [diff] [blame] | 222 | sn = signal_name (i); |
| 223 | /* Make sure that signals whose names are unknown (for whatever reason) |
| 224 | are printed as signal numbers. */ |
| 225 | if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7)) |
| 226 | printf ("trap -- %s %d\n", t ? t : "''", i); |
| Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 227 | else if (posixly_correct) |
| 228 | { |
| 229 | if (STREQN (sn, "SIG", 3)) |
| 230 | printf ("trap -- %s %s\n", t ? t : "''", sn+3); |
| 231 | else |
| 232 | printf ("trap -- %s %s\n", t ? t : "''", sn); |
| 233 | } |
| Jari Aalto | e8ce775 | 1997-09-22 20:22:27 +0000 | [diff] [blame] | 234 | else |
| 235 | printf ("trap -- %s %s\n", t ? t : "''", sn); |
| 236 | |
| 237 | FREE (t); |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | static int |
| 241 | display_traps (list) |
| 242 | WORD_LIST *list; |
| 243 | { |
| 244 | int result, i; |
| 245 | |
| 246 | if (list == 0) |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 247 | { |
| Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 248 | for (i = 0; i < BASH_NSIG; i++) |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 249 | showtrap (i); |
| 250 | return (EXECUTION_SUCCESS); |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 251 | } |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 252 | |
| 253 | for (result = EXECUTION_SUCCESS; list; list = list->next) |
| 254 | { |
| Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 255 | i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX); |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 256 | if (i == NO_SIG) |
| 257 | { |
| Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 258 | sh_invalidsig (list->word->word); |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 259 | result = EXECUTION_FAILURE; |
| Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 260 | } |
| 261 | else |
| 262 | showtrap (i); |
| 263 | } |
| 264 | |
| 265 | return (result); |
| Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 266 | } |