tc.sig.c revision 145479
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 35RCSID("$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 47static 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]; 52static int stk_ptr = -1; 53 54 55/* queue child signals 56 */ 57static RETSIGTYPE 58sig_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 */ 72static RETSIGTYPE 73sig_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. */ 85RETSIGTYPE 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 */ 97void 98sigrelse(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 */ 112void 113xsighold(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 */ 126void 127xsigignore(a) 128 int a; 129{ 130 (void) signal(a, SIG_IGN); 131} 132 133/* atomically release one signal 134 */ 135void 136xsigpause(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 */ 147pid_t 148ourwait(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 178RETSIGTYPE 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. */ 198void 199sigpause(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 */ 218RETSIGTYPE 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 247extern 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 259char *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 */ 268sigmask_t 269sigsetmask(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 */ 304sigmask_t 305sigblock(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 */ 344void 345bsd_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 */ 364RETSIGTYPE (*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 398static long Synch_Cnt = 0; 399 400RETSIGTYPE 401synch_handler(sno) 402int sno; 403{ 404 if (sno != SIGSYNCH) 405 abort(); 406 Synch_Cnt++; 407} 408#endif /* SIGSYNCH */ 409