Home | History | Annotate | Download | only in sys
      1     0  stevel /*
      2     0  stevel  * CDDL HEADER START
      3     0  stevel  *
      4     0  stevel  * The contents of this file are subject to the terms of the
      5  5891     raf  * Common Development and Distribution License (the "License").
      6  5891     raf  * You may not use this file except in compliance with the License.
      7     0  stevel  *
      8     0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0  stevel  * or http://www.opensolaris.org/os/licensing.
     10     0  stevel  * See the License for the specific language governing permissions
     11     0  stevel  * and limitations under the License.
     12     0  stevel  *
     13     0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0  stevel  *
     19     0  stevel  * CDDL HEADER END
     20     0  stevel  */
     21  5891     raf 
     22     0  stevel /*
     23  5891     raf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24     0  stevel  * Use is subject to license terms.
     25     0  stevel  */
     26     0  stevel 
     27     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28     0  stevel 
     29  6812     raf #pragma weak _signal = signal
     30  6812     raf #pragma weak _sighold = sighold
     31  6812     raf #pragma weak _sigrelse = sigrelse
     32  6812     raf #pragma weak _sigignore = sigignore
     33  6812     raf #pragma weak _sigset = sigset
     34     0  stevel 
     35  6812     raf #include "lint.h"
     36     0  stevel #include <sys/types.h>
     37     0  stevel #include <unistd.h>
     38     0  stevel #include <errno.h>
     39     0  stevel #include <signal.h>
     40     0  stevel #include <wait.h>
     41     0  stevel 
     42     0  stevel /*
     43     0  stevel  * Check for valid signal number as per SVID.
     44     0  stevel  */
     45     0  stevel #define	CHECK_SIG(s, code) \
     46     0  stevel 	if ((s) <= 0 || (s) >= NSIG || (s) == SIGKILL || (s) == SIGSTOP) { \
     47     0  stevel 		errno = EINVAL; \
     48     0  stevel 		return (code); \
     49     0  stevel 	}
     50     0  stevel 
     51     0  stevel /*
     52     0  stevel  * Equivalent to stopdefault set in the kernel implementation (sig.c).
     53     0  stevel  */
     54     0  stevel #define	STOPDEFAULT(s) \
     55     0  stevel 	((s) == SIGSTOP || (s) == SIGTSTP || (s) == SIGTTOU || (s) == SIGTTIN)
     56     0  stevel 
     57     0  stevel 
     58     0  stevel /*
     59     0  stevel  * SVr3.x signal compatibility routines. They are now
     60     0  stevel  * implemented as library routines instead of system
     61     0  stevel  * calls.
     62     0  stevel  */
     63     0  stevel 
     64     0  stevel void(*
     65     0  stevel signal(int sig, void(*func)(int)))(int)
     66     0  stevel {
     67     0  stevel 	struct sigaction nact;
     68     0  stevel 	struct sigaction oact;
     69     0  stevel 
     70     0  stevel 	CHECK_SIG(sig, SIG_ERR);
     71     0  stevel 
     72     0  stevel 	nact.sa_handler = func;
     73     0  stevel 	nact.sa_flags = SA_RESETHAND|SA_NODEFER;
     74     0  stevel 	(void) sigemptyset(&nact.sa_mask);
     75     0  stevel 
     76     0  stevel 	/*
     77     0  stevel 	 * Pay special attention if sig is SIGCHLD and
     78     0  stevel 	 * the disposition is SIG_IGN, per sysV signal man page.
     79     0  stevel 	 */
     80     0  stevel 	if (sig == SIGCHLD) {
     81     0  stevel 		nact.sa_flags |= SA_NOCLDSTOP;
     82     0  stevel 		if (func == SIG_IGN)
     83     0  stevel 			nact.sa_flags |= SA_NOCLDWAIT;
     84     0  stevel 	}
     85     0  stevel 
     86     0  stevel 	if (STOPDEFAULT(sig))
     87     0  stevel 		nact.sa_flags |= SA_RESTART;
     88     0  stevel 
     89     0  stevel 	if (sigaction(sig, &nact, &oact) < 0)
     90     0  stevel 		return (SIG_ERR);
     91     0  stevel 
     92     0  stevel 	return (oact.sa_handler);
     93     0  stevel }
     94     0  stevel 
     95     0  stevel int
     96     0  stevel sighold(int sig)
     97     0  stevel {
     98     0  stevel 	sigset_t set;
     99     0  stevel 
    100     0  stevel 	CHECK_SIG(sig, -1);
    101     0  stevel 
    102     0  stevel 	/*
    103     0  stevel 	 * errno set on failure by either sigaddset or sigprocmask.
    104     0  stevel 	 */
    105     0  stevel 	(void) sigemptyset(&set);
    106     0  stevel 	if (sigaddset(&set, sig) < 0)
    107     0  stevel 		return (-1);
    108     0  stevel 	return (sigprocmask(SIG_BLOCK, &set, (sigset_t *)0));
    109     0  stevel }
    110     0  stevel 
    111     0  stevel int
    112     0  stevel sigrelse(int sig)
    113     0  stevel {
    114     0  stevel 	sigset_t set;
    115     0  stevel 
    116     0  stevel 	CHECK_SIG(sig, -1);
    117     0  stevel 
    118     0  stevel 	/*
    119     0  stevel 	 * errno set on failure by either sigaddset or sigprocmask.
    120     0  stevel 	 */
    121     0  stevel 	(void) sigemptyset(&set);
    122     0  stevel 	if (sigaddset(&set, sig) < 0)
    123     0  stevel 		return (-1);
    124     0  stevel 	return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0));
    125     0  stevel }
    126     0  stevel 
    127     0  stevel int
    128     0  stevel sigignore(int sig)
    129     0  stevel {
    130     0  stevel 	struct sigaction act;
    131     0  stevel 	sigset_t set;
    132     0  stevel 
    133     0  stevel 	CHECK_SIG(sig, -1);
    134     0  stevel 
    135     0  stevel 	act.sa_handler = SIG_IGN;
    136     0  stevel 	act.sa_flags = 0;
    137     0  stevel 	(void) sigemptyset(&act.sa_mask);
    138     0  stevel 
    139     0  stevel 	/*
    140     0  stevel 	 * Pay special attention if sig is SIGCHLD and
    141     0  stevel 	 * the disposition is SIG_IGN, per sysV signal man page.
    142     0  stevel 	 */
    143     0  stevel 	if (sig == SIGCHLD) {
    144     0  stevel 		act.sa_flags |= SA_NOCLDSTOP;
    145     0  stevel 		act.sa_flags |= SA_NOCLDWAIT;
    146     0  stevel 	}
    147     0  stevel 
    148     0  stevel 	if (STOPDEFAULT(sig))
    149     0  stevel 		act.sa_flags |= SA_RESTART;
    150     0  stevel 
    151     0  stevel 	if (sigaction(sig, &act, (struct sigaction *)0) < 0)
    152     0  stevel 		return (-1);
    153     0  stevel 
    154     0  stevel 	(void) sigemptyset(&set);
    155     0  stevel 	if (sigaddset(&set, sig) < 0)
    156     0  stevel 		return (-1);
    157     0  stevel 	return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0));
    158     0  stevel }
    159     0  stevel 
    160     0  stevel int
    161  5891     raf __sigpause(int sig)
    162     0  stevel {
    163     0  stevel 	sigset_t set;
    164     0  stevel 	int rval;
    165     0  stevel 
    166     0  stevel 	CHECK_SIG(sig, -1);
    167     0  stevel 
    168     0  stevel 	/*
    169     0  stevel 	 * sigpause() is defined to unblock the signal
    170     0  stevel 	 * and not block it again on return.
    171     0  stevel 	 * sigsuspend() restores the original signal set,
    172     0  stevel 	 * so we have to unblock sig overtly.
    173     0  stevel 	 */
    174     0  stevel 	(void) sigprocmask(0, (sigset_t *)0, &set);
    175     0  stevel 	if (sigdelset(&set, sig) < 0)
    176     0  stevel 		return (-1);
    177     0  stevel 	rval = sigsuspend(&set);
    178     0  stevel 	(void) sigrelse(sig);
    179     0  stevel 	return (rval);
    180     0  stevel }
    181     0  stevel 
    182     0  stevel void(*
    183     0  stevel sigset(int sig, void(*func)(int)))(int)
    184     0  stevel {
    185     0  stevel 	struct sigaction nact;
    186     0  stevel 	struct sigaction oact;
    187     0  stevel 	sigset_t nset;
    188     0  stevel 	sigset_t oset;
    189     0  stevel 	int code;
    190     0  stevel 
    191     0  stevel 	CHECK_SIG(sig, SIG_ERR);
    192     0  stevel 
    193     0  stevel 	(void) sigemptyset(&nset);
    194     0  stevel 	if (sigaddset(&nset, sig) < 0)
    195     0  stevel 		return (SIG_ERR);
    196     0  stevel 
    197     0  stevel 	if (func == SIG_HOLD) {
    198     0  stevel 		if (sigprocmask(SIG_BLOCK, &nset, &oset) < 0)
    199     0  stevel 			return (SIG_ERR);
    200     0  stevel 		if (sigaction(sig, (struct sigaction *)0, &oact) < 0)
    201     0  stevel 			return (SIG_ERR);
    202     0  stevel 	} else {
    203     0  stevel 		nact.sa_handler = func;
    204     0  stevel 		nact.sa_flags = 0;
    205     0  stevel 		(void) sigemptyset(&nact.sa_mask);
    206     0  stevel 		/*
    207     0  stevel 		 * Pay special attention if sig is SIGCHLD and
    208     0  stevel 		 * the disposition is SIG_IGN, per sysV signal man page.
    209     0  stevel 		 */
    210     0  stevel 		if (sig == SIGCHLD) {
    211     0  stevel 			nact.sa_flags |= SA_NOCLDSTOP;
    212     0  stevel 			if (func == SIG_IGN)
    213     0  stevel 				nact.sa_flags |= SA_NOCLDWAIT;
    214     0  stevel 		}
    215     0  stevel 
    216     0  stevel 		if (STOPDEFAULT(sig))
    217     0  stevel 			nact.sa_flags |= SA_RESTART;
    218     0  stevel 
    219     0  stevel 		if (sigaction(sig, &nact, &oact) < 0)
    220     0  stevel 			return (SIG_ERR);
    221     0  stevel 
    222     0  stevel 		if (sigprocmask(SIG_UNBLOCK, &nset, &oset) < 0)
    223     0  stevel 			return (SIG_ERR);
    224     0  stevel 	}
    225     0  stevel 
    226     0  stevel 	if ((code = sigismember(&oset, sig)) < 0)
    227     0  stevel 		return (SIG_ERR);
    228     0  stevel 	else if (code == 1)
    229     0  stevel 		return (SIG_HOLD);
    230     0  stevel 
    231     0  stevel 	return (oact.sa_handler);
    232     0  stevel }
    233