1236769Sobrien/* 2236769Sobrien * NAME: 3236769Sobrien * sigcompat - BSD compat signals via POSIX 4236769Sobrien * 5236769Sobrien * SYNOPSIS: 6236769Sobrien * void (*signal(int "sig", void (*"handler")(int)))(int); 7236769Sobrien * int sigsetmask(int "mask"); 8236769Sobrien * int sigblock(int "mask"); 9236769Sobrien * int sigpause(int "mask"); 10236769Sobrien * int sigvec(int "signo", struct sigvec *"sv", struct sigvec *"osv"); 11236769Sobrien * 12236769Sobrien * DESCRIPTION: 13236769Sobrien * These implement the old BSD routines via the POSIX equivalents. 14236769Sobrien * This module can be used to provide the missing routines, or if 15236769Sobrien * 'FORCE_POSIX_SIGNALS' is defined, force use of these. 16236769Sobrien * 17236769Sobrien * Note that signal() is identical to my Signal() routine except 18236769Sobrien * for checking for recursion. Within libsig, signal() just 19236769Sobrien * calls Signal(). 20236769Sobrien * 21236769Sobrien * BUGS: 22236769Sobrien * This package assumes POSIX signal handling is available and 23236769Sobrien * NOT implemeneted using these routines. To be safe, we check 24236769Sobrien * for recursion and abort(3) if detected. 25236769Sobrien * 26236769Sobrien * Sadly, on some systems, sigset_t is an array, and we cannot 27236769Sobrien * test for this via #if sizeof(sigset_t) ..., so unless 28236769Sobrien * 'SIGSET_T_INT' is defined, we have to assume the worst and use 29236769Sobrien * memcpy(3) to handle args and return values. 30236769Sobrien * 31236769Sobrien * HISTORY: 32236769Sobrien * These routines originate from BSD, and are derrived from the 33236769Sobrien * NetBSD 1.1 implementation. They have been seriously hacked to 34236769Sobrien * make them portable to other systems. 35236769Sobrien * 36236769Sobrien * AUTHOR: 37236769Sobrien * Simon J. Gerraty <sjg@crufty.net> 38236769Sobrien */ 39236769Sobrien/* 40236769Sobrien * @(#)Copyright (c) 1994, Simon J. Gerraty. 41236769Sobrien * 42236769Sobrien * This is free software. It comes with NO WARRANTY. 43236769Sobrien * Permission to use, modify and distribute this source code 44236769Sobrien * is granted subject to the following conditions. 45236769Sobrien * 1/ that the above copyright notice and this notice 46236769Sobrien * are preserved in all copies and that due credit be given 47236769Sobrien * to the author. 48236769Sobrien * 2/ that any changes to this code are clearly commented 49236769Sobrien * as such so that the author does not get blamed for bugs 50236769Sobrien * other than his own. 51236769Sobrien * 52236769Sobrien * Please send copies of changes and bug-fixes to: 53236769Sobrien * sjg@crufty.net 54236769Sobrien */ 55236769Sobrien 56236769Sobrien/* 57236769Sobrien * Copyright (c) 1989 The Regents of the University of California. 58236769Sobrien * All rights reserved. 59236769Sobrien * 60236769Sobrien * Redistribution and use in source and binary forms, with or without 61236769Sobrien * modification, are permitted provided that the following conditions 62236769Sobrien * are met: 63236769Sobrien * 1. Redistributions of source code must retain the above copyright 64236769Sobrien * notice, this list of conditions and the following disclaimer. 65236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 66236769Sobrien * notice, this list of conditions and the following disclaimer in the 67236769Sobrien * documentation and/or other materials provided with the distribution. 68236769Sobrien * 3. All advertising materials mentioning features or use of this software 69236769Sobrien * must display the following acknowledgement: 70236769Sobrien * This product includes software developed by the University of 71236769Sobrien * California, Berkeley and its contributors. 72236769Sobrien * 4. Neither the name of the University nor the names of its contributors 73236769Sobrien * may be used to endorse or promote products derived from this software 74236769Sobrien * without specific prior written permission. 75236769Sobrien * 76236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 77236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79236769Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86236769Sobrien * SUCH DAMAGE. 87236769Sobrien */ 88236769Sobrien#ifdef HAVE_CONFIG_H 89236769Sobrien# include "config.h" 90236769Sobrien#endif 91236769Sobrien#include <signal.h> 92236769Sobrien#ifdef HAVE_UNISTD_H 93236769Sobrien#include <unistd.h> 94236769Sobrien#endif 95236769Sobrien 96236769Sobrien#if defined(sun) && !(defined(__svr4__) || defined(__SVR4)) 97236769Sobrien# define NO_SIGCOMPAT 98236769Sobrien#endif 99236769Sobrien#if defined(__MINT__) 100236769Sobrien# define NO_SIGCOMPAT 101236769Sobrien#endif 102236769Sobrien 103236769Sobrien#if !defined(NO_SIGCOMPAT) && (defined(HAVE_SIGACTION) || defined(SA_NOCLDSTOP)) 104236769Sobrien 105236769Sobrien#if defined(LIBC_SCCS) && !defined(lint) 106236769Sobrien/*static char *sccsid = "from: @(#)sigcompat.c 5.3 (Berkeley) 2/24/91";*/ 107236769Sobrienstatic char *rcsid = "$Id: sigcompat.c,v 1.23 2011/02/14 00:07:11 sjg Exp $"; 108236769Sobrien#endif /* LIBC_SCCS and not lint */ 109236769Sobrien 110236769Sobrien#undef signal 111236769Sobrien#include <stdio.h> 112236769Sobrien#include <string.h> 113236769Sobrien#include <sys/param.h> 114236769Sobrien#include <sys/cdefs.h> 115236769Sobrien#include "assert.h" 116236769Sobrien 117236769Sobrien#ifndef ASSERT 118236769Sobrien# define ASSERT assert 119236769Sobrien#endif 120236769Sobrien 121236769Sobrien#ifdef NDEBUG 122236769Sobrien# define _DBUG(x) 123236769Sobrien#else 124236769Sobrien# define _DBUG(x) x 125236769Sobrien#endif 126236769Sobrien 127236769Sobrien#ifndef SA_RESTART 128236769Sobrien# define SA_RESTART 2 129236769Sobrien#endif 130236769Sobrien#ifndef SV_INTERRUPT 131236769Sobrien# define SV_INTERRUPT SA_RESTART 132236769Sobrien#endif 133236769Sobrien 134236769Sobrien#ifndef MASK_T 135236769Sobrien# if defined(__hpux__) || defined(__hpux) 136236769Sobrien# define MASK_T long 137236769Sobrien# else 138236769Sobrien# define MASK_T int 139236769Sobrien# endif 140236769Sobrien#endif 141236769Sobrien/* I just hate HPsUX */ 142236769Sobrien#if (defined(__HPUX_VERSION) && __HPUX_VERSION > 9) || defined(__hpux) 143236769Sobrien# define PAUSE_MASK_T int 144236769Sobrien#else 145236769Sobrien# define PAUSE_MASK_T MASK_T 146236769Sobrien#endif 147236769Sobrien 148236769Sobrien#ifndef SIG_HDLR 149236769Sobrien# define SIG_HDLR void 150236769Sobrien#endif 151236769Sobrien 152236769Sobrien#ifdef FORCE_POSIX_SIGNALS 153236769Sobrien#if !(defined(libsig) || defined(libsjg)) 154236769Sobrien/* 155236769Sobrien * This little block is almost identical to Signal(), 156236769Sobrien * and make this module standalone. 157236769Sobrien * We don't use it in libsig by default, as some apps might use both 158236769Sobrien * and expect _SignalFlags to be used by both. 159236769Sobrien */ 160236769Sobrien 161236769Sobrien#ifndef SIGNAL_FLAGS 162236769Sobrien# define SIGNAL_FLAGS 0 /* no auto-restart */ 163236769Sobrien#endif 164236769Sobrienint _signalFlags = SIGNAL_FLAGS; 165236769Sobrien 166236769SobrienSIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) 167236769Sobrien{ 168236769Sobrien _DBUG(static int depth_signal = 0); 169236769Sobrien struct sigaction act, oact; 170236769Sobrien int n; 171236769Sobrien 172236769Sobrien _DBUG(++depth_signal); 173236769Sobrien ASSERT(depth_signal < 2); 174236769Sobrien act.sa_handler = handler; 175236769Sobrien sigemptyset(&act.sa_mask); 176236769Sobrien act.sa_flags = _signalFlags; 177236769Sobrien n = sigaction(sig, &act, &oact); 178236769Sobrien _DBUG(--depth_signal); 179236769Sobrien if (n < 0) 180236769Sobrien return (SIG_ERR); 181236769Sobrien return (oact.sa_handler); 182236769Sobrien} 183236769Sobrien#else 184236769SobrienSIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) 185236769Sobrien{ 186236769Sobrien extern SIG_HDLR(*Signal(int, void (*)(int)))(int); 187236769Sobrien _DBUG(static int depth_signal = 0); 188236769Sobrien SIG_HDLR(*old) __P((int)); 189236769Sobrien 190236769Sobrien _DBUG(++depth_signal); 191236769Sobrien ASSERT(depth_signal < 2); 192236769Sobrien old = Signal(sig, handler); 193236769Sobrien _DBUG(--depth_signal); 194236769Sobrien return old; 195236769Sobrien} 196236769Sobrien#endif 197236769Sobrien#endif 198236769Sobrien 199236769Sobrien/* 200236769Sobrien * on some systems, sigset_t is an array... 201236769Sobrien * it would be nicer if we could do 202236769Sobrien * #if sizeof(sigset_t) > sizeof(MASK_T) 203236769Sobrien */ 204236769Sobrien#ifdef SIGSET_T_INT 205236769Sobrien# define ss2m(ss) (MASK_T) *(ss) 206236769Sobrien# define m2ss(ss, m) *ss = (sigset_t) *(m) 207236769Sobrien#else 208236769Sobrienstatic MASK_T 209236769Sobrienss2m(sigset_t *ss) 210236769Sobrien{ 211236769Sobrien MASK_T ma[(sizeof(sigset_t) / sizeof(MASK_T)) + 1]; 212236769Sobrien 213236769Sobrien memcpy((char *) ma, (char *) ss, sizeof(sigset_t)); 214236769Sobrien return ma[0]; 215236769Sobrien} 216236769Sobrien 217236769Sobrienstatic void 218236769Sobrienm2ss(sigset_t *ss, MASK_T *m) 219236769Sobrien{ 220236769Sobrien if (sizeof(sigset_t) > sizeof(MASK_T)) 221236769Sobrien memset((char *) ss, 0, sizeof(sigset_t)); 222236769Sobrien 223236769Sobrien memcpy((char *) ss, (char *) m, sizeof(MASK_T)); 224236769Sobrien} 225236769Sobrien#endif 226236769Sobrien 227236769Sobrien#if !defined(HAVE_SIGSETMASK) || defined(FORCE_POSIX_SIGNALS) 228236769SobrienMASK_T 229236769Sobriensigsetmask(MASK_T mask) 230236769Sobrien{ 231236769Sobrien _DBUG(static int depth_sigsetmask = 0); 232236769Sobrien sigset_t m, omask; 233236769Sobrien int n; 234236769Sobrien 235236769Sobrien _DBUG(++depth_sigsetmask); 236236769Sobrien ASSERT(depth_sigsetmask < 2); 237236769Sobrien m2ss(&m, &mask); 238236769Sobrien n = sigprocmask(SIG_SETMASK, (sigset_t *) & m, (sigset_t *) & omask); 239236769Sobrien _DBUG(--depth_sigsetmask); 240236769Sobrien if (n) 241236769Sobrien return (n); 242236769Sobrien 243236769Sobrien return ss2m(&omask); 244236769Sobrien} 245236769Sobrien 246236769Sobrien 247236769SobrienMASK_T 248236769Sobriensigblock(MASK_T mask) 249236769Sobrien{ 250236769Sobrien _DBUG(static int depth_sigblock = 0); 251236769Sobrien sigset_t m, omask; 252236769Sobrien int n; 253236769Sobrien 254236769Sobrien _DBUG(++depth_sigblock); 255236769Sobrien ASSERT(depth_sigblock < 2); 256236769Sobrien if (mask) 257236769Sobrien m2ss(&m, &mask); 258236769Sobrien n = sigprocmask(SIG_BLOCK, (sigset_t *) ((mask) ? &m : 0), (sigset_t *) & omask); 259236769Sobrien _DBUG(--depth_sigblock); 260236769Sobrien if (n) 261236769Sobrien return (n); 262236769Sobrien return ss2m(&omask); 263236769Sobrien} 264236769Sobrien 265236769Sobrien#undef sigpause /* Linux at least */ 266236769Sobrien 267236769SobrienPAUSE_MASK_T 268236769Sobriensigpause(PAUSE_MASK_T mask) 269236769Sobrien{ 270236769Sobrien _DBUG(static int depth_sigpause = 0); 271236769Sobrien sigset_t m; 272236769Sobrien PAUSE_MASK_T n; 273236769Sobrien 274236769Sobrien _DBUG(++depth_sigpause); 275236769Sobrien ASSERT(depth_sigpause < 2); 276236769Sobrien m2ss(&m, &mask); 277236769Sobrien n = sigsuspend(&m); 278236769Sobrien _DBUG(--depth_sigpause); 279236769Sobrien return n; 280236769Sobrien} 281236769Sobrien#endif 282236769Sobrien 283236769Sobrien#if defined(HAVE_SIGVEC) && defined(FORCE_POSIX_SIGNALS) 284236769Sobrienint 285236769Sobriensigvec(int signo, struct sigvec *sv, struct sigvec *osv) 286236769Sobrien{ 287236769Sobrien _DBUG(static int depth_sigvec = 0); 288236769Sobrien int ret; 289236769Sobrien struct sigvec nsv; 290236769Sobrien 291236769Sobrien _DBUG(++depth_sigvec); 292236769Sobrien ASSERT(depth_sigvec < 2); 293236769Sobrien if (sv) { 294236769Sobrien nsv = *sv; 295236769Sobrien nsv.sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ 296236769Sobrien } 297236769Sobrien ret = sigaction(signo, sv ? (struct sigaction *) & nsv : NULL, 298236769Sobrien (struct sigaction *) osv); 299236769Sobrien _DBUG(--depth_sigvec); 300236769Sobrien if (ret == 0 && osv) 301236769Sobrien osv->sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ 302236769Sobrien return (ret); 303236769Sobrien} 304236769Sobrien#endif 305236769Sobrien 306236769Sobrien#ifdef MAIN 307236769Sobrien# ifndef sigmask 308236769Sobrien# define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1))) 309236769Sobrien# endif 310236769Sobrien 311236769Sobrienint 312236769Sobrienmain(int argc, char *argv[]) 313236769Sobrien{ 314236769Sobrien MASK_T old = 0; 315236769Sobrien 316236769Sobrien printf("expect: old=0,old=2\n"); 317236769Sobrien fflush(stdout); 318236769Sobrien signal(SIGQUIT, SIG_IGN); 319236769Sobrien old = sigblock(sigmask(SIGINT)); 320236769Sobrien printf("old=%d,", old); 321236769Sobrien old = sigsetmask(sigmask(SIGALRM)); 322236769Sobrien printf("old=%d\n", old); 323236769Sobrien} 324236769Sobrien#endif 325236769Sobrien#endif 326