diff options
author | April Chin <April.Chin@Sun.COM> | 2008-12-27 14:59:38 -0800 |
---|---|---|
committer | April Chin <April.Chin@Sun.COM> | 2008-12-27 14:59:38 -0800 |
commit | 7c2fbfb345896881c631598ee3852ce9ce33fb07 (patch) | |
tree | 4b173b5657508562dfc0aa05f7d056d1e9add505 /usr/src/lib/libshell/common/sh/fault.c | |
parent | 6071ac1de68fed78e1e10052045bbb5f1732a263 (diff) | |
download | illumos-gate-7c2fbfb345896881c631598ee3852ce9ce33fb07.tar.gz |
PSARC/2008/094 ksh93 Update 1
PSARC/2008/344 ksh93 Integration Update 1 Amendments 1
PSARC/2008/589 Remove /usr/bin/printf from PSARC case 2008 094
6619428 *ksh93* RFE: Update ksh93 in Solaris to ast-ksh.2008-11-04
6788659 RFE: Update libpp in Solaris to ast-open.2008-07-25
6561901 RFE: Add "shcomp" (shell script compiler) + kernel module to exec binary sh code
6599668 RFE: Move consumers of alias.sh over to ksh93
6595183 *ksh93* RFE: Update ksh93-integration demo code
6775901 *ksh93* no C message catalogs are generated for ksh93
6451262 *sleep* RFE: /usr/bin/sleep should support floating-point values
6687139 *ksh93* command substitution, exec, and stdout redirection cause allocation loop
6703761 *ksh93* crashes in script containing uncommon output redirections
6715496 *ksh93* SEGVs on array reinitialization
6713682 *ksh93* Creating a compound variable in a subshell "bleeds through" to the calling subshell
6672350 *ksh93* causes parent shell to die when child shell is suspended
6745015 *ksh93* VARIABLE=`command substitution` assignment is not reliable on OpenSolaris
6710205 *ksh93* problem with command substitution (within back quotes) containing \$'
6737600 *ksh93* exits debugger when user presses ctrl-c
6748645 *ksh93* fc -l -e - is mis-parsed, outputs wrong error message "-e - requires single argument"
6754020 *ksh93* does weird '[' expansion
6753538 *ksh93* umask modification leaks out of a ksh93 subshell
6766246 *ksh93* bug in pattern matching
6763594 *ksh93* executes command after "command" builtin twice on failure
6762665 *ksh93* Difficult-to-reproduce SIGSEGV in ksh93
Diffstat (limited to 'usr/src/lib/libshell/common/sh/fault.c')
-rw-r--r-- | usr/src/lib/libshell/common/sh/fault.c | 252 |
1 files changed, 150 insertions, 102 deletions
diff --git a/usr/src/lib/libshell/common/sh/fault.c b/usr/src/lib/libshell/common/sh/fault.c index 2d71736187..60af63972d 100644 --- a/usr/src/lib/libshell/common/sh/fault.c +++ b/usr/src/lib/libshell/common/sh/fault.c @@ -1,10 +1,10 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1982-2007 AT&T Knowledge Ventures * +* Copyright (c) 1982-2008 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * -* by AT&T Knowledge Ventures * +* by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * @@ -30,10 +30,11 @@ #include <fcin.h> #include "io.h" #include "history.h" -#include "shnodes.h" +#include "shlex.h" #include "variables.h" #include "jobs.h" #include "path.h" +#include "builtins.h" #define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV) @@ -59,9 +60,10 @@ static char indone; */ void sh_fault(register int sig) { - register int flag=0; - register char *trap; - register struct checkpt *pp = (struct checkpt*)sh.jmplist; + register Shell_t *shp = sh_getinterp(); + register int flag=0; + register char *trap; + register struct checkpt *pp = (struct checkpt*)shp->jmplist; int action=0; /* reset handler */ if(!(sig&SH_TRAP)) @@ -74,37 +76,56 @@ void sh_fault(register int sig) int32_t v; astwinsize(2,&rows,&cols); if(v = cols) - nv_putval(COLUMNS, (char*)&v, NV_INT32); + nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY); if(v = rows) - nv_putval(LINES, (char*)&v, NV_INT32); + nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY); + shp->winch++; } #endif /* SIGWINCH */ - if(sh.savesig) + if(shp->savesig) { /* critical region, save and process later */ - sh.savesig = sig; + shp->savesig = sig; + return; + } + trap = shp->st.trapcom[sig]; + if(sig==SIGALRM && shp->bltinfun==b_sleep) + { + if(trap && *trap) + { + shp->trapnote |= SH_SIGTRAP; + shp->sigflag[sig] |= SH_SIGTRAP; + } + return; + } + if(shp->subshell && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH) + { + shp->exitval = SH_EXITSIG|sig; + sh_subfork(); + shp->exitval = 0; return; } - /* handle ignored signals */ - if((trap=sh.st.trapcom[sig]) && *trap==0) + if(trap && *trap==0) return; - flag = sh.sigflag[sig]&~SH_SIGOFF; + flag = shp->sigflag[sig]&~SH_SIGOFF; if(!trap) { + if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE)) + return; if(flag&SH_SIGIGNORE) return; if(flag&SH_SIGDONE) { void *ptr=0; - if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! sh.subshell) + if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell) { /* check for TERM signal between fork/exec */ if(sig==SIGTERM && job.in_critical) - sh.trapnote |= SH_SIGTERM; + shp->trapnote |= SH_SIGTERM; return; } - sh.lastsig = sig; + shp->lastsig = sig; sigrelease(sig); if(pp->mode < SH_JMPFUN) pp->mode = SH_JMPFUN; @@ -114,14 +135,14 @@ void sh_fault(register int sig) { if(ptr) free(ptr); - if(!sh.subshell) - sh_done(sig); + if(!shp->subshell) + sh_done(shp,sig); sh_exit(SH_EXITSIG); } /* mark signal and continue */ - sh.trapnote |= SH_SIGSET; - if(sig < sh.sigmax) - sh.sigflag[sig] |= SH_SIGSET; + shp->trapnote |= SH_SIGSET; + if(sig < shp->sigmax) + shp->sigflag[sig] |= SH_SIGSET; #if defined(VMFL) && (VMALLOC_VERSION>=20031205L) if(abortsig(sig)) { @@ -137,7 +158,7 @@ void sh_fault(register int sig) } errno = 0; if(pp->mode==SH_JMPCMD) - sh.lastsig = sig; + shp->lastsig = sig; if(trap) { /* @@ -149,12 +170,12 @@ void sh_fault(register int sig) } else { - sh.lastsig = sig; + shp->lastsig = sig; flag = SH_SIGSET; #ifdef SIGTSTP if(sig==SIGTSTP) { - sh.trapnote |= SH_SIGTSTP; + shp->trapnote |= SH_SIGTSTP; if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK)) { sigrelease(sig); @@ -165,14 +186,20 @@ void sh_fault(register int sig) #endif /* SIGTSTP */ } #ifdef ERROR_NOTIFY - if((error_info.flags&ERROR_NOTIFY) && sh.bltinfun) - action = (*sh.bltinfun)(-sig,(char**)0,(void*)0); -#endif + /* This is obsolete */ + if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun) + action = (*shp->bltinfun)(-sig,(char**)0,(void*)0); if(action>0) return; - sh.trapnote |= flag; - if(sig < sh.sigmax) - sh.sigflag[sig] |= flag; +#endif + if(shp->bltinfun && shp->bltindata.notify) + { + shp->bltindata.sigset = 1; + return; + } + shp->trapnote |= flag; + if(sig < shp->sigmax) + shp->sigflag[sig] |= flag; if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK)) { if(action<0) @@ -185,45 +212,45 @@ void sh_fault(register int sig) /* * initialize signal handling */ -void sh_siginit(void) +void sh_siginit(void *ptr) { + Shell_t *shp = (Shell_t*)ptr; register int sig, n=SIGTERM+1; register const struct shtable2 *tp = shtab_signals; sig_begin(); /* find the largest signal number in the table */ +#ifdef SIGRTMIN + shp->sigruntime[SH_SIGRTMIN] = SIGRTMIN; +#endif /* SIGRTMIN */ +#ifdef SIGRTMAX + shp->sigruntime[SH_SIGRTMAX] = SIGRTMAX; +#endif /* SIGRTMAX */ while(*tp->sh_name) { - if((sig=tp->sh_number&((1<<SH_SIGBITS)-1))>n && sig<SH_TRAP) + sig = tp->sh_number&((1<<SH_SIGBITS)-1); + if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) + sig = shp->sigruntime[sig-1]; + if(sig>n && sig<SH_TRAP) n = sig; tp++; } -#if defined(_SC_SIGRT_MAX) && defined(_SIGRTMAX) - if((sig=SIGRTMAX+1)>n && sig<SH_TRAP) - n = sig; -#endif - sh.sigmax = n; - sh.st.trapcom = (char**)calloc(n,sizeof(char*)); - sh.sigflag = (unsigned char*)calloc(n,1); - sh.sigmsg = (char**)calloc(n,sizeof(char*)); + shp->sigmax = n++; + shp->st.trapcom = (char**)calloc(n,sizeof(char*)); + shp->sigflag = (unsigned char*)calloc(n,1); + shp->sigmsg = (char**)calloc(n,sizeof(char*)); for(tp=shtab_signals; sig=tp->sh_number; tp++) { n = (sig>>SH_SIGBITS); - if((sig &= ((1<<SH_SIGBITS)-1)) > sh.sigmax) + if((sig &= ((1<<SH_SIGBITS)-1)) > shp->sigmax) continue; sig--; -#if defined(_SC_SIGRT_MIN) && defined(_SIGRTMIN) - if(sig==_SIGRTMIN) - sig = SIGRTMIN; -#endif -#if defined(_SC_SIGRT_MAX) && defined(_SIGRTMAX) - if(sig==_SIGRTMAX) - sig = SIGRTMAX; -#endif + if(n&SH_SIGRUNTIME) + sig = shp->sigruntime[sig]; if(sig>=0) { - sh.sigflag[sig] = n; + shp->sigflag[sig] = n; if(*tp->sh_name) - sh.sigmsg[sig] = (char*)tp->sh_value; + shp->sigmsg[sig] = (char*)tp->sh_value; } } } @@ -301,7 +328,7 @@ void sh_sigreset(register int mode) sh.sigflag[sig] = flag; } } - for(sig=SH_DEBUGTRAP;sig>=0;sig--) + for(sig=SH_DEBUGTRAP-1;sig>=0;sig--) { if(trap=sh.st.trap[sig]) { @@ -344,7 +371,7 @@ void sh_chktrap(void) { register int sig=sh.st.trapmax; register char *trap; - if(!sh.trapnote) + if(!(sh.trapnote&~SH_SIGIGNORE)) sig=0; sh.trapnote &= ~SH_SIGTRAP; /* execute errexit trap first */ @@ -353,7 +380,12 @@ void sh_chktrap(void) int sav_trapnote = sh.trapnote; sh.trapnote &= ~SH_SIGSET; if(sh.st.trap[SH_ERRTRAP]) - sh_trap(sh.st.trap[SH_ERRTRAP],0); + { + trap = sh.st.trap[SH_ERRTRAP]; + sh.st.trap[SH_ERRTRAP] = 0; + sh_trap(trap,0); + sh.st.trap[SH_ERRTRAP] = trap; + } sh.trapnote = sav_trapnote; if(sh_isoption(SH_ERREXIT)) { @@ -382,7 +414,8 @@ void sh_chktrap(void) */ int sh_trap(const char *trap, int mode) { - int jmpval, savxit = sh.exitval; + Shell_t *shp = sh_getinterp(); + int jmpval, savxit = shp->exitval; int was_history = sh_isstate(SH_HISTORY); int was_verbose = sh_isstate(SH_VERBOSE); int staktop = staktell(); @@ -392,7 +425,7 @@ int sh_trap(const char *trap, int mode) fcsave(&savefc); sh_offstate(SH_HISTORY); sh_offstate(SH_VERBOSE); - sh.intrap++; + shp->intrap++; sh_pushcontext(&buff,SH_JMPTRAP); jmpval = sigsetjmp(buff.buff,0); if(jmpval == 0) @@ -416,15 +449,15 @@ int sh_trap(const char *trap, int mode) else { if(jmpval==SH_JMPEXIT) - savxit = sh.exitval; + savxit = shp->exitval; jmpval=SH_JMPTRAP; } } sh_popcontext(&buff); - sh.intrap--; - sfsync(sh.outpool); - if(jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN) - sh.exitval=savxit; + shp->intrap--; + sfsync(shp->outpool); + if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN) + shp->exitval=savxit; stakset(savptr,staktop); fcrestore(&savefc); if(was_history) @@ -433,8 +466,8 @@ int sh_trap(const char *trap, int mode) sh_onstate(SH_VERBOSE); exitset(); if(jmpval>SH_JMPTRAP) - siglongjmp(*sh.jmplist,jmpval); - return(sh.exitval); + siglongjmp(*shp->jmplist,jmpval); + return(shp->exitval); } /* @@ -442,95 +475,109 @@ int sh_trap(const char *trap, int mode) */ void sh_exit(register int xno) { - register struct checkpt *pp = (struct checkpt*)sh.jmplist; + Shell_t *shp = &sh; + register struct checkpt *pp = (struct checkpt*)shp->jmplist; register int sig=0; register Sfio_t* pool; - sh.exitval=xno; + shp->exitval=xno; if(xno==SH_EXITSIG) - sh.exitval |= (sig=sh.lastsig); + shp->exitval |= (sig=shp->lastsig); #ifdef SIGTSTP - if(sh.trapnote&SH_SIGTSTP) + if(shp->trapnote&SH_SIGTSTP) { /* ^Z detected by the shell */ - sh.trapnote = 0; - sh.sigflag[SIGTSTP] = 0; - if(!sh.subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK)) + shp->trapnote = 0; + shp->sigflag[SIGTSTP] = 0; + if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK)) return; if(sh_isstate(SH_TIMING)) return; /* Handles ^Z for shell builtins, subshells, and functs */ - sh.lastsig = 0; + shp->lastsig = 0; sh_onstate(SH_MONITOR); sh_offstate(SH_STOPOK); - sh.trapnote = 0; - if(!sh.subshell && (sig=sh_fork(0,NIL(int*)))) + shp->trapnote = 0; + if(!shp->subshell && (sig=sh_fork(0,NIL(int*)))) { job.curpgid = 0; job.parent = (pid_t)-1; job_wait(sig); job.parent = 0; - sh.sigflag[SIGTSTP] = 0; + shp->sigflag[SIGTSTP] = 0; /* wait for child to stop */ - sh.exitval = (SH_EXITSIG|SIGTSTP); + shp->exitval = (SH_EXITSIG|SIGTSTP); /* return to prompt mode */ pp->mode = SH_JMPERREXIT; } else { - if(sh.subshell) + if(shp->subshell) sh_subfork(); /* child process, put to sleep */ sh_offstate(SH_STOPOK); sh_offstate(SH_MONITOR); - sh.sigflag[SIGTSTP] = 0; + shp->sigflag[SIGTSTP] = 0; /* stop child job */ killpg(job.curpgid,SIGTSTP); /* child resumes */ job_clear(); - sh.forked = 1; - sh.exitval = (xno&SH_EXITMASK); + shp->forked = 1; + shp->exitval = (xno&SH_EXITMASK); return; } } #endif /* SIGTSTP */ /* unlock output pool */ sh_offstate(SH_NOTRACK); - if(!(pool=sfpool(NIL(Sfio_t*),sh.outpool,SF_WRITE))) - pool = sh.outpool; /* can't happen? */ + if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE))) + pool = shp->outpool; /* can't happen? */ sfclrlock(pool); #ifdef SIGPIPE - if(sh.lastsig==SIGPIPE) + if(shp->lastsig==SIGPIPE) sfpurge(pool); #endif /* SIGPIPE */ sfclrlock(sfstdin); if(!pp) - sh_done(sig); - sh.prefix = 0; + sh_done(shp,sig); + shp->prefix = 0; +#if SHOPT_TYPEDEF + shp->mktype = 0; +#endif /* SHOPT_TYPEDEF*/ if(pp->mode == SH_JMPSCRIPT && !pp->prev) - sh_done(sig); - siglongjmp(pp->buff,pp->mode); + sh_done(shp,sig); + if(pp->mode) + siglongjmp(pp->buff,pp->mode); +} + +static void array_notify(Namval_t *np, void *data) +{ + Namarr_t *ap = nv_arrayptr(np); + NOT_USED(data); + if(ap && ap->fun) + (*ap->fun)(np, 0, NV_AFREE); } /* * This is the exit routine for the shell */ -void sh_done(register int sig) +void sh_done(void *ptr, register int sig) { + Shell_t *shp = (Shell_t*)ptr; register char *t; - register int savxit = sh.exitval; - sh.trapnote = 0; + register int savxit = shp->exitval; + shp->trapnote = 0; indone=1; if(sig==0) - sig = sh.lastsig; - if(sh.userinit) - (*sh.userinit)(-1); - if(t=sh.st.trapcom[0]) + sig = shp->lastsig; + if(shp->userinit) + (*shp->userinit)(shp, -1); + if(t=shp->st.trapcom[0]) { - sh.st.trapcom[0]=0; /*should free but not long */ - sh.oldexit = savxit; + shp->st.trapcom[0]=0; /*should free but not long */ + shp->oldexit = savxit; sh_trap(t,0); - savxit = sh.exitval; + savxit = shp->exitval; } else { @@ -538,7 +585,8 @@ void sh_done(register int sig) sh_offstate(SH_ERREXIT); sh_chktrap(); } - sh_freeup(); + nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY); + sh_freeup(shp); #if SHOPT_ACCT sh_accend(); #endif /* SHOPT_ACCT */ @@ -547,14 +595,14 @@ void sh_done(register int sig) tty_cooked(-1); #endif #ifdef JOBS - if((sh_isoption(SH_INTERACTIVE) && sh.login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) + if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**)); #endif /* JOBS */ - job_close(); - if(nv_search("VMTRACE", sh.var_tree,0)) + job_close(shp); + if(nv_search("VMTRACE", shp->var_tree,0)) strmatch((char*)0,(char*)0); sfsync((Sfio_t*)sfstdin); - sfsync((Sfio_t*)sh.outpool); + sfsync((Sfio_t*)shp->outpool); sfsync((Sfio_t*)sfstdout); if(sig) { @@ -566,7 +614,7 @@ void sh_done(register int sig) } #if SHOPT_KIA if(sh_isoption(SH_NOEXEC)) - kiaclose(); + kiaclose((Lex_t*)shp->lex_context); #endif /* SHOPT_KIA */ exit(savxit&SH_EXITMASK); } |