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