00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
00039 #endif
00040
00041 #include "shell.h"
00042 #include "main.h"
00043 #include "nodes.h"
00044 #include "eval.h"
00045 #include "jobs.h"
00046 #include "options.h"
00047 #include "syntax.h"
00048 #include "signames.h"
00049 #include "output.h"
00050 #include "memalloc.h"
00051 #include "error.h"
00052 #include "trap.h"
00053 #include "mystring.h"
00054 #include <sys/types.h>
00055 #include <signal.h>
00056
00057
00058
00059
00060
00061
00062
00063
00064 #define S_DFL 1
00065 #define S_CATCH 2
00066 #define S_IGN 3
00067 #define S_HARD_IGN 4
00068
00069
00070 extern char nullstr[1];
00071
00072 char *trap[MAXSIG+1];
00073 MKINIT char sigmode[MAXSIG];
00074 char gotsig[MAXSIG];
00075 int pendingsigs;
00076
00077
00078
00079
00080
00081 trapcmd(argc, argv) char **argv; {
00082 char *action;
00083 char **ap;
00084 int signo;
00085
00086 if (argc <= 1) {
00087 for (signo = 0 ; signo <= MAXSIG ; signo++) {
00088 if (trap[signo] != NULL)
00089 out1fmt("%d: %s\n", signo, trap[signo]);
00090 }
00091 return 0;
00092 }
00093 ap = argv + 1;
00094 if (is_number(*ap))
00095 action = NULL;
00096 else
00097 action = *ap++;
00098 while (*ap) {
00099 if ((signo = number(*ap)) < 0 || signo > MAXSIG)
00100 error("%s: bad trap", *ap);
00101 INTOFF;
00102 if (action)
00103 action = savestr(action);
00104 if (trap[signo])
00105 ckfree(trap[signo]);
00106 trap[signo] = action;
00107 if (signo != 0)
00108 setsignal(signo);
00109 INTON;
00110 ap++;
00111 }
00112 return 0;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121 void
00122 clear_traps() {
00123 char **tp;
00124
00125 for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
00126 if (*tp && **tp) {
00127 INTOFF;
00128 ckfree(*tp);
00129 *tp = NULL;
00130 if (tp != &trap[0])
00131 setsignal(tp - trap);
00132 INTON;
00133 }
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 int
00145 setsignal(signo) {
00146 int action;
00147 sig_t sigact;
00148 char *t;
00149 extern void onsig();
00150
00151 if ((t = trap[signo]) == NULL)
00152 action = S_DFL;
00153 else if (*t != '\0')
00154 action = S_CATCH;
00155 else
00156 action = S_IGN;
00157 if (rootshell && action == S_DFL) {
00158 switch (signo) {
00159 case SIGINT:
00160 if (iflag)
00161 action = S_CATCH;
00162 break;
00163 case SIGQUIT:
00164 #if DEBUG
00165 {
00166 extern int debug;
00167
00168 if (debug)
00169 break;
00170 }
00171 #endif
00172
00173 case SIGTERM:
00174 if (iflag)
00175 action = S_IGN;
00176 break;
00177 #if JOBS
00178 case SIGTSTP:
00179 case SIGTTOU:
00180 if (jflag)
00181 action = S_IGN;
00182 break;
00183 #endif
00184 }
00185 }
00186 t = &sigmode[signo - 1];
00187 if (*t == 0) {
00188
00189
00190
00191
00192 if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
00193 error("Signal system call failed");
00194 if (sigact == SIG_IGN) {
00195 *t = S_HARD_IGN;
00196 } else {
00197 *t = S_IGN;
00198 }
00199 }
00200 if (*t == S_HARD_IGN || *t == action)
00201 return 0;
00202 switch (action) {
00203 case S_DFL: sigact = SIG_DFL; break;
00204 case S_CATCH: sigact = onsig; break;
00205 case S_IGN: sigact = SIG_IGN; break;
00206 }
00207 *t = action;
00208 return (int)signal(signo, sigact);
00209 }
00210
00211
00212
00213
00214
00215
00216 void
00217 ignoresig(signo) {
00218 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
00219 signal(signo, SIG_IGN);
00220 }
00221 sigmode[signo - 1] = S_HARD_IGN;
00222 }
00223
00224
00225 #ifdef mkinit
00226 INCLUDE "signames.h"
00227 INCLUDE "trap.h"
00228
00229 SHELLPROC {
00230 char *sm;
00231
00232 clear_traps();
00233 for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
00234 if (*sm == S_IGN)
00235 *sm = S_HARD_IGN;
00236 }
00237 }
00238 #endif
00239
00240
00241
00242
00243
00244
00245
00246 void
00247 onsig(signo) {
00248 signal(signo, onsig);
00249 if (signo == SIGINT && trap[SIGINT] == NULL) {
00250 onint();
00251 return;
00252 }
00253 gotsig[signo - 1] = 1;
00254 pendingsigs++;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 void
00265 dotrap() {
00266 int i;
00267 int savestatus;
00268
00269 for (;;) {
00270 for (i = 1 ; ; i++) {
00271 if (gotsig[i - 1])
00272 break;
00273 if (i >= MAXSIG)
00274 goto done;
00275 }
00276 gotsig[i - 1] = 0;
00277 savestatus=exitstatus;
00278 evalstring(trap[i]);
00279 exitstatus=savestatus;
00280 }
00281 done:
00282 pendingsigs = 0;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 int is_interactive;
00292
00293 void
00294 setinteractive(on) {
00295 if (on == is_interactive)
00296 return;
00297 setsignal(SIGINT);
00298 setsignal(SIGQUIT);
00299 setsignal(SIGTERM);
00300 is_interactive = on;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 void
00310 exitshell(status) {
00311 struct jmploc loc1, loc2;
00312 char *p;
00313
00314 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
00315 if (setjmp(loc1.loc)) goto l1;
00316 if (setjmp(loc2.loc)) goto l2;
00317 handler = &loc1;
00318 if ((p = trap[0]) != NULL && *p != '\0') {
00319 trap[0] = NULL;
00320 evalstring(p);
00321 }
00322 l1: handler = &loc2;
00323 flushall();
00324 #if JOBS
00325 setjobctl(0);
00326 #endif
00327 l2: _exit(status);
00328 }