xref: /src/contrib/bmake/sigaction.c (revision c60f6422ffae3ea85e7b10bad950ad27c463af18)
1 /* NAME:
2  *      sigact.c - fake sigaction(2)
3  *
4  * SYNOPSIS:
5  *      #include "sigact.h"
6  *
7  *      int sigaction(int sig, struct sigaction *act,
8  *                      struct sigaction *oact);
9  *      int sigaddset(sigset_t *mask, int sig);
10  *      int sigdelset(sigset_t *mask, int sig);
11  *      int sigemptyset(sigset_t *mask);
12  *      int sigfillset(sigset_t *mask);
13  *      int sigismember(sigset_t *mask, int sig);
14  *      int sigpending(sigset_t *set);
15  *      int sigprocmask(int how, sigset_t *set, sigset_t *oset);
16  *      int sigsuspend(sigset_t *mask);
17  *
18  *      SIG_HDLR (*Signal(int sig, SIG_HDLR (*disp)(int)))(int);
19  *
20  * DESCRIPTION:
21  *      This is a fake sigaction implementation.  It uses
22  *      sigsetmask(2) et al or sigset(2) and friends if
23  *      available, otherwise it just uses signal(2).  If it
24  *      thinks sigaction(2) really exists it compiles to "almost"
25  *      nothing.
26  *
27  *      In any case it provides a Signal() function that is
28  *      implemented in terms of sigaction().
29  *      If not using signal(2) as part of the underlying
30  *      implementation (USE_SIGNAL or USE_SIGMASK), and
31  *      NO_SIGNAL is not defined, it also provides a signal()
32  *      function that calls Signal().
33  *
34  *      The need for all this mucking about is the problems
35  *      caused by mixing various signal handling mechanisms in
36  *      the one process.  This module allows for a consistent
37  *      POSIX compliant interface to whatever is actually
38  *      available.
39  *
40  *      sigaction() allows the caller to examine and/or set the
41  *      action to be associated with a given signal. "act" and
42  *      "oact" are pointers to 'sigaction structs':
43  *.nf
44  *
45  *      struct sigaction
46  *      {
47  *             SIG_HDLR  (*sa_handler)();
48  *             sigset_t  sa_mask;
49  *             int       sa_flags;
50  *      };
51  *.fi
52  *
53  *      SIG_HDLR is normally 'void' in the POSIX implementation
54  *      and for most current systems.  On some older UNIX
55  *      systems, signal handlers do not return 'void', so
56  *      this implementation keeps 'sa_handler' inline with the
57  *      hosts normal signal handling conventions.
58  *      'sa_mask' controls which signals will be blocked while
59  *      the selected signal handler is active.  It is not used
60  *      in this implementation.
61  *      'sa_flags' controls various semantics such as whether
62  *      system calls should be automagically restarted
63  *      (SA_RESTART) etc.  It is not used in this
64  *      implementation.
65  *      Either "act" or "oact" may be NULL in which case the
66  *      appropriate operation is skipped.
67  *
68  *      sigaddset() adds "sig" to the sigset_t pointed to by "mask".
69  *
70  *      sigdelset() removes "sig" from the sigset_t pointed to
71  *      by "mask".
72  *
73  *      sigemptyset() makes the sigset_t pointed to by "mask" empty.
74  *
75  *      sigfillset() makes the sigset_t pointed to by "mask"
76  *      full ie. match all signals.
77  *
78  *      sigismember() returns true if "sig" is found in "*mask".
79  *
80  *      sigpending() is supposed to return "set" loaded with the
81  *      set of signals that are blocked and pending for the
82  *      calling process.  It does nothing in this impementation.
83  *
84  *      sigprocmask() is used to examine and/or change the
85  *      signal mask for the calling process.  Either "set" or
86  *      "oset" may be NULL in which case the appropriate
87  *      operation is skipped.  "how" may be one of SIG_BLOCK,
88  *      SIG_UNBLOCK or SIG_SETMASK.  If this package is built
89  *      with USE_SIGNAL, then this routine achieves nothing.
90  *
91  *      sigsuspend() sets the signal mask to "*mask" and waits
92  *      for a signal to be delivered after which the previous
93  *      mask is restored.
94  *
95  *
96  * RETURN VALUE:
97  *      0==success, -1==failure
98  *
99  * BUGS:
100  *      Since we fake most of this, don't expect fancy usage to
101  *      work.
102  *
103  * AUTHOR:
104  *      Simon J. Gerraty <sjg@crufty.net>
105  */
106 /* COPYRIGHT:
107  *      @(#)Copyright (c) 1992-2025, Simon J. Gerraty
108  *
109  *      SPDX-License-Identifier: BSD-2-Clause
110  *
111  *      Please send copies of changes and bug-fixes to:
112  *      sjg@crufty.net
113  *
114  */
115 #ifndef lint
116 static char *RCSid = "$Id: sigact.c,v 1.9 2025/08/09 22:11:45 sjg Exp $";
117 #endif
118 
119 #undef _ANSI_SOURCE		/* causes problems */
120 
121 #include <signal.h>
122 #include <sys/cdefs.h>
123 
124 #ifdef HAVE_CONFIG_H
125 # include "config.h"
126 # ifdef NO_SIGSET
127 #   undef HAVE_SIGSET
128 # endif
129 # ifndef HAVE_SIGACTION
130 #   ifdef HAVE_SIGSETMASK
131 #     define USE_SIGMASK
132 #   else
133 #     ifdef HAVE_SIGSET
134 #       define USE_SIGSET
135 #     else
136 #       define USE_SIGNAL
137 #     endif
138 #   endif
139 # endif
140 #endif
141 
142 /*
143  * some systems have a faulty sigaction() implementation!
144  * Allow us to bypass it.
145  * Or they may have installed sigact.h as signal.h which is why
146  * we have SA_NOCLDSTOP defined.
147  */
148 #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
149 
150 /*
151  * if we haven't been told,
152  * try and guess what we should implement with.
153  */
154 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
155 # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
156 #   define USE_SIGMASK
157 # else
158 #   ifndef NO_SIGSET
159 #     define USE_SIGSET
160 #   else
161 #     define USE_SIGNAL
162 #   endif
163 # endif
164 #endif
165 /*
166  * if we still don't know, we're in trouble
167  */
168 #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
169 error must know what to implement with
170 #endif
171 
172 #include "sigact.h"
173 
174 /*
175  * in case signal() has been mapped to our Signal().
176  */
177 #undef signal
178 
179 
180 int
sigaction(int sig,const struct sigaction * act,struct sigaction * oact)181 sigaction(int sig,
182     const struct sigaction *act,
183     struct sigaction *oact)
184 {
185 	SIG_HDLR(*oldh) ();
186 
187 	if (act) {
188 #ifdef USE_SIGSET
189 		oldh = sigset(sig, act->sa_handler);
190 #else
191 		oldh = signal(sig, act->sa_handler);
192 #endif
193 	} else {
194 		if (oact) {
195 #ifdef USE_SIGSET
196 			oldh = sigset(sig, SIG_IGN);
197 #else
198 			oldh = signal(sig, SIG_IGN);
199 #endif
200 			if (oldh != SIG_IGN && oldh != SIG_ERR) {
201 #ifdef USE_SIGSET
202 				(void) sigset(sig, oldh);
203 #else
204 				(void) signal(sig, oldh);
205 #endif
206 			}
207 		}
208 	}
209 	if (oact) {
210 		oact->sa_handler = oldh;
211 	}
212 	return 0;		/* hey we're faking it */
213 }
214 
215 #ifndef HAVE_SIGADDSET
216 int
sigaddset(sigset_t * mask,int sig)217 sigaddset(sigset_t *mask, int sig)
218 {
219 	*mask |= sigmask(sig);
220 	return 0;
221 }
222 
223 
224 int
sigdelset(sigset_t * mask,int sig)225 sigdelset(sigset_t *mask, int sig)
226 {
227 	*mask &= ~(sigmask(sig));
228 	return 0;
229 }
230 
231 
232 int
sigemptyset(sigset_t * mask)233 sigemptyset(sigset_t *mask)
234 {
235 	*mask = 0;
236 	return 0;
237 }
238 
239 
240 int
sigfillset(sigset_t * mask)241 sigfillset(sigset_t *mask)
242 {
243 	*mask = ~0;
244 	return 0;
245 }
246 
247 
248 int
sigismember(const sigset_t * mask,int sig)249 sigismember(const sigset_t *mask, int sig)
250 {
251 	return ((*mask) & sigmask(sig));
252 }
253 #endif
254 
255 #ifndef HAVE_SIGPENDING
256 int
sigpending(sigset_t * set)257 sigpending(sigset_t *set)
258 {
259 	return 0;		/* faking it! */
260 }
261 #endif
262 
263 #ifndef HAVE_SIGPROCMASK
264 int
sigprocmask(int how,const sigset_t * set,sigset_t * oset)265 sigprocmask(int how, const sigset_t *set, sigset_t *oset)
266 {
267 #ifdef USE_SIGSET
268 	int i;
269 #endif
270 	static sigset_t sm;
271 	static int once = 0;
272 
273 	if (!once) {
274 		/*
275 	         * initally we clear sm,
276 	         * there after, it represents the last
277 	         * thing we did.
278 	         */
279 		once++;
280 #ifdef USE_SIGMASK
281 		sm = sigblock(0);
282 #else
283 		sm = 0;
284 #endif
285 	}
286 	if (oset)
287 		*oset = sm;
288 	if (set) {
289 		switch (how) {
290 		case SIG_BLOCK:
291 			sm |= *set;
292 			break;
293 		case SIG_UNBLOCK:
294 			sm &= ~(*set);
295 			break;
296 		case SIG_SETMASK:
297 			sm = *set;
298 			break;
299 		}
300 #ifdef USE_SIGMASK
301 		(void) sigsetmask(sm);
302 #else
303 #ifdef USE_SIGSET
304 		for (i = 1; i < NSIG; i++) {
305 			if (how == SIG_UNBLOCK) {
306 				if (*set & sigmask(i))
307 					sigrelse(i);
308 			} else
309 				if (sm & sigmask(i)) {
310 					sighold(i);
311 				}
312 		}
313 #endif
314 #endif
315 	}
316 	return 0;
317 }
318 #endif
319 
320 #ifndef HAVE_SIGSUSPEND
321 int
sigsuspend(sigset_t * mask)322 sigsuspend(sigset_t *mask)
323 {
324 #ifdef USE_SIGMASK
325 	sigpause(*mask);
326 #else
327 	int i;
328 
329 #ifdef USE_SIGSET
330 
331 	for (i = 1; i < NSIG; i++) {
332 		if (*mask & sigmask(i)) {
333 			/* not the same sigpause() as above! */
334 			sigpause(i);
335 			break;
336 		}
337 	}
338 #else				/* signal(2) only */
339 	SIG_HDLR(*oldh) ();
340 
341 	/*
342          * make sure that signals in mask will not
343          * be ignored.
344          */
345 	for (i = 1; i < NSIG; i++) {
346 		if (*mask & sigmask(i)) {
347 			if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
348 			    oldh != SIG_IGN &&
349 			    oldh != SIG_DFL)
350 				(void) signal(i, oldh);	/* restore handler */
351 		}
352 	}
353 	pause();		/* wait for a signal */
354 #endif
355 #endif
356 	return 0;
357 }
358 #endif
359 #endif				/* ! SA_NOCLDSTOP */
360 
361 #if 0
362 #if !defined(SIG_HDLR)
363 #define SIG_HDLR void
364 #endif
365 #if !defined(SIG_ERR)
366 #define SIG_ERR	(SIG_HDLR (*)())-1
367 #endif
368 
369 #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
370 /*
371  * ensure we avoid signal mayhem
372  */
373 
374 extern void (*Signal (int sig, void (*handler) (int)))(int);
375 
376 SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int))
377 {
378 	return (Signal(sig, handler));
379 }
380 #endif
381 #endif
382 
383 /* This lot (for GNU-Emacs) goes at the end of the file. */
384 /*
385  * Local Variables:
386  * version-control:t
387  * comment-column:40
388  * End:
389  */
390