1 /* $Header: /src/pub/tcsh/tc.sig.c,v 3.26 2002/03/08 17:36:47 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.26 2002/03/08 17:36:47 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 sigret_t 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 # ifndef SIGVOID 69 return(0); 70 # endif /* SIGVOID */ 71 } 72 73 /* process all awaiting child signals 74 */ 75 static sigret_t 76 sig_ch_rel() 77 { 78 while (stk_ptr > -1) 79 pchild(SIGCHLD); 80 # ifdef JOBDEBUG 81 xprintf("signal(SIGCHLD, pchild);\n"); 82 # endif /* JOBDEBUG */ 83 (void) signal(SIGCHLD, pchild); 84 # ifndef SIGVOID 85 return(0); 86 # endif /* SIGVOID */ 87 } 88 89 90 /* libc.a contains these functions in SYSVREL >= 3. */ 91 sigret_t 92 (*xsigset(a, b)) () 93 int a; 94 signalfun_t b; 95 { 96 return (signal(a, b)); 97 } 98 99 /* release signal 100 * release all queued signals and 101 * set the default signal handler 102 */ 103 void 104 sigrelse(what) 105 int what; 106 { 107 if (what == SIGCHLD) 108 sig_ch_rel(); 109 110 # ifdef COHERENT 111 (void) signal(what, what == SIGINT ? pintr : SIG_DFL); 112 # endif /* COHERENT */ 113 } 114 115 /* hold signal 116 * only works with child and interrupt 117 */ 118 void 119 xsighold(what) 120 int what; 121 { 122 if (what == SIGCHLD) 123 (void) signal(SIGCHLD, sig_ch_queue); 124 125 # ifdef COHERENT 126 (void) signal(what, SIG_IGN); 127 # endif /* COHERENT */ 128 } 129 130 /* ignore signal 131 */ 132 void 133 xsigignore(a) 134 int a; 135 { 136 (void) signal(a, SIG_IGN); 137 } 138 139 /* atomically release one signal 140 */ 141 void 142 xsigpause(what) 143 int what; 144 { 145 /* From: Jim Mattson <mattson%cs@ucsd.edu> */ 146 if (what == SIGCHLD) 147 pchild(SIGCHLD); 148 } 149 150 151 /* return either awaiting processes or do a wait now 152 */ 153 pid_t 154 ourwait(w) 155 int *w; 156 { 157 pid_t pid; 158 159 # ifdef JOBDEBUG 160 xprintf(CGETS(25, 1, "our wait %d\n"), stk_ptr); 161 flush(); 162 # endif /* JOBDEBUG */ 163 164 if (stk_ptr == -1) { 165 /* stack empty return signal from stack */ 166 pid = (pid_t) wait(w); 167 # ifdef JOBDEBUG 168 xprintf("signal(SIGCHLD, pchild);\n"); 169 # endif /* JOBDEBUG */ 170 (void) signal(SIGCHLD, pchild); 171 return (pid); 172 } 173 else { 174 /* return signal from stack */ 175 errno = stk[stk_ptr].s_errno; 176 *w = stk[stk_ptr].s_w; 177 stk_ptr--; 178 return (stk[stk_ptr + 1].s_pid); 179 } 180 } /* end ourwait */ 181 182 # ifdef COHERENT 183 # undef signal 184 sigret_t 185 (*xsignal(a, b)) () 186 int a; 187 signalfun_t b; 188 { 189 if (a == SIGCHLD) 190 return SIG_DFL; 191 else 192 return (signal(a, b)); 193 } 194 # endif /* COHERENT */ 195 196 # endif /* UNRELSIGS */ 197 198 # ifdef SXA 199 /* 200 * SX/A is SYSVREL3 but does not have sys5-sigpause(). 201 * I've heard that sigpause() is not defined in SYSVREL3. 202 */ 203 /* This is not need if you make tcsh by BSD option's cc. */ 204 void 205 sigpause(what) 206 { 207 if (what == SIGCHLD) { 208 (void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD)); 209 } 210 else if (what == 0) { 211 pause(); 212 } 213 else { 214 xprintf("sigpause(%d)\n", what); 215 pause(); 216 } 217 } 218 # endif /* SXA */ 219 220 #endif /* !BSDSIGS */ 221 222 #ifdef NEEDsignal 223 /* turn into bsd signals */ 224 sigret_t 225 (*xsignal(s, a)) () 226 int s; 227 signalfun_t a; 228 { 229 sigvec_t osv, sv; 230 231 (void) mysigvec(s, NULL, &osv); 232 sv = osv; 233 sv.sv_handler = a; 234 #ifdef SIG_STK 235 sv.sv_onstack = SIG_STK; 236 #endif /* SIG_STK */ 237 #ifdef SV_BSDSIG 238 sv.sv_flags = SV_BSDSIG; 239 #endif /* SV_BSDSIG */ 240 241 if (mysigvec(s, &sv, NULL) < 0) 242 return (BADSIG); 243 return (osv.sv_handler); 244 } 245 246 #endif /* NEEDsignal */ 247 248 #ifdef POSIXSIGS 249 /* 250 * Support for signals. 251 */ 252 253 extern int errno; 254 255 /* Set and test a bit. Bits numbered 1 to 32 */ 256 257 #define SETBIT(x, y) x |= sigmask(y) 258 #define ISSET(x, y) ((x & sigmask(y)) != 0) 259 260 #ifdef DEBUG 261 # define SHOW_SIGNALS 1 /* to assist in debugging signals */ 262 #endif /* DEBUG */ 263 264 #ifdef SHOW_SIGNALS 265 char *show_sig_mask(); 266 #endif /* SHOW_SIGNALS */ 267 268 #ifndef __PARAGON__ 269 /* 270 * sigsetmask(mask) 271 * 272 * Set a new signal mask. Return old mask. 273 */ 274 sigmask_t 275 sigsetmask(mask) 276 sigmask_t mask; 277 { 278 sigset_t set, oset; 279 int m; 280 register int i; 281 282 (void) sigemptyset(&set); 283 (void) sigemptyset(&oset); 284 285 for (i = 1; i <= MAXSIG; i++) 286 if (ISSET(mask, i)) 287 (void) sigaddset(&set, i); 288 289 if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) { 290 xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d", 291 mask, errno); 292 } 293 294 m = 0; 295 for (i = 1; i <= MAXSIG; i++) 296 if (sigismember(&oset, i)) 297 SETBIT(m, i); 298 299 return (m); 300 } 301 #endif /* __PARAGON__ */ 302 303 #ifndef __DGUX__ 304 /* 305 * sigblock(mask) 306 * 307 * Add "mask" set of signals to the present signal mask. 308 * Return old mask. 309 */ 310 sigmask_t 311 sigblock(mask) 312 sigmask_t mask; 313 { 314 sigset_t set, oset; 315 int m; 316 register int i; 317 318 (void) sigemptyset(&set); 319 (void) sigemptyset(&oset); 320 321 /* Get present set of signals. */ 322 if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1) 323 stderror(ERR_SYSTEM, "sigprocmask", strerror(errno)); 324 325 /* Add in signals from mask. */ 326 for (i = 1; i <= MAXSIG; i++) 327 if (ISSET(mask, i)) 328 (void) sigaddset(&set, i); 329 330 if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) 331 stderror(ERR_SYSTEM, "sigprocmask", strerror(errno)); 332 333 /* Return old mask to user. */ 334 m = 0; 335 for (i = 1; i <= MAXSIG; i++) 336 if (sigismember(&oset, i)) 337 SETBIT(m, i); 338 339 return (m); 340 } 341 #endif /* __DGUX__ */ 342 343 344 /* 345 * bsd_sigpause(mask) 346 * 347 * Set new signal mask and wait for signal; 348 * Old mask is restored on signal. 349 */ 350 void 351 bsd_sigpause(mask) 352 sigmask_t mask; 353 { 354 sigset_t set; 355 register int i; 356 357 (void) sigemptyset(&set); 358 359 for (i = 1; i <= MAXSIG; i++) 360 if (ISSET(mask, i)) 361 (void) sigaddset(&set, i); 362 (void) sigsuspend(&set); 363 } 364 365 /* 366 * bsd_signal(sig, func) 367 * 368 * Emulate bsd style signal() 369 */ 370 sigret_t (*bsd_signal(sig, func)) () 371 int sig; 372 signalfun_t func; 373 { 374 struct sigaction act, oact; 375 sigset_t set; 376 signalfun_t r_func; 377 378 if (sig < 0 || sig > MAXSIG) { 379 xprintf(CGETS(25, 2, 380 "error: bsd_signal(%d) signal out of range\n"), sig); 381 return((signalfun_t) SIG_IGN); 382 } 383 384 (void) sigemptyset(&set); 385 386 act.sa_handler = (signalfun_t) func; /* user function */ 387 act.sa_mask = set; /* signal mask */ 388 act.sa_flags = 0; /* no special actions */ 389 390 if (sigaction(sig, &act, &oact)) { 391 xprintf(CGETS(25, 3, 392 "error: bsd_signal(%d) - sigaction failed, errno %d\n"), 393 sig, errno); 394 return((signalfun_t) SIG_IGN); 395 } 396 397 r_func = (signalfun_t) oact.sa_handler; 398 return(r_func); 399 } 400 #endif /* POSIXSIG */ 401 402 403 #ifdef SIGSYNCH 404 static long Synch_Cnt = 0; 405 406 sigret_t 407 synch_handler(sno) 408 int sno; 409 { 410 if (sno != SIGSYNCH) 411 abort(); 412 Synch_Cnt++; 413 } 414 #endif /* SIGSYNCH */ 415