fault.c revision 3e14f97f673e8a630f076077de35afdd43dc1587
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Fault handling routines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char indone;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This exception handler is called after vmalloc() unlocks the region
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Most signals caught or ignored by the shell come here
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int flag=0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register char *trap;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct checkpt *pp = (struct checkpt*)shp->jmplist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset handler */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGWINCH */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* critical region, save and process later */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(shp->subshell && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH && sig!=SIGCONT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* handle ignored signals */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for TERM signal between fork/exec */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* mark signal and continue */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* abort inside malloc, process when malloc returns */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* VMFL defined when using vmalloc() */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * propogate signal to foreground group
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin action = (*shp->bltinfun)(-sig,(char**)0,(void*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize signal handling
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register int sig, n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* find the largest signal number in the table */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((n = SIGRTMIN) > 0 && (sig = SIGRTMAX) > n && sig < SH_TRAP)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SIGRTMIN && SIGRTMAX */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->st.trapcom = (char**)calloc(n,sizeof(char*));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((sig &= ((1<<SH_SIGBITS)-1)) > (shp->sigmax+1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Turn on trap handler for signal <sig>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin void (*fun)(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't set signal if already set or off by parent */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * set signal handler so sh_done is called for all caught signals
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Restore to default signals
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Free the trap strings if mode is non-zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If mode>1 then ignored traps cause signal to be ignored
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *trap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(sig-- > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * free up trap if set and restore signal handler if modified
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *trap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * check for traps
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *trap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* execute errexit trap first */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD])
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#endif /* SHOPT_BGX */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sig==SIGPIPE && (fp=sfpool((Sfio_t*)0,sh.outpool,SF_WRITE)) && sferror(fp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * parse and execute the given trap string, stream or tree depending on mode
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * mode==0 for string, mode==1 for stream, mode==2 for parse tree
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner memcpy(ifstable,shp->ifstable,sizeof(ifstable));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner memcpy(shp->ifstable,ifstable,sizeof(ifstable));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * exit the current scope and jump to an earlier one based on pp->mode
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct checkpt *pp = (struct checkpt*)shp->jmplist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int sig=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* ^Z detected by the shell */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Handles ^Z for shell builtins, subshells, and functs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait for child to stop */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* return to prompt mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* child process, put to sleep */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* stop child job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* child resumes */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* unlock output pool */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGPIPE */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif /* SHOPT_TYPEDEF*/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void array_notify(Namval_t *np, void *data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is the exit routine for the shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *t;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->st.trapcom[0]=0; /*should free but not long */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* avoid recursive call for set -e */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_ACCT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strmatch((char*)0,(char*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* generate fault termination code */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */