xref: /freebsd/contrib/tcsh/tc.sig.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /* $Header: /src/pub/tcsh/tc.sig.c,v 3.25 2000/07/04 19:46:24 christos Exp $ */
2 /*
3  * tc.sig.c: Signal routine emulations
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include "sh.h"
38 
39 RCSID("$Id: tc.sig.c,v 3.25 2000/07/04 19:46:24 christos Exp $")
40 
41 #include "tc.wait.h"
42 
43 #ifndef BSDSIGS
44 
45 /* this stack is used to queue signals
46  * we can handle up to MAX_CHLD outstanding children now;
47  */
48 #define MAX_CHLD 50
49 
50 # ifdef UNRELSIGS
51 static struct mysigstack {
52     int     s_w;		/* wait report			 */
53     int     s_errno;		/* errno returned;		 */
54     pid_t   s_pid;		/* pid returned			 */
55 }       stk[MAX_CHLD];
56 static int stk_ptr = -1;
57 
58 
59 /* queue child signals
60  */
61 static sigret_t
62 sig_ch_queue()
63 {
64 #  ifdef JOBDEBUG
65     xprintf("queue SIGCHLD\n");
66     flush();
67 #  endif /* JOBDEBUG */
68     stk_ptr++;
69     stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w);
70     stk[stk_ptr].s_errno = errno;
71     (void) signal(SIGCHLD, sig_ch_queue);
72 #  ifndef SIGVOID
73     return(0);
74 #  endif /* SIGVOID */
75 }
76 
77 /* process all awaiting child signals
78  */
79 static sigret_t
80 sig_ch_rel()
81 {
82     while (stk_ptr > -1)
83 	pchild(SIGCHLD);
84 #  ifdef JOBDEBUG
85     xprintf("signal(SIGCHLD, pchild);\n");
86 #  endif /* JOBDEBUG */
87     (void) signal(SIGCHLD, pchild);
88 #  ifndef SIGVOID
89     return(0);
90 #  endif /* SIGVOID */
91 }
92 
93 
94 /* libc.a contains these functions in SYSVREL >= 3. */
95 sigret_t
96 (*xsigset(a, b)) ()
97     int     a;
98     signalfun_t  b;
99 {
100     return (signal(a, b));
101 }
102 
103 /* release signal
104  *	release all queued signals and
105  *	set the default signal handler
106  */
107 void
108 sigrelse(what)
109     int     what;
110 {
111     if (what == SIGCHLD)
112 	sig_ch_rel();
113 
114 #  ifdef COHERENT
115     (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
116 #  endif /* COHERENT */
117 }
118 
119 /* hold signal
120  * only works with child and interrupt
121  */
122 void
123 xsighold(what)
124     int     what;
125 {
126     if (what == SIGCHLD)
127 	(void) signal(SIGCHLD, sig_ch_queue);
128 
129 #  ifdef COHERENT
130     (void) signal(what, SIG_IGN);
131 #  endif /* COHERENT */
132 }
133 
134 /* ignore signal
135  */
136 void
137 xsigignore(a)
138     int     a;
139 {
140     (void) signal(a, SIG_IGN);
141 }
142 
143 /* atomically release one signal
144  */
145 void
146 xsigpause(what)
147     int     what;
148 {
149     /* From: Jim Mattson <mattson%cs@ucsd.edu> */
150     if (what == SIGCHLD)
151 	pchild(SIGCHLD);
152 }
153 
154 
155 /* return either awaiting processes or do a wait now
156  */
157 pid_t
158 ourwait(w)
159     int    *w;
160 {
161     pid_t pid;
162 
163 #  ifdef JOBDEBUG
164     xprintf(CGETS(25, 1, "our wait %d\n"), stk_ptr);
165     flush();
166 #  endif /* JOBDEBUG */
167 
168     if (stk_ptr == -1) {
169 	/* stack empty return signal from stack */
170 	pid = (pid_t) wait(w);
171 #  ifdef JOBDEBUG
172 	xprintf("signal(SIGCHLD, pchild);\n");
173 #  endif /* JOBDEBUG */
174 	(void) signal(SIGCHLD, pchild);
175 	return (pid);
176     }
177     else {
178 	/* return signal from stack */
179 	errno = stk[stk_ptr].s_errno;
180 	*w = stk[stk_ptr].s_w;
181 	stk_ptr--;
182 	return (stk[stk_ptr + 1].s_pid);
183     }
184 } /* end ourwait */
185 
186 #  ifdef COHERENT
187 #   undef signal
188 sigret_t
189 (*xsignal(a, b)) ()
190     int     a;
191     signalfun_t  b;
192 {
193     if (a == SIGCHLD)
194 	return SIG_DFL;
195     else
196 	return (signal(a, b));
197 }
198 #  endif /* COHERENT */
199 
200 # endif /* UNRELSIGS */
201 
202 # ifdef SXA
203 /*
204  * SX/A is SYSVREL3 but does not have sys5-sigpause().
205  * I've heard that sigpause() is not defined in SYSVREL3.
206  */
207 /* This is not need if you make tcsh by BSD option's cc. */
208 void
209 sigpause(what)
210 {
211     if (what == SIGCHLD) {
212 	(void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
213     }
214     else if (what == 0) {
215 	pause();
216     }
217     else {
218 	xprintf("sigpause(%d)\n", what);
219 	pause();
220     }
221 }
222 # endif /* SXA */
223 
224 #endif /* !BSDSIGS */
225 
226 #ifdef NEEDsignal
227 /* turn into bsd signals */
228 sigret_t
229 (*xsignal(s, a)) ()
230     int     s;
231     signalfun_t a;
232 {
233     sigvec_t osv, sv;
234 
235     (void) mysigvec(s, NULL, &osv);
236     sv = osv;
237     sv.sv_handler = a;
238 #ifdef SIG_STK
239     sv.sv_onstack = SIG_STK;
240 #endif /* SIG_STK */
241 #ifdef SV_BSDSIG
242     sv.sv_flags = SV_BSDSIG;
243 #endif /* SV_BSDSIG */
244 
245     if (mysigvec(s, &sv, NULL) < 0)
246 	return (BADSIG);
247     return (osv.sv_handler);
248 }
249 
250 #endif /* NEEDsignal */
251 
252 #ifdef POSIXSIGS
253 /*
254  * Support for signals.
255  */
256 
257 extern int errno;
258 
259 /* Set and test a bit.  Bits numbered 1 to 32 */
260 
261 #define SETBIT(x, y)	x |= sigmask(y)
262 #define ISSET(x, y)	((x & sigmask(y)) != 0)
263 
264 #ifdef DEBUG
265 # define SHOW_SIGNALS	1	/* to assist in debugging signals */
266 #endif /* DEBUG */
267 
268 #ifdef SHOW_SIGNALS
269 char   *show_sig_mask();
270 #endif /* SHOW_SIGNALS */
271 
272 #ifndef __PARAGON__
273 /*
274  * sigsetmask(mask)
275  *
276  * Set a new signal mask.  Return old mask.
277  */
278 sigmask_t
279 sigsetmask(mask)
280     sigmask_t     mask;
281 {
282     sigset_t set, oset;
283     int     m;
284     register int i;
285 
286     (void) sigemptyset(&set);
287     (void) sigemptyset(&oset);
288 
289     for (i = 1; i <= MAXSIG; i++)
290 	if (ISSET(mask, i))
291 	    (void) sigaddset(&set, i);
292 
293     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) {
294 	xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
295 		mask, errno);
296     }
297 
298     m = 0;
299     for (i = 1; i <= MAXSIG; i++)
300 	if (sigismember(&oset, i))
301 	    SETBIT(m, i);
302 
303     return (m);
304 }
305 #endif /* __PARAGON__ */
306 
307 #ifndef __DGUX__
308 /*
309  * sigblock(mask)
310  *
311  * Add "mask" set of signals to the present signal mask.
312  * Return old mask.
313  */
314 sigmask_t
315 sigblock(mask)
316     sigmask_t     mask;
317 {
318     sigset_t set, oset;
319     int     m;
320     register int i;
321 
322     (void) sigemptyset(&set);
323     (void) sigemptyset(&oset);
324 
325     /* Get present set of signals. */
326     if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1)
327 	stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
328 
329     /* Add in signals from mask. */
330     for (i = 1; i <= MAXSIG; i++)
331 	if (ISSET(mask, i))
332 	    (void) sigaddset(&set, i);
333 
334     if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1)
335 	stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
336 
337     /* Return old mask to user. */
338     m = 0;
339     for (i = 1; i <= MAXSIG; i++)
340 	if (sigismember(&oset, i))
341 	    SETBIT(m, i);
342 
343     return (m);
344 }
345 #endif /* __DGUX__ */
346 
347 
348 /*
349  * bsd_sigpause(mask)
350  *
351  * Set new signal mask and wait for signal;
352  * Old mask is restored on signal.
353  */
354 void
355 bsd_sigpause(mask)
356     sigmask_t     mask;
357 {
358     sigset_t set;
359     register int i;
360 
361     (void) sigemptyset(&set);
362 
363     for (i = 1; i <= MAXSIG; i++)
364 	if (ISSET(mask, i))
365 	    (void) sigaddset(&set, i);
366     (void) sigsuspend(&set);
367 }
368 
369 /*
370  * bsd_signal(sig, func)
371  *
372  * Emulate bsd style signal()
373  */
374 sigret_t (*bsd_signal(sig, func)) ()
375         int sig;
376         signalfun_t func;
377 {
378         struct sigaction act, oact;
379         sigset_t set;
380         signalfun_t r_func;
381 
382         if (sig < 0 || sig > MAXSIG) {
383                 xprintf(CGETS(25, 2,
384 			"error: bsd_signal(%d) signal out of range\n"), sig);
385                 return((signalfun_t) SIG_IGN);
386         }
387 
388         (void) sigemptyset(&set);
389 
390         act.sa_handler = (signalfun_t) func; /* user function */
391         act.sa_mask = set;                      /* signal mask */
392         act.sa_flags = 0;                       /* no special actions */
393 
394         if (sigaction(sig, &act, &oact)) {
395                 xprintf(CGETS(25, 3,
396 			"error: bsd_signal(%d) - sigaction failed, errno %d\n"),
397 			sig, errno);
398                 return((signalfun_t) SIG_IGN);
399         }
400 
401         r_func = (signalfun_t) oact.sa_handler;
402         return(r_func);
403 }
404 #endif /* POSIXSIG */
405 
406 
407 #ifdef SIGSYNCH
408 static long Synch_Cnt = 0;
409 
410 sigret_t
411 synch_handler(sno)
412 int sno;
413 {
414     if (sno != SIGSYNCH)
415 	abort();
416     Synch_Cnt++;
417 }
418 #endif /* SIGSYNCH */
419