206 lines
4.0 KiB
C
206 lines
4.0 KiB
C
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
|
|
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
|
|
/* UNIX System Laboratories, Inc. */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
#ident "@(#)ksh:sh/error.c 1.4.4.2"
|
|
|
|
/*
|
|
* UNIX shell
|
|
*
|
|
* S. R. Bourne
|
|
* Rewritten by David Korn
|
|
* AT&T Bell Laboratories
|
|
*
|
|
*/
|
|
|
|
#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 */
|
|
|
|
/* ======== 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;
|
|
{
|
|
sh_fail(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,errval)
|
|
register const char *s1;
|
|
register MSG s2;
|
|
register int errval;
|
|
{
|
|
mac_check();
|
|
p_setout(ERRIO);
|
|
p_prp(s1);
|
|
if(s2)
|
|
{
|
|
p_str(e_colon,0);
|
|
p_str(s2,NL);
|
|
}
|
|
else
|
|
newline();
|
|
sh_exit(errval);
|
|
}
|
|
/* same as sh_fail, but print errno msg also, if errno set; started
|
|
* using this in io.c. Unlike sh_fail, s2 must be valid. Olson, 10/96 */
|
|
void
|
|
sh_fail_why(const char *s1, MSG s2, int errval)
|
|
{
|
|
static char ebuf[256];
|
|
if (!s2)
|
|
s2 = NULLSTR;
|
|
strcpy(ebuf, s2);
|
|
if(errno) {
|
|
strcat(ebuf, ": ");
|
|
strncat(ebuf, strerror(errno), sizeof(ebuf)-(strlen(s2)+3));
|
|
}
|
|
sh_fail(s1, ebuf, errval);
|
|
}
|
|
|
|
|
|
/* 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))
|
|
{
|
|
#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)
|
|
{
|
|
*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);
|
|
job.pipeflag = 0;
|
|
st.states = state;
|
|
LONGJMP(*sh.freturn,1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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_terminate();
|
|
#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);
|
|
}
|
|
|