1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 /*
32 * UNIX shell
33 */
34
35 #include "defs.h"
36 #include <sys/procset.h>
37 #include <siginfo.h>
38 #include <ucontext.h>
39 #include <errno.h>
40 #include <string.h>
41
42 extern void hupforegnd(void);
43
44 /* previous signal handler for signal 0 */
45 static void (*psig0_func)() = SIG_ERR;
46 static char sigsegv_stack[SIGSTKSZ];
47
48 static void sigsegv(int sig, siginfo_t *sip, ucontext_t *uap);
49 static void fault();
50 static BOOL sleeping = 0;
51 static unsigned char *trapcom[MAXTRAP]; /* array of actions, one per signal */
52 static BOOL trapflg[MAXTRAP] =
53 {
54 0,
55 0, /* hangup */
56 0, /* interrupt */
57 0, /* quit */
58 0, /* illegal instr */
59 0, /* trace trap */
60 0, /* IOT */
61 0, /* EMT */
62 0, /* float pt. exp */
63 0, /* kill */
64 0, /* bus error */
65 0, /* memory faults */
66 0, /* bad sys call */
67 0, /* bad pipe call */
68 0, /* alarm */
69 0, /* software termination */
70 0, /* unassigned */
71 0, /* unassigned */
72 0, /* death of child */
73 0, /* power fail */
74 0, /* window size change */
75 0, /* urgent IO condition */
76 0, /* pollable event occured */
77 0, /* stopped by signal */
78 0, /* stopped by user */
79 0, /* continued */
80 0, /* stopped by tty input */
81 0, /* stopped by tty output */
82 0, /* virtual timer expired */
83 0, /* profiling timer expired */
84 0, /* exceeded cpu limit */
85 0, /* exceeded file size limit */
86 0, /* process's lwps are blocked */
87 0, /* special signal used by thread library */
88 0, /* check point freeze */
89 0, /* check point thaw */
90 };
91
92 static void (*(
93 sigval[MAXTRAP]))() =
94 {
95 0,
96 done, /* hangup */
97 fault, /* interrupt */
98 fault, /* quit */
99 done, /* illegal instr */
100 done, /* trace trap */
101 done, /* IOT */
102 done, /* EMT */
103 done, /* floating pt. exp */
104 0, /* kill */
105 done, /* bus error */
106 sigsegv, /* memory faults */
107 done, /* bad sys call */
108 done, /* bad pipe call */
109 done, /* alarm */
110 fault, /* software termination */
111 done, /* unassigned */
112 done, /* unassigned */
113 0, /* death of child */
114 done, /* power fail */
115 0, /* window size change */
116 done, /* urgent IO condition */
117 done, /* pollable event occured */
118 0, /* uncatchable stop */
119 0, /* foreground stop */
120 0, /* stopped process continued */
121 0, /* background tty read */
122 0, /* background tty write */
123 done, /* virtual timer expired */
124 done, /* profiling timer expired */
125 done, /* exceeded cpu limit */
126 done, /* exceeded file size limit */
127 0, /* process's lwps are blocked */
128 0, /* special signal used by thread library */
129 0, /* check point freeze */
130 0, /* check point thaw */
131 };
132
133 static int
ignoring(int i)134 ignoring(int i)
135 {
136 struct sigaction act;
137 if (trapflg[i] & SIGIGN)
138 return (1);
139 sigaction(i, 0, &act);
140 if (act.sa_handler == SIG_IGN) {
141 trapflg[i] |= SIGIGN;
142 return (1);
143 }
144 return (0);
145 }
146
147 static void
clrsig(i)148 clrsig(i)
149 int i;
150 {
151 if (trapcom[i] != 0) {
152 free(trapcom[i]);
153 trapcom[i] = 0;
154 }
155
156
157 if (trapflg[i] & SIGMOD) {
158 /*
159 * If the signal has been set to SIGIGN and we are now
160 * clearing the disposition of the signal (restoring it
161 * back to its default value) then we need to clear this
162 * bit as well
163 *
164 */
165 if (trapflg[i] & SIGIGN)
166 trapflg[i] &= ~SIGIGN;
167
168 trapflg[i] &= ~SIGMOD;
169 handle(i, sigval[i]);
170 }
171 }
172
173 void
done(sig)174 done(sig)
175 {
176 unsigned char *t;
177 int savxit;
178
179 if (t = trapcom[0]) {
180 trapcom[0] = 0;
181 /* Save exit value so trap handler will not change its val */
182 savxit = exitval;
183 execexp(t, 0);
184 exitval = savxit; /* Restore exit value */
185 free(t);
186 }
187 else
188 chktrap();
189
190 rmtemp(0);
191 rmfunctmp();
192
193 #ifdef ACCT
194 doacct();
195 #endif
196 if (flags & subsh) {
197 /* in a subshell, need to wait on foreground job */
198 collect_fg_job();
199 }
200
201 (void) endjobs(0);
202 if (sig) {
203 sigset_t set;
204
205 /*
206 * If the signal is SIGHUP, then it should be delivered
207 * to the process group leader of the foreground job.
208 */
209 if (sig == SIGHUP)
210 hupforegnd();
211
212 sigemptyset(&set);
213 sigaddset(&set, sig);
214 sigprocmask(SIG_UNBLOCK, &set, 0);
215 handle(sig, SIG_DFL);
216 kill(mypid, sig);
217 }
218 exit(exitval);
219 }
220
221 static void
fault(int sig)222 fault(int sig)
223 {
224 int flag;
225
226 switch (sig) {
227 case SIGALRM:
228 if (sleeping)
229 return;
230 break;
231 }
232
233 if (trapcom[sig])
234 flag = TRAPSET;
235 else if (flags & subsh)
236 done(sig);
237 else
238 flag = SIGSET;
239
240 trapnote |= flag;
241 trapflg[sig] |= flag;
242 }
243
244 int
handle(sig,func)245 handle(sig, func)
246 int sig;
247 void (*func)();
248 {
249 int ret;
250 struct sigaction act, oact;
251
252 if (func == SIG_IGN && (trapflg[sig] & SIGIGN))
253 return (0);
254
255 /*
256 * Ensure that sigaction is only called with valid signal numbers,
257 * we can get random values back for oact.sa_handler if the signal
258 * number is invalid
259 *
260 */
261 if (sig > MINTRAP && sig < MAXTRAP) {
262 sigemptyset(&act.sa_mask);
263 act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0;
264 act.sa_handler = func;
265 sigaction(sig, &act, &oact);
266 }
267
268 if (func == SIG_IGN)
269 trapflg[sig] |= SIGIGN;
270
271 /*
272 * Special case for signal zero, we can not obtain the previos
273 * action by calling sigaction, instead we save it in the variable
274 * psig0_func, so we can test it next time through this code
275 *
276 */
277 if (sig == 0) {
278 ret = (psig0_func != func);
279 psig0_func = func;
280 } else {
281 ret = (func != oact.sa_handler);
282 }
283
284 return (ret);
285 }
286
287 void
stdsigs()288 stdsigs()
289 {
290 int i;
291 stack_t ss;
292 int rtmin = (int)SIGRTMIN;
293 int rtmax = (int)SIGRTMAX;
294
295 ss.ss_size = SIGSTKSZ;
296 ss.ss_sp = sigsegv_stack;
297 ss.ss_flags = 0;
298 if (sigaltstack(&ss, NULL) == -1) {
299 error("sigaltstack(2) failed");
300 }
301
302 for (i = 1; i < MAXTRAP; i++) {
303 if (i == rtmin) {
304 i = rtmax;
305 continue;
306 }
307 if (sigval[i] == 0)
308 continue;
309 if (i != SIGSEGV && ignoring(i))
310 continue;
311 handle(i, sigval[i]);
312 }
313
314 /*
315 * handle all the realtime signals
316 *
317 */
318 for (i = rtmin; i <= rtmax; i++) {
319 handle(i, done);
320 }
321 }
322
323 void
oldsigs()324 oldsigs()
325 {
326 int i;
327 unsigned char *t;
328
329 i = MAXTRAP;
330 while (i--) {
331 t = trapcom[i];
332 if (t == 0 || *t)
333 clrsig(i);
334 trapflg[i] = 0;
335 }
336 trapnote = 0;
337 }
338
339 /*
340 * check for traps
341 */
342
343 void
chktrap()344 chktrap()
345 {
346 int i = MAXTRAP;
347 unsigned char *t;
348
349 trapnote &= ~TRAPSET;
350 while (--i) {
351 if (trapflg[i] & TRAPSET) {
352 trapflg[i] &= ~TRAPSET;
353 if (t = trapcom[i]) {
354 int savxit = exitval;
355
356 execexp(t, 0);
357 exitval = savxit;
358 exitset();
359 }
360 }
361 }
362 }
363
364 void
systrap(int argc,char ** argv)365 systrap(int argc, char **argv)
366 {
367 int sig;
368
369 if (argc == 1) {
370 /*
371 * print out the current action associated with each signal
372 * handled by the shell
373 *
374 */
375 for (sig = 0; sig < MAXTRAP; sig++) {
376 if (trapcom[sig]) {
377 prn_buff(sig);
378 prs_buff(colon);
379 prs_buff(trapcom[sig]);
380 prc_buff(NL);
381 }
382 }
383 } else {
384 /*
385 * set the action for the list of signals
386 *
387 */
388 char *cmd = *argv, *a1 = *(argv+1);
389 BOOL noa1;
390 noa1 = (str2sig(a1, &sig) == 0);
391 if (noa1 == 0)
392 ++argv;
393 while (*++argv) {
394 if (str2sig(*argv, &sig) < 0 ||
395 sig >= MAXTRAP || sig < MINTRAP ||
396 sig == SIGSEGV) {
397 failure(cmd, badtrap);
398 } else if (noa1) {
399 /*
400 * no action specifed so reset the siganl
401 * to its default disposition
402 *
403 */
404 clrsig(sig);
405 } else if (*a1) {
406 /*
407 * set the action associated with the signal
408 * to a1
409 *
410 */
411 if (trapflg[sig] & SIGMOD || sig == 0 ||
412 !ignoring(sig)) {
413 handle(sig, fault);
414 trapflg[sig] |= SIGMOD;
415 replace(&trapcom[sig], a1);
416 }
417 } else if (handle(sig, SIG_IGN)) {
418 /*
419 * set the action associated with the signal
420 * to SIG_IGN
421 *
422 */
423 trapflg[sig] |= SIGMOD;
424 replace(&trapcom[sig], a1);
425 }
426 }
427 }
428 }
429
430 void
sh_sleep(unsigned int ticks)431 sh_sleep(unsigned int ticks)
432 {
433 sigset_t set, oset;
434 struct sigaction act, oact;
435
436
437 /*
438 * add SIGALRM to mask
439 */
440
441 sigemptyset(&set);
442 sigaddset(&set, SIGALRM);
443 sigprocmask(SIG_BLOCK, &set, &oset);
444
445 /*
446 * catch SIGALRM
447 */
448
449 sigemptyset(&act.sa_mask);
450 act.sa_flags = 0;
451 act.sa_handler = fault;
452 sigaction(SIGALRM, &act, &oact);
453
454 /*
455 * start alarm and wait for signal
456 */
457
458 alarm(ticks);
459 sleeping = 1;
460 sigsuspend(&oset);
461 sleeping = 0;
462
463 /*
464 * reset alarm, catcher and mask
465 */
466
467 alarm(0);
468 sigaction(SIGALRM, &oact, NULL);
469 sigprocmask(SIG_SETMASK, &oset, 0);
470
471 }
472
473 void
sigsegv(int sig,siginfo_t * sip,ucontext_t * uap)474 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap)
475 {
476 if (sip == (siginfo_t *)NULL) {
477 /*
478 * This should never happen, but if it does this is all we
479 * can do. It can only happen if sigaction(2) for SIGSEGV
480 * has been called without SA_SIGINFO being set.
481 *
482 */
483
484 exit(ERROR);
485 } else {
486 if (sip->si_code <= 0) {
487 /*
488 * If we are here then SIGSEGV must have been sent to
489 * us from a user process NOT as a result of an
490 * internal error within the shell eg
491 * kill -SEGV $$
492 * will bring us here. So do the normal thing.
493 *
494 */
495 fault(sig);
496 } else {
497 /*
498 * If we are here then there must have been an internal
499 * error within the shell to generate SIGSEGV eg
500 * the stack is full and we cannot call any more
501 * functions (Remeber this signal handler is running
502 * on an alternate stack). So we just exit cleanly
503 * with an error status (no core file).
504 */
505 exit(ERROR);
506 }
507 }
508 }
509