2021-10-11 19:38:01 -03:00

231 lines
4.1 KiB
C
Executable File

#ident "@(#)error.c 1.8 95/01/14 SMI" /* From AT&T Toolchest */
/*
* UNIX shell
*
* S. R. Bourne
* Rewritten by David Korn
* AT&T Bell Laboratories
*
*/
#include <limits.h>
#include "defs.h"
#include "jobs.h"
#include "history.h"
/* These routines are used by this module but defined elsewhere */
extern void mac_check();
extern void name_unscope();
extern void rm_files();
#ifdef VFORK
extern void vfork_restore();
#endif /* VFORK */
void cmd_shfail();
/* ======== error handling ======== */
/* Find out if it is time to go away.
* `trapnote' is set to SIGSET when fault is seen and
* no trap has been set.
*/
void sh_cfail(message)
MSG message;
{
cmd_shfail(sh.cmdname, message, ERROR);
}
/*
* This routine is called when fatal errors are encountered
* A message is printed out and the shell tries to exit
*/
void sh_fail(s1,s2)
register const char *s1;
register MSG s2;
{
cmd_shfail(s1, s2, ERROR);
}
/* Arrive here from `FATAL' errors
* a) exit command,
* b) default trap,
* c) fault with no trap set.
*
* Action is to return to command level or exit.
*/
void sh_exit(xno)
int xno;
{
register unsigned state=(st.states&~(ERRFLG|MONITOR));
sh.exitval=xno;
if(xno==SIGFAIL)
sh.exitval |= sh.lastsig;
sh.un.com = 0;
if((state&(BUILTIN|LASTPIPE)) || st.dot_depth>0)
{
#if VSH || ESH
tty_cooked(-1);
#endif
io_clear(sh.savio);
LONGJMP(*sh.freturn,1);
}
state |= is_option(ERRFLG|MONITOR);
if( (state&(ERRFLG|FORKED)) ||
(!(state&(PROFILE|PROMPT|FUNCTION)) && job_close() >= 0))
{
st.states = state;
st.peekn = 0;
sh_done(0);
}
else
{
if(!(state&FUNCTION))
{
p_flush();
name_unscope();
arg_clear();
io_clear((struct fileblk*)0);
io_restore(0);
if(st.standin)
{
if (st.standin->last)
*st.standin->last = 0;
/* flush out input buffer */
while(finbuff(st.standin)>0)
io_readc();
}
}
#ifdef VFORK
vfork_restore();
#endif /* VFORK */
st.execbrk = st.breakcnt = 0;
st.exec_flag = st.subflag = 0;
st.dot_depth = 0;
hist_flush();
state &= ~(FUNCTION|FIXFLG|RWAIT|PROMPT|READPR|MONITOR|BUILTIN|
LASTPIPE|VFORKED|GRACE);
state |= is_option(INTFLG|READPR|MONITOR);
st.states = state;
LONGJMP(*sh.freturn,1);
}
}
#ifdef JOBS
/* send signal to background process groups */
static int job_terminate(pw,sig)
register struct process *pw;
register int sig;
{
if(pw->p_pgrp)
job_kill(pw,sig);
return(0);
}
#endif /* JOBS */
/*
* This is the exit routine for the shell
*/
void sh_done(sig)
register int sig;
{
register char *t;
register int savxit = sh.exitval;
if(sh.trapnote&SIGBEGIN)
return;
sh.trapnote = 0;
if(t=st.trapcom[0])
{
st.trapcom[0]=0; /*should free but not long */
sh.oldexit = savxit;
sh.intrap++;
sh_eval(t);
sh.intrap--;
}
else
{
/* avoid recursive call for set -e */
st.states &= ~ERRFLG;
sh_chktrap();
}
sh_freeup();
#ifdef ACCT
doacct();
#endif /* ACCT */
#if VSH || ESH
if(is_option(EMACS|EDITVI|GMACS))
tty_cooked(-1);
#endif
if(st.states&RM_TMP)
/* clean up all temp files */
rm_files(io_tmpname);
p_flush();
#ifdef JOBS
if(sig==SIGHUP || (is_option(INTFLG)&&sh.login_sh))
job_walk(job_terminate,SIGHUP,(char**)0);
#endif /* JOBS */
job_close();
io_sync();
if(sig)
{
/* generate fault termination code */
signal(sig,SIG_DFL);
sigrelease(sig);
kill(getpid(),sig);
pause();
}
_exit(savxit&EXITMASK);
}
/*
* all_shfail:
* Generic error handler
*/
void static
all_shfail(cmdname, message)
register const char *cmdname;
MSG message;
{
mac_check();
p_setout(ERRIO);
p_prp(cmdname);
if (message) {
p_str(e_colon, 0);
p_str(message, NL);
} else
newline();
}
/*
* cmd_shfail:
* Abort with given command name, message and error code.
* Work like sh_fail(), but allow the error code passed.
*/
void
cmd_shfail(cmdname, message, err_code)
register const char *cmdname;
MSG message;
int err_code;
{
all_shfail(cmdname, message);
p_flush();
sh_exit(err_code);
}
/*
* Work like sh_cfail(), but allow the error code passed.
*/
void
cmd_shcfail(message, err_code)
MSG message;
int err_code;
{
/* Generate error */
cmd_shfail(sh.cmdname, message, err_code);
}