14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * Fault handling routines 234887Schin * 244887Schin * David Korn 254887Schin * AT&T Labs 264887Schin * 274887Schin */ 284887Schin 294887Schin #include "defs.h" 304887Schin #include <fcin.h> 314887Schin #include "io.h" 324887Schin #include "history.h" 33*8462SApril.Chin@Sun.COM #include "shlex.h" 344887Schin #include "variables.h" 354887Schin #include "jobs.h" 364887Schin #include "path.h" 37*8462SApril.Chin@Sun.COM #include "builtins.h" 384887Schin 394887Schin #define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV) 404887Schin 414887Schin static char indone; 424887Schin 434887Schin #if !_std_malloc 444887Schin # include <vmalloc.h> 454887Schin #endif 464887Schin #if defined(VMFL) && (VMALLOC_VERSION>=20031205L) 474887Schin /* 484887Schin * This exception handler is called after vmalloc() unlocks the region 494887Schin */ 504887Schin static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp) 514887Schin { 524887Schin dp->exceptf = 0; 534887Schin sh_exit(SH_EXITSIG); 544887Schin return(0); 554887Schin } 564887Schin #endif 574887Schin 584887Schin /* 594887Schin * Most signals caught or ignored by the shell come here 604887Schin */ 614887Schin void sh_fault(register int sig) 624887Schin { 63*8462SApril.Chin@Sun.COM register Shell_t *shp = sh_getinterp(); 64*8462SApril.Chin@Sun.COM register int flag=0; 65*8462SApril.Chin@Sun.COM register char *trap; 66*8462SApril.Chin@Sun.COM register struct checkpt *pp = (struct checkpt*)shp->jmplist; 674887Schin int action=0; 684887Schin /* reset handler */ 694887Schin if(!(sig&SH_TRAP)) 704887Schin signal(sig, sh_fault); 714887Schin sig &= ~SH_TRAP; 724887Schin #ifdef SIGWINCH 734887Schin if(sig==SIGWINCH) 744887Schin { 754887Schin int rows=0, cols=0; 764887Schin int32_t v; 774887Schin astwinsize(2,&rows,&cols); 784887Schin if(v = cols) 79*8462SApril.Chin@Sun.COM nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY); 804887Schin if(v = rows) 81*8462SApril.Chin@Sun.COM nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY); 82*8462SApril.Chin@Sun.COM shp->winch++; 834887Schin } 844887Schin #endif /* SIGWINCH */ 85*8462SApril.Chin@Sun.COM if(shp->savesig) 864887Schin { 874887Schin /* critical region, save and process later */ 88*8462SApril.Chin@Sun.COM shp->savesig = sig; 89*8462SApril.Chin@Sun.COM return; 90*8462SApril.Chin@Sun.COM } 91*8462SApril.Chin@Sun.COM trap = shp->st.trapcom[sig]; 92*8462SApril.Chin@Sun.COM if(sig==SIGALRM && shp->bltinfun==b_sleep) 93*8462SApril.Chin@Sun.COM { 94*8462SApril.Chin@Sun.COM if(trap && *trap) 95*8462SApril.Chin@Sun.COM { 96*8462SApril.Chin@Sun.COM shp->trapnote |= SH_SIGTRAP; 97*8462SApril.Chin@Sun.COM shp->sigflag[sig] |= SH_SIGTRAP; 98*8462SApril.Chin@Sun.COM } 994887Schin return; 1004887Schin } 101*8462SApril.Chin@Sun.COM if(shp->subshell && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH) 102*8462SApril.Chin@Sun.COM { 103*8462SApril.Chin@Sun.COM shp->exitval = SH_EXITSIG|sig; 104*8462SApril.Chin@Sun.COM sh_subfork(); 105*8462SApril.Chin@Sun.COM shp->exitval = 0; 106*8462SApril.Chin@Sun.COM return; 107*8462SApril.Chin@Sun.COM } 1084887Schin /* handle ignored signals */ 109*8462SApril.Chin@Sun.COM if(trap && *trap==0) 1104887Schin return; 111*8462SApril.Chin@Sun.COM flag = shp->sigflag[sig]&~SH_SIGOFF; 1124887Schin if(!trap) 1134887Schin { 114*8462SApril.Chin@Sun.COM if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE)) 115*8462SApril.Chin@Sun.COM return; 1164887Schin if(flag&SH_SIGIGNORE) 1174887Schin return; 1184887Schin if(flag&SH_SIGDONE) 1194887Schin { 1204887Schin void *ptr=0; 121*8462SApril.Chin@Sun.COM if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell) 1224887Schin { 1234887Schin /* check for TERM signal between fork/exec */ 1244887Schin if(sig==SIGTERM && job.in_critical) 125*8462SApril.Chin@Sun.COM shp->trapnote |= SH_SIGTERM; 1264887Schin return; 1274887Schin } 128*8462SApril.Chin@Sun.COM shp->lastsig = sig; 1294887Schin sigrelease(sig); 1304887Schin if(pp->mode < SH_JMPFUN) 1314887Schin pp->mode = SH_JMPFUN; 1324887Schin else 1334887Schin pp->mode = SH_JMPEXIT; 1344887Schin if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1)))) 1354887Schin { 1364887Schin if(ptr) 1374887Schin free(ptr); 138*8462SApril.Chin@Sun.COM if(!shp->subshell) 139*8462SApril.Chin@Sun.COM sh_done(shp,sig); 1404887Schin sh_exit(SH_EXITSIG); 1414887Schin } 1424887Schin /* mark signal and continue */ 143*8462SApril.Chin@Sun.COM shp->trapnote |= SH_SIGSET; 144*8462SApril.Chin@Sun.COM if(sig < shp->sigmax) 145*8462SApril.Chin@Sun.COM shp->sigflag[sig] |= SH_SIGSET; 1464887Schin #if defined(VMFL) && (VMALLOC_VERSION>=20031205L) 1474887Schin if(abortsig(sig)) 1484887Schin { 1494887Schin /* abort inside malloc, process when malloc returns */ 1504887Schin /* VMFL defined when using vmalloc() */ 1514887Schin Vmdisc_t* dp = vmdisc(Vmregion,0); 1524887Schin if(dp) 1534887Schin dp->exceptf = malloc_done; 1544887Schin } 1554887Schin #endif 1564887Schin return; 1574887Schin } 1584887Schin } 1594887Schin errno = 0; 1604887Schin if(pp->mode==SH_JMPCMD) 161*8462SApril.Chin@Sun.COM shp->lastsig = sig; 1624887Schin if(trap) 1634887Schin { 1644887Schin /* 1654887Schin * propogate signal to foreground group 1664887Schin */ 1674887Schin if(sig==SIGHUP && job.curpgid) 1684887Schin killpg(job.curpgid,SIGHUP); 1694887Schin flag = SH_SIGTRAP; 1704887Schin } 1714887Schin else 1724887Schin { 173*8462SApril.Chin@Sun.COM shp->lastsig = sig; 1744887Schin flag = SH_SIGSET; 1754887Schin #ifdef SIGTSTP 1764887Schin if(sig==SIGTSTP) 1774887Schin { 178*8462SApril.Chin@Sun.COM shp->trapnote |= SH_SIGTSTP; 1794887Schin if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK)) 1804887Schin { 1814887Schin sigrelease(sig); 1824887Schin sh_exit(SH_EXITSIG); 1834887Schin flag = 0; 1844887Schin } 1854887Schin } 1864887Schin #endif /* SIGTSTP */ 1874887Schin } 1884887Schin #ifdef ERROR_NOTIFY 189*8462SApril.Chin@Sun.COM /* This is obsolete */ 190*8462SApril.Chin@Sun.COM if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun) 191*8462SApril.Chin@Sun.COM action = (*shp->bltinfun)(-sig,(char**)0,(void*)0); 1924887Schin if(action>0) 1934887Schin return; 194*8462SApril.Chin@Sun.COM #endif 195*8462SApril.Chin@Sun.COM if(shp->bltinfun && shp->bltindata.notify) 196*8462SApril.Chin@Sun.COM { 197*8462SApril.Chin@Sun.COM shp->bltindata.sigset = 1; 198*8462SApril.Chin@Sun.COM return; 199*8462SApril.Chin@Sun.COM } 200*8462SApril.Chin@Sun.COM shp->trapnote |= flag; 201*8462SApril.Chin@Sun.COM if(sig < shp->sigmax) 202*8462SApril.Chin@Sun.COM shp->sigflag[sig] |= flag; 2034887Schin if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK)) 2044887Schin { 2054887Schin if(action<0) 2064887Schin return; 2074887Schin sigrelease(sig); 2084887Schin sh_exit(SH_EXITSIG); 2094887Schin } 2104887Schin } 2114887Schin 2124887Schin /* 2134887Schin * initialize signal handling 2144887Schin */ 215*8462SApril.Chin@Sun.COM void sh_siginit(void *ptr) 2164887Schin { 217*8462SApril.Chin@Sun.COM Shell_t *shp = (Shell_t*)ptr; 2184887Schin register int sig, n=SIGTERM+1; 2194887Schin register const struct shtable2 *tp = shtab_signals; 2204887Schin sig_begin(); 2214887Schin /* find the largest signal number in the table */ 222*8462SApril.Chin@Sun.COM #ifdef SIGRTMIN 223*8462SApril.Chin@Sun.COM shp->sigruntime[SH_SIGRTMIN] = SIGRTMIN; 224*8462SApril.Chin@Sun.COM #endif /* SIGRTMIN */ 225*8462SApril.Chin@Sun.COM #ifdef SIGRTMAX 226*8462SApril.Chin@Sun.COM shp->sigruntime[SH_SIGRTMAX] = SIGRTMAX; 227*8462SApril.Chin@Sun.COM #endif /* SIGRTMAX */ 2284887Schin while(*tp->sh_name) 2294887Schin { 230*8462SApril.Chin@Sun.COM sig = tp->sh_number&((1<<SH_SIGBITS)-1); 231*8462SApril.Chin@Sun.COM if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) 232*8462SApril.Chin@Sun.COM sig = shp->sigruntime[sig-1]; 233*8462SApril.Chin@Sun.COM if(sig>n && sig<SH_TRAP) 2344887Schin n = sig; 2354887Schin tp++; 2364887Schin } 237*8462SApril.Chin@Sun.COM shp->sigmax = n++; 238*8462SApril.Chin@Sun.COM shp->st.trapcom = (char**)calloc(n,sizeof(char*)); 239*8462SApril.Chin@Sun.COM shp->sigflag = (unsigned char*)calloc(n,1); 240*8462SApril.Chin@Sun.COM shp->sigmsg = (char**)calloc(n,sizeof(char*)); 2414887Schin for(tp=shtab_signals; sig=tp->sh_number; tp++) 2424887Schin { 2434887Schin n = (sig>>SH_SIGBITS); 244*8462SApril.Chin@Sun.COM if((sig &= ((1<<SH_SIGBITS)-1)) > shp->sigmax) 2454887Schin continue; 2464887Schin sig--; 247*8462SApril.Chin@Sun.COM if(n&SH_SIGRUNTIME) 248*8462SApril.Chin@Sun.COM sig = shp->sigruntime[sig]; 2494887Schin if(sig>=0) 2504887Schin { 251*8462SApril.Chin@Sun.COM shp->sigflag[sig] = n; 2524887Schin if(*tp->sh_name) 253*8462SApril.Chin@Sun.COM shp->sigmsg[sig] = (char*)tp->sh_value; 2544887Schin } 2554887Schin } 2564887Schin } 2574887Schin 2584887Schin /* 2594887Schin * Turn on trap handler for signal <sig> 2604887Schin */ 2614887Schin void sh_sigtrap(register int sig) 2624887Schin { 2634887Schin register int flag; 2644887Schin void (*fun)(int); 2654887Schin sh.st.otrapcom = 0; 2664887Schin if(sig==0) 2674887Schin sh_sigdone(); 2684887Schin else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF))) 2694887Schin { 2704887Schin /* don't set signal if already set or off by parent */ 2714887Schin if((fun=signal(sig,sh_fault))==SIG_IGN) 2724887Schin { 2734887Schin signal(sig,SIG_IGN); 2744887Schin flag |= SH_SIGOFF; 2754887Schin } 2764887Schin else 2774887Schin { 2784887Schin flag |= SH_SIGFAULT; 2794887Schin if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault) 2804887Schin signal(sig,fun); 2814887Schin } 2824887Schin flag &= ~(SH_SIGSET|SH_SIGTRAP); 2834887Schin sh.sigflag[sig] = flag; 2844887Schin } 2854887Schin } 2864887Schin 2874887Schin /* 2884887Schin * set signal handler so sh_done is called for all caught signals 2894887Schin */ 2904887Schin void sh_sigdone(void) 2914887Schin { 2924887Schin register int flag, sig = sh.sigmax; 2934887Schin sh.sigflag[0] |= SH_SIGFAULT; 2944887Schin while(--sig>0) 2954887Schin { 2964887Schin flag = sh.sigflag[sig]; 2974887Schin if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF))) 2984887Schin sh_sigtrap(sig); 2994887Schin } 3004887Schin } 3014887Schin 3024887Schin /* 3034887Schin * Restore to default signals 3044887Schin * Free the trap strings if mode is non-zero 3054887Schin * If mode>1 then ignored traps cause signal to be ignored 3064887Schin */ 3074887Schin void sh_sigreset(register int mode) 3084887Schin { 3094887Schin register char *trap; 3104887Schin register int flag, sig=sh.st.trapmax; 3114887Schin while(sig-- > 0) 3124887Schin { 3134887Schin if(trap=sh.st.trapcom[sig]) 3144887Schin { 3154887Schin flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET); 3164887Schin if(*trap) 3174887Schin { 3184887Schin if(mode) 3194887Schin free(trap); 3204887Schin sh.st.trapcom[sig] = 0; 3214887Schin } 3224887Schin else if(sig && mode>1) 3234887Schin { 3244887Schin signal(sig,SIG_IGN); 3254887Schin flag &= ~SH_SIGFAULT; 3264887Schin flag |= SH_SIGOFF; 3274887Schin } 3284887Schin sh.sigflag[sig] = flag; 3294887Schin } 3304887Schin } 331*8462SApril.Chin@Sun.COM for(sig=SH_DEBUGTRAP-1;sig>=0;sig--) 3324887Schin { 3334887Schin if(trap=sh.st.trap[sig]) 3344887Schin { 3354887Schin if(mode) 3364887Schin free(trap); 3374887Schin sh.st.trap[sig] = 0; 3384887Schin } 3394887Schin 3404887Schin } 3414887Schin sh.st.trapcom[0] = 0; 3424887Schin if(mode) 3434887Schin sh.st.trapmax = 0; 3444887Schin sh.trapnote=0; 3454887Schin } 3464887Schin 3474887Schin /* 3484887Schin * free up trap if set and restore signal handler if modified 3494887Schin */ 3504887Schin void sh_sigclear(register int sig) 3514887Schin { 3524887Schin register int flag = sh.sigflag[sig]; 3534887Schin register char *trap; 3544887Schin sh.st.otrapcom=0; 3554887Schin if(!(flag&SH_SIGFAULT)) 3564887Schin return; 3574887Schin flag &= ~(SH_SIGTRAP|SH_SIGSET); 3584887Schin if(trap=sh.st.trapcom[sig]) 3594887Schin { 3604887Schin free(trap); 3614887Schin sh.st.trapcom[sig]=0; 3624887Schin } 3634887Schin sh.sigflag[sig] = flag; 3644887Schin } 3654887Schin 3664887Schin /* 3674887Schin * check for traps 3684887Schin */ 3694887Schin 3704887Schin void sh_chktrap(void) 3714887Schin { 3724887Schin register int sig=sh.st.trapmax; 3734887Schin register char *trap; 374*8462SApril.Chin@Sun.COM if(!(sh.trapnote&~SH_SIGIGNORE)) 3754887Schin sig=0; 3764887Schin sh.trapnote &= ~SH_SIGTRAP; 3774887Schin /* execute errexit trap first */ 3784887Schin if(sh_isstate(SH_ERREXIT) && sh.exitval) 3794887Schin { 3804887Schin int sav_trapnote = sh.trapnote; 3814887Schin sh.trapnote &= ~SH_SIGSET; 3824887Schin if(sh.st.trap[SH_ERRTRAP]) 383*8462SApril.Chin@Sun.COM { 384*8462SApril.Chin@Sun.COM trap = sh.st.trap[SH_ERRTRAP]; 385*8462SApril.Chin@Sun.COM sh.st.trap[SH_ERRTRAP] = 0; 386*8462SApril.Chin@Sun.COM sh_trap(trap,0); 387*8462SApril.Chin@Sun.COM sh.st.trap[SH_ERRTRAP] = trap; 388*8462SApril.Chin@Sun.COM } 3894887Schin sh.trapnote = sav_trapnote; 3904887Schin if(sh_isoption(SH_ERREXIT)) 3914887Schin { 3924887Schin struct checkpt *pp = (struct checkpt*)sh.jmplist; 3934887Schin pp->mode = SH_JMPEXIT; 3944887Schin sh_exit(sh.exitval); 3954887Schin } 3964887Schin } 3974887Schin if(sh.sigflag[SIGALRM]&SH_SIGALRM) 3984887Schin sh_timetraps(); 3994887Schin while(--sig>=0) 4004887Schin { 4014887Schin if(sh.sigflag[sig]&SH_SIGTRAP) 4024887Schin { 4034887Schin sh.sigflag[sig] &= ~SH_SIGTRAP; 4044887Schin if(trap=sh.st.trapcom[sig]) 4054887Schin sh_trap(trap,0); 4064887Schin } 4074887Schin } 4084887Schin } 4094887Schin 4104887Schin 4114887Schin /* 4124887Schin * parse and execute the given trap string, stream or tree depending on mode 4134887Schin * mode==0 for string, mode==1 for stream, mode==2 for parse tree 4144887Schin */ 4154887Schin int sh_trap(const char *trap, int mode) 4164887Schin { 417*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 418*8462SApril.Chin@Sun.COM int jmpval, savxit = shp->exitval; 4194887Schin int was_history = sh_isstate(SH_HISTORY); 4204887Schin int was_verbose = sh_isstate(SH_VERBOSE); 4214887Schin int staktop = staktell(); 4224887Schin char *savptr = stakfreeze(0); 4234887Schin struct checkpt buff; 4244887Schin Fcin_t savefc; 4254887Schin fcsave(&savefc); 4264887Schin sh_offstate(SH_HISTORY); 4274887Schin sh_offstate(SH_VERBOSE); 428*8462SApril.Chin@Sun.COM shp->intrap++; 4294887Schin sh_pushcontext(&buff,SH_JMPTRAP); 4304887Schin jmpval = sigsetjmp(buff.buff,0); 4314887Schin if(jmpval == 0) 4324887Schin { 4334887Schin if(mode==2) 4344887Schin sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT)); 4354887Schin else 4364887Schin { 4374887Schin Sfio_t *sp; 4384887Schin if(mode) 4394887Schin sp = (Sfio_t*)trap; 4404887Schin else 4414887Schin sp = sfopen(NIL(Sfio_t*),trap,"s"); 4424887Schin sh_eval(sp,0); 4434887Schin } 4444887Schin } 4454887Schin else if(indone) 4464887Schin { 4474887Schin if(jmpval==SH_JMPSCRIPT) 4484887Schin indone=0; 4494887Schin else 4504887Schin { 4514887Schin if(jmpval==SH_JMPEXIT) 452*8462SApril.Chin@Sun.COM savxit = shp->exitval; 4534887Schin jmpval=SH_JMPTRAP; 4544887Schin } 4554887Schin } 4564887Schin sh_popcontext(&buff); 457*8462SApril.Chin@Sun.COM shp->intrap--; 458*8462SApril.Chin@Sun.COM sfsync(shp->outpool); 459*8462SApril.Chin@Sun.COM if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN) 460*8462SApril.Chin@Sun.COM shp->exitval=savxit; 4614887Schin stakset(savptr,staktop); 4624887Schin fcrestore(&savefc); 4634887Schin if(was_history) 4644887Schin sh_onstate(SH_HISTORY); 4654887Schin if(was_verbose) 4664887Schin sh_onstate(SH_VERBOSE); 4674887Schin exitset(); 4684887Schin if(jmpval>SH_JMPTRAP) 469*8462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 470*8462SApril.Chin@Sun.COM return(shp->exitval); 4714887Schin } 4724887Schin 4734887Schin /* 4744887Schin * exit the current scope and jump to an earlier one based on pp->mode 4754887Schin */ 4764887Schin void sh_exit(register int xno) 4774887Schin { 478*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 479*8462SApril.Chin@Sun.COM register struct checkpt *pp = (struct checkpt*)shp->jmplist; 4804887Schin register int sig=0; 4814887Schin register Sfio_t* pool; 482*8462SApril.Chin@Sun.COM shp->exitval=xno; 4834887Schin if(xno==SH_EXITSIG) 484*8462SApril.Chin@Sun.COM shp->exitval |= (sig=shp->lastsig); 4854887Schin #ifdef SIGTSTP 486*8462SApril.Chin@Sun.COM if(shp->trapnote&SH_SIGTSTP) 4874887Schin { 4884887Schin /* ^Z detected by the shell */ 489*8462SApril.Chin@Sun.COM shp->trapnote = 0; 490*8462SApril.Chin@Sun.COM shp->sigflag[SIGTSTP] = 0; 491*8462SApril.Chin@Sun.COM if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK)) 4924887Schin return; 4934887Schin if(sh_isstate(SH_TIMING)) 4944887Schin return; 4954887Schin /* Handles ^Z for shell builtins, subshells, and functs */ 496*8462SApril.Chin@Sun.COM shp->lastsig = 0; 4974887Schin sh_onstate(SH_MONITOR); 4984887Schin sh_offstate(SH_STOPOK); 499*8462SApril.Chin@Sun.COM shp->trapnote = 0; 500*8462SApril.Chin@Sun.COM if(!shp->subshell && (sig=sh_fork(0,NIL(int*)))) 5014887Schin { 5024887Schin job.curpgid = 0; 5034887Schin job.parent = (pid_t)-1; 5044887Schin job_wait(sig); 5054887Schin job.parent = 0; 506*8462SApril.Chin@Sun.COM shp->sigflag[SIGTSTP] = 0; 5074887Schin /* wait for child to stop */ 508*8462SApril.Chin@Sun.COM shp->exitval = (SH_EXITSIG|SIGTSTP); 5094887Schin /* return to prompt mode */ 5104887Schin pp->mode = SH_JMPERREXIT; 5114887Schin } 5124887Schin else 5134887Schin { 514*8462SApril.Chin@Sun.COM if(shp->subshell) 5154887Schin sh_subfork(); 5164887Schin /* child process, put to sleep */ 5174887Schin sh_offstate(SH_STOPOK); 5184887Schin sh_offstate(SH_MONITOR); 519*8462SApril.Chin@Sun.COM shp->sigflag[SIGTSTP] = 0; 5204887Schin /* stop child job */ 5214887Schin killpg(job.curpgid,SIGTSTP); 5224887Schin /* child resumes */ 5234887Schin job_clear(); 524*8462SApril.Chin@Sun.COM shp->forked = 1; 525*8462SApril.Chin@Sun.COM shp->exitval = (xno&SH_EXITMASK); 5264887Schin return; 5274887Schin } 5284887Schin } 5294887Schin #endif /* SIGTSTP */ 5304887Schin /* unlock output pool */ 5314887Schin sh_offstate(SH_NOTRACK); 532*8462SApril.Chin@Sun.COM if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE))) 533*8462SApril.Chin@Sun.COM pool = shp->outpool; /* can't happen? */ 5344887Schin sfclrlock(pool); 5354887Schin #ifdef SIGPIPE 536*8462SApril.Chin@Sun.COM if(shp->lastsig==SIGPIPE) 5374887Schin sfpurge(pool); 5384887Schin #endif /* SIGPIPE */ 5394887Schin sfclrlock(sfstdin); 5404887Schin if(!pp) 541*8462SApril.Chin@Sun.COM sh_done(shp,sig); 542*8462SApril.Chin@Sun.COM shp->prefix = 0; 543*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 544*8462SApril.Chin@Sun.COM shp->mktype = 0; 545*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF*/ 5464887Schin if(pp->mode == SH_JMPSCRIPT && !pp->prev) 547*8462SApril.Chin@Sun.COM sh_done(shp,sig); 548*8462SApril.Chin@Sun.COM if(pp->mode) 549*8462SApril.Chin@Sun.COM siglongjmp(pp->buff,pp->mode); 550*8462SApril.Chin@Sun.COM } 551*8462SApril.Chin@Sun.COM 552*8462SApril.Chin@Sun.COM static void array_notify(Namval_t *np, void *data) 553*8462SApril.Chin@Sun.COM { 554*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 555*8462SApril.Chin@Sun.COM NOT_USED(data); 556*8462SApril.Chin@Sun.COM if(ap && ap->fun) 557*8462SApril.Chin@Sun.COM (*ap->fun)(np, 0, NV_AFREE); 5584887Schin } 5594887Schin 5604887Schin /* 5614887Schin * This is the exit routine for the shell 5624887Schin */ 5634887Schin 564*8462SApril.Chin@Sun.COM void sh_done(void *ptr, register int sig) 5654887Schin { 566*8462SApril.Chin@Sun.COM Shell_t *shp = (Shell_t*)ptr; 5674887Schin register char *t; 568*8462SApril.Chin@Sun.COM register int savxit = shp->exitval; 569*8462SApril.Chin@Sun.COM shp->trapnote = 0; 5704887Schin indone=1; 5714887Schin if(sig==0) 572*8462SApril.Chin@Sun.COM sig = shp->lastsig; 573*8462SApril.Chin@Sun.COM if(shp->userinit) 574*8462SApril.Chin@Sun.COM (*shp->userinit)(shp, -1); 575*8462SApril.Chin@Sun.COM if(t=shp->st.trapcom[0]) 5764887Schin { 577*8462SApril.Chin@Sun.COM shp->st.trapcom[0]=0; /*should free but not long */ 578*8462SApril.Chin@Sun.COM shp->oldexit = savxit; 5794887Schin sh_trap(t,0); 580*8462SApril.Chin@Sun.COM savxit = shp->exitval; 5814887Schin } 5824887Schin else 5834887Schin { 5844887Schin /* avoid recursive call for set -e */ 5854887Schin sh_offstate(SH_ERREXIT); 5864887Schin sh_chktrap(); 5874887Schin } 588*8462SApril.Chin@Sun.COM nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY); 589*8462SApril.Chin@Sun.COM sh_freeup(shp); 5904887Schin #if SHOPT_ACCT 5914887Schin sh_accend(); 5924887Schin #endif /* SHOPT_ACCT */ 5934887Schin #if SHOPT_VSH || SHOPT_ESH 5944887Schin if(sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS)) 5954887Schin tty_cooked(-1); 5964887Schin #endif 5974887Schin #ifdef JOBS 598*8462SApril.Chin@Sun.COM if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) 5994887Schin job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**)); 6004887Schin #endif /* JOBS */ 601*8462SApril.Chin@Sun.COM job_close(shp); 602*8462SApril.Chin@Sun.COM if(nv_search("VMTRACE", shp->var_tree,0)) 6034887Schin strmatch((char*)0,(char*)0); 6044887Schin sfsync((Sfio_t*)sfstdin); 605*8462SApril.Chin@Sun.COM sfsync((Sfio_t*)shp->outpool); 6064887Schin sfsync((Sfio_t*)sfstdout); 6074887Schin if(sig) 6084887Schin { 6094887Schin /* generate fault termination code */ 6104887Schin signal(sig,SIG_DFL); 6114887Schin sigrelease(sig); 6124887Schin kill(getpid(),sig); 6134887Schin pause(); 6144887Schin } 6154887Schin #if SHOPT_KIA 6164887Schin if(sh_isoption(SH_NOEXEC)) 617*8462SApril.Chin@Sun.COM kiaclose((Lex_t*)shp->lex_context); 6184887Schin #endif /* SHOPT_KIA */ 6194887Schin exit(savxit&SH_EXITMASK); 6204887Schin } 6214887Schin 622