tc.sig.c revision 59243
1/* $Header: /src/pub/tcsh/tc.sig.c,v 3.24 1998/04/08 17:57:36 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 39RCSID("$Id: tc.sig.c,v 3.24 1998/04/08 17:57:36 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 51static 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]; 56static int stk_ptr = -1; 57 58 59/* queue child signals 60 */ 61static sigret_t 62sig_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 */ 79static sigret_t 80sig_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. */ 95sigret_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 */ 107void 108sigrelse(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 */ 122void 123xsighold(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 */ 136void 137xsigignore(a) 138 int a; 139{ 140 (void) signal(a, SIG_IGN); 141} 142 143/* atomically release one signal 144 */ 145void 146xsigpause(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 */ 157pid_t 158ourwait(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 188sigret_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. */ 208void 209sigpause(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 */ 228sigret_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 257extern 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 269char *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 */ 278sigmask_t 279sigsetmask(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 */ 314sigmask_t 315sigblock(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 */ 354void 355bsd_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 */ 374sigret_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 408static long Synch_Cnt = 0; 409 410sigret_t 411synch_handler(sno) 412int sno; 413{ 414 if (sno != SIGSYNCH) 415 abort(); 416 Synch_Cnt++; 417} 418#endif /* SIGSYNCH */ 419