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