1 /* $Header: /src/pub/tcsh/tc.sig.c,v 3.29 2005/01/18 20:24:51 christos Exp $ */ 2 /* 3 * tc.sig.c: Signal routine emulations 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 #include "sh.h" 34 35 RCSID("$Id: tc.sig.c,v 3.29 2005/01/18 20:24:51 christos Exp $") 36 37 #include "tc.wait.h" 38 39 #ifndef BSDSIGS 40 41 /* this stack is used to queue signals 42 * we can handle up to MAX_CHLD outstanding children now; 43 */ 44 #define MAX_CHLD 50 45 46 # ifdef UNRELSIGS 47 static struct mysigstack { 48 int s_w; /* wait report */ 49 int s_errno; /* errno returned; */ 50 pid_t s_pid; /* pid returned */ 51 } stk[MAX_CHLD]; 52 static int stk_ptr = -1; 53 54 55 /* queue child signals 56 */ 57 static RETSIGTYPE 58 sig_ch_queue() 59 { 60 # ifdef JOBDEBUG 61 xprintf("queue SIGCHLD\n"); 62 flush(); 63 # endif /* JOBDEBUG */ 64 stk_ptr++; 65 stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w); 66 stk[stk_ptr].s_errno = errno; 67 (void) signal(SIGCHLD, sig_ch_queue); 68 } 69 70 /* process all awaiting child signals 71 */ 72 static RETSIGTYPE 73 sig_ch_rel() 74 { 75 while (stk_ptr > -1) 76 pchild(SIGCHLD); 77 # ifdef JOBDEBUG 78 xprintf("signal(SIGCHLD, pchild);\n"); 79 # endif /* JOBDEBUG */ 80 (void) signal(SIGCHLD, pchild); 81 } 82 83 84 /* libc.a contains these functions in SYSVREL >= 3. */ 85 RETSIGTYPE 86 (*xsigset(a, b)) () 87 int a; 88 signalfun_t b; 89 { 90 return (signal(a, b)); 91 } 92 93 /* release signal 94 * release all queued signals and 95 * set the default signal handler 96 */ 97 void 98 sigrelse(what) 99 int what; 100 { 101 if (what == SIGCHLD) 102 sig_ch_rel(); 103 104 # ifdef COHERENT 105 (void) signal(what, what == SIGINT ? pintr : SIG_DFL); 106 # endif /* COHERENT */ 107 } 108 109 /* hold signal 110 * only works with child and interrupt 111 */ 112 void 113 xsighold(what) 114 int what; 115 { 116 if (what == SIGCHLD) 117 (void) signal(SIGCHLD, sig_ch_queue); 118 119 # ifdef COHERENT 120 (void) signal(what, SIG_IGN); 121 # endif /* COHERENT */ 122 } 123 124 /* ignore signal 125 */ 126 void 127 xsigignore(a) 128 int a; 129 { 130 (void) signal(a, SIG_IGN); 131 } 132 133 /* atomically release one signal 134 */ 135 void 136 xsigpause(what) 137 int what; 138 { 139 /* From: Jim Mattson <mattson%cs@ucsd.edu> */ 140 if (what == SIGCHLD) 141 pchild(SIGCHLD); 142 } 143 144 145 /* return either awaiting processes or do a wait now 146 */ 147 pid_t 148 ourwait(w) 149 int *w; 150 { 151 pid_t pid; 152 153 # ifdef JOBDEBUG 154 xprintf(CGETS(25, 1, "our wait %d\n"), stk_ptr); 155 flush(); 156 # endif /* JOBDEBUG */ 157 158 if (stk_ptr == -1) { 159 /* stack empty return signal from stack */ 160 pid = (pid_t) wait(w); 161 # ifdef JOBDEBUG 162 xprintf("signal(SIGCHLD, pchild);\n"); 163 # endif /* JOBDEBUG */ 164 (void) signal(SIGCHLD, pchild); 165 return (pid); 166 } 167 else { 168 /* return signal from stack */ 169 errno = stk[stk_ptr].s_errno; 170 *w = stk[stk_ptr].s_w; 171 stk_ptr--; 172 return (stk[stk_ptr + 1].s_pid); 173 } 174 } /* end ourwait */ 175 176 # ifdef COHERENT 177 # undef signal 178 RETSIGTYPE 179 (*xsignal(a, b)) () 180 int a; 181 signalfun_t b; 182 { 183 if (a == SIGCHLD) 184 return SIG_DFL; 185 else 186 return (signal(a, b)); 187 } 188 # endif /* COHERENT */ 189 190 # endif /* UNRELSIGS */ 191 192 # ifdef SXA 193 /* 194 * SX/A is SYSVREL3 but does not have sys5-sigpause(). 195 * I've heard that sigpause() is not defined in SYSVREL3. 196 */ 197 /* This is not need if you make tcsh by BSD option's cc. */ 198 void 199 sigpause(what) 200 { 201 if (what == SIGCHLD) { 202 (void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD)); 203 } 204 else if (what == 0) { 205 pause(); 206 } 207 else { 208 xprintf("sigpause(%d)\n", what); 209 pause(); 210 } 211 } 212 # endif /* SXA */ 213 214 #endif /* !BSDSIGS */ 215 216 #ifdef NEEDsignal 217 /* turn into bsd signals */ 218 RETSIGTYPE 219 (*xsignal(s, a)) () 220 int s; 221 signalfun_t a; 222 { 223 sigvec_t osv, sv; 224 225 (void) mysigvec(s, NULL, &osv); 226 sv = osv; 227 sv.sv_handler = a; 228 #ifdef SIG_STK 229 sv.sv_onstack = SIG_STK; 230 #endif /* SIG_STK */ 231 #ifdef SV_BSDSIG 232 sv.sv_flags = SV_BSDSIG; 233 #endif /* SV_BSDSIG */ 234 235 if (mysigvec(s, &sv, NULL) < 0) 236 return (BADSIG); 237 return (osv.sv_handler); 238 } 239 240 #endif /* NEEDsignal */ 241 242 #ifdef POSIXSIGS 243 /* 244 * Support for signals. 245 */ 246 247 extern int errno; 248 249 /* Set and test a bit. Bits numbered 1 to 32 */ 250 251 #define SETBIT(x, y) x |= sigmask(y) 252 #define ISSET(x, y) ((x & sigmask(y)) != 0) 253 254 #ifdef DEBUG 255 # define SHOW_SIGNALS 1 /* to assist in debugging signals */ 256 #endif /* DEBUG */ 257 258 #ifdef SHOW_SIGNALS 259 char *show_sig_mask(); 260 #endif /* SHOW_SIGNALS */ 261 262 #ifndef __PARAGON__ 263 /* 264 * sigsetmask(mask) 265 * 266 * Set a new signal mask. Return old mask. 267 */ 268 sigmask_t 269 sigsetmask(mask) 270 sigmask_t mask; 271 { 272 sigset_t set, oset; 273 int m; 274 int i; 275 276 (void) sigemptyset(&set); 277 (void) sigemptyset(&oset); 278 279 for (i = 1; i <= MAXSIG; i++) 280 if (ISSET(mask, i)) 281 (void) sigaddset(&set, i); 282 283 if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) { 284 xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d", 285 mask, errno); 286 } 287 288 m = 0; 289 for (i = 1; i <= MAXSIG; i++) 290 if (sigismember(&oset, i) == 1) 291 SETBIT(m, i); 292 293 return (m); 294 } 295 #endif /* __PARAGON__ */ 296 297 #ifndef __DGUX__ 298 /* 299 * sigblock(mask) 300 * 301 * Add "mask" set of signals to the present signal mask. 302 * Return old mask. 303 */ 304 sigmask_t 305 sigblock(mask) 306 sigmask_t mask; 307 { 308 sigset_t set, oset; 309 int m; 310 int i; 311 312 (void) sigemptyset(&set); 313 (void) sigemptyset(&oset); 314 315 /* Get present set of signals. */ 316 if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1) 317 stderror(ERR_SYSTEM, "sigprocmask", strerror(errno)); 318 319 /* Add in signals from mask. */ 320 for (i = 1; i <= MAXSIG; i++) 321 if (ISSET(mask, i)) 322 (void) sigaddset(&set, i); 323 324 if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) 325 stderror(ERR_SYSTEM, "sigprocmask", strerror(errno)); 326 327 /* Return old mask to user. */ 328 m = 0; 329 for (i = 1; i <= MAXSIG; i++) 330 if (sigismember(&oset, i) == 1) 331 SETBIT(m, i); 332 333 return (m); 334 } 335 #endif /* __DGUX__ */ 336 337 338 /* 339 * bsd_sigpause(mask) 340 * 341 * Set new signal mask and wait for signal; 342 * Old mask is restored on signal. 343 */ 344 void 345 bsd_sigpause(mask) 346 sigmask_t mask; 347 { 348 sigset_t set; 349 int i; 350 351 (void) sigemptyset(&set); 352 353 for (i = 1; i <= MAXSIG; i++) 354 if (ISSET(mask, i)) 355 (void) sigaddset(&set, i); 356 (void) sigsuspend(&set); 357 } 358 359 /* 360 * bsd_signal(sig, func) 361 * 362 * Emulate bsd style signal() 363 */ 364 RETSIGTYPE (*bsd_signal(sig, func)) () 365 int sig; 366 signalfun_t func; 367 { 368 struct sigaction act, oact; 369 sigset_t set; 370 signalfun_t r_func; 371 372 if (sig < 0 || sig > MAXSIG) { 373 xprintf(CGETS(25, 2, 374 "error: bsd_signal(%d) signal out of range\n"), sig); 375 return((signalfun_t) SIG_IGN); 376 } 377 378 (void) sigemptyset(&set); 379 380 act.sa_handler = (signalfun_t) func; /* user function */ 381 act.sa_mask = set; /* signal mask */ 382 act.sa_flags = 0; /* no special actions */ 383 384 if (sigaction(sig, &act, &oact)) { 385 xprintf(CGETS(25, 3, 386 "error: bsd_signal(%d) - sigaction failed, errno %d\n"), 387 sig, errno); 388 return((signalfun_t) SIG_IGN); 389 } 390 391 r_func = (signalfun_t) oact.sa_handler; 392 return(r_func); 393 } 394 #endif /* POSIXSIG */ 395 396 397 #ifdef SIGSYNCH 398 static long Synch_Cnt = 0; 399 400 RETSIGTYPE 401 synch_handler(sno) 402 int sno; 403 { 404 if (sno != SIGSYNCH) 405 abort(); 406 Synch_Cnt++; 407 } 408 #endif /* SIGSYNCH */ 409