1/* trap.c, created from trap.def. */ 2#line 23 "trap.def" 3 4#line 42 "trap.def" 5 6#include <config.h> 7 8#if defined (HAVE_UNISTD_H) 9# ifdef _MINIX 10# include <sys/types.h> 11# endif 12# include <unistd.h> 13#endif 14 15#include "../bashtypes.h" 16#include <signal.h> 17#include <stdio.h> 18#include "../bashansi.h" 19 20#include "../shell.h" 21#include "../trap.h" 22#include "common.h" 23#include "bashgetopt.h" 24 25static void showtrap __P((int)); 26static int display_traps __P((WORD_LIST *)); 27 28/* The trap command: 29 30 trap <arg> <signal ...> 31 trap <signal ...> 32 trap -l 33 trap -p [sigspec ...] 34 trap [--] 35 36 Set things up so that ARG is executed when SIGNAL(s) N is recieved. 37 If ARG is the empty string, then ignore the SIGNAL(s). If there is 38 no ARG, then set the trap for SIGNAL(s) to its original value. Just 39 plain "trap" means to print out the list of commands associated with 40 each signal number. Single arg of "-l" means list the signal names. */ 41 42/* Possible operations to perform on the list of signals.*/ 43#define SET 0 /* Set this signal to first_arg. */ 44#define REVERT 1 /* Revert to this signals original value. */ 45#define IGNORE 2 /* Ignore this signal. */ 46 47extern int posixly_correct; 48 49int 50trap_builtin (list) 51 WORD_LIST *list; 52{ 53 int list_signal_names, display, result, opt; 54 55 list_signal_names = display = 0; 56 result = EXECUTION_SUCCESS; 57 reset_internal_getopt (); 58 while ((opt = internal_getopt (list, "lp")) != -1) 59 { 60 switch (opt) 61 { 62 case 'l': 63 list_signal_names++; 64 break; 65 case 'p': 66 display++; 67 break; 68 default: 69 builtin_usage (); 70 return (EX_USAGE); 71 } 72 } 73 list = loptend; 74 75 opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */ 76 77 if (list_signal_names) 78 return (display_signal_list ((WORD_LIST *)NULL, 1)); 79 else if (display || list == 0) 80 return (display_traps (list)); 81 else 82 { 83 char *first_arg; 84 int operation, sig, first_signal; 85 86 operation = SET; 87 first_arg = list->word->word; 88 first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt); 89 90 /* Backwards compatibility. XXX - question about whether or not we 91 should throw an error if an all-digit argument doesn't correspond 92 to a valid signal number (e.g., if it's `50' on a system with only 93 32 signals). */ 94 if (first_signal) 95 operation = REVERT; 96 /* When in posix mode, the historical behavior of looking for a 97 missing first argument is disabled. To revert to the original 98 signal handling disposition, use `-' as the first argument. */ 99 else if (posixly_correct == 0 && first_arg && *first_arg && 100 (*first_arg != '-' || first_arg[1]) && 101 signal_object_p (first_arg, opt) && list->next == 0) 102 operation = REVERT; 103 else 104 { 105 list = list->next; 106 if (list == 0) 107 { 108 builtin_usage (); 109 return (EX_USAGE); 110 } 111 else if (*first_arg == '\0') 112 operation = IGNORE; 113 else if (first_arg[0] == '-' && !first_arg[1]) 114 operation = REVERT; 115 } 116 117 while (list) 118 { 119 sig = decode_signal (list->word->word, opt); 120 121 if (sig == NO_SIG) 122 { 123 sh_invalidsig (list->word->word); 124 result = EXECUTION_FAILURE; 125 } 126 else 127 { 128 switch (operation) 129 { 130 case SET: 131 set_signal (sig, first_arg); 132 break; 133 134 case REVERT: 135 restore_default_signal (sig); 136 137 /* Signals that the shell treats specially need special 138 handling. */ 139 switch (sig) 140 { 141 case SIGINT: 142 if (interactive) 143 set_signal_handler (SIGINT, sigint_sighandler); 144 else 145 set_signal_handler (SIGINT, termsig_sighandler); 146 break; 147 148 case SIGQUIT: 149 /* Always ignore SIGQUIT. */ 150 set_signal_handler (SIGQUIT, SIG_IGN); 151 break; 152 case SIGTERM: 153#if defined (JOB_CONTROL) 154 case SIGTTIN: 155 case SIGTTOU: 156 case SIGTSTP: 157#endif /* JOB_CONTROL */ 158 if (interactive) 159 set_signal_handler (sig, SIG_IGN); 160 break; 161 } 162 break; 163 164 case IGNORE: 165 ignore_signal (sig); 166 break; 167 } 168 } 169 list = list->next; 170 } 171 } 172 173 return (result); 174} 175 176static void 177showtrap (i) 178 int i; 179{ 180 char *t, *p, *sn; 181 182 p = trap_list[i]; 183 if (p == (char *)DEFAULT_SIG) 184 return; 185 186 t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p); 187 sn = signal_name (i); 188 /* Make sure that signals whose names are unknown (for whatever reason) 189 are printed as signal numbers. */ 190 if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7)) 191 printf ("trap -- %s %d\n", t ? t : "''", i); 192 else if (posixly_correct) 193 { 194 if (STREQN (sn, "SIG", 3)) 195 printf ("trap -- %s %s\n", t ? t : "''", sn+3); 196 else 197 printf ("trap -- %s %s\n", t ? t : "''", sn); 198 } 199 else 200 printf ("trap -- %s %s\n", t ? t : "''", sn); 201 202 FREE (t); 203} 204 205static int 206display_traps (list) 207 WORD_LIST *list; 208{ 209 int result, i; 210 211 if (list == 0) 212 { 213 for (i = 0; i < BASH_NSIG; i++) 214 showtrap (i); 215 return (EXECUTION_SUCCESS); 216 } 217 218 for (result = EXECUTION_SUCCESS; list; list = list->next) 219 { 220 i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX); 221 if (i == NO_SIG) 222 { 223 sh_invalidsig (list->word->word); 224 result = EXECUTION_FAILURE; 225 } 226 else 227 showtrap (i); 228 } 229 230 return (result); 231} 232