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 weak _signal = signal 28 #pragma weak _sighold = sighold 29 #pragma weak _sigrelse = sigrelse 30 #pragma weak _sigignore = sigignore 31 #pragma weak _sigset = sigset 32 33 #include "lint.h" 34 #include <sys/types.h> 35 #include <unistd.h> 36 #include <errno.h> 37 #include <signal.h> 38 #include <wait.h> 39 40 /* 41 * Check for valid signal number as per SVID. 42 */ 43 #define CHECK_SIG(s, code) \ 44 if ((s) <= 0 || (s) >= NSIG || (s) == SIGKILL || (s) == SIGSTOP) { \ 45 errno = EINVAL; \ 46 return (code); \ 47 } 48 49 /* 50 * Equivalent to stopdefault set in the kernel implementation (sig.c). 51 */ 52 #define STOPDEFAULT(s) \ 53 ((s) == SIGSTOP || (s) == SIGTSTP || (s) == SIGTTOU || (s) == SIGTTIN) 54 55 56 /* 57 * SVr3.x signal compatibility routines. They are now 58 * implemented as library routines instead of system 59 * calls. 60 */ 61 62 void(* 63 signal(int sig, void(*func)(int)))(int) 64 { 65 struct sigaction nact; 66 struct sigaction oact; 67 68 CHECK_SIG(sig, SIG_ERR); 69 70 nact.sa_handler = func; 71 nact.sa_flags = SA_RESETHAND|SA_NODEFER; 72 (void) sigemptyset(&nact.sa_mask); 73 74 /* 75 * Pay special attention if sig is SIGCHLD and 76 * the disposition is SIG_IGN, per sysV signal man page. 77 */ 78 if (sig == SIGCHLD) { 79 nact.sa_flags |= SA_NOCLDSTOP; 80 if (func == SIG_IGN) 81 nact.sa_flags |= SA_NOCLDWAIT; 82 } 83 84 if (STOPDEFAULT(sig)) 85 nact.sa_flags |= SA_RESTART; 86 87 if (sigaction(sig, &nact, &oact) < 0) 88 return (SIG_ERR); 89 90 return (oact.sa_handler); 91 } 92 93 int 94 sighold(int sig) 95 { 96 sigset_t set; 97 98 CHECK_SIG(sig, -1); 99 100 /* 101 * errno set on failure by either sigaddset or sigprocmask. 102 */ 103 (void) sigemptyset(&set); 104 if (sigaddset(&set, sig) < 0) 105 return (-1); 106 return (sigprocmask(SIG_BLOCK, &set, (sigset_t *)0)); 107 } 108 109 int 110 sigrelse(int sig) 111 { 112 sigset_t set; 113 114 CHECK_SIG(sig, -1); 115 116 /* 117 * errno set on failure by either sigaddset or sigprocmask. 118 */ 119 (void) sigemptyset(&set); 120 if (sigaddset(&set, sig) < 0) 121 return (-1); 122 return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0)); 123 } 124 125 int 126 sigignore(int sig) 127 { 128 struct sigaction act; 129 sigset_t set; 130 131 CHECK_SIG(sig, -1); 132 133 act.sa_handler = SIG_IGN; 134 act.sa_flags = 0; 135 (void) sigemptyset(&act.sa_mask); 136 137 /* 138 * Pay special attention if sig is SIGCHLD and 139 * the disposition is SIG_IGN, per sysV signal man page. 140 */ 141 if (sig == SIGCHLD) { 142 act.sa_flags |= SA_NOCLDSTOP; 143 act.sa_flags |= SA_NOCLDWAIT; 144 } 145 146 if (STOPDEFAULT(sig)) 147 act.sa_flags |= SA_RESTART; 148 149 if (sigaction(sig, &act, (struct sigaction *)0) < 0) 150 return (-1); 151 152 (void) sigemptyset(&set); 153 if (sigaddset(&set, sig) < 0) 154 return (-1); 155 return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0)); 156 } 157 158 int 159 __sigpause(int sig) 160 { 161 sigset_t set; 162 int rval; 163 164 CHECK_SIG(sig, -1); 165 166 /* 167 * sigpause() is defined to unblock the signal 168 * and not block it again on return. 169 * sigsuspend() restores the original signal set, 170 * so we have to unblock sig overtly. 171 */ 172 (void) sigprocmask(0, (sigset_t *)0, &set); 173 if (sigdelset(&set, sig) < 0) 174 return (-1); 175 rval = sigsuspend(&set); 176 (void) sigrelse(sig); 177 return (rval); 178 } 179 180 void(* 181 sigset(int sig, void(*func)(int)))(int) 182 { 183 struct sigaction nact; 184 struct sigaction oact; 185 sigset_t nset; 186 sigset_t oset; 187 int code; 188 189 CHECK_SIG(sig, SIG_ERR); 190 191 (void) sigemptyset(&nset); 192 if (sigaddset(&nset, sig) < 0) 193 return (SIG_ERR); 194 195 if (func == SIG_HOLD) { 196 if (sigprocmask(SIG_BLOCK, &nset, &oset) < 0) 197 return (SIG_ERR); 198 if (sigaction(sig, (struct sigaction *)0, &oact) < 0) 199 return (SIG_ERR); 200 } else { 201 nact.sa_handler = func; 202 nact.sa_flags = 0; 203 (void) sigemptyset(&nact.sa_mask); 204 /* 205 * Pay special attention if sig is SIGCHLD and 206 * the disposition is SIG_IGN, per sysV signal man page. 207 */ 208 if (sig == SIGCHLD) { 209 nact.sa_flags |= SA_NOCLDSTOP; 210 if (func == SIG_IGN) 211 nact.sa_flags |= SA_NOCLDWAIT; 212 } 213 214 if (STOPDEFAULT(sig)) 215 nact.sa_flags |= SA_RESTART; 216 217 if (sigaction(sig, &nact, &oact) < 0) 218 return (SIG_ERR); 219 220 if (sigprocmask(SIG_UNBLOCK, &nset, &oset) < 0) 221 return (SIG_ERR); 222 } 223 224 if ((code = sigismember(&oset, sig)) < 0) 225 return (SIG_ERR); 226 else if (code == 1) 227 return (SIG_HOLD); 228 229 return (oact.sa_handler); 230 } 231