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