xref: /titanic_44/usr/src/cmd/sh/fault.c (revision 39e7390a771e8a17884d4f1558a2a41422b38104)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*39e7390aSna195498  * Common Development and Distribution License (the "License").
6*39e7390aSna195498  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21965005c8Schin 
22965005c8Schin /*
23*39e7390aSna195498  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24965005c8Schin  * Use is subject to license terms.
25965005c8Schin  */
26965005c8Schin 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
31965005c8Schin #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * UNIX shell
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include	"defs.h"
377c478bd9Sstevel@tonic-gate #include	<sys/procset.h>
387c478bd9Sstevel@tonic-gate #include	<siginfo.h>
397c478bd9Sstevel@tonic-gate #include	<ucontext.h>
407c478bd9Sstevel@tonic-gate #include	<errno.h>
417c478bd9Sstevel@tonic-gate #include	<string.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate static	void (*psig0_func)() = SIG_ERR;	/* previous signal handler for signal 0 */
447c478bd9Sstevel@tonic-gate static	char sigsegv_stack[SIGSTKSZ];
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate static void sigsegv(int sig, siginfo_t *sip, ucontext_t *uap);
477c478bd9Sstevel@tonic-gate static void fault();
487c478bd9Sstevel@tonic-gate static BOOL sleeping = 0;
497c478bd9Sstevel@tonic-gate static unsigned char *trapcom[MAXTRAP]; /* array of actions, one per signal */
507c478bd9Sstevel@tonic-gate static BOOL trapflg[MAXTRAP] =
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate 	0,
537c478bd9Sstevel@tonic-gate 	0,	/* hangup */
547c478bd9Sstevel@tonic-gate 	0,	/* interrupt */
557c478bd9Sstevel@tonic-gate 	0,	/* quit */
567c478bd9Sstevel@tonic-gate 	0,	/* illegal instr */
577c478bd9Sstevel@tonic-gate 	0,	/* trace trap */
587c478bd9Sstevel@tonic-gate 	0,	/* IOT */
597c478bd9Sstevel@tonic-gate 	0,	/* EMT */
607c478bd9Sstevel@tonic-gate 	0,	/* float pt. exp */
617c478bd9Sstevel@tonic-gate 	0,	/* kill */
627c478bd9Sstevel@tonic-gate 	0, 	/* bus error */
637c478bd9Sstevel@tonic-gate 	0,	/* memory faults */
647c478bd9Sstevel@tonic-gate 	0,	/* bad sys call */
657c478bd9Sstevel@tonic-gate 	0,	/* bad pipe call */
667c478bd9Sstevel@tonic-gate 	0,	/* alarm */
677c478bd9Sstevel@tonic-gate 	0, 	/* software termination */
687c478bd9Sstevel@tonic-gate 	0,	/* unassigned */
697c478bd9Sstevel@tonic-gate 	0,	/* unassigned */
707c478bd9Sstevel@tonic-gate 	0,	/* death of child */
717c478bd9Sstevel@tonic-gate 	0,	/* power fail */
727c478bd9Sstevel@tonic-gate 	0,	/* window size change */
737c478bd9Sstevel@tonic-gate 	0,	/* urgent IO condition */
747c478bd9Sstevel@tonic-gate 	0,	/* pollable event occured */
757c478bd9Sstevel@tonic-gate 	0,	/* stopped by signal */
767c478bd9Sstevel@tonic-gate 	0,	/* stopped by user */
777c478bd9Sstevel@tonic-gate 	0,	/* continued */
787c478bd9Sstevel@tonic-gate 	0,	/* stopped by tty input */
797c478bd9Sstevel@tonic-gate 	0,	/* stopped by tty output */
807c478bd9Sstevel@tonic-gate 	0,	/* virtual timer expired */
817c478bd9Sstevel@tonic-gate 	0,	/* profiling timer expired */
827c478bd9Sstevel@tonic-gate 	0,	/* exceeded cpu limit */
837c478bd9Sstevel@tonic-gate 	0,	/* exceeded file size limit */
847c478bd9Sstevel@tonic-gate 	0, 	/* process's lwps are blocked */
857c478bd9Sstevel@tonic-gate 	0,	/* special signal used by thread library */
867c478bd9Sstevel@tonic-gate 	0, 	/* check point freeze */
877c478bd9Sstevel@tonic-gate 	0,	/* check point thaw */
887c478bd9Sstevel@tonic-gate };
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static void (*(
917c478bd9Sstevel@tonic-gate sigval[MAXTRAP]))() =
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	0,
947c478bd9Sstevel@tonic-gate 	done, 	/* hangup */
957c478bd9Sstevel@tonic-gate 	fault,	/* interrupt */
967c478bd9Sstevel@tonic-gate 	fault,	/* quit */
977c478bd9Sstevel@tonic-gate 	done,	/* illegal instr */
987c478bd9Sstevel@tonic-gate 	done,	/* trace trap */
997c478bd9Sstevel@tonic-gate 	done,	/* IOT */
1007c478bd9Sstevel@tonic-gate 	done,	/* EMT */
1017c478bd9Sstevel@tonic-gate 	done,	/* floating pt. exp */
1027c478bd9Sstevel@tonic-gate 	0,	/* kill */
1037c478bd9Sstevel@tonic-gate 	done, 	/* bus error */
1047c478bd9Sstevel@tonic-gate 	sigsegv,	/* memory faults */
1057c478bd9Sstevel@tonic-gate 	done, 	/* bad sys call */
1067c478bd9Sstevel@tonic-gate 	done,	/* bad pipe call */
1077c478bd9Sstevel@tonic-gate 	done,	/* alarm */
1087c478bd9Sstevel@tonic-gate 	fault,	/* software termination */
1097c478bd9Sstevel@tonic-gate 	done,	/* unassigned */
1107c478bd9Sstevel@tonic-gate 	done,	/* unassigned */
1117c478bd9Sstevel@tonic-gate 	0,	/* death of child */
1127c478bd9Sstevel@tonic-gate 	done,	/* power fail */
1137c478bd9Sstevel@tonic-gate 	0,	/* window size change */
1147c478bd9Sstevel@tonic-gate 	done,	/* urgent IO condition */
1157c478bd9Sstevel@tonic-gate 	done,	/* pollable event occured */
1167c478bd9Sstevel@tonic-gate 	0,	/* uncatchable stop */
1177c478bd9Sstevel@tonic-gate 	0,	/* foreground stop */
1187c478bd9Sstevel@tonic-gate 	0,	/* stopped process continued */
1197c478bd9Sstevel@tonic-gate 	0,	/* background tty read */
1207c478bd9Sstevel@tonic-gate 	0,	/* background tty write */
1217c478bd9Sstevel@tonic-gate 	done,	/* virtual timer expired */
1227c478bd9Sstevel@tonic-gate 	done,	/* profiling timer expired */
1237c478bd9Sstevel@tonic-gate 	done,	/* exceeded cpu limit */
1247c478bd9Sstevel@tonic-gate 	done,	/* exceeded file size limit */
1257c478bd9Sstevel@tonic-gate 	0, 	/* process's lwps are blocked */
1267c478bd9Sstevel@tonic-gate 	0,	/* special signal used by thread library */
1277c478bd9Sstevel@tonic-gate 	0, 	/* check point freeze */
1287c478bd9Sstevel@tonic-gate 	0,	/* check point thaw */
1297c478bd9Sstevel@tonic-gate };
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate static int
132965005c8Schin ignoring(int i)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 	struct sigaction act;
1357c478bd9Sstevel@tonic-gate 	if (trapflg[i] & SIGIGN)
1367c478bd9Sstevel@tonic-gate 		return (1);
1377c478bd9Sstevel@tonic-gate 	sigaction(i, 0, &act);
1387c478bd9Sstevel@tonic-gate 	if (act.sa_handler == SIG_IGN) {
1397c478bd9Sstevel@tonic-gate 		trapflg[i] |= SIGIGN;
1407c478bd9Sstevel@tonic-gate 		return (1);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 	return (0);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate static void
1467c478bd9Sstevel@tonic-gate clrsig(i)
1477c478bd9Sstevel@tonic-gate int	i;
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate 	if (trapcom[i] != 0) {
1507c478bd9Sstevel@tonic-gate 		free(trapcom[i]);
1517c478bd9Sstevel@tonic-gate 		trapcom[i] = 0;
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if (trapflg[i] & SIGMOD) {
1567c478bd9Sstevel@tonic-gate 		/*
1577c478bd9Sstevel@tonic-gate 		 * If the signal has been set to SIGIGN and we are now
1587c478bd9Sstevel@tonic-gate 		 * clearing the disposition of the signal (restoring it
1597c478bd9Sstevel@tonic-gate 		 * back to its default value) then we need to clear this
1607c478bd9Sstevel@tonic-gate 		 * bit as well
1617c478bd9Sstevel@tonic-gate 		 *
1627c478bd9Sstevel@tonic-gate 		 */
1637c478bd9Sstevel@tonic-gate 		if (trapflg[i] & SIGIGN)
1647c478bd9Sstevel@tonic-gate 			trapflg[i] &= ~SIGIGN;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		trapflg[i] &= ~SIGMOD;
1677c478bd9Sstevel@tonic-gate 		handle(i, sigval[i]);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate void
1727c478bd9Sstevel@tonic-gate done(sig)
1737c478bd9Sstevel@tonic-gate {
174965005c8Schin 	unsigned char	*t;
1757c478bd9Sstevel@tonic-gate 	int	savxit;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	if (t = trapcom[0])
1787c478bd9Sstevel@tonic-gate 	{
1797c478bd9Sstevel@tonic-gate 		trapcom[0] = 0;
1807c478bd9Sstevel@tonic-gate 		/* Save exit value so trap handler will not change its val */
1817c478bd9Sstevel@tonic-gate 		savxit = exitval;
1827c478bd9Sstevel@tonic-gate 		execexp(t, 0);
1837c478bd9Sstevel@tonic-gate 		exitval = savxit;		/* Restore exit value */
1847c478bd9Sstevel@tonic-gate 		free(t);
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 	else
1877c478bd9Sstevel@tonic-gate 		chktrap();
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	rmtemp(0);
1907c478bd9Sstevel@tonic-gate 	rmfunctmp();
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate #ifdef ACCT
1937c478bd9Sstevel@tonic-gate 	doacct();
1947c478bd9Sstevel@tonic-gate #endif
1957c478bd9Sstevel@tonic-gate 	if (flags & subsh) {
1967c478bd9Sstevel@tonic-gate 		/* in a subshell, need to wait on foreground job */
1977c478bd9Sstevel@tonic-gate 		collect_fg_job();
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	(void) endjobs(0);
2017c478bd9Sstevel@tonic-gate 	if (sig) {
2027c478bd9Sstevel@tonic-gate 		sigset_t set;
2037c478bd9Sstevel@tonic-gate 		sigemptyset(&set);
2047c478bd9Sstevel@tonic-gate 		sigaddset(&set, sig);
2057c478bd9Sstevel@tonic-gate 		sigprocmask(SIG_UNBLOCK, &set, 0);
2067c478bd9Sstevel@tonic-gate 		handle(sig, SIG_DFL);
2077c478bd9Sstevel@tonic-gate 		kill(mypid, sig);
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 	exit(exitval);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate static void
213965005c8Schin fault(int sig)
2147c478bd9Sstevel@tonic-gate {
215965005c8Schin 	int flag;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	switch (sig) {
2187c478bd9Sstevel@tonic-gate 		case SIGALRM:
2197c478bd9Sstevel@tonic-gate 			if (sleeping)
2207c478bd9Sstevel@tonic-gate 				return;
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (trapcom[sig])
2257c478bd9Sstevel@tonic-gate 		flag = TRAPSET;
2267c478bd9Sstevel@tonic-gate 	else if (flags & subsh)
2277c478bd9Sstevel@tonic-gate 		done(sig);
2287c478bd9Sstevel@tonic-gate 	else
2297c478bd9Sstevel@tonic-gate 		flag = SIGSET;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	trapnote |= flag;
2327c478bd9Sstevel@tonic-gate 	trapflg[sig] |= flag;
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate int
2367c478bd9Sstevel@tonic-gate handle(sig, func)
2377c478bd9Sstevel@tonic-gate 	int sig;
2387c478bd9Sstevel@tonic-gate 	void (*func)();
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	int	ret;
2417c478bd9Sstevel@tonic-gate 	struct sigaction act, oact;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	if (func == SIG_IGN && (trapflg[sig] & SIGIGN))
2447c478bd9Sstevel@tonic-gate 		return (0);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/*
2477c478bd9Sstevel@tonic-gate 	 * Ensure that sigaction is only called with valid signal numbers,
2487c478bd9Sstevel@tonic-gate 	 * we can get random values back for oact.sa_handler if the signal
2497c478bd9Sstevel@tonic-gate 	 * number is invalid
2507c478bd9Sstevel@tonic-gate 	 *
2517c478bd9Sstevel@tonic-gate 	 */
2527c478bd9Sstevel@tonic-gate 	if (sig > MINTRAP && sig < MAXTRAP) {
2537c478bd9Sstevel@tonic-gate 		sigemptyset(&act.sa_mask);
2547c478bd9Sstevel@tonic-gate 		act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0;
2557c478bd9Sstevel@tonic-gate 		act.sa_handler = func;
2567c478bd9Sstevel@tonic-gate 		sigaction(sig, &act, &oact);
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	if (func == SIG_IGN)
2607c478bd9Sstevel@tonic-gate 		trapflg[sig] |= SIGIGN;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * Special case for signal zero, we can not obtain the previos
2647c478bd9Sstevel@tonic-gate 	 * action by calling sigaction, instead we save it in the variable
2657c478bd9Sstevel@tonic-gate 	 * psig0_func, so we can test it next time through this code
2667c478bd9Sstevel@tonic-gate 	 *
2677c478bd9Sstevel@tonic-gate 	 */
2687c478bd9Sstevel@tonic-gate 	if (sig == 0) {
2697c478bd9Sstevel@tonic-gate 		ret = (psig0_func != func);
2707c478bd9Sstevel@tonic-gate 		psig0_func = func;
2717c478bd9Sstevel@tonic-gate 	} else {
2727c478bd9Sstevel@tonic-gate 		ret = (func != oact.sa_handler);
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	return (ret);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate void
2797c478bd9Sstevel@tonic-gate stdsigs()
2807c478bd9Sstevel@tonic-gate {
281965005c8Schin 	int	i;
2827c478bd9Sstevel@tonic-gate 	stack_t	ss;
2837c478bd9Sstevel@tonic-gate 	int rtmin = (int)SIGRTMIN;
2847c478bd9Sstevel@tonic-gate 	int rtmax = (int)SIGRTMAX;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	ss.ss_size = SIGSTKSZ;
2877c478bd9Sstevel@tonic-gate 	ss.ss_sp = sigsegv_stack;
2887c478bd9Sstevel@tonic-gate 	ss.ss_flags = 0;
289*39e7390aSna195498 	if (sigaltstack(&ss, NULL) == -1) {
290*39e7390aSna195498 		error("sigaltstack(2) failed");
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	for (i = 1; i < MAXTRAP; i++) {
2947c478bd9Sstevel@tonic-gate 		if (i == rtmin) {
2957c478bd9Sstevel@tonic-gate 			i = rtmax;
2967c478bd9Sstevel@tonic-gate 			continue;
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 		if (sigval[i] == 0)
2997c478bd9Sstevel@tonic-gate 			continue;
3007c478bd9Sstevel@tonic-gate 		if (i != SIGSEGV && ignoring(i))
3017c478bd9Sstevel@tonic-gate 			continue;
3027c478bd9Sstevel@tonic-gate 		handle(i, sigval[i]);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	/*
3067c478bd9Sstevel@tonic-gate 	 * handle all the realtime signals
3077c478bd9Sstevel@tonic-gate 	 *
3087c478bd9Sstevel@tonic-gate 	 */
3097c478bd9Sstevel@tonic-gate 	for (i = rtmin; i <= rtmax; i++) {
3107c478bd9Sstevel@tonic-gate 		handle(i, done);
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate void
3157c478bd9Sstevel@tonic-gate oldsigs()
3167c478bd9Sstevel@tonic-gate {
317965005c8Schin 	int	i;
318965005c8Schin 	unsigned char	*t;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	i = MAXTRAP;
3217c478bd9Sstevel@tonic-gate 	while (i--)
3227c478bd9Sstevel@tonic-gate 	{
3237c478bd9Sstevel@tonic-gate 		t = trapcom[i];
3247c478bd9Sstevel@tonic-gate 		if (t == 0 || *t)
3257c478bd9Sstevel@tonic-gate 			clrsig(i);
3267c478bd9Sstevel@tonic-gate 		trapflg[i] = 0;
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	trapnote = 0;
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate  * check for traps
3337c478bd9Sstevel@tonic-gate  */
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate void
3367c478bd9Sstevel@tonic-gate chktrap()
3377c478bd9Sstevel@tonic-gate {
338965005c8Schin 	int	i = MAXTRAP;
339965005c8Schin 	unsigned char	*t;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	trapnote &= ~TRAPSET;
3427c478bd9Sstevel@tonic-gate 	while (--i)
3437c478bd9Sstevel@tonic-gate 	{
3447c478bd9Sstevel@tonic-gate 		if (trapflg[i] & TRAPSET)
3457c478bd9Sstevel@tonic-gate 		{
3467c478bd9Sstevel@tonic-gate 			trapflg[i] &= ~TRAPSET;
3477c478bd9Sstevel@tonic-gate 			if (t = trapcom[i])
3487c478bd9Sstevel@tonic-gate 			{
3497c478bd9Sstevel@tonic-gate 				int	savxit = exitval;
3507c478bd9Sstevel@tonic-gate 				execexp(t, 0);
3517c478bd9Sstevel@tonic-gate 				exitval = savxit;
3527c478bd9Sstevel@tonic-gate 				exitset();
3537c478bd9Sstevel@tonic-gate 			}
3547c478bd9Sstevel@tonic-gate 		}
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
358965005c8Schin void
359965005c8Schin systrap(int argc, char **argv)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	int sig;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	if (argc == 1) {
3647c478bd9Sstevel@tonic-gate 		/*
3657c478bd9Sstevel@tonic-gate 		 * print out the current action associated with each signal
3667c478bd9Sstevel@tonic-gate 		 * handled by the shell
3677c478bd9Sstevel@tonic-gate 		 *
3687c478bd9Sstevel@tonic-gate 		 */
3697c478bd9Sstevel@tonic-gate 		for (sig = 0; sig < MAXTRAP; sig++) {
3707c478bd9Sstevel@tonic-gate 			if (trapcom[sig]) {
3717c478bd9Sstevel@tonic-gate 				prn_buff(sig);
3727c478bd9Sstevel@tonic-gate 				prs_buff(colon);
3737c478bd9Sstevel@tonic-gate 				prs_buff(trapcom[sig]);
3747c478bd9Sstevel@tonic-gate 				prc_buff(NL);
3757c478bd9Sstevel@tonic-gate 			}
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 	} else {
3787c478bd9Sstevel@tonic-gate 		/*
3797c478bd9Sstevel@tonic-gate 		 * set the action for the list of signals
3807c478bd9Sstevel@tonic-gate 		 *
3817c478bd9Sstevel@tonic-gate 		 */
3827c478bd9Sstevel@tonic-gate 		char *cmd = *argv, *a1 = *(argv+1);
3837c478bd9Sstevel@tonic-gate 		BOOL noa1;
3847c478bd9Sstevel@tonic-gate 		noa1 = (str2sig(a1, &sig) == 0);
3857c478bd9Sstevel@tonic-gate 		if (noa1 == 0)
3867c478bd9Sstevel@tonic-gate 			++argv;
3877c478bd9Sstevel@tonic-gate 		while (*++argv) {
3887c478bd9Sstevel@tonic-gate 			if (str2sig(*argv, &sig) < 0 ||
3897c478bd9Sstevel@tonic-gate 			    sig >= MAXTRAP || sig < MINTRAP ||
3907c478bd9Sstevel@tonic-gate 			    sig == SIGSEGV) {
3917c478bd9Sstevel@tonic-gate 				failure(cmd, badtrap);
3927c478bd9Sstevel@tonic-gate 			} else if (noa1) {
3937c478bd9Sstevel@tonic-gate 				/*
3947c478bd9Sstevel@tonic-gate 				 * no action specifed so reset the siganl
3957c478bd9Sstevel@tonic-gate 				 * to its default disposition
3967c478bd9Sstevel@tonic-gate 				 *
3977c478bd9Sstevel@tonic-gate 				 */
3987c478bd9Sstevel@tonic-gate 				clrsig(sig);
3997c478bd9Sstevel@tonic-gate 			} else if (*a1) {
4007c478bd9Sstevel@tonic-gate 				/*
4017c478bd9Sstevel@tonic-gate 				 * set the action associated with the signal
4027c478bd9Sstevel@tonic-gate 				 * to a1
4037c478bd9Sstevel@tonic-gate 				 *
4047c478bd9Sstevel@tonic-gate 				 */
4057c478bd9Sstevel@tonic-gate 				if (trapflg[sig] & SIGMOD || sig == 0 ||
4067c478bd9Sstevel@tonic-gate 				    !ignoring(sig)) {
4077c478bd9Sstevel@tonic-gate 					handle(sig, fault);
4087c478bd9Sstevel@tonic-gate 					trapflg[sig] |= SIGMOD;
4097c478bd9Sstevel@tonic-gate 					replace(&trapcom[sig], a1);
4107c478bd9Sstevel@tonic-gate 				}
4117c478bd9Sstevel@tonic-gate 			} else if (handle(sig, SIG_IGN)) {
4127c478bd9Sstevel@tonic-gate 				/*
4137c478bd9Sstevel@tonic-gate 				 * set the action associated with the signal
4147c478bd9Sstevel@tonic-gate 				 * to SIG_IGN
4157c478bd9Sstevel@tonic-gate 				 *
4167c478bd9Sstevel@tonic-gate 				 */
4177c478bd9Sstevel@tonic-gate 				trapflg[sig] |= SIGMOD;
4187c478bd9Sstevel@tonic-gate 				replace(&trapcom[sig], a1);
4197c478bd9Sstevel@tonic-gate 			}
4207c478bd9Sstevel@tonic-gate 		}
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
424965005c8Schin void
425965005c8Schin sh_sleep(unsigned int ticks)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate 	sigset_t set, oset;
4287c478bd9Sstevel@tonic-gate 	struct sigaction act, oact;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/*
4327c478bd9Sstevel@tonic-gate 	 * add SIGALRM to mask
4337c478bd9Sstevel@tonic-gate 	 */
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	sigemptyset(&set);
4367c478bd9Sstevel@tonic-gate 	sigaddset(&set, SIGALRM);
4377c478bd9Sstevel@tonic-gate 	sigprocmask(SIG_BLOCK, &set, &oset);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	/*
4407c478bd9Sstevel@tonic-gate 	 * catch SIGALRM
4417c478bd9Sstevel@tonic-gate 	 */
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	sigemptyset(&act.sa_mask);
4447c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
4457c478bd9Sstevel@tonic-gate 	act.sa_handler = fault;
4467c478bd9Sstevel@tonic-gate 	sigaction(SIGALRM, &act, &oact);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	/*
4497c478bd9Sstevel@tonic-gate 	 * start alarm and wait for signal
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	alarm(ticks);
4537c478bd9Sstevel@tonic-gate 	sleeping = 1;
4547c478bd9Sstevel@tonic-gate 	sigsuspend(&oset);
4557c478bd9Sstevel@tonic-gate 	sleeping = 0;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/*
4587c478bd9Sstevel@tonic-gate 	 * reset alarm, catcher and mask
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	alarm(0);
4627c478bd9Sstevel@tonic-gate 	sigaction(SIGALRM, &oact, NULL);
4637c478bd9Sstevel@tonic-gate 	sigprocmask(SIG_SETMASK, &oset, 0);
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate void
4687c478bd9Sstevel@tonic-gate sigsegv(int sig, siginfo_t *sip, ucontext_t *uap)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	if (sip == (siginfo_t *)NULL) {
4717c478bd9Sstevel@tonic-gate 		/*
4727c478bd9Sstevel@tonic-gate 		 * This should never happen, but if it does this is all we
4737c478bd9Sstevel@tonic-gate 		 * can do. It can only happen if sigaction(2) for SIGSEGV
4747c478bd9Sstevel@tonic-gate 		 * has been called without SA_SIGINFO being set.
4757c478bd9Sstevel@tonic-gate 		 *
4767c478bd9Sstevel@tonic-gate 		 */
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		exit(ERROR);
4797c478bd9Sstevel@tonic-gate 	} else {
4807c478bd9Sstevel@tonic-gate 		if (sip->si_code <= 0) {
4817c478bd9Sstevel@tonic-gate 			/*
4827c478bd9Sstevel@tonic-gate 			 * If we are here then SIGSEGV must have been sent to
4837c478bd9Sstevel@tonic-gate 			 * us from a user process NOT as a result of an
4847c478bd9Sstevel@tonic-gate 			 * internal error within the shell eg
4857c478bd9Sstevel@tonic-gate 			 * kill -SEGV $$
4867c478bd9Sstevel@tonic-gate 			 * will bring us here. So do the normal thing.
4877c478bd9Sstevel@tonic-gate 			 *
4887c478bd9Sstevel@tonic-gate 			 */
4897c478bd9Sstevel@tonic-gate 			fault(sig);
4907c478bd9Sstevel@tonic-gate 		} else {
4917c478bd9Sstevel@tonic-gate 			/*
4927c478bd9Sstevel@tonic-gate 			 * If we are here then there must have been an internal
4937c478bd9Sstevel@tonic-gate 			 * error within the shell to generate SIGSEGV eg
4947c478bd9Sstevel@tonic-gate 			 * the stack is full and we cannot call any more
4957c478bd9Sstevel@tonic-gate 			 * functions (Remeber this signal handler is running
4967c478bd9Sstevel@tonic-gate 			 * on an alternate stack). So we just exit cleanly
4977c478bd9Sstevel@tonic-gate 			 * with an error status (no core file).
4987c478bd9Sstevel@tonic-gate 			 */
4997c478bd9Sstevel@tonic-gate 			exit(ERROR);
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate }
503