1 /*
2
3 * Copyright (c) 1984, 1985, 1986 AT&T
4 * All Rights Reserved
5
6 * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7 * CODE OF AT&T.
8 * The copyright notice above does not
9 * evidence any actual or intended
10 * publication of such source code.
11
12 */
13 /* @(#)error.c 1.1 */
14 /*
15 * UNIX shell
16 *
17 * S. R. Bourne
18 * Rewritten by David Korn
19 * AT&T Bell Laboratories
20 *
21 */
22
23 #include "flags.h"
24 #include "defs.h"
25 #include "io.h"
26 #include "brkincr.h"
27 #include "jobs.h"
28 #include "sym.h"
29
30 /* These routines are defined by this module */
31 void exitsh();
32 void done();
33 void failed();
34 void rmtemp();
35
36 /* These routines are used by this module but defined elsewhere */
37 extern void arg_clear();
38 extern void chktrap();
39 extern void free();
40 extern void hist_flush();
41 extern char *movstr();
42 extern void name_unscope();
43 extern void p_flush();
44 extern void p_prp();
45 extern void p_setout();
46 extern void p_str();
47 extern void restore();
48 extern void rm_files();
49 extern void setcooked();
50 #ifdef VFORK
51 extern void vfork_restore();
52 #endif /* VFORK */
53
54 /* ======== error handling ======== */
55
56 /* Find out if it is time to go away.
57 * `trapnote' is set to SIGSET when fault is seen and
58 * no trap has been set.
59 */
60
61 /*
62 * This routine is called when fatal errors are encountered
63 * A message is printed out and the shell tries to exit
64 */
65
failed(s1,s2)66 void failed(s1,s2)
67 register char *s1,*s2;
68 {
69 p_setout(stderr);
70 p_prp(s1,s2?':':NL);
71 if(s2)
72 {
73 putc(SP,output);
74 p_str(s2,NL);
75 }
76 exitsh(ERROR);
77 }
78
79 /* Arrive here from `FATAL' errors
80 * a) exit command,
81 * b) default trap,
82 * c) fault with no trap set.
83 *
84 * Action is to return to command level or exit.
85 */
86
exitsh(xno)87 void exitsh(xno)
88 int xno;
89 {
90 register unsigned state=(states&~(ERRFLG|MONITOR));
91 exitval=xno;
92 if(state&BUILTIN)
93 longjmp(*freturn,1);
94 state |= is_option(ERRFLG|MONITOR);
95 if((state&(ERRFLG|FORKED|TTYFLG)) != TTYFLG)
96 {
97 states = state;
98 done(0);
99 }
100 else
101 {
102 if((state&FUNCTION)==0)
103 {
104 p_flush();
105 /* flush out input buffer */
106 setbuf(input,input->_base);
107 name_unscope();
108 arg_clear();
109 restore(0);
110 }
111 #ifdef VFORK
112 vfork_restore();
113 #endif /* VFORK */
114 execbrk = breakcnt = 0;
115 aliflg = 0;
116 exec_flag = 0;
117 hist_flush();
118 #ifdef JOBS
119 state &= ~(FUNCTION|FIXFLG|NONSTOP|READC|RWAIT|PROMPT|READPR|MONITOR|BUILTIN|VFORKED);
120 state |= is_option(INTFLG|READPR|MONITOR);
121 jobstat.j_flag = 0;
122 #else
123 state &= ~(FUNCTION|FIXFLG|RWAIT|PROMPT|READPR|BUILTIN);
124 state |= is_option(INTFLG|READPR);
125 #endif /* JOBS */
126 states = state;
127 longjmp(*freturn,1);
128 }
129 }
130
131 /*
132 * This is the exit routine for the shell
133 */
134
done(sig)135 void done(sig)
136 register int sig;
137 {
138 register char *t;
139 register int savxit = exitval;
140 if(t=trapcom[0])
141 {
142 trapcom[0]=0; /*should free but not long */
143 execexp(t,(FILE*)0);
144 }
145 else
146 {
147 /* avoid recursive call for set -e */
148 states &= ~ERRFLG;
149 chktrap();
150 }
151 rmtemp((IOPTR)0);
152 #ifdef ACCT
153 doacct();
154 #endif /* ACCT */
155 #if VSH || ESH
156 if(is_option(EMACS|EDITVI|GMACS) && standin->fstak==0)
157 setcooked(fileno(input));
158 #endif
159 if(states&RM_TMP)
160 /* clean up all temp files */
161 rm_files(tmpout);
162 p_flush();
163 #ifdef JOBS
164 if(sig==SIGHUP || (is_option(INTFLG)&&(getppid()==1)))
165 kill_all();
166 #endif /* JOBS */
167 if(sig)
168 {
169 /* generate fault termination code */
170 signal(sig,SIG_DFL);
171 #ifdef BSD_4_2
172 sigrelse(sig);
173 #endif /* BSD_4_2 */
174 kill(getpid(),sig);
175 pause();
176 }
177 exit(savxit);
178 }
179
180 /*
181 * remove temporary files
182 */
183
rmtemp(base)184 void rmtemp(base)
185 IOPTR base;
186 {
187 register IOPTR iop = iotemp;
188 while(iop>base)
189 {
190 unlink(iop->ioname);
191 free(iop->iolink);
192 iop=iop->iolst;
193 }
194 iotemp = iop;
195 }
196