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-2021, Simon J. Gerraty
108 *
109 *      This is free software.  It comes with NO WARRANTY.
110 *      Permission to use, modify and distribute this source code
111 *      is granted subject to the following conditions.
112 *      1/ that that the above copyright notice and this notice
113 *      are preserved in all copies and that due credit be given
114 *      to the author.
115 *      2/ that any changes to this code are clearly commented
116 *      as such so that the author does get blamed for bugs
117 *      other than his own.
118 *
119 *      Please send copies of changes and bug-fixes to:
120 *      sjg@crufty.net
121 *
122 */
123#ifndef lint
124static char *RCSid = "$Id: sigact.c,v 1.8 2021/10/14 19:39:17 sjg Exp $";
125#endif
126
127#undef _ANSI_SOURCE		/* causes problems */
128
129#include <signal.h>
130#include <sys/cdefs.h>
131
132#ifdef HAVE_CONFIG_H
133# include "config.h"
134# ifdef NO_SIGSET
135#   undef HAVE_SIGSET
136# endif
137# ifndef HAVE_SIGACTION
138#   ifdef HAVE_SIGSETMASK
139#     define USE_SIGMASK
140#   else
141#     ifdef HAVE_SIGSET
142#       define USE_SIGSET
143#     else
144#       define USE_SIGNAL
145#     endif
146#   endif
147# endif
148#endif
149
150/*
151 * some systems have a faulty sigaction() implementation!
152 * Allow us to bypass it.
153 * Or they may have installed sigact.h as signal.h which is why
154 * we have SA_NOCLDSTOP defined.
155 */
156#if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
157
158/*
159 * if we haven't been told,
160 * try and guess what we should implement with.
161 */
162#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
163# if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
164#   define USE_SIGMASK
165# else
166#   ifndef NO_SIGSET
167#     define USE_SIGSET
168#   else
169#     define USE_SIGNAL
170#   endif
171# endif
172#endif
173/*
174 * if we still don't know, we're in trouble
175 */
176#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
177error must know what to implement with
178#endif
179
180#include "sigact.h"
181
182/*
183 * in case signal() has been mapped to our Signal().
184 */
185#undef signal
186
187
188int
189sigaction(int sig,
190    const struct sigaction *act,
191    struct sigaction *oact)
192{
193	SIG_HDLR(*oldh) ();
194
195	if (act) {
196#ifdef USE_SIGSET
197		oldh = sigset(sig, act->sa_handler);
198#else
199		oldh = signal(sig, act->sa_handler);
200#endif
201	} else {
202		if (oact) {
203#ifdef USE_SIGSET
204			oldh = sigset(sig, SIG_IGN);
205#else
206			oldh = signal(sig, SIG_IGN);
207#endif
208			if (oldh != SIG_IGN && oldh != SIG_ERR) {
209#ifdef USE_SIGSET
210				(void) sigset(sig, oldh);
211#else
212				(void) signal(sig, oldh);
213#endif
214			}
215		}
216	}
217	if (oact) {
218		oact->sa_handler = oldh;
219	}
220	return 0;		/* hey we're faking it */
221}
222
223#ifndef HAVE_SIGADDSET
224int
225sigaddset(sigset_t *mask, int sig)
226{
227	*mask |= sigmask(sig);
228	return 0;
229}
230
231
232int
233sigdelset(sigset_t *mask, int sig)
234{
235	*mask &= ~(sigmask(sig));
236	return 0;
237}
238
239
240int
241sigemptyset(sigset_t *mask)
242{
243	*mask = 0;
244	return 0;
245}
246
247
248int
249sigfillset(sigset_t *mask)
250{
251	*mask = ~0;
252	return 0;
253}
254
255
256int
257sigismember(const sigset_t *mask, int sig)
258{
259	return ((*mask) & sigmask(sig));
260}
261#endif
262
263#ifndef HAVE_SIGPENDING
264int
265sigpending(sigset_t *set)
266{
267	return 0;		/* faking it! */
268}
269#endif
270
271#ifndef HAVE_SIGPROCMASK
272int
273sigprocmask(int how, const sigset_t *set, sigset_t *oset)
274{
275#ifdef USE_SIGSET
276	int i;
277#endif
278	static sigset_t sm;
279	static int once = 0;
280
281	if (!once) {
282		/*
283	         * initally we clear sm,
284	         * there after, it represents the last
285	         * thing we did.
286	         */
287		once++;
288#ifdef USE_SIGMASK
289		sm = sigblock(0);
290#else
291		sm = 0;
292#endif
293	}
294	if (oset)
295		*oset = sm;
296	if (set) {
297		switch (how) {
298		case SIG_BLOCK:
299			sm |= *set;
300			break;
301		case SIG_UNBLOCK:
302			sm &= ~(*set);
303			break;
304		case SIG_SETMASK:
305			sm = *set;
306			break;
307		}
308#ifdef USE_SIGMASK
309		(void) sigsetmask(sm);
310#else
311#ifdef USE_SIGSET
312		for (i = 1; i < NSIG; i++) {
313			if (how == SIG_UNBLOCK) {
314				if (*set & sigmask(i))
315					sigrelse(i);
316			} else
317				if (sm & sigmask(i)) {
318					sighold(i);
319				}
320		}
321#endif
322#endif
323	}
324	return 0;
325}
326#endif
327
328#ifndef HAVE_SIGSUSPEND
329int
330sigsuspend(sigset_t *mask)
331{
332#ifdef USE_SIGMASK
333	sigpause(*mask);
334#else
335	int i;
336
337#ifdef USE_SIGSET
338
339	for (i = 1; i < NSIG; i++) {
340		if (*mask & sigmask(i)) {
341			/* not the same sigpause() as above! */
342			sigpause(i);
343			break;
344		}
345	}
346#else				/* signal(2) only */
347	SIG_HDLR(*oldh) ();
348
349	/*
350         * make sure that signals in mask will not
351         * be ignored.
352         */
353	for (i = 1; i < NSIG; i++) {
354		if (*mask & sigmask(i)) {
355			if ((oldh = signal(i, SIG_DFL)) != SIG_ERR &&
356			    oldh != SIG_IGN &&
357			    oldh != SIG_DFL)
358				(void) signal(i, oldh);	/* restore handler */
359		}
360	}
361	pause();		/* wait for a signal */
362#endif
363#endif
364	return 0;
365}
366#endif
367#endif				/* ! SA_NOCLDSTOP */
368
369#if 0
370#if !defined(SIG_HDLR)
371#define SIG_HDLR void
372#endif
373#if !defined(SIG_ERR)
374#define SIG_ERR	(SIG_HDLR (*)())-1
375#endif
376
377#if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
378/*
379 * ensure we avoid signal mayhem
380 */
381
382extern void (*Signal (int sig, void (*handler) (int)))(int);
383
384SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int))
385{
386	return (Signal(sig, handler));
387}
388#endif
389#endif
390
391/* This lot (for GNU-Emacs) goes at the end of the file. */
392/*
393 * Local Variables:
394 * version-control:t
395 * comment-column:40
396 * End:
397 */
398