1 /* 2 * NAME: 3 * sigcompat - BSD compat signals via POSIX 4 * 5 * SYNOPSIS: 6 * void (*signal(int "sig", void (*"handler")(int)))(int); 7 * int sigsetmask(int "mask"); 8 * int sigblock(int "mask"); 9 * int sigpause(int "mask"); 10 * int sigvec(int "signo", struct sigvec *"sv", struct sigvec *"osv"); 11 * 12 * DESCRIPTION: 13 * These implement the old BSD routines via the POSIX equivalents. 14 * This module can be used to provide the missing routines, or if 15 * 'FORCE_POSIX_SIGNALS' is defined, force use of these. 16 * 17 * Note that signal() is identical to my Signal() routine except 18 * for checking for recursion. Within libsig, signal() just 19 * calls Signal(). 20 * 21 * BUGS: 22 * This package assumes POSIX signal handling is available and 23 * NOT implemeneted using these routines. To be safe, we check 24 * for recursion and abort(3) if detected. 25 * 26 * Sadly, on some systems, sigset_t is an array, and we cannot 27 * test for this via #if sizeof(sigset_t) ..., so unless 28 * 'SIGSET_T_INT' is defined, we have to assume the worst and use 29 * memcpy(3) to handle args and return values. 30 * 31 * HISTORY: 32 * These routines originate from BSD, and are derrived from the 33 * NetBSD 1.1 implementation. They have been seriously hacked to 34 * make them portable to other systems. 35 * 36 * AUTHOR: 37 * Simon J. Gerraty <sjg@crufty.net> 38 */ 39 /* 40 * @(#)Copyright (c) 1994, Simon J. Gerraty. 41 * 42 * This is free software. It comes with NO WARRANTY. 43 * Permission to use, modify and distribute this source code 44 * is granted subject to the following conditions. 45 * 1/ that the above copyright notice and this notice 46 * are preserved in all copies and that due credit be given 47 * to the author. 48 * 2/ that any changes to this code are clearly commented 49 * as such so that the author does not get blamed for bugs 50 * other than his own. 51 * 52 * Please send copies of changes and bug-fixes to: 53 * sjg@crufty.net 54 */ 55 56 /* 57 * Copyright (c) 1989 The Regents of the University of California. 58 * All rights reserved. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 1. Redistributions of source code must retain the above copyright 64 * notice, this list of conditions and the following disclaimer. 65 * 2. Redistributions in binary form must reproduce the above copyright 66 * notice, this list of conditions and the following disclaimer in the 67 * documentation and/or other materials provided with the distribution. 68 * 3. All advertising materials mentioning features or use of this software 69 * must display the following acknowledgement: 70 * This product includes software developed by the University of 71 * California, Berkeley and its contributors. 72 * 4. Neither the name of the University nor the names of its contributors 73 * may be used to endorse or promote products derived from this software 74 * without specific prior written permission. 75 * 76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * SUCH DAMAGE. 87 */ 88 #ifdef HAVE_CONFIG_H 89 # include "config.h" 90 #endif 91 #include <signal.h> 92 #ifdef HAVE_UNISTD_H 93 #include <unistd.h> 94 #endif 95 96 #if defined(sun) && !(defined(__svr4__) || defined(__SVR4)) 97 # define NO_SIGCOMPAT 98 #endif 99 #if defined(__MINT__) 100 # define NO_SIGCOMPAT 101 #endif 102 103 #if !defined(NO_SIGCOMPAT) && (defined(HAVE_SIGACTION) || defined(SA_NOCLDSTOP)) 104 105 #if defined(LIBC_SCCS) && !defined(lint) 106 /*static char *sccsid = "from: @(#)sigcompat.c 5.3 (Berkeley) 2/24/91";*/ 107 static char *rcsid = "$Id: sigcompat.c,v 1.23 2011/02/14 00:07:11 sjg Exp $"; 108 #endif /* LIBC_SCCS and not lint */ 109 110 #undef signal 111 #include <stdio.h> 112 #include <string.h> 113 #include <sys/param.h> 114 #include <sys/cdefs.h> 115 #include "assert.h" 116 117 #ifndef ASSERT 118 # define ASSERT assert 119 #endif 120 121 #ifdef NDEBUG 122 # define _DBUG(x) 123 #else 124 # define _DBUG(x) x 125 #endif 126 127 #ifndef SA_RESTART 128 # define SA_RESTART 2 129 #endif 130 #ifndef SV_INTERRUPT 131 # define SV_INTERRUPT SA_RESTART 132 #endif 133 134 #ifndef MASK_T 135 # if defined(__hpux__) || defined(__hpux) 136 # define MASK_T long 137 # else 138 # define MASK_T int 139 # endif 140 #endif 141 /* I just hate HPsUX */ 142 #if (defined(__HPUX_VERSION) && __HPUX_VERSION > 9) || defined(__hpux) 143 # define PAUSE_MASK_T int 144 #else 145 # define PAUSE_MASK_T MASK_T 146 #endif 147 148 #ifndef SIG_HDLR 149 # define SIG_HDLR void 150 #endif 151 152 #ifdef FORCE_POSIX_SIGNALS 153 #if !(defined(libsig) || defined(libsjg)) 154 /* 155 * This little block is almost identical to Signal(), 156 * and make this module standalone. 157 * We don't use it in libsig by default, as some apps might use both 158 * and expect _SignalFlags to be used by both. 159 */ 160 161 #ifndef SIGNAL_FLAGS 162 # define SIGNAL_FLAGS 0 /* no auto-restart */ 163 #endif 164 int _signalFlags = SIGNAL_FLAGS; 165 166 SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) 167 { 168 _DBUG(static int depth_signal = 0); 169 struct sigaction act, oact; 170 int n; 171 172 _DBUG(++depth_signal); 173 ASSERT(depth_signal < 2); 174 act.sa_handler = handler; 175 sigemptyset(&act.sa_mask); 176 act.sa_flags = _signalFlags; 177 n = sigaction(sig, &act, &oact); 178 _DBUG(--depth_signal); 179 if (n < 0) 180 return (SIG_ERR); 181 return (oact.sa_handler); 182 } 183 #else 184 SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) 185 { 186 extern SIG_HDLR(*Signal(int, void (*)(int)))(int); 187 _DBUG(static int depth_signal = 0); 188 SIG_HDLR(*old) __P((int)); 189 190 _DBUG(++depth_signal); 191 ASSERT(depth_signal < 2); 192 old = Signal(sig, handler); 193 _DBUG(--depth_signal); 194 return old; 195 } 196 #endif 197 #endif 198 199 /* 200 * on some systems, sigset_t is an array... 201 * it would be nicer if we could do 202 * #if sizeof(sigset_t) > sizeof(MASK_T) 203 */ 204 #ifdef SIGSET_T_INT 205 # define ss2m(ss) (MASK_T) *(ss) 206 # define m2ss(ss, m) *ss = (sigset_t) *(m) 207 #else 208 static MASK_T 209 ss2m(sigset_t *ss) 210 { 211 MASK_T ma[(sizeof(sigset_t) / sizeof(MASK_T)) + 1]; 212 213 memcpy((char *) ma, (char *) ss, sizeof(sigset_t)); 214 return ma[0]; 215 } 216 217 static void 218 m2ss(sigset_t *ss, MASK_T *m) 219 { 220 if (sizeof(sigset_t) > sizeof(MASK_T)) 221 memset((char *) ss, 0, sizeof(sigset_t)); 222 223 memcpy((char *) ss, (char *) m, sizeof(MASK_T)); 224 } 225 #endif 226 227 #if !defined(HAVE_SIGSETMASK) || defined(FORCE_POSIX_SIGNALS) 228 MASK_T 229 sigsetmask(MASK_T mask) 230 { 231 _DBUG(static int depth_sigsetmask = 0); 232 sigset_t m, omask; 233 int n; 234 235 _DBUG(++depth_sigsetmask); 236 ASSERT(depth_sigsetmask < 2); 237 m2ss(&m, &mask); 238 n = sigprocmask(SIG_SETMASK, (sigset_t *) & m, (sigset_t *) & omask); 239 _DBUG(--depth_sigsetmask); 240 if (n) 241 return (n); 242 243 return ss2m(&omask); 244 } 245 246 247 MASK_T 248 sigblock(MASK_T mask) 249 { 250 _DBUG(static int depth_sigblock = 0); 251 sigset_t m, omask; 252 int n; 253 254 _DBUG(++depth_sigblock); 255 ASSERT(depth_sigblock < 2); 256 if (mask) 257 m2ss(&m, &mask); 258 n = sigprocmask(SIG_BLOCK, (sigset_t *) ((mask) ? &m : 0), (sigset_t *) & omask); 259 _DBUG(--depth_sigblock); 260 if (n) 261 return (n); 262 return ss2m(&omask); 263 } 264 265 #undef sigpause /* Linux at least */ 266 267 PAUSE_MASK_T 268 sigpause(PAUSE_MASK_T mask) 269 { 270 _DBUG(static int depth_sigpause = 0); 271 sigset_t m; 272 PAUSE_MASK_T n; 273 274 _DBUG(++depth_sigpause); 275 ASSERT(depth_sigpause < 2); 276 m2ss(&m, &mask); 277 n = sigsuspend(&m); 278 _DBUG(--depth_sigpause); 279 return n; 280 } 281 #endif 282 283 #if defined(HAVE_SIGVEC) && defined(FORCE_POSIX_SIGNALS) 284 int 285 sigvec(int signo, struct sigvec *sv, struct sigvec *osv) 286 { 287 _DBUG(static int depth_sigvec = 0); 288 int ret; 289 struct sigvec nsv; 290 291 _DBUG(++depth_sigvec); 292 ASSERT(depth_sigvec < 2); 293 if (sv) { 294 nsv = *sv; 295 nsv.sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ 296 } 297 ret = sigaction(signo, sv ? (struct sigaction *) & nsv : NULL, 298 (struct sigaction *) osv); 299 _DBUG(--depth_sigvec); 300 if (ret == 0 && osv) 301 osv->sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ 302 return (ret); 303 } 304 #endif 305 306 #ifdef MAIN 307 # ifndef sigmask 308 # define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1))) 309 # endif 310 311 int 312 main(int argc, char *argv[]) 313 { 314 MASK_T old = 0; 315 316 printf("expect: old=0,old=2\n"); 317 fflush(stdout); 318 signal(SIGQUIT, SIG_IGN); 319 old = sigblock(sigmask(SIGINT)); 320 printf("old=%d,", old); 321 old = sigsetmask(sigmask(SIGALRM)); 322 printf("old=%d\n", old); 323 } 324 #endif 325 #endif 326