summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/fault.c
diff options
context:
space:
mode:
authorApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
committerApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
commit7c2fbfb345896881c631598ee3852ce9ce33fb07 (patch)
tree4b173b5657508562dfc0aa05f7d056d1e9add505 /usr/src/lib/libshell/common/sh/fault.c
parent6071ac1de68fed78e1e10052045bbb5f1732a263 (diff)
downloadillumos-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.c252
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);
}