tc.sig.c revision 100616
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 35RCSID("$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 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 sigret_t 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# ifndef SIGVOID 69 return(0); 70# endif /* SIGVOID */ 71} 72 73/* process all awaiting child signals 74 */ 75static sigret_t 76sig_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. */ 91sigret_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 */ 103void 104sigrelse(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 */ 118void 119xsighold(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 */ 132void 133xsigignore(a) 134 int a; 135{ 136 (void) signal(a, SIG_IGN); 137} 138 139/* atomically release one signal 140 */ 141void 142xsigpause(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 */ 153pid_t 154ourwait(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 184sigret_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. */ 204void 205sigpause(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 */ 224sigret_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 253extern 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 265char *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 */ 274sigmask_t 275sigsetmask(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 */ 310sigmask_t 311sigblock(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 */ 350void 351bsd_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 */ 370sigret_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 404static long Synch_Cnt = 0; 405 406sigret_t 407synch_handler(sno) 408int sno; 409{ 410 if (sno != SIGSYNCH) 411 abort(); 412 Synch_Cnt++; 413} 414#endif /* SIGSYNCH */ 415