/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2011 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 *
* (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"
#include "ulimit.h"
static char indone;
#if !_std_malloc
# include <vmalloc.h>
#endif
/*
* This exception handler is called after vmalloc() unlocks the region
*/
{
return(0);
}
#endif
/*
* Most signals caught or ignored by the shell come here
*/
{
register int flag=0;
register char *trap;
int action=0;
/* reset handler */
#ifdef SIGWINCH
{
int32_t v;
if(v = cols)
if(v = rows)
}
#endif /* SIGWINCH */
{
/* critical region, save and process later */
return;
}
{
{
}
return;
}
{
sh_subfork();
return;
}
/* handle ignored signals */
return;
if(!trap)
{
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)
{
return;
}
{
else
}
{
if(ptr)
}
/* mark signal and continue */
{
/* abort inside malloc, process when malloc returns */
/* VMFL defined when using vmalloc() */
if(dp)
}
#endif
return;
}
}
errno = 0;
if(trap)
{
/*
* propogate signal to foreground group
*/
flag = SH_SIGTRAP;
}
else
{
#ifdef SIGTSTP
{
{
flag = 0;
}
}
#endif /* SIGTSTP */
}
#ifdef ERROR_NOTIFY
if(action>0)
return;
#endif
{
return;
}
{
if(action<0)
return;
}
}
/*
* initialize signal handling
*/
{
register int sig, n;
sig_begin();
/* find the largest signal number in the table */
{
}
#endif /* SIGRTMIN && SIGRTMAX */
n = SIGTERM;
{
{
n = sig;
}
tp++;
}
{
n = (sig>>SH_SIGBITS);
continue;
sig--;
if(n&SH_SIGRUNTIME)
if(sig>=0)
{
}
}
}
/*
* Turn on trap handler for signal <sig>
*/
{
register int flag;
void (*fun)(int);
if(sig==0)
sh_sigdone();
{
/* don't set signal if already set or off by parent */
{
}
else
{
flag |= SH_SIGFAULT;
}
}
}
/*
* set signal handler so sh_done is called for all caught signals
*/
void sh_sigdone(void)
{
{
}
}
/*
* Restore to default signals
* Free the trap strings if mode is non-zero
* If mode>1 then ignored traps cause signal to be ignored
*/
{
register char *trap;
while(sig-- > 0)
{
{
if(*trap)
{
if(mode)
}
{
flag &= ~SH_SIGFAULT;
}
}
}
{
{
if(mode)
}
}
if(mode)
}
/*
* free up trap if set and restore signal handler if modified
*/
{
register char *trap;
if(!(flag&SH_SIGFAULT))
return;
{
}
}
/*
* check for traps
*/
{
register char *trap;
sig=0;
/* execute errexit trap first */
{
{
}
if(sh_isoption(SH_ERREXIT))
{
}
}
#ifdef SHOPT_BGX
#endif /* SHOPT_BGX */
while(--sig>=0)
{
continue;
#ifdef SHOPT_BGX
continue;
#endif /* SHOPT_BGX */
{
{
cursig = -1;
}
}
}
}
/*
* 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
*/
{
if(jmpval == 0)
{
if(mode==2)
else
{
if(mode)
else
}
}
else if(indone)
{
if(jmpval==SH_JMPSCRIPT)
indone=0;
else
{
if(jmpval==SH_JMPEXIT)
}
}
if(was_history)
if(was_verbose)
exitset();
if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT))
}
/*
* exit the current scope and jump to an earlier one based on pp->mode
*/
{
register int sig=0;
if(xno==SH_EXITSIG)
cursig = -1;
#ifdef SIGTSTP
{
/* ^Z detected by the shell */
return;
if(sh_isstate(SH_TIMING))
return;
/* Handles ^Z for shell builtins, subshells, and functs */
{
/* wait for child to stop */
/* return to prompt mode */
}
else
{
sh_subfork();
/* child process, put to sleep */
/* stop child job */
/* child resumes */
job_clear();
return;
}
}
#endif /* SIGTSTP */
/* unlock output pool */
#ifdef SIGPIPE
#endif /* SIGPIPE */
if(!pp)
#if SHOPT_TYPEDEF
#endif /* SHOPT_TYPEDEF*/
}
{
}
/*
* This is the exit routine for the shell
*/
{
register char *t;
indone=1;
if(sig)
{
sh_trap(t,0);
}
else
{
/* avoid recursive call for set -e */
}
#if SHOPT_ACCT
sh_accend();
#endif /* SHOPT_ACCT */
tty_cooked(-1);
#endif
#ifdef JOBS
if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
#endif /* JOBS */
strmatch((char*)0,(char*)0);
if(savxit&SH_EXITSIG)
if(sig)
{
/* generate fault termination code */
{
#ifdef _lib_getrlimit
#else
vlimit(RLIMIT_CORE,0);
#endif
}
pause();
}
#if SHOPT_KIA
if(sh_isoption(SH_NOEXEC))
#endif /* SHOPT_KIA */
}