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 124 static 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) 177 error 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 188 int 189 sigaction(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 224 int 225 sigaddset(sigset_t *mask, int sig) 226 { 227 *mask |= sigmask(sig); 228 return 0; 229 } 230 231 232 int 233 sigdelset(sigset_t *mask, int sig) 234 { 235 *mask &= ~(sigmask(sig)); 236 return 0; 237 } 238 239 240 int 241 sigemptyset(sigset_t *mask) 242 { 243 *mask = 0; 244 return 0; 245 } 246 247 248 int 249 sigfillset(sigset_t *mask) 250 { 251 *mask = ~0; 252 return 0; 253 } 254 255 256 int 257 sigismember(const sigset_t *mask, int sig) 258 { 259 return ((*mask) & sigmask(sig)); 260 } 261 #endif 262 263 #ifndef HAVE_SIGPENDING 264 int 265 sigpending(sigset_t *set) 266 { 267 return 0; /* faking it! */ 268 } 269 #endif 270 271 #ifndef HAVE_SIGPROCMASK 272 int 273 sigprocmask(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 329 int 330 sigsuspend(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 382 extern void (*Signal (int sig, void (*handler) (int)))(int); 383 384 SIG_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