/* * Copyright (c) 1984, 1985, 1986 AT&T * All Rights Reserved * THIS IS UNPUBLISHED PROPRIETARY SOURCE * CODE OF AT&T. * The copyright notice above does not * evidence any actual or intended * publication of such source code. */ /* @(#)error.c 1.1 */ /* * UNIX shell * * S. R. Bourne * Rewritten by David Korn * AT&T Bell Laboratories * */ #include "flags.h" #include "defs.h" #include "io.h" #include "brkincr.h" #include "jobs.h" #include "sym.h" /* These routines are defined by this module */ void exitsh(); void done(); void failed(); void rmtemp(); /* These routines are used by this module but defined elsewhere */ extern void arg_clear(); extern void chktrap(); extern void free(); extern void hist_flush(); extern char *movstr(); extern void name_unscope(); extern void p_flush(); extern void p_prp(); extern void p_setout(); extern void p_str(); extern void restore(); extern void rm_files(); extern void setcooked(); #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. */ /* * This routine is called when fatal errors are encountered * A message is printed out and the shell tries to exit */ void failed(s1,s2) register char *s1,*s2; { p_setout(stderr); p_prp(s1,s2?':':NL); if(s2) { putc(SP,output); p_str(s2,NL); } exitsh(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 exitsh(xno) int xno; { register unsigned state=(states&~(ERRFLG|MONITOR)); exitval=xno; if(state&BUILTIN) longjmp(*freturn,1); state |= is_option(ERRFLG|MONITOR); if((state&(ERRFLG|FORKED|TTYFLG)) != TTYFLG) { states = state; done(0); } else { if((state&FUNCTION)==0) { p_flush(); /* flush out input buffer */ setbuf(input,input->_base); name_unscope(); arg_clear(); restore(0); } #ifdef VFORK vfork_restore(); #endif /* VFORK */ execbrk = breakcnt = 0; aliflg = 0; exec_flag = 0; hist_flush(); #ifdef JOBS state &= ~(FUNCTION|FIXFLG|NONSTOP|READC|RWAIT|PROMPT|READPR|MONITOR|BUILTIN|VFORKED); state |= is_option(INTFLG|READPR|MONITOR); jobstat.j_flag = 0; #else state &= ~(FUNCTION|FIXFLG|RWAIT|PROMPT|READPR|BUILTIN); state |= is_option(INTFLG|READPR); #endif /* JOBS */ states = state; longjmp(*freturn,1); } } /* * This is the exit routine for the shell */ void done(sig) register int sig; { register char *t; register int savxit = exitval; if(t=trapcom[0]) { trapcom[0]=0; /*should free but not long */ execexp(t,(FILE*)0); } else { /* avoid recursive call for set -e */ states &= ~ERRFLG; chktrap(); } rmtemp((IOPTR)0); #ifdef ACCT doacct(); #endif /* ACCT */ #if VSH || ESH if(is_option(EMACS|EDITVI|GMACS) && standin->fstak==0) setcooked(fileno(input)); #endif if(states&RM_TMP) /* clean up all temp files */ rm_files(tmpout); p_flush(); #ifdef JOBS if(sig==SIGHUP || (is_option(INTFLG)&&(getppid()==1))) kill_all(); #endif /* JOBS */ if(sig) { /* generate fault termination code */ signal(sig,SIG_DFL); #ifdef BSD_4_2 sigrelse(sig); #endif /* BSD_4_2 */ kill(getpid(),sig); pause(); } exit(savxit); } /* * remove temporary files */ void rmtemp(base) IOPTR base; { register IOPTR iop = iotemp; while(iop>base) { unlink(iop->ioname); free(iop->iolink); iop=iop->iolst; } iotemp = iop; }