2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: fault.c /main/4 1996/08/16 15:31:41 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF *
29 * AT&T BELL LABORATORIES *
30 * AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN *
31 * ACCORDANCE WITH APPLICABLE AGREEMENTS *
33 * Copyright (c) 1995 AT&T Corp. *
34 * Unpublished & Not for Publication *
35 * All Rights Reserved *
37 * The copyright notice above does not evidence any *
38 * actual or intended publication of such source code *
40 * This software was created by the *
41 * Advanced Software Technology Department *
42 * AT&T Bell Laboratories *
44 * For further information contact *
45 * {research,attmail}!dgk *
47 ***************************************************************/
49 /* : : generated by proto : : */
51 #if !defined(__PROTO__)
52 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
53 #if defined(__cplusplus)
54 #define __MANGLE__ "C"
59 #define __PROTO__(x) x
61 #define __PARAM__(n,o) n
62 #if !defined(__STDC__) && !defined(__cplusplus)
63 #if !defined(c_plusplus)
74 #define __PROTO__(x) ()
75 #define __OTORP__(x) x
76 #define __PARAM__(n,o) o
84 #if defined(__cplusplus) || defined(c_plusplus)
85 #define __VARARG__ ...
89 #if defined(__STDARG__)
90 #define __VA_START__(p,a) va_start(p,a)
92 #define __VA_START__(p,a) va_start(p)
107 * Most signals caught or ignored by the shell come here
109 void sh_fault __PARAM__((register int sig), (sig)) __OTORP__(register int sig;){
112 register struct checkpt *pp = (struct checkpt*)sh.jmplist;
114 signal(sig, sh_fault);
115 /* handle ignored signals */
116 if((trap=sh.st.trapcom[sig]) && *trap==0)
118 flag = sh.sigflag[sig];
121 if(flag&SH_SIGIGNORE)
125 if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! sh.subshell)
129 if(pp->mode < SH_JMPFUN)
130 pp->mode = SH_JMPFUN;
132 pp->mode = SH_JMPEXIT;
137 if(pp->mode==SH_JMPCMD)
142 * propogage signal to foreground group
144 if(sig==SIGHUP && job.curpgid)
145 killpg(job.curpgid,SIGHUP);
155 sh.trapnote |= SH_SIGTSTP;
156 if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
167 sh.sigflag[sig] |= flag;
168 if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
176 * initialize signal handling
178 void sh_siginit __PARAM__((void), ()){
179 register int sig, n=SIGTERM+1;
180 register const struct shtable2 *tp = shtab_signals;
181 init_shtab_signals();
183 /* find the largest signal number in the table */
186 if((sig=tp->sh_number&((1<<SH_SIGBITS)-1))>n && sig<SH_TRAP)
191 sh.st.trapcom = (char**)calloc(n,sizeof(char*));
192 sh.sigflag = (unsigned char*)calloc(n,1);
193 sh.sigmsg = (char**)calloc(n,sizeof(char*));
194 for(tp=shtab_signals; sig=tp->sh_number; tp++)
196 n = (sig>>SH_SIGBITS);
197 if((sig &= ((1<<SH_SIGBITS)-1)) > sh.sigmax)
200 #if defined(_SC_SIGRT_MIN) && defined(_SIGRTMIN)
204 #if defined(_SC_SIGRT_MAX) && defined(_SIGRTMAX)
210 sh.sigmsg[sig] = (char*)tp->sh_value;
215 * Turn on trap handler for signal <sig>
217 void sh_sigtrap __PARAM__((register int sig), (sig)) __OTORP__(register int sig;){
222 else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
224 /* don't set signal if already set or off by parent */
225 if(signal(sig,sh_fault)==SIG_IGN)
232 flag &= ~(SH_SIGSET|SH_SIGTRAP);
233 sh.sigflag[sig] = flag;
238 * set signal handler so sh_done is called for all caught signals
240 void sh_sigdone __PARAM__((void), ()){
241 register int flag, sig = sh.sigmax;
243 sh.sigflag[0] |= SH_SIGFAULT;
246 flag = sh.sigflag[sig];
247 if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
253 * Restore to default signals
254 * Free the trap strings if mode is non-zero
255 * If mode>1 then ignored traps cause signal to be ignored
257 void sh_sigreset __PARAM__((register int mode), (mode)) __OTORP__(register int mode;){
259 register int flag, sig=sh.st.trapmax;
262 if(trap=sh.st.trapcom[sig])
264 flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET);
269 sh.st.trapcom[sig] = 0;
271 else if(sig && mode>1)
274 flag &= ~SH_SIGFAULT;
277 sh.sigflag[sig] = flag;
280 for(sig=SH_DEBUGTRAP;sig>=0;sig--)
282 if(trap=sh.st.trap[sig])
290 sh.st.trapcom[0] = 0;
297 * free up trap if set and restore signal handler if modified
299 void sh_sigclear __PARAM__((register int sig), (sig)) __OTORP__(register int sig;){
300 register int flag = sh.sigflag[sig];
303 if(!(flag&SH_SIGFAULT))
305 flag &= ~(SH_SIGTRAP|SH_SIGSET);
306 if(trap=sh.st.trapcom[sig])
309 sh.st.trapcom[sig]=0;
311 sh.sigflag[sig] = flag;
318 void sh_chktrap __PARAM__((void), ()){
319 register int sig=sh.st.trapmax;
323 sh.trapnote &= ~SH_SIGTRAP;
324 /* execute errexit trap first */
325 if(sh_isstate(SH_ERREXIT) && sh.exitval)
327 int sav_trapnote = sh.trapnote;
328 sh.trapnote &= ~SH_SIGSET;
329 if(sh.st.trap[SH_ERRTRAP])
330 sh_trap(sh.st.trap[SH_ERRTRAP],0);
331 sh.trapnote = sav_trapnote;
332 if(sh_isoption(SH_ERREXIT))
334 struct checkpt *pp = (struct checkpt*)sh.jmplist;
335 pp->mode = SH_JMPEXIT;
339 if(sh.sigflag[SIGALRM]&SH_SIGTRAP)
343 if(sh.sigflag[sig]&SH_SIGTRAP)
345 sh.sigflag[sig] &= ~SH_SIGTRAP;
346 if(trap=sh.st.trapcom[sig])
354 * parse and execute the given trap string or tree if mode!=0
356 int sh_trap __PARAM__((const char *trap, int mode), (trap, mode)) __OTORP__(const char *trap; int mode;){
357 int jmpval, savxit = sh.exitval;
358 int save_states= sh_isstate(SH_HISTORY|SH_VERBOSE);
359 int staktop = staktell();
360 char *savptr = stakfreeze(0);
364 sh_offstate(SH_HISTORY|SH_VERBOSE);
366 sh_pushcontext(&buff,SH_JMPTRAP);
367 jmpval = sigsetjmp(buff.buff,0);
371 sh_exec((union anynode*)trap,sh_isstate(SH_ERREXIT));
373 sh_eval(sfopen(NIL(Sfio_t*),trap,"s"),0);
377 if(jmpval==SH_JMPSCRIPT)
381 if(jmpval==SH_JMPEXIT)
386 sh_popcontext(&buff);
389 if(jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
391 stakset(savptr,staktop);
393 sh_onstate(save_states);
395 if(jmpval>SH_JMPTRAP)
396 siglongjmp(*sh.jmplist,jmpval);
402 * exit the current scope and jump to an earlier one based on pp->mode
404 void sh_exit __PARAM__((register int xno), (xno)) __OTORP__(register int xno;){
405 register struct checkpt *pp = (struct checkpt*)sh.jmplist;
409 sh.exitval |= (sig=sh.lastsig);
411 if(sh.trapnote&SH_SIGTSTP)
413 /* ^Z detected by the shell */
415 sh.sigflag[SIGTSTP] = 0;
416 if(!sh.subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
418 if(sh_isstate(SH_TIMING))
420 /* Handles ^Z for shell builtins, subshells, and functs */
422 sh_onstate(SH_MONITOR);
423 sh_offstate(SH_STOPOK);
425 if(!sh.subshell && (sig=sh_fork(0,NIL(int*))))
428 job.parent = (pid_t)-1;
431 sh.sigflag[SIGTSTP] = 0;
432 /* wait for child to stop */
433 sh.exitval = (SH_EXITSIG|SIGTSTP);
434 /* return to prompt mode */
435 pp->mode = SH_JMPERREXIT;
441 /* child process, put to sleep */
442 sh_offstate(SH_MONITOR|SH_STOPOK);
443 sh.sigflag[SIGTSTP] = 0;
445 killpg(job.curpgid,SIGTSTP);
449 sh.exitval = (xno&SH_EXITMASK);
454 /* unlock output pool */
455 sh_offstate(SH_NOTRACK);
456 sfclrlock(sfpool(NIL(Sfio_t*),sh.outpool,SF_WRITE));
458 if(sh.lastsig==SIGPIPE)
459 sfpurge(sfpool(NIL(Sfio_t*),sh.outpool,SF_WRITE));
465 if(pp->mode == SH_JMPSCRIPT && !pp->prev)
467 siglongjmp(pp->buff,pp->mode);
471 * This is the exit routine for the shell
474 void sh_done __PARAM__((register int sig), (sig)) __OTORP__(register int sig;){
476 register int savxit = sh.exitval;
481 if(t=sh.st.trapcom[0])
483 sh.st.trapcom[0]=0; /*should free but not long */
490 /* avoid recursive call for set -e */
491 sh_offstate(SH_ERREXIT);
497 #endif /* SHOPT_ACCT */
498 #if SHOPT_VSH || SHOPT_ESH
499 if(sh_isoption(SH_EMACS|SH_VI|SH_GMACS))
503 if((sh_isoption(SH_INTERACTIVE) && sh.login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
504 job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**));
507 sfsync((Sfio_t*)sfstdin);
508 sfsync((Sfio_t*)sh.outpool);
509 sfsync((Sfio_t*)sfstdout);
512 /* generate fault termination code */
519 if(sh_isoption(SH_NOEXEC))
521 #endif /* SHOPT_KIA */
522 exit(savxit&SH_EXITMASK);