1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin /*
22*4887Schin  * Fault handling routines
23*4887Schin  *
24*4887Schin  *   David Korn
25*4887Schin  *   AT&T Labs
26*4887Schin  *
27*4887Schin  */
28*4887Schin 
29*4887Schin #include	"defs.h"
30*4887Schin #include	<fcin.h>
31*4887Schin #include	"io.h"
32*4887Schin #include	"history.h"
33*4887Schin #include	"shnodes.h"
34*4887Schin #include	"variables.h"
35*4887Schin #include	"jobs.h"
36*4887Schin #include	"path.h"
37*4887Schin 
38*4887Schin #define abortsig(sig)	(sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV)
39*4887Schin 
40*4887Schin static char	indone;
41*4887Schin 
42*4887Schin #if !_std_malloc
43*4887Schin #   include	<vmalloc.h>
44*4887Schin #endif
45*4887Schin #if  defined(VMFL) && (VMALLOC_VERSION>=20031205L)
46*4887Schin     /*
47*4887Schin      * This exception handler is called after vmalloc() unlocks the region
48*4887Schin      */
49*4887Schin     static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp)
50*4887Schin     {
51*4887Schin 	dp->exceptf = 0;
52*4887Schin 	sh_exit(SH_EXITSIG);
53*4887Schin 	return(0);
54*4887Schin     }
55*4887Schin #endif
56*4887Schin 
57*4887Schin /*
58*4887Schin  * Most signals caught or ignored by the shell come here
59*4887Schin */
60*4887Schin void	sh_fault(register int sig)
61*4887Schin {
62*4887Schin 	register int 	flag=0;
63*4887Schin 	register char	*trap;
64*4887Schin 	register struct checkpt	*pp = (struct checkpt*)sh.jmplist;
65*4887Schin 	int	action=0;
66*4887Schin 	/* reset handler */
67*4887Schin 	if(!(sig&SH_TRAP))
68*4887Schin 		signal(sig, sh_fault);
69*4887Schin 	sig &= ~SH_TRAP;
70*4887Schin #ifdef SIGWINCH
71*4887Schin 	if(sig==SIGWINCH)
72*4887Schin 	{
73*4887Schin 		int rows=0, cols=0;
74*4887Schin 		int32_t v;
75*4887Schin 		astwinsize(2,&rows,&cols);
76*4887Schin 		if(v = cols)
77*4887Schin 			nv_putval(COLUMNS, (char*)&v, NV_INT32);
78*4887Schin 		if(v = rows)
79*4887Schin 			nv_putval(LINES, (char*)&v, NV_INT32);
80*4887Schin 	}
81*4887Schin #endif  /* SIGWINCH */
82*4887Schin 	if(sh.savesig)
83*4887Schin 	{
84*4887Schin 		/* critical region, save and process later */
85*4887Schin 		sh.savesig = sig;
86*4887Schin 		return;
87*4887Schin 	}
88*4887Schin 
89*4887Schin 	/* handle ignored signals */
90*4887Schin 	if((trap=sh.st.trapcom[sig]) && *trap==0)
91*4887Schin 		return;
92*4887Schin 	flag = sh.sigflag[sig]&~SH_SIGOFF;
93*4887Schin 	if(!trap)
94*4887Schin 	{
95*4887Schin 		if(flag&SH_SIGIGNORE)
96*4887Schin 			return;
97*4887Schin 		if(flag&SH_SIGDONE)
98*4887Schin 		{
99*4887Schin 			void *ptr=0;
100*4887Schin 			if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! sh.subshell)
101*4887Schin 			{
102*4887Schin 				/* check for TERM signal between fork/exec */
103*4887Schin 				if(sig==SIGTERM && job.in_critical)
104*4887Schin 					sh.trapnote |= SH_SIGTERM;
105*4887Schin 				return;
106*4887Schin 			}
107*4887Schin 			sh.lastsig = sig;
108*4887Schin 			sigrelease(sig);
109*4887Schin 			if(pp->mode < SH_JMPFUN)
110*4887Schin 				pp->mode = SH_JMPFUN;
111*4887Schin 			else
112*4887Schin 				pp->mode = SH_JMPEXIT;
113*4887Schin 			if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1))))
114*4887Schin 			{
115*4887Schin 				if(ptr)
116*4887Schin 					free(ptr);
117*4887Schin 				if(!sh.subshell)
118*4887Schin 					sh_done(sig);
119*4887Schin 				sh_exit(SH_EXITSIG);
120*4887Schin 			}
121*4887Schin 			/* mark signal and continue */
122*4887Schin 			sh.trapnote |= SH_SIGSET;
123*4887Schin 			if(sig < sh.sigmax)
124*4887Schin 				sh.sigflag[sig] |= SH_SIGSET;
125*4887Schin #if  defined(VMFL) && (VMALLOC_VERSION>=20031205L)
126*4887Schin 			if(abortsig(sig))
127*4887Schin 			{
128*4887Schin 				/* abort inside malloc, process when malloc returns */
129*4887Schin 				/* VMFL defined when using vmalloc() */
130*4887Schin 				Vmdisc_t* dp = vmdisc(Vmregion,0);
131*4887Schin 				if(dp)
132*4887Schin 					dp->exceptf = malloc_done;
133*4887Schin 			}
134*4887Schin #endif
135*4887Schin 			return;
136*4887Schin 		}
137*4887Schin 	}
138*4887Schin 	errno = 0;
139*4887Schin 	if(pp->mode==SH_JMPCMD)
140*4887Schin 		sh.lastsig = sig;
141*4887Schin 	if(trap)
142*4887Schin 	{
143*4887Schin 		/*
144*4887Schin 		 * propogate signal to foreground group
145*4887Schin 		 */
146*4887Schin 		if(sig==SIGHUP && job.curpgid)
147*4887Schin 			killpg(job.curpgid,SIGHUP);
148*4887Schin 		flag = SH_SIGTRAP;
149*4887Schin 	}
150*4887Schin 	else
151*4887Schin 	{
152*4887Schin 		sh.lastsig = sig;
153*4887Schin 		flag = SH_SIGSET;
154*4887Schin #ifdef SIGTSTP
155*4887Schin 		if(sig==SIGTSTP)
156*4887Schin 		{
157*4887Schin 			sh.trapnote |= SH_SIGTSTP;
158*4887Schin 			if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
159*4887Schin 			{
160*4887Schin 				sigrelease(sig);
161*4887Schin 				sh_exit(SH_EXITSIG);
162*4887Schin 				flag = 0;
163*4887Schin 			}
164*4887Schin 		}
165*4887Schin #endif /* SIGTSTP */
166*4887Schin 	}
167*4887Schin #ifdef ERROR_NOTIFY
168*4887Schin 	if((error_info.flags&ERROR_NOTIFY) && sh.bltinfun)
169*4887Schin 		action = (*sh.bltinfun)(-sig,(char**)0,(void*)0);
170*4887Schin #endif
171*4887Schin 	if(action>0)
172*4887Schin 		return;
173*4887Schin 	sh.trapnote |= flag;
174*4887Schin 	if(sig < sh.sigmax)
175*4887Schin 		sh.sigflag[sig] |= flag;
176*4887Schin 	if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
177*4887Schin 	{
178*4887Schin 		if(action<0)
179*4887Schin 			return;
180*4887Schin 		sigrelease(sig);
181*4887Schin 		sh_exit(SH_EXITSIG);
182*4887Schin 	}
183*4887Schin }
184*4887Schin 
185*4887Schin /*
186*4887Schin  * initialize signal handling
187*4887Schin  */
188*4887Schin void sh_siginit(void)
189*4887Schin {
190*4887Schin 	register int sig, n=SIGTERM+1;
191*4887Schin 	register const struct shtable2	*tp = shtab_signals;
192*4887Schin 	sig_begin();
193*4887Schin 	/* find the largest signal number in the table */
194*4887Schin 	while(*tp->sh_name)
195*4887Schin 	{
196*4887Schin 		if((sig=tp->sh_number&((1<<SH_SIGBITS)-1))>n && sig<SH_TRAP)
197*4887Schin 			n = sig;
198*4887Schin 		tp++;
199*4887Schin 	}
200*4887Schin #if defined(_SC_SIGRT_MAX) && defined(_SIGRTMAX)
201*4887Schin 	if((sig=SIGRTMAX+1)>n && sig<SH_TRAP)
202*4887Schin 		n = sig;
203*4887Schin #endif
204*4887Schin 	sh.sigmax = n;
205*4887Schin 	sh.st.trapcom = (char**)calloc(n,sizeof(char*));
206*4887Schin 	sh.sigflag = (unsigned char*)calloc(n,1);
207*4887Schin 	sh.sigmsg = (char**)calloc(n,sizeof(char*));
208*4887Schin 	for(tp=shtab_signals; sig=tp->sh_number; tp++)
209*4887Schin 	{
210*4887Schin 		n = (sig>>SH_SIGBITS);
211*4887Schin 		if((sig &= ((1<<SH_SIGBITS)-1)) > sh.sigmax)
212*4887Schin 			continue;
213*4887Schin 		sig--;
214*4887Schin #if defined(_SC_SIGRT_MIN) && defined(_SIGRTMIN)
215*4887Schin 		if(sig==_SIGRTMIN)
216*4887Schin 			sig = SIGRTMIN;
217*4887Schin #endif
218*4887Schin #if defined(_SC_SIGRT_MAX) && defined(_SIGRTMAX)
219*4887Schin 		if(sig==_SIGRTMAX)
220*4887Schin 			sig = SIGRTMAX;
221*4887Schin #endif
222*4887Schin 		if(sig>=0)
223*4887Schin 		{
224*4887Schin 			sh.sigflag[sig] = n;
225*4887Schin 			if(*tp->sh_name)
226*4887Schin 				sh.sigmsg[sig] = (char*)tp->sh_value;
227*4887Schin 		}
228*4887Schin 	}
229*4887Schin }
230*4887Schin 
231*4887Schin /*
232*4887Schin  * Turn on trap handler for signal <sig>
233*4887Schin  */
234*4887Schin void	sh_sigtrap(register int sig)
235*4887Schin {
236*4887Schin 	register int flag;
237*4887Schin 	void (*fun)(int);
238*4887Schin 	sh.st.otrapcom = 0;
239*4887Schin 	if(sig==0)
240*4887Schin 		sh_sigdone();
241*4887Schin 	else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
242*4887Schin 	{
243*4887Schin 		/* don't set signal if already set or off by parent */
244*4887Schin 		if((fun=signal(sig,sh_fault))==SIG_IGN)
245*4887Schin 		{
246*4887Schin 			signal(sig,SIG_IGN);
247*4887Schin 			flag |= SH_SIGOFF;
248*4887Schin 		}
249*4887Schin 		else
250*4887Schin 		{
251*4887Schin 			flag |= SH_SIGFAULT;
252*4887Schin 			if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault)
253*4887Schin 				signal(sig,fun);
254*4887Schin 		}
255*4887Schin 		flag &= ~(SH_SIGSET|SH_SIGTRAP);
256*4887Schin 		sh.sigflag[sig] = flag;
257*4887Schin 	}
258*4887Schin }
259*4887Schin 
260*4887Schin /*
261*4887Schin  * set signal handler so sh_done is called for all caught signals
262*4887Schin  */
263*4887Schin void	sh_sigdone(void)
264*4887Schin {
265*4887Schin 	register int 	flag, sig = sh.sigmax;
266*4887Schin 	sh.sigflag[0] |= SH_SIGFAULT;
267*4887Schin 	while(--sig>0)
268*4887Schin 	{
269*4887Schin 		flag = sh.sigflag[sig];
270*4887Schin 		if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
271*4887Schin 			sh_sigtrap(sig);
272*4887Schin 	}
273*4887Schin }
274*4887Schin 
275*4887Schin /*
276*4887Schin  * Restore to default signals
277*4887Schin  * Free the trap strings if mode is non-zero
278*4887Schin  * If mode>1 then ignored traps cause signal to be ignored
279*4887Schin  */
280*4887Schin void	sh_sigreset(register int mode)
281*4887Schin {
282*4887Schin 	register char	*trap;
283*4887Schin 	register int 	flag, sig=sh.st.trapmax;
284*4887Schin 	while(sig-- > 0)
285*4887Schin 	{
286*4887Schin 		if(trap=sh.st.trapcom[sig])
287*4887Schin 		{
288*4887Schin 			flag  = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET);
289*4887Schin 			if(*trap)
290*4887Schin 			{
291*4887Schin 				if(mode)
292*4887Schin 					free(trap);
293*4887Schin 				sh.st.trapcom[sig] = 0;
294*4887Schin 			}
295*4887Schin 			else if(sig && mode>1)
296*4887Schin 			{
297*4887Schin 				signal(sig,SIG_IGN);
298*4887Schin 				flag &= ~SH_SIGFAULT;
299*4887Schin 				flag |= SH_SIGOFF;
300*4887Schin 			}
301*4887Schin 			sh.sigflag[sig] = flag;
302*4887Schin 		}
303*4887Schin 	}
304*4887Schin 	for(sig=SH_DEBUGTRAP;sig>=0;sig--)
305*4887Schin 	{
306*4887Schin 		if(trap=sh.st.trap[sig])
307*4887Schin 		{
308*4887Schin 			if(mode)
309*4887Schin 				free(trap);
310*4887Schin 			sh.st.trap[sig] = 0;
311*4887Schin 		}
312*4887Schin 
313*4887Schin 	}
314*4887Schin 	sh.st.trapcom[0] = 0;
315*4887Schin 	if(mode)
316*4887Schin 		sh.st.trapmax = 0;
317*4887Schin 	sh.trapnote=0;
318*4887Schin }
319*4887Schin 
320*4887Schin /*
321*4887Schin  * free up trap if set and restore signal handler if modified
322*4887Schin  */
323*4887Schin void	sh_sigclear(register int sig)
324*4887Schin {
325*4887Schin 	register int flag = sh.sigflag[sig];
326*4887Schin 	register char *trap;
327*4887Schin 	sh.st.otrapcom=0;
328*4887Schin 	if(!(flag&SH_SIGFAULT))
329*4887Schin 		return;
330*4887Schin 	flag &= ~(SH_SIGTRAP|SH_SIGSET);
331*4887Schin 	if(trap=sh.st.trapcom[sig])
332*4887Schin 	{
333*4887Schin 		free(trap);
334*4887Schin 		sh.st.trapcom[sig]=0;
335*4887Schin 	}
336*4887Schin 	sh.sigflag[sig] = flag;
337*4887Schin }
338*4887Schin 
339*4887Schin /*
340*4887Schin  * check for traps
341*4887Schin  */
342*4887Schin 
343*4887Schin void	sh_chktrap(void)
344*4887Schin {
345*4887Schin 	register int 	sig=sh.st.trapmax;
346*4887Schin 	register char *trap;
347*4887Schin 	if(!sh.trapnote)
348*4887Schin 		sig=0;
349*4887Schin 	sh.trapnote &= ~SH_SIGTRAP;
350*4887Schin 	/* execute errexit trap first */
351*4887Schin 	if(sh_isstate(SH_ERREXIT) && sh.exitval)
352*4887Schin 	{
353*4887Schin 		int	sav_trapnote = sh.trapnote;
354*4887Schin 		sh.trapnote &= ~SH_SIGSET;
355*4887Schin 		if(sh.st.trap[SH_ERRTRAP])
356*4887Schin 			sh_trap(sh.st.trap[SH_ERRTRAP],0);
357*4887Schin 		sh.trapnote = sav_trapnote;
358*4887Schin 		if(sh_isoption(SH_ERREXIT))
359*4887Schin 		{
360*4887Schin 			struct checkpt	*pp = (struct checkpt*)sh.jmplist;
361*4887Schin 			pp->mode = SH_JMPEXIT;
362*4887Schin 			sh_exit(sh.exitval);
363*4887Schin 		}
364*4887Schin 	}
365*4887Schin 	if(sh.sigflag[SIGALRM]&SH_SIGALRM)
366*4887Schin 		sh_timetraps();
367*4887Schin 	while(--sig>=0)
368*4887Schin 	{
369*4887Schin 		if(sh.sigflag[sig]&SH_SIGTRAP)
370*4887Schin 		{
371*4887Schin 			sh.sigflag[sig] &= ~SH_SIGTRAP;
372*4887Schin 			if(trap=sh.st.trapcom[sig])
373*4887Schin 				sh_trap(trap,0);
374*4887Schin 		}
375*4887Schin 	}
376*4887Schin }
377*4887Schin 
378*4887Schin 
379*4887Schin /*
380*4887Schin  * parse and execute the given trap string, stream or tree depending on mode
381*4887Schin  * mode==0 for string, mode==1 for stream, mode==2 for parse tree
382*4887Schin  */
383*4887Schin int sh_trap(const char *trap, int mode)
384*4887Schin {
385*4887Schin 	int	jmpval, savxit = sh.exitval;
386*4887Schin 	int	was_history = sh_isstate(SH_HISTORY);
387*4887Schin 	int	was_verbose = sh_isstate(SH_VERBOSE);
388*4887Schin 	int	staktop = staktell();
389*4887Schin 	char	*savptr = stakfreeze(0);
390*4887Schin 	struct	checkpt buff;
391*4887Schin 	Fcin_t	savefc;
392*4887Schin 	fcsave(&savefc);
393*4887Schin 	sh_offstate(SH_HISTORY);
394*4887Schin 	sh_offstate(SH_VERBOSE);
395*4887Schin 	sh.intrap++;
396*4887Schin 	sh_pushcontext(&buff,SH_JMPTRAP);
397*4887Schin 	jmpval = sigsetjmp(buff.buff,0);
398*4887Schin 	if(jmpval == 0)
399*4887Schin 	{
400*4887Schin 		if(mode==2)
401*4887Schin 			sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT));
402*4887Schin 		else
403*4887Schin 		{
404*4887Schin 			Sfio_t *sp;
405*4887Schin 			if(mode)
406*4887Schin 				sp = (Sfio_t*)trap;
407*4887Schin 			else
408*4887Schin 				sp = sfopen(NIL(Sfio_t*),trap,"s");
409*4887Schin 			sh_eval(sp,0);
410*4887Schin 		}
411*4887Schin 	}
412*4887Schin 	else if(indone)
413*4887Schin 	{
414*4887Schin 		if(jmpval==SH_JMPSCRIPT)
415*4887Schin 			indone=0;
416*4887Schin 		else
417*4887Schin 		{
418*4887Schin 			if(jmpval==SH_JMPEXIT)
419*4887Schin 				savxit = sh.exitval;
420*4887Schin 			jmpval=SH_JMPTRAP;
421*4887Schin 		}
422*4887Schin 	}
423*4887Schin 	sh_popcontext(&buff);
424*4887Schin 	sh.intrap--;
425*4887Schin 	sfsync(sh.outpool);
426*4887Schin 	if(jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
427*4887Schin 		sh.exitval=savxit;
428*4887Schin 	stakset(savptr,staktop);
429*4887Schin 	fcrestore(&savefc);
430*4887Schin 	if(was_history)
431*4887Schin 		sh_onstate(SH_HISTORY);
432*4887Schin 	if(was_verbose)
433*4887Schin 		sh_onstate(SH_VERBOSE);
434*4887Schin 	exitset();
435*4887Schin 	if(jmpval>SH_JMPTRAP)
436*4887Schin 		siglongjmp(*sh.jmplist,jmpval);
437*4887Schin 	return(sh.exitval);
438*4887Schin }
439*4887Schin 
440*4887Schin /*
441*4887Schin  * exit the current scope and jump to an earlier one based on pp->mode
442*4887Schin  */
443*4887Schin void sh_exit(register int xno)
444*4887Schin {
445*4887Schin 	register struct checkpt	*pp = (struct checkpt*)sh.jmplist;
446*4887Schin 	register int		sig=0;
447*4887Schin 	register Sfio_t*	pool;
448*4887Schin 	sh.exitval=xno;
449*4887Schin 	if(xno==SH_EXITSIG)
450*4887Schin 		sh.exitval |= (sig=sh.lastsig);
451*4887Schin #ifdef SIGTSTP
452*4887Schin 	if(sh.trapnote&SH_SIGTSTP)
453*4887Schin 	{
454*4887Schin 		/* ^Z detected by the shell */
455*4887Schin 		sh.trapnote = 0;
456*4887Schin 		sh.sigflag[SIGTSTP] = 0;
457*4887Schin 		if(!sh.subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
458*4887Schin 			return;
459*4887Schin 		if(sh_isstate(SH_TIMING))
460*4887Schin 			return;
461*4887Schin 		/* Handles ^Z for shell builtins, subshells, and functs */
462*4887Schin 		sh.lastsig = 0;
463*4887Schin 		sh_onstate(SH_MONITOR);
464*4887Schin 		sh_offstate(SH_STOPOK);
465*4887Schin 		sh.trapnote = 0;
466*4887Schin 		if(!sh.subshell && (sig=sh_fork(0,NIL(int*))))
467*4887Schin 		{
468*4887Schin 			job.curpgid = 0;
469*4887Schin 			job.parent = (pid_t)-1;
470*4887Schin 			job_wait(sig);
471*4887Schin 			job.parent = 0;
472*4887Schin 			sh.sigflag[SIGTSTP] = 0;
473*4887Schin 			/* wait for child to stop */
474*4887Schin 			sh.exitval = (SH_EXITSIG|SIGTSTP);
475*4887Schin 			/* return to prompt mode */
476*4887Schin 			pp->mode = SH_JMPERREXIT;
477*4887Schin 		}
478*4887Schin 		else
479*4887Schin 		{
480*4887Schin 			if(sh.subshell)
481*4887Schin 				sh_subfork();
482*4887Schin 			/* child process, put to sleep */
483*4887Schin 			sh_offstate(SH_STOPOK);
484*4887Schin 			sh_offstate(SH_MONITOR);
485*4887Schin 			sh.sigflag[SIGTSTP] = 0;
486*4887Schin 			/* stop child job */
487*4887Schin 			killpg(job.curpgid,SIGTSTP);
488*4887Schin 			/* child resumes */
489*4887Schin 			job_clear();
490*4887Schin 			sh.forked = 1;
491*4887Schin 			sh.exitval = (xno&SH_EXITMASK);
492*4887Schin 			return;
493*4887Schin 		}
494*4887Schin 	}
495*4887Schin #endif /* SIGTSTP */
496*4887Schin 	/* unlock output pool */
497*4887Schin 	sh_offstate(SH_NOTRACK);
498*4887Schin 	if(!(pool=sfpool(NIL(Sfio_t*),sh.outpool,SF_WRITE)))
499*4887Schin 		pool = sh.outpool; /* can't happen? */
500*4887Schin 	sfclrlock(pool);
501*4887Schin #ifdef SIGPIPE
502*4887Schin 	if(sh.lastsig==SIGPIPE)
503*4887Schin 		sfpurge(pool);
504*4887Schin #endif /* SIGPIPE */
505*4887Schin 	sfclrlock(sfstdin);
506*4887Schin 	if(!pp)
507*4887Schin 		sh_done(sig);
508*4887Schin 	sh.prefix = 0;
509*4887Schin 	if(pp->mode == SH_JMPSCRIPT && !pp->prev)
510*4887Schin 		sh_done(sig);
511*4887Schin 	siglongjmp(pp->buff,pp->mode);
512*4887Schin }
513*4887Schin 
514*4887Schin /*
515*4887Schin  * This is the exit routine for the shell
516*4887Schin  */
517*4887Schin 
518*4887Schin void sh_done(register int sig)
519*4887Schin {
520*4887Schin 	register char *t;
521*4887Schin 	register int savxit = sh.exitval;
522*4887Schin 	sh.trapnote = 0;
523*4887Schin 	indone=1;
524*4887Schin 	if(sig==0)
525*4887Schin 		sig = sh.lastsig;
526*4887Schin 	if(sh.userinit)
527*4887Schin 		(*sh.userinit)(-1);
528*4887Schin 	if(t=sh.st.trapcom[0])
529*4887Schin 	{
530*4887Schin 		sh.st.trapcom[0]=0; /*should free but not long */
531*4887Schin 		sh.oldexit = savxit;
532*4887Schin 		sh_trap(t,0);
533*4887Schin 		savxit = sh.exitval;
534*4887Schin 	}
535*4887Schin 	else
536*4887Schin 	{
537*4887Schin 		/* avoid recursive call for set -e */
538*4887Schin 		sh_offstate(SH_ERREXIT);
539*4887Schin 		sh_chktrap();
540*4887Schin 	}
541*4887Schin 	sh_freeup();
542*4887Schin #if SHOPT_ACCT
543*4887Schin 	sh_accend();
544*4887Schin #endif	/* SHOPT_ACCT */
545*4887Schin #if SHOPT_VSH || SHOPT_ESH
546*4887Schin 	if(sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
547*4887Schin 		tty_cooked(-1);
548*4887Schin #endif
549*4887Schin #ifdef JOBS
550*4887Schin 	if((sh_isoption(SH_INTERACTIVE) && sh.login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
551*4887Schin 		job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**));
552*4887Schin #endif	/* JOBS */
553*4887Schin 	job_close();
554*4887Schin 	if(nv_search("VMTRACE", sh.var_tree,0))
555*4887Schin 		strmatch((char*)0,(char*)0);
556*4887Schin 	sfsync((Sfio_t*)sfstdin);
557*4887Schin 	sfsync((Sfio_t*)sh.outpool);
558*4887Schin 	sfsync((Sfio_t*)sfstdout);
559*4887Schin 	if(sig)
560*4887Schin 	{
561*4887Schin 		/* generate fault termination code */
562*4887Schin 		signal(sig,SIG_DFL);
563*4887Schin 		sigrelease(sig);
564*4887Schin 		kill(getpid(),sig);
565*4887Schin 		pause();
566*4887Schin 	}
567*4887Schin #if SHOPT_KIA
568*4887Schin 	if(sh_isoption(SH_NOEXEC))
569*4887Schin 		kiaclose();
570*4887Schin #endif /* SHOPT_KIA */
571*4887Schin 	exit(savxit&SH_EXITMASK);
572*4887Schin }
573*4887Schin 
574