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