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";*/ 107static 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 164int _signalFlags = SIGNAL_FLAGS; 165 166SIG_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 184SIG_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 208static MASK_T 209ss2m(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 217static void 218m2ss(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) 228MASK_T 229sigsetmask(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 247MASK_T 248sigblock(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 267PAUSE_MASK_T 268sigpause(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) 284int 285sigvec(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 311int 312main(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