summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/fault.c
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2020-12-27 17:47:37 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-01-30 17:13:33 +0000
commitb30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch)
tree6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libshell/common/sh/fault.c
parentdf36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff)
downloadillumos-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.c646
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);
-}
-