diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-12-27 17:47:37 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-01-30 17:13:33 +0000 |
commit | b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch) | |
tree | 6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libshell/common/sh/fault.c | |
parent | df36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff) | |
download | illumos-gate-b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f.tar.gz |
13405 ksh93 update to 2012-08-01
13434 sh: mishandles backslash as last character of a block of input
11750 ksh mkdir builtin doesn't honor special file permissions
9199 ksh93 builtin *grep -v mishandles blank lines, blows up libgcrypt-config
6756 sh (and ksh) have issues with ${1+"$@"}
6520 ksh: sleep could wait forever
4860 ksh93: core in printf
3791 /bin/sh's builtin 'rm' busted: 'rm -f' without arguments returns error
1047 ksh overwrites child core files
880 ksh93 coredumps on 'unset'
499 "interrupted system call" when using "tee" builtin in ksh
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by: Dominik Hassler <hadfl@omnios.org>
Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libshell/common/sh/fault.c')
-rw-r--r-- | usr/src/lib/libshell/common/sh/fault.c | 646 |
1 files changed, 0 insertions, 646 deletions
diff --git a/usr/src/lib/libshell/common/sh/fault.c b/usr/src/lib/libshell/common/sh/fault.c deleted file mode 100644 index e7bb6f9fad..0000000000 --- a/usr/src/lib/libshell/common/sh/fault.c +++ /dev/null @@ -1,646 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1982-2010 AT&T Intellectual Property * -* and is licensed under the * -* Common Public License, Version 1.0 * -* by AT&T Intellectual Property * -* * -* A copy of the License is available at * -* http://www.opensource.org/licenses/cpl1.0.txt * -* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * -* * -* Information and Software Systems Research * -* AT&T Research * -* Florham Park NJ * -* * -* David Korn <dgk@research.att.com> * -* * -***********************************************************************/ -#pragma prototyped -/* - * Fault handling routines - * - * David Korn - * AT&T Labs - * - */ - -#include "defs.h" -#include <fcin.h> -#include "io.h" -#include "history.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) - -static char indone; - -#if !_std_malloc -# include <vmalloc.h> -#endif -#if defined(VMFL) && (VMALLOC_VERSION>=20031205L) - /* - * This exception handler is called after vmalloc() unlocks the region - */ - static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp) - { - dp->exceptf = 0; - sh_exit(SH_EXITSIG); - return(0); - } -#endif - -/* - * Most signals caught or ignored by the shell come here -*/ -void sh_fault(register int sig) -{ - 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)) - signal(sig, sh_fault); - sig &= ~SH_TRAP; -#ifdef SIGWINCH - if(sig==SIGWINCH) - { - int rows=0, cols=0; - int32_t v; - astwinsize(2,&rows,&cols); - if(v = cols) - nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY); - if(v = rows) - nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY); - shp->winch++; - } -#endif /* SIGWINCH */ - if(shp->savesig) - { - /* critical region, save and process later */ - 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 && sig!=SIGCONT) - { - shp->exitval = SH_EXITSIG|sig; - sh_subfork(); - shp->exitval = 0; - return; - } - /* handle ignored signals */ - if(trap && *trap==0) - return; - 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) && ! shp->subshell) - { - /* check for TERM signal between fork/exec */ - if(sig==SIGTERM && job.in_critical) - shp->trapnote |= SH_SIGTERM; - return; - } - shp->lastsig = sig; - sigrelease(sig); - if(pp->mode < SH_JMPFUN) - pp->mode = SH_JMPFUN; - else - pp->mode = SH_JMPEXIT; - if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1)))) - { - if(ptr) - free(ptr); - if(!shp->subshell) - sh_done(shp,sig); - sh_exit(SH_EXITSIG); - } - /* mark signal and continue */ - shp->trapnote |= SH_SIGSET; - if(sig <= shp->sigmax) - shp->sigflag[sig] |= SH_SIGSET; -#if defined(VMFL) && (VMALLOC_VERSION>=20031205L) - if(abortsig(sig)) - { - /* abort inside malloc, process when malloc returns */ - /* VMFL defined when using vmalloc() */ - Vmdisc_t* dp = vmdisc(Vmregion,0); - if(dp) - dp->exceptf = malloc_done; - } -#endif - return; - } - } - errno = 0; - if(pp->mode==SH_JMPCMD) - shp->lastsig = sig; - if(trap) - { - /* - * propogate signal to foreground group - */ - if(sig==SIGHUP && job.curpgid) - killpg(job.curpgid,SIGHUP); - flag = SH_SIGTRAP; - } - else - { - shp->lastsig = sig; - flag = SH_SIGSET; -#ifdef SIGTSTP - if(sig==SIGTSTP) - { - shp->trapnote |= SH_SIGTSTP; - if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK)) - { - sigrelease(sig); - sh_exit(SH_EXITSIG); - flag = 0; - } - } -#endif /* SIGTSTP */ - } -#ifdef ERROR_NOTIFY - if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun) - action = (*shp->bltinfun)(-sig,(char**)0,(void*)0); - if(action>0) - return; -#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) - return; - sigrelease(sig); - sh_exit(SH_EXITSIG); - } -} - -/* - * initialize signal handling - */ -void sh_siginit(void *ptr) -{ - Shell_t *shp = (Shell_t*)ptr; - register int sig, n; - register const struct shtable2 *tp = shtab_signals; - sig_begin(); - /* find the largest signal number in the table */ -#if defined(SIGRTMIN) && defined(SIGRTMAX) - if ((n = SIGRTMIN) > 0 && (sig = SIGRTMAX) > n && sig < SH_TRAP) - { - shp->sigruntime[SH_SIGRTMIN] = n; - shp->sigruntime[SH_SIGRTMAX] = sig; - } -#endif /* SIGRTMIN && SIGRTMAX */ - n = SIGTERM; - while(*tp->sh_name) - { - sig = (tp->sh_number&((1<<SH_SIGBITS)-1)); - if (!(sig-- & SH_TRAP)) - { - if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) - sig = shp->sigruntime[sig]; - if(sig>n && sig<SH_TRAP) - n = sig; - } - tp++; - } - 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)) > (shp->sigmax+1)) - continue; - sig--; - if(n&SH_SIGRUNTIME) - sig = shp->sigruntime[sig]; - if(sig>=0) - { - shp->sigflag[sig] = n; - if(*tp->sh_name) - shp->sigmsg[sig] = (char*)tp->sh_value; - } - } -} - -/* - * Turn on trap handler for signal <sig> - */ -void sh_sigtrap(register int sig) -{ - register int flag; - void (*fun)(int); - sh.st.otrapcom = 0; - if(sig==0) - sh_sigdone(); - else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF))) - { - /* don't set signal if already set or off by parent */ - if((fun=signal(sig,sh_fault))==SIG_IGN) - { - signal(sig,SIG_IGN); - flag |= SH_SIGOFF; - } - else - { - flag |= SH_SIGFAULT; - if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault) - signal(sig,fun); - } - flag &= ~(SH_SIGSET|SH_SIGTRAP); - sh.sigflag[sig] = flag; - } -} - -/* - * set signal handler so sh_done is called for all caught signals - */ -void sh_sigdone(void) -{ - register int flag, sig = sh.sigmax; - sh.sigflag[0] |= SH_SIGFAULT; - for(sig=sh.sigmax; sig>0; sig--) - { - flag = sh.sigflag[sig]; - if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF))) - sh_sigtrap(sig); - } -} - -/* - * Restore to default signals - * Free the trap strings if mode is non-zero - * If mode>1 then ignored traps cause signal to be ignored - */ -void sh_sigreset(register int mode) -{ - register char *trap; - register int flag, sig=sh.st.trapmax; - while(sig-- > 0) - { - if(trap=sh.st.trapcom[sig]) - { - flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET); - if(*trap) - { - if(mode) - free(trap); - sh.st.trapcom[sig] = 0; - } - else if(sig && mode>1) - { - if(sig!=SIGCHLD) - signal(sig,SIG_IGN); - flag &= ~SH_SIGFAULT; - flag |= SH_SIGOFF; - } - sh.sigflag[sig] = flag; - } - } - for(sig=SH_DEBUGTRAP-1;sig>=0;sig--) - { - if(trap=sh.st.trap[sig]) - { - if(mode) - free(trap); - sh.st.trap[sig] = 0; - } - - } - sh.st.trapcom[0] = 0; - if(mode) - sh.st.trapmax = 0; - sh.trapnote=0; -} - -/* - * free up trap if set and restore signal handler if modified - */ -void sh_sigclear(register int sig) -{ - register int flag = sh.sigflag[sig]; - register char *trap; - sh.st.otrapcom=0; - if(!(flag&SH_SIGFAULT)) - return; - flag &= ~(SH_SIGTRAP|SH_SIGSET); - if(trap=sh.st.trapcom[sig]) - { - if(!sh.subshell) - free(trap); - sh.st.trapcom[sig]=0; - } - sh.sigflag[sig] = flag; -} - -/* - * check for traps - */ - -void sh_chktrap(void) -{ - register int sig=sh.st.trapmax; - register char *trap; - if(!(sh.trapnote&~SH_SIGIGNORE)) - sig=0; - sh.trapnote &= ~SH_SIGTRAP; - /* execute errexit trap first */ - if(sh_isstate(SH_ERREXIT) && sh.exitval) - { - int sav_trapnote = sh.trapnote; - sh.trapnote &= ~SH_SIGSET; - if(sh.st.trap[SH_ERRTRAP]) - { - 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)) - { - struct checkpt *pp = (struct checkpt*)sh.jmplist; - pp->mode = SH_JMPEXIT; - sh_exit(sh.exitval); - } - } - if(sh.sigflag[SIGALRM]&SH_SIGALRM) - sh_timetraps(); -#ifdef SHOPT_BGX - if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD]) - job_chldtrap(&sh,sh.st.trapcom[SIGCHLD],1); -#endif /* SHOPT_BGX */ - while(--sig>=0) - { -#ifdef SHOPT_BGX - if(sig==SIGCHLD) - continue; -#endif /* SHOPT_BGX */ - if(sh.sigflag[sig]&SH_SIGTRAP) - { - sh.sigflag[sig] &= ~SH_SIGTRAP; - if(trap=sh.st.trapcom[sig]) - { - Sfio_t *fp; - if(sig==SIGPIPE && (fp=sfpool((Sfio_t*)0,sh.outpool,SF_WRITE)) && sferror(fp)) - sfclose(fp); - sh.oldexit = SH_EXITSIG|sig; - sh_trap(trap,0); - } - } - } -} - - -/* - * parse and execute the given trap string, stream or tree depending on mode - * mode==0 for string, mode==1 for stream, mode==2 for parse tree - */ -int sh_trap(const char *trap, int mode) -{ - 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(); - char *savptr = stakfreeze(0); - char ifstable[256]; - struct checkpt buff; - Fcin_t savefc; - fcsave(&savefc); - memcpy(ifstable,shp->ifstable,sizeof(ifstable)); - sh_offstate(SH_HISTORY); - sh_offstate(SH_VERBOSE); - shp->intrap++; - sh_pushcontext(&buff,SH_JMPTRAP); - jmpval = sigsetjmp(buff.buff,0); - if(jmpval == 0) - { - if(mode==2) - sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT)); - else - { - Sfio_t *sp; - if(mode) - sp = (Sfio_t*)trap; - else - sp = sfopen(NIL(Sfio_t*),trap,"s"); - sh_eval(sp,0); - } - } - else if(indone) - { - if(jmpval==SH_JMPSCRIPT) - indone=0; - else - { - if(jmpval==SH_JMPEXIT) - savxit = shp->exitval; - jmpval=SH_JMPTRAP; - } - } - sh_popcontext(&buff); - shp->intrap--; - sfsync(shp->outpool); - if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN) - shp->exitval=savxit; - stakset(savptr,staktop); - fcrestore(&savefc); - memcpy(shp->ifstable,ifstable,sizeof(ifstable)); - if(was_history) - sh_onstate(SH_HISTORY); - if(was_verbose) - sh_onstate(SH_VERBOSE); - exitset(); - if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT)) - siglongjmp(*shp->jmplist,jmpval); - return(shp->exitval); -} - -/* - * exit the current scope and jump to an earlier one based on pp->mode - */ -void sh_exit(register int xno) -{ - Shell_t *shp = &sh; - register struct checkpt *pp = (struct checkpt*)shp->jmplist; - register int sig=0; - register Sfio_t* pool; - shp->exitval=xno; - if(xno==SH_EXITSIG) - shp->exitval |= (sig=shp->lastsig); -#ifdef SIGTSTP - if(shp->trapnote&SH_SIGTSTP) - { - /* ^Z detected by the shell */ - 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 */ - shp->lastsig = 0; - sh_onstate(SH_MONITOR); - sh_offstate(SH_STOPOK); - 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; - shp->sigflag[SIGTSTP] = 0; - /* wait for child to stop */ - shp->exitval = (SH_EXITSIG|SIGTSTP); - /* return to prompt mode */ - pp->mode = SH_JMPERREXIT; - } - else - { - if(shp->subshell) - sh_subfork(); - /* child process, put to sleep */ - sh_offstate(SH_STOPOK); - sh_offstate(SH_MONITOR); - shp->sigflag[SIGTSTP] = 0; - /* stop child job */ - killpg(job.curpgid,SIGTSTP); - /* child resumes */ - job_clear(); - shp->forked = 1; - shp->exitval = (xno&SH_EXITMASK); - return; - } - } -#endif /* SIGTSTP */ - /* unlock output pool */ - sh_offstate(SH_NOTRACK); - if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE))) - pool = shp->outpool; /* can't happen? */ - sfclrlock(pool); -#ifdef SIGPIPE - if(shp->lastsig==SIGPIPE) - sfpurge(pool); -#endif /* SIGPIPE */ - sfclrlock(sfstdin); - if(!pp) - 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(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(void *ptr, register int sig) -{ - Shell_t *shp = (Shell_t*)ptr; - register char *t; - register int savxit = shp->exitval; - shp->trapnote = 0; - indone=1; - if(sig) - savxit = SH_EXITSIG|sig; - if(shp->userinit) - (*shp->userinit)(shp, -1); - if(t=shp->st.trapcom[0]) - { - shp->st.trapcom[0]=0; /*should free but not long */ - shp->oldexit = savxit; - sh_trap(t,0); - savxit = shp->exitval; - } - else - { - /* avoid recursive call for set -e */ - sh_offstate(SH_ERREXIT); - sh_chktrap(); - } - nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY); - sh_freeup(shp); -#if SHOPT_ACCT - sh_accend(); -#endif /* SHOPT_ACCT */ -#if SHOPT_VSH || SHOPT_ESH - if(sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS)) - tty_cooked(-1); -#endif -#ifdef JOBS - 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(shp); - if(nv_search("VMTRACE", shp->var_tree,0)) - strmatch((char*)0,(char*)0); - sfsync((Sfio_t*)sfstdin); - sfsync((Sfio_t*)shp->outpool); - sfsync((Sfio_t*)sfstdout); - if(savxit&SH_EXITSIG) - sig = savxit&SH_EXITMASK; - if(sig) - { - /* generate fault termination code */ - signal(sig,SIG_DFL); - sigrelease(sig); - kill(getpid(),sig); - pause(); - } -#if SHOPT_KIA - if(sh_isoption(SH_NOEXEC)) - kiaclose((Lex_t*)shp->lex_context); -#endif /* SHOPT_KIA */ - exit(savxit&SH_EXITMASK); -} - |