1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1982-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * Fault handling routines
23da2e3ebdSchin *
24da2e3ebdSchin * David Korn
25da2e3ebdSchin * AT&T Labs
26da2e3ebdSchin *
27da2e3ebdSchin */
28da2e3ebdSchin
29da2e3ebdSchin #include "defs.h"
30da2e3ebdSchin #include <fcin.h>
31da2e3ebdSchin #include "io.h"
32da2e3ebdSchin #include "history.h"
337c2fbfb3SApril Chin #include "shlex.h"
34da2e3ebdSchin #include "variables.h"
35da2e3ebdSchin #include "jobs.h"
36da2e3ebdSchin #include "path.h"
377c2fbfb3SApril Chin #include "builtins.h"
38*b30d1939SAndy Fiddaman #include "ulimit.h"
39da2e3ebdSchin
40da2e3ebdSchin #define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV)
41da2e3ebdSchin
42da2e3ebdSchin static char indone;
43*b30d1939SAndy Fiddaman static int cursig = -1;
44da2e3ebdSchin
45da2e3ebdSchin #if !_std_malloc
46da2e3ebdSchin # include <vmalloc.h>
47da2e3ebdSchin #endif
48da2e3ebdSchin #if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
49da2e3ebdSchin /*
50da2e3ebdSchin * This exception handler is called after vmalloc() unlocks the region
51da2e3ebdSchin */
malloc_done(Vmalloc_t * vm,int type,Void_t * val,Vmdisc_t * dp)52da2e3ebdSchin static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp)
53da2e3ebdSchin {
54da2e3ebdSchin dp->exceptf = 0;
55da2e3ebdSchin sh_exit(SH_EXITSIG);
56da2e3ebdSchin return(0);
57da2e3ebdSchin }
58da2e3ebdSchin #endif
59da2e3ebdSchin
60da2e3ebdSchin /*
61da2e3ebdSchin * Most signals caught or ignored by the shell come here
62da2e3ebdSchin */
sh_fault(register int sig)63da2e3ebdSchin void sh_fault(register int sig)
64da2e3ebdSchin {
657c2fbfb3SApril Chin register Shell_t *shp = sh_getinterp();
667c2fbfb3SApril Chin register int flag=0;
677c2fbfb3SApril Chin register char *trap;
687c2fbfb3SApril Chin register struct checkpt *pp = (struct checkpt*)shp->jmplist;
69da2e3ebdSchin int action=0;
70da2e3ebdSchin /* reset handler */
71da2e3ebdSchin if(!(sig&SH_TRAP))
72da2e3ebdSchin signal(sig, sh_fault);
73da2e3ebdSchin sig &= ~SH_TRAP;
74da2e3ebdSchin #ifdef SIGWINCH
75da2e3ebdSchin if(sig==SIGWINCH)
76da2e3ebdSchin {
77da2e3ebdSchin int rows=0, cols=0;
78da2e3ebdSchin int32_t v;
79da2e3ebdSchin astwinsize(2,&rows,&cols);
80da2e3ebdSchin if(v = cols)
817c2fbfb3SApril Chin nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY);
82da2e3ebdSchin if(v = rows)
837c2fbfb3SApril Chin nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY);
847c2fbfb3SApril Chin shp->winch++;
85da2e3ebdSchin }
86da2e3ebdSchin #endif /* SIGWINCH */
87*b30d1939SAndy Fiddaman trap = shp->st.trapcom[sig];
887c2fbfb3SApril Chin if(shp->savesig)
89da2e3ebdSchin {
90da2e3ebdSchin /* critical region, save and process later */
91*b30d1939SAndy Fiddaman if(!(shp->sigflag[sig]&SH_SIGIGNORE))
92*b30d1939SAndy Fiddaman shp->savesig = sig;
937c2fbfb3SApril Chin return;
947c2fbfb3SApril Chin }
957c2fbfb3SApril Chin if(sig==SIGALRM && shp->bltinfun==b_sleep)
967c2fbfb3SApril Chin {
977c2fbfb3SApril Chin if(trap && *trap)
987c2fbfb3SApril Chin {
997c2fbfb3SApril Chin shp->trapnote |= SH_SIGTRAP;
1007c2fbfb3SApril Chin shp->sigflag[sig] |= SH_SIGTRAP;
1017c2fbfb3SApril Chin }
1027c2fbfb3SApril Chin return;
1037c2fbfb3SApril Chin }
104*b30d1939SAndy Fiddaman if(shp->subshell && trap && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH && sig!=SIGCONT)
1057c2fbfb3SApril Chin {
1067c2fbfb3SApril Chin shp->exitval = SH_EXITSIG|sig;
1077c2fbfb3SApril Chin sh_subfork();
1087c2fbfb3SApril Chin shp->exitval = 0;
109da2e3ebdSchin return;
110da2e3ebdSchin }
111da2e3ebdSchin /* handle ignored signals */
1127c2fbfb3SApril Chin if(trap && *trap==0)
113da2e3ebdSchin return;
1147c2fbfb3SApril Chin flag = shp->sigflag[sig]&~SH_SIGOFF;
115da2e3ebdSchin if(!trap)
116da2e3ebdSchin {
1177c2fbfb3SApril Chin if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE))
1187c2fbfb3SApril Chin return;
119da2e3ebdSchin if(flag&SH_SIGIGNORE)
120*b30d1939SAndy Fiddaman {
121*b30d1939SAndy Fiddaman if(shp->subshell)
122*b30d1939SAndy Fiddaman shp->ignsig = sig;
123*b30d1939SAndy Fiddaman sigrelease(sig);
124da2e3ebdSchin return;
125*b30d1939SAndy Fiddaman }
126da2e3ebdSchin if(flag&SH_SIGDONE)
127da2e3ebdSchin {
128da2e3ebdSchin void *ptr=0;
1297c2fbfb3SApril Chin if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell)
130da2e3ebdSchin {
131da2e3ebdSchin /* check for TERM signal between fork/exec */
132da2e3ebdSchin if(sig==SIGTERM && job.in_critical)
1337c2fbfb3SApril Chin shp->trapnote |= SH_SIGTERM;
134da2e3ebdSchin return;
135da2e3ebdSchin }
1367c2fbfb3SApril Chin shp->lastsig = sig;
137da2e3ebdSchin sigrelease(sig);
138*b30d1939SAndy Fiddaman if(pp->mode != SH_JMPSUB)
139*b30d1939SAndy Fiddaman {
140*b30d1939SAndy Fiddaman if(pp->mode < SH_JMPSUB)
141*b30d1939SAndy Fiddaman pp->mode = shp->subshell?SH_JMPSUB:SH_JMPFUN;
142*b30d1939SAndy Fiddaman else
143*b30d1939SAndy Fiddaman pp->mode = SH_JMPEXIT;
144*b30d1939SAndy Fiddaman }
145*b30d1939SAndy Fiddaman if(shp->subshell)
146*b30d1939SAndy Fiddaman sh_exit(SH_EXITSIG);
147da2e3ebdSchin if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1))))
148da2e3ebdSchin {
149da2e3ebdSchin if(ptr)
150da2e3ebdSchin free(ptr);
151*b30d1939SAndy Fiddaman sh_done(shp,sig);
152da2e3ebdSchin }
153da2e3ebdSchin /* mark signal and continue */
1547c2fbfb3SApril Chin shp->trapnote |= SH_SIGSET;
155*b30d1939SAndy Fiddaman if(sig <= shp->gd->sigmax)
1567c2fbfb3SApril Chin shp->sigflag[sig] |= SH_SIGSET;
157da2e3ebdSchin #if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
158da2e3ebdSchin if(abortsig(sig))
159da2e3ebdSchin {
160da2e3ebdSchin /* abort inside malloc, process when malloc returns */
161da2e3ebdSchin /* VMFL defined when using vmalloc() */
162da2e3ebdSchin Vmdisc_t* dp = vmdisc(Vmregion,0);
163da2e3ebdSchin if(dp)
164da2e3ebdSchin dp->exceptf = malloc_done;
165da2e3ebdSchin }
166da2e3ebdSchin #endif
167da2e3ebdSchin return;
168da2e3ebdSchin }
169da2e3ebdSchin }
170da2e3ebdSchin errno = 0;
171*b30d1939SAndy Fiddaman if(pp->mode==SH_JMPCMD || (pp->mode==1 && shp->bltinfun) && !(flag&SH_SIGIGNORE))
1727c2fbfb3SApril Chin shp->lastsig = sig;
173da2e3ebdSchin if(trap)
174da2e3ebdSchin {
175da2e3ebdSchin /*
176da2e3ebdSchin * propogate signal to foreground group
177da2e3ebdSchin */
178da2e3ebdSchin if(sig==SIGHUP && job.curpgid)
179da2e3ebdSchin killpg(job.curpgid,SIGHUP);
180da2e3ebdSchin flag = SH_SIGTRAP;
181da2e3ebdSchin }
182da2e3ebdSchin else
183da2e3ebdSchin {
1847c2fbfb3SApril Chin shp->lastsig = sig;
185da2e3ebdSchin flag = SH_SIGSET;
186da2e3ebdSchin #ifdef SIGTSTP
187da2e3ebdSchin if(sig==SIGTSTP)
188da2e3ebdSchin {
1897c2fbfb3SApril Chin shp->trapnote |= SH_SIGTSTP;
190da2e3ebdSchin if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
191da2e3ebdSchin {
192da2e3ebdSchin sigrelease(sig);
193da2e3ebdSchin sh_exit(SH_EXITSIG);
194*b30d1939SAndy Fiddaman return;
195da2e3ebdSchin }
196da2e3ebdSchin }
197da2e3ebdSchin #endif /* SIGTSTP */
198da2e3ebdSchin }
199da2e3ebdSchin #ifdef ERROR_NOTIFY
2007c2fbfb3SApril Chin if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun)
2017c2fbfb3SApril Chin action = (*shp->bltinfun)(-sig,(char**)0,(void*)0);
202da2e3ebdSchin if(action>0)
203da2e3ebdSchin return;
2047c2fbfb3SApril Chin #endif
2057c2fbfb3SApril Chin if(shp->bltinfun && shp->bltindata.notify)
2067c2fbfb3SApril Chin {
2077c2fbfb3SApril Chin shp->bltindata.sigset = 1;
2087c2fbfb3SApril Chin return;
2097c2fbfb3SApril Chin }
2107c2fbfb3SApril Chin shp->trapnote |= flag;
211*b30d1939SAndy Fiddaman if(sig <= shp->gd->sigmax)
2127c2fbfb3SApril Chin shp->sigflag[sig] |= flag;
213da2e3ebdSchin if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
214da2e3ebdSchin {
215da2e3ebdSchin if(action<0)
216da2e3ebdSchin return;
217da2e3ebdSchin sigrelease(sig);
218da2e3ebdSchin sh_exit(SH_EXITSIG);
219da2e3ebdSchin }
220da2e3ebdSchin }
221da2e3ebdSchin
222da2e3ebdSchin /*
223da2e3ebdSchin * initialize signal handling
224da2e3ebdSchin */
sh_siginit(void * ptr)2257c2fbfb3SApril Chin void sh_siginit(void *ptr)
226da2e3ebdSchin {
2277c2fbfb3SApril Chin Shell_t *shp = (Shell_t*)ptr;
22834f9b3eeSRoland Mainz register int sig, n;
229da2e3ebdSchin register const struct shtable2 *tp = shtab_signals;
230da2e3ebdSchin sig_begin();
231da2e3ebdSchin /* find the largest signal number in the table */
23234f9b3eeSRoland Mainz #if defined(SIGRTMIN) && defined(SIGRTMAX)
23334f9b3eeSRoland Mainz if ((n = SIGRTMIN) > 0 && (sig = SIGRTMAX) > n && sig < SH_TRAP)
23434f9b3eeSRoland Mainz {
235*b30d1939SAndy Fiddaman shp->gd->sigruntime[SH_SIGRTMIN] = n;
236*b30d1939SAndy Fiddaman shp->gd->sigruntime[SH_SIGRTMAX] = sig;
23734f9b3eeSRoland Mainz }
23834f9b3eeSRoland Mainz #endif /* SIGRTMIN && SIGRTMAX */
23934f9b3eeSRoland Mainz n = SIGTERM;
240da2e3ebdSchin while(*tp->sh_name)
241da2e3ebdSchin {
24234f9b3eeSRoland Mainz sig = (tp->sh_number&((1<<SH_SIGBITS)-1));
24334f9b3eeSRoland Mainz if (!(sig-- & SH_TRAP))
24434f9b3eeSRoland Mainz {
24534f9b3eeSRoland Mainz if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME)
246*b30d1939SAndy Fiddaman sig = shp->gd->sigruntime[sig];
24734f9b3eeSRoland Mainz if(sig>n && sig<SH_TRAP)
24834f9b3eeSRoland Mainz n = sig;
24934f9b3eeSRoland Mainz }
250da2e3ebdSchin tp++;
251da2e3ebdSchin }
252*b30d1939SAndy Fiddaman shp->gd->sigmax = n++;
2537c2fbfb3SApril Chin shp->st.trapcom = (char**)calloc(n,sizeof(char*));
2547c2fbfb3SApril Chin shp->sigflag = (unsigned char*)calloc(n,1);
255*b30d1939SAndy Fiddaman shp->gd->sigmsg = (char**)calloc(n,sizeof(char*));
256da2e3ebdSchin for(tp=shtab_signals; sig=tp->sh_number; tp++)
257da2e3ebdSchin {
258da2e3ebdSchin n = (sig>>SH_SIGBITS);
259*b30d1939SAndy Fiddaman if((sig &= ((1<<SH_SIGBITS)-1)) > (shp->gd->sigmax+1))
260da2e3ebdSchin continue;
261da2e3ebdSchin sig--;
2627c2fbfb3SApril Chin if(n&SH_SIGRUNTIME)
263*b30d1939SAndy Fiddaman sig = shp->gd->sigruntime[sig];
264da2e3ebdSchin if(sig>=0)
265da2e3ebdSchin {
2667c2fbfb3SApril Chin shp->sigflag[sig] = n;
267da2e3ebdSchin if(*tp->sh_name)
268*b30d1939SAndy Fiddaman shp->gd->sigmsg[sig] = (char*)tp->sh_value;
269da2e3ebdSchin }
270da2e3ebdSchin }
271da2e3ebdSchin }
272da2e3ebdSchin
273da2e3ebdSchin /*
274da2e3ebdSchin * Turn on trap handler for signal <sig>
275da2e3ebdSchin */
sh_sigtrap(register int sig)276da2e3ebdSchin void sh_sigtrap(register int sig)
277da2e3ebdSchin {
278da2e3ebdSchin register int flag;
279da2e3ebdSchin void (*fun)(int);
280da2e3ebdSchin sh.st.otrapcom = 0;
281da2e3ebdSchin if(sig==0)
282da2e3ebdSchin sh_sigdone();
283da2e3ebdSchin else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
284da2e3ebdSchin {
285da2e3ebdSchin /* don't set signal if already set or off by parent */
286da2e3ebdSchin if((fun=signal(sig,sh_fault))==SIG_IGN)
287da2e3ebdSchin {
288da2e3ebdSchin signal(sig,SIG_IGN);
289da2e3ebdSchin flag |= SH_SIGOFF;
290da2e3ebdSchin }
291da2e3ebdSchin else
292da2e3ebdSchin {
293da2e3ebdSchin flag |= SH_SIGFAULT;
294da2e3ebdSchin if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault)
295da2e3ebdSchin signal(sig,fun);
296da2e3ebdSchin }
297da2e3ebdSchin flag &= ~(SH_SIGSET|SH_SIGTRAP);
298da2e3ebdSchin sh.sigflag[sig] = flag;
299da2e3ebdSchin }
300da2e3ebdSchin }
301da2e3ebdSchin
302da2e3ebdSchin /*
303da2e3ebdSchin * set signal handler so sh_done is called for all caught signals
304da2e3ebdSchin */
sh_sigdone(void)305da2e3ebdSchin void sh_sigdone(void)
306da2e3ebdSchin {
307*b30d1939SAndy Fiddaman register int flag, sig = shgd->sigmax;
308da2e3ebdSchin sh.sigflag[0] |= SH_SIGFAULT;
309*b30d1939SAndy Fiddaman for(sig=shgd->sigmax; sig>0; sig--)
310da2e3ebdSchin {
311da2e3ebdSchin flag = sh.sigflag[sig];
312da2e3ebdSchin if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
313da2e3ebdSchin sh_sigtrap(sig);
314da2e3ebdSchin }
315da2e3ebdSchin }
316da2e3ebdSchin
317da2e3ebdSchin /*
318da2e3ebdSchin * Restore to default signals
319da2e3ebdSchin * Free the trap strings if mode is non-zero
320da2e3ebdSchin * If mode>1 then ignored traps cause signal to be ignored
321da2e3ebdSchin */
sh_sigreset(register int mode)322da2e3ebdSchin void sh_sigreset(register int mode)
323da2e3ebdSchin {
324da2e3ebdSchin register char *trap;
325da2e3ebdSchin register int flag, sig=sh.st.trapmax;
326da2e3ebdSchin while(sig-- > 0)
327da2e3ebdSchin {
328da2e3ebdSchin if(trap=sh.st.trapcom[sig])
329da2e3ebdSchin {
330da2e3ebdSchin flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET);
331da2e3ebdSchin if(*trap)
332da2e3ebdSchin {
333da2e3ebdSchin if(mode)
334da2e3ebdSchin free(trap);
335da2e3ebdSchin sh.st.trapcom[sig] = 0;
336da2e3ebdSchin }
337da2e3ebdSchin else if(sig && mode>1)
338da2e3ebdSchin {
33934f9b3eeSRoland Mainz if(sig!=SIGCHLD)
34034f9b3eeSRoland Mainz signal(sig,SIG_IGN);
341da2e3ebdSchin flag &= ~SH_SIGFAULT;
342da2e3ebdSchin flag |= SH_SIGOFF;
343da2e3ebdSchin }
344da2e3ebdSchin sh.sigflag[sig] = flag;
345da2e3ebdSchin }
346da2e3ebdSchin }
3477c2fbfb3SApril Chin for(sig=SH_DEBUGTRAP-1;sig>=0;sig--)
348da2e3ebdSchin {
349da2e3ebdSchin if(trap=sh.st.trap[sig])
350da2e3ebdSchin {
351da2e3ebdSchin if(mode)
352da2e3ebdSchin free(trap);
353da2e3ebdSchin sh.st.trap[sig] = 0;
354da2e3ebdSchin }
355da2e3ebdSchin
356da2e3ebdSchin }
357da2e3ebdSchin sh.st.trapcom[0] = 0;
358da2e3ebdSchin if(mode)
359da2e3ebdSchin sh.st.trapmax = 0;
360da2e3ebdSchin sh.trapnote=0;
361da2e3ebdSchin }
362da2e3ebdSchin
363da2e3ebdSchin /*
364da2e3ebdSchin * free up trap if set and restore signal handler if modified
365da2e3ebdSchin */
sh_sigclear(register int sig)366da2e3ebdSchin void sh_sigclear(register int sig)
367da2e3ebdSchin {
368da2e3ebdSchin register int flag = sh.sigflag[sig];
369da2e3ebdSchin register char *trap;
370da2e3ebdSchin sh.st.otrapcom=0;
371da2e3ebdSchin if(!(flag&SH_SIGFAULT))
372da2e3ebdSchin return;
373da2e3ebdSchin flag &= ~(SH_SIGTRAP|SH_SIGSET);
374da2e3ebdSchin if(trap=sh.st.trapcom[sig])
375da2e3ebdSchin {
3763e14f97fSRoger A. Faulkner if(!sh.subshell)
3773e14f97fSRoger A. Faulkner free(trap);
378da2e3ebdSchin sh.st.trapcom[sig]=0;
379da2e3ebdSchin }
380da2e3ebdSchin sh.sigflag[sig] = flag;
381da2e3ebdSchin }
382da2e3ebdSchin
383da2e3ebdSchin /*
384da2e3ebdSchin * check for traps
385da2e3ebdSchin */
386da2e3ebdSchin
sh_chktrap(Shell_t * shp)387*b30d1939SAndy Fiddaman void sh_chktrap(Shell_t* shp)
388da2e3ebdSchin {
389*b30d1939SAndy Fiddaman register int sig=shp->st.trapmax;
390da2e3ebdSchin register char *trap;
391*b30d1939SAndy Fiddaman if(!(shp->trapnote&~SH_SIGIGNORE))
392da2e3ebdSchin sig=0;
393*b30d1939SAndy Fiddaman shp->trapnote &= ~SH_SIGTRAP;
394da2e3ebdSchin /* execute errexit trap first */
395*b30d1939SAndy Fiddaman if(sh_isstate(SH_ERREXIT) && shp->exitval)
396da2e3ebdSchin {
397*b30d1939SAndy Fiddaman int sav_trapnote = shp->trapnote;
398*b30d1939SAndy Fiddaman shp->trapnote &= ~SH_SIGSET;
399*b30d1939SAndy Fiddaman if(shp->st.trap[SH_ERRTRAP])
4007c2fbfb3SApril Chin {
401*b30d1939SAndy Fiddaman trap = shp->st.trap[SH_ERRTRAP];
402*b30d1939SAndy Fiddaman shp->st.trap[SH_ERRTRAP] = 0;
4037c2fbfb3SApril Chin sh_trap(trap,0);
404*b30d1939SAndy Fiddaman shp->st.trap[SH_ERRTRAP] = trap;
4057c2fbfb3SApril Chin }
406*b30d1939SAndy Fiddaman shp->trapnote = sav_trapnote;
407da2e3ebdSchin if(sh_isoption(SH_ERREXIT))
408da2e3ebdSchin {
409*b30d1939SAndy Fiddaman struct checkpt *pp = (struct checkpt*)shp->jmplist;
410da2e3ebdSchin pp->mode = SH_JMPEXIT;
411*b30d1939SAndy Fiddaman sh_exit(shp->exitval);
412da2e3ebdSchin }
413da2e3ebdSchin }
414*b30d1939SAndy Fiddaman if(shp->sigflag[SIGALRM]&SH_SIGALRM)
415*b30d1939SAndy Fiddaman sh_timetraps(shp);
41634f9b3eeSRoland Mainz #ifdef SHOPT_BGX
417*b30d1939SAndy Fiddaman if((shp->sigflag[SIGCHLD]&SH_SIGTRAP) && shp->st.trapcom[SIGCHLD])
418*b30d1939SAndy Fiddaman job_chldtrap(shp,shp->st.trapcom[SIGCHLD],1);
41934f9b3eeSRoland Mainz #endif /* SHOPT_BGX */
4203e14f97fSRoger A. Faulkner while(--sig>=0)
421da2e3ebdSchin {
422*b30d1939SAndy Fiddaman if(sig==cursig)
423*b30d1939SAndy Fiddaman continue;
4243e14f97fSRoger A. Faulkner #ifdef SHOPT_BGX
4253e14f97fSRoger A. Faulkner if(sig==SIGCHLD)
4263e14f97fSRoger A. Faulkner continue;
4273e14f97fSRoger A. Faulkner #endif /* SHOPT_BGX */
428*b30d1939SAndy Fiddaman if(shp->sigflag[sig]&SH_SIGTRAP)
429da2e3ebdSchin {
430*b30d1939SAndy Fiddaman shp->sigflag[sig] &= ~SH_SIGTRAP;
431*b30d1939SAndy Fiddaman if(trap=shp->st.trapcom[sig])
43234f9b3eeSRoland Mainz {
433*b30d1939SAndy Fiddaman cursig = sig;
43434f9b3eeSRoland Mainz sh_trap(trap,0);
435*b30d1939SAndy Fiddaman cursig = -1;
43634f9b3eeSRoland Mainz }
437da2e3ebdSchin }
438da2e3ebdSchin }
439da2e3ebdSchin }
440da2e3ebdSchin
441da2e3ebdSchin
442da2e3ebdSchin /*
443da2e3ebdSchin * parse and execute the given trap string, stream or tree depending on mode
444da2e3ebdSchin * mode==0 for string, mode==1 for stream, mode==2 for parse tree
445da2e3ebdSchin */
sh_trap(const char * trap,int mode)446da2e3ebdSchin int sh_trap(const char *trap, int mode)
447da2e3ebdSchin {
4487c2fbfb3SApril Chin Shell_t *shp = sh_getinterp();
4497c2fbfb3SApril Chin int jmpval, savxit = shp->exitval;
450da2e3ebdSchin int was_history = sh_isstate(SH_HISTORY);
451da2e3ebdSchin int was_verbose = sh_isstate(SH_VERBOSE);
452da2e3ebdSchin int staktop = staktell();
453da2e3ebdSchin char *savptr = stakfreeze(0);
4543e14f97fSRoger A. Faulkner char ifstable[256];
455da2e3ebdSchin struct checkpt buff;
456da2e3ebdSchin Fcin_t savefc;
457da2e3ebdSchin fcsave(&savefc);
4583e14f97fSRoger A. Faulkner memcpy(ifstable,shp->ifstable,sizeof(ifstable));
459da2e3ebdSchin sh_offstate(SH_HISTORY);
460da2e3ebdSchin sh_offstate(SH_VERBOSE);
4617c2fbfb3SApril Chin shp->intrap++;
462*b30d1939SAndy Fiddaman sh_pushcontext(shp,&buff,SH_JMPTRAP);
463da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
464da2e3ebdSchin if(jmpval == 0)
465da2e3ebdSchin {
466da2e3ebdSchin if(mode==2)
467da2e3ebdSchin sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT));
468da2e3ebdSchin else
469da2e3ebdSchin {
470da2e3ebdSchin Sfio_t *sp;
471da2e3ebdSchin if(mode)
472da2e3ebdSchin sp = (Sfio_t*)trap;
473da2e3ebdSchin else
474da2e3ebdSchin sp = sfopen(NIL(Sfio_t*),trap,"s");
475da2e3ebdSchin sh_eval(sp,0);
476da2e3ebdSchin }
477da2e3ebdSchin }
478da2e3ebdSchin else if(indone)
479da2e3ebdSchin {
480da2e3ebdSchin if(jmpval==SH_JMPSCRIPT)
481da2e3ebdSchin indone=0;
482da2e3ebdSchin else
483da2e3ebdSchin {
484da2e3ebdSchin if(jmpval==SH_JMPEXIT)
4857c2fbfb3SApril Chin savxit = shp->exitval;
486da2e3ebdSchin jmpval=SH_JMPTRAP;
487da2e3ebdSchin }
488da2e3ebdSchin }
489*b30d1939SAndy Fiddaman sh_popcontext(shp,&buff);
4907c2fbfb3SApril Chin shp->intrap--;
4917c2fbfb3SApril Chin sfsync(shp->outpool);
4927c2fbfb3SApril Chin if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
4937c2fbfb3SApril Chin shp->exitval=savxit;
494da2e3ebdSchin stakset(savptr,staktop);
495da2e3ebdSchin fcrestore(&savefc);
4963e14f97fSRoger A. Faulkner memcpy(shp->ifstable,ifstable,sizeof(ifstable));
497da2e3ebdSchin if(was_history)
498da2e3ebdSchin sh_onstate(SH_HISTORY);
499da2e3ebdSchin if(was_verbose)
500da2e3ebdSchin sh_onstate(SH_VERBOSE);
501da2e3ebdSchin exitset();
50234f9b3eeSRoland Mainz if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT))
5037c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
5047c2fbfb3SApril Chin return(shp->exitval);
505da2e3ebdSchin }
506da2e3ebdSchin
507da2e3ebdSchin /*
508da2e3ebdSchin * exit the current scope and jump to an earlier one based on pp->mode
509da2e3ebdSchin */
sh_exit(register int xno)510da2e3ebdSchin void sh_exit(register int xno)
511da2e3ebdSchin {
512*b30d1939SAndy Fiddaman Shell_t *shp = sh_getinterp();
5137c2fbfb3SApril Chin register struct checkpt *pp = (struct checkpt*)shp->jmplist;
514da2e3ebdSchin register int sig=0;
515da2e3ebdSchin register Sfio_t* pool;
5167c2fbfb3SApril Chin shp->exitval=xno;
517da2e3ebdSchin if(xno==SH_EXITSIG)
5187c2fbfb3SApril Chin shp->exitval |= (sig=shp->lastsig);
519*b30d1939SAndy Fiddaman if(pp && pp->mode>1)
520*b30d1939SAndy Fiddaman cursig = -1;
521da2e3ebdSchin #ifdef SIGTSTP
522*b30d1939SAndy Fiddaman if(shp->trapnote&SH_SIGTSTP && job.jobcontrol)
523da2e3ebdSchin {
524da2e3ebdSchin /* ^Z detected by the shell */
5257c2fbfb3SApril Chin shp->trapnote = 0;
5267c2fbfb3SApril Chin shp->sigflag[SIGTSTP] = 0;
5277c2fbfb3SApril Chin if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
528da2e3ebdSchin return;
529da2e3ebdSchin if(sh_isstate(SH_TIMING))
530da2e3ebdSchin return;
531da2e3ebdSchin /* Handles ^Z for shell builtins, subshells, and functs */
5327c2fbfb3SApril Chin shp->lastsig = 0;
533da2e3ebdSchin sh_onstate(SH_MONITOR);
534da2e3ebdSchin sh_offstate(SH_STOPOK);
5357c2fbfb3SApril Chin shp->trapnote = 0;
536*b30d1939SAndy Fiddaman shp->forked = 1;
537*b30d1939SAndy Fiddaman if(!shp->subshell && (sig=sh_fork(shp,0,NIL(int*))))
538da2e3ebdSchin {
539da2e3ebdSchin job.curpgid = 0;
540da2e3ebdSchin job.parent = (pid_t)-1;
541da2e3ebdSchin job_wait(sig);
542*b30d1939SAndy Fiddaman shp->forked = 0;
543da2e3ebdSchin job.parent = 0;
5447c2fbfb3SApril Chin shp->sigflag[SIGTSTP] = 0;
545da2e3ebdSchin /* wait for child to stop */
5467c2fbfb3SApril Chin shp->exitval = (SH_EXITSIG|SIGTSTP);
547da2e3ebdSchin /* return to prompt mode */
548da2e3ebdSchin pp->mode = SH_JMPERREXIT;
549da2e3ebdSchin }
550da2e3ebdSchin else
551da2e3ebdSchin {
5527c2fbfb3SApril Chin if(shp->subshell)
553da2e3ebdSchin sh_subfork();
554da2e3ebdSchin /* child process, put to sleep */
555da2e3ebdSchin sh_offstate(SH_STOPOK);
556da2e3ebdSchin sh_offstate(SH_MONITOR);
5577c2fbfb3SApril Chin shp->sigflag[SIGTSTP] = 0;
558da2e3ebdSchin /* stop child job */
559da2e3ebdSchin killpg(job.curpgid,SIGTSTP);
560da2e3ebdSchin /* child resumes */
561da2e3ebdSchin job_clear();
5627c2fbfb3SApril Chin shp->exitval = (xno&SH_EXITMASK);
563da2e3ebdSchin return;
564da2e3ebdSchin }
565da2e3ebdSchin }
566da2e3ebdSchin #endif /* SIGTSTP */
567da2e3ebdSchin /* unlock output pool */
568da2e3ebdSchin sh_offstate(SH_NOTRACK);
5697c2fbfb3SApril Chin if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE)))
5707c2fbfb3SApril Chin pool = shp->outpool; /* can't happen? */
571da2e3ebdSchin sfclrlock(pool);
572da2e3ebdSchin #ifdef SIGPIPE
5737c2fbfb3SApril Chin if(shp->lastsig==SIGPIPE)
574da2e3ebdSchin sfpurge(pool);
575da2e3ebdSchin #endif /* SIGPIPE */
576da2e3ebdSchin sfclrlock(sfstdin);
577da2e3ebdSchin if(!pp)
5787c2fbfb3SApril Chin sh_done(shp,sig);
5797c2fbfb3SApril Chin shp->prefix = 0;
5807c2fbfb3SApril Chin #if SHOPT_TYPEDEF
5817c2fbfb3SApril Chin shp->mktype = 0;
5827c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF*/
583*b30d1939SAndy Fiddaman if(job.in_critical)
584*b30d1939SAndy Fiddaman job_unlock();
585da2e3ebdSchin if(pp->mode == SH_JMPSCRIPT && !pp->prev)
5867c2fbfb3SApril Chin sh_done(shp,sig);
5877c2fbfb3SApril Chin if(pp->mode)
5887c2fbfb3SApril Chin siglongjmp(pp->buff,pp->mode);
5897c2fbfb3SApril Chin }
5907c2fbfb3SApril Chin
array_notify(Namval_t * np,void * data)5917c2fbfb3SApril Chin static void array_notify(Namval_t *np, void *data)
5927c2fbfb3SApril Chin {
5937c2fbfb3SApril Chin Namarr_t *ap = nv_arrayptr(np);
5947c2fbfb3SApril Chin NOT_USED(data);
5957c2fbfb3SApril Chin if(ap && ap->fun)
5967c2fbfb3SApril Chin (*ap->fun)(np, 0, NV_AFREE);
597da2e3ebdSchin }
598da2e3ebdSchin
599da2e3ebdSchin /*
600da2e3ebdSchin * This is the exit routine for the shell
601da2e3ebdSchin */
602da2e3ebdSchin
sh_done(void * ptr,register int sig)6037c2fbfb3SApril Chin void sh_done(void *ptr, register int sig)
604da2e3ebdSchin {
6057c2fbfb3SApril Chin Shell_t *shp = (Shell_t*)ptr;
606da2e3ebdSchin register char *t;
6077c2fbfb3SApril Chin register int savxit = shp->exitval;
6087c2fbfb3SApril Chin shp->trapnote = 0;
609da2e3ebdSchin indone=1;
61034f9b3eeSRoland Mainz if(sig)
61134f9b3eeSRoland Mainz savxit = SH_EXITSIG|sig;
6127c2fbfb3SApril Chin if(shp->userinit)
6137c2fbfb3SApril Chin (*shp->userinit)(shp, -1);
6147c2fbfb3SApril Chin if(t=shp->st.trapcom[0])
615da2e3ebdSchin {
6167c2fbfb3SApril Chin shp->st.trapcom[0]=0; /*should free but not long */
6177c2fbfb3SApril Chin shp->oldexit = savxit;
618da2e3ebdSchin sh_trap(t,0);
6197c2fbfb3SApril Chin savxit = shp->exitval;
620da2e3ebdSchin }
621da2e3ebdSchin else
622da2e3ebdSchin {
623da2e3ebdSchin /* avoid recursive call for set -e */
624da2e3ebdSchin sh_offstate(SH_ERREXIT);
625*b30d1939SAndy Fiddaman sh_chktrap(shp);
626da2e3ebdSchin }
6277c2fbfb3SApril Chin nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY);
6287c2fbfb3SApril Chin sh_freeup(shp);
629da2e3ebdSchin #if SHOPT_ACCT
630da2e3ebdSchin sh_accend();
631da2e3ebdSchin #endif /* SHOPT_ACCT */
632da2e3ebdSchin #if SHOPT_VSH || SHOPT_ESH
633*b30d1939SAndy Fiddaman if(mbwide()||sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
634da2e3ebdSchin tty_cooked(-1);
635da2e3ebdSchin #endif
636da2e3ebdSchin #ifdef JOBS
6377c2fbfb3SApril Chin if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
638*b30d1939SAndy Fiddaman job_walk(sfstderr, job_hup, SIGHUP, NIL(char**));
639da2e3ebdSchin #endif /* JOBS */
6407c2fbfb3SApril Chin job_close(shp);
6417c2fbfb3SApril Chin if(nv_search("VMTRACE", shp->var_tree,0))
642da2e3ebdSchin strmatch((char*)0,(char*)0);
643da2e3ebdSchin sfsync((Sfio_t*)sfstdin);
6447c2fbfb3SApril Chin sfsync((Sfio_t*)shp->outpool);
645da2e3ebdSchin sfsync((Sfio_t*)sfstdout);
64634f9b3eeSRoland Mainz if(savxit&SH_EXITSIG)
64734f9b3eeSRoland Mainz sig = savxit&SH_EXITMASK;
648da2e3ebdSchin if(sig)
649da2e3ebdSchin {
650da2e3ebdSchin /* generate fault termination code */
651*b30d1939SAndy Fiddaman if(RLIMIT_CORE!=RLIMIT_UNKNOWN)
652*b30d1939SAndy Fiddaman {
653*b30d1939SAndy Fiddaman #ifdef _lib_getrlimit
654*b30d1939SAndy Fiddaman struct rlimit rlp;
655*b30d1939SAndy Fiddaman getrlimit(RLIMIT_CORE,&rlp);
656*b30d1939SAndy Fiddaman rlp.rlim_cur = 0;
657*b30d1939SAndy Fiddaman setrlimit(RLIMIT_CORE,&rlp);
658*b30d1939SAndy Fiddaman #else
659*b30d1939SAndy Fiddaman vlimit(RLIMIT_CORE,0);
660*b30d1939SAndy Fiddaman #endif
661*b30d1939SAndy Fiddaman }
662da2e3ebdSchin signal(sig,SIG_DFL);
663da2e3ebdSchin sigrelease(sig);
664da2e3ebdSchin kill(getpid(),sig);
665da2e3ebdSchin pause();
666da2e3ebdSchin }
667da2e3ebdSchin #if SHOPT_KIA
668da2e3ebdSchin if(sh_isoption(SH_NOEXEC))
6697c2fbfb3SApril Chin kiaclose((Lex_t*)shp->lex_context);
670da2e3ebdSchin #endif /* SHOPT_KIA */
671da2e3ebdSchin exit(savxit&SH_EXITMASK);
672da2e3ebdSchin }
673da2e3ebdSchin
674