8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sh / fault.c
blob8c4c67259b820649cfb34bd8c99abda59438a9b5
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
32 * UNIX shell
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>
42 extern void hupforegnd(void);
44 /* previous signal handler for signal 0 */
45 static void (*psig0_func)() = SIG_ERR;
46 static char sigsegv_stack[SIGSTKSZ];
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] =
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 */
92 static void (*(
93 sigval[MAXTRAP]))() =
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 */
133 static int
134 ignoring(int i)
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);
144 return (0);
147 static void
148 clrsig(i)
149 int i;
151 if (trapcom[i] != 0) {
152 free(trapcom[i]);
153 trapcom[i] = 0;
157 if (trapflg[i] & SIGMOD) {
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
165 if (trapflg[i] & SIGIGN)
166 trapflg[i] &= ~SIGIGN;
168 trapflg[i] &= ~SIGMOD;
169 handle(i, sigval[i]);
173 void
174 done(sig)
176 unsigned char *t;
177 int savxit;
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);
187 else
188 chktrap();
190 rmtemp(0);
191 rmfunctmp();
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();
201 (void) endjobs(0);
202 if (sig) {
203 sigset_t set;
206 * If the signal is SIGHUP, then it should be delivered
207 * to the process group leader of the foreground job.
209 if (sig == SIGHUP)
210 hupforegnd();
212 sigemptyset(&set);
213 sigaddset(&set, sig);
214 sigprocmask(SIG_UNBLOCK, &set, 0);
215 handle(sig, SIG_DFL);
216 kill(mypid, sig);
218 exit(exitval);
221 static void
222 fault(int sig)
224 int flag;
226 switch (sig) {
227 case SIGALRM:
228 if (sleeping)
229 return;
230 break;
233 if (trapcom[sig])
234 flag = TRAPSET;
235 else if (flags & subsh)
236 done(sig);
237 else
238 flag = SIGSET;
240 trapnote |= flag;
241 trapflg[sig] |= flag;
245 handle(sig, func)
246 int sig;
247 void (*func)();
249 int ret;
250 struct sigaction act, oact;
252 if (func == SIG_IGN && (trapflg[sig] & SIGIGN))
253 return (0);
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
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);
268 if (func == SIG_IGN)
269 trapflg[sig] |= SIGIGN;
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
277 if (sig == 0) {
278 ret = (psig0_func != func);
279 psig0_func = func;
280 } else {
281 ret = (func != oact.sa_handler);
284 return (ret);
287 void
288 stdsigs()
290 int i;
291 stack_t ss;
292 int rtmin = (int)SIGRTMIN;
293 int rtmax = (int)SIGRTMAX;
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");
302 for (i = 1; i < MAXTRAP; i++) {
303 if (i == rtmin) {
304 i = rtmax;
305 continue;
307 if (sigval[i] == 0)
308 continue;
309 if (i != SIGSEGV && ignoring(i))
310 continue;
311 handle(i, sigval[i]);
315 * handle all the realtime signals
318 for (i = rtmin; i <= rtmax; i++) {
319 handle(i, done);
323 void
324 oldsigs()
326 int i;
327 unsigned char *t;
329 i = MAXTRAP;
330 while (i--) {
331 t = trapcom[i];
332 if (t == 0 || *t)
333 clrsig(i);
334 trapflg[i] = 0;
336 trapnote = 0;
340 * check for traps
343 void
344 chktrap()
346 int i = MAXTRAP;
347 unsigned char *t;
349 trapnote &= ~TRAPSET;
350 while (--i) {
351 if (trapflg[i] & TRAPSET) {
352 trapflg[i] &= ~TRAPSET;
353 if (t = trapcom[i]) {
354 int savxit = exitval;
356 execexp(t, 0);
357 exitval = savxit;
358 exitset();
364 void
365 systrap(int argc, char **argv)
367 int sig;
369 if (argc == 1) {
371 * print out the current action associated with each signal
372 * handled by the shell
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);
383 } else {
385 * set the action for the list of signals
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) {
400 * no action specifed so reset the siganl
401 * to its default disposition
404 clrsig(sig);
405 } else if (*a1) {
407 * set the action associated with the signal
408 * to a1
411 if (trapflg[sig] & SIGMOD || sig == 0 ||
412 !ignoring(sig)) {
413 handle(sig, fault);
414 trapflg[sig] |= SIGMOD;
415 replace(&trapcom[sig], a1);
417 } else if (handle(sig, SIG_IGN)) {
419 * set the action associated with the signal
420 * to SIG_IGN
423 trapflg[sig] |= SIGMOD;
424 replace(&trapcom[sig], a1);
430 void
431 sh_sleep(unsigned int ticks)
433 sigset_t set, oset;
434 struct sigaction act, oact;
438 * add SIGALRM to mask
441 sigemptyset(&set);
442 sigaddset(&set, SIGALRM);
443 sigprocmask(SIG_BLOCK, &set, &oset);
446 * catch SIGALRM
449 sigemptyset(&act.sa_mask);
450 act.sa_flags = 0;
451 act.sa_handler = fault;
452 sigaction(SIGALRM, &act, &oact);
455 * start alarm and wait for signal
458 alarm(ticks);
459 sleeping = 1;
460 sigsuspend(&oset);
461 sleeping = 0;
464 * reset alarm, catcher and mask
467 alarm(0);
468 sigaction(SIGALRM, &oact, NULL);
469 sigprocmask(SIG_SETMASK, &oset, 0);
473 void
474 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap)
476 if (sip == (siginfo_t *)NULL) {
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.
484 exit(ERROR);
485 } else {
486 if (sip->si_code <= 0) {
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.
495 fault(sig);
496 } else {
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).
505 exit(ERROR);