1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1996, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.13.17.1 */ 32 /* 33 * UNIX shell 34 */ 35 36 #include "defs.h" 37 #include <sys/procset.h> 38 #include <siginfo.h> 39 #include <ucontext.h> 40 #include <errno.h> 41 #include <string.h> 42 43 static void (*psig0_func)() = SIG_ERR; /* previous signal handler for signal 0 */ 44 static char sigsegv_stack[SIGSTKSZ]; 45 46 static void sigsegv(int sig, siginfo_t *sip, ucontext_t *uap); 47 static void fault(); 48 static BOOL sleeping = 0; 49 static unsigned char *trapcom[MAXTRAP]; /* array of actions, one per signal */ 50 static BOOL trapflg[MAXTRAP] = 51 { 52 0, 53 0, /* hangup */ 54 0, /* interrupt */ 55 0, /* quit */ 56 0, /* illegal instr */ 57 0, /* trace trap */ 58 0, /* IOT */ 59 0, /* EMT */ 60 0, /* float pt. exp */ 61 0, /* kill */ 62 0, /* bus error */ 63 0, /* memory faults */ 64 0, /* bad sys call */ 65 0, /* bad pipe call */ 66 0, /* alarm */ 67 0, /* software termination */ 68 0, /* unassigned */ 69 0, /* unassigned */ 70 0, /* death of child */ 71 0, /* power fail */ 72 0, /* window size change */ 73 0, /* urgent IO condition */ 74 0, /* pollable event occured */ 75 0, /* stopped by signal */ 76 0, /* stopped by user */ 77 0, /* continued */ 78 0, /* stopped by tty input */ 79 0, /* stopped by tty output */ 80 0, /* virtual timer expired */ 81 0, /* profiling timer expired */ 82 0, /* exceeded cpu limit */ 83 0, /* exceeded file size limit */ 84 0, /* process's lwps are blocked */ 85 0, /* special signal used by thread library */ 86 0, /* check point freeze */ 87 0, /* check point thaw */ 88 }; 89 90 static void (*( 91 sigval[MAXTRAP]))() = 92 { 93 0, 94 done, /* hangup */ 95 fault, /* interrupt */ 96 fault, /* quit */ 97 done, /* illegal instr */ 98 done, /* trace trap */ 99 done, /* IOT */ 100 done, /* EMT */ 101 done, /* floating pt. exp */ 102 0, /* kill */ 103 done, /* bus error */ 104 sigsegv, /* memory faults */ 105 done, /* bad sys call */ 106 done, /* bad pipe call */ 107 done, /* alarm */ 108 fault, /* software termination */ 109 done, /* unassigned */ 110 done, /* unassigned */ 111 0, /* death of child */ 112 done, /* power fail */ 113 0, /* window size change */ 114 done, /* urgent IO condition */ 115 done, /* pollable event occured */ 116 0, /* uncatchable stop */ 117 0, /* foreground stop */ 118 0, /* stopped process continued */ 119 0, /* background tty read */ 120 0, /* background tty write */ 121 done, /* virtual timer expired */ 122 done, /* profiling timer expired */ 123 done, /* exceeded cpu limit */ 124 done, /* exceeded file size limit */ 125 0, /* process's lwps are blocked */ 126 0, /* special signal used by thread library */ 127 0, /* check point freeze */ 128 0, /* check point thaw */ 129 }; 130 131 static int 132 ignoring(i) 133 register int i; 134 { 135 struct sigaction act; 136 if (trapflg[i] & SIGIGN) 137 return (1); 138 sigaction(i, 0, &act); 139 if (act.sa_handler == SIG_IGN) { 140 trapflg[i] |= SIGIGN; 141 return (1); 142 } 143 return (0); 144 } 145 146 static void 147 clrsig(i) 148 int i; 149 { 150 if (trapcom[i] != 0) { 151 free(trapcom[i]); 152 trapcom[i] = 0; 153 } 154 155 156 if (trapflg[i] & SIGMOD) { 157 /* 158 * If the signal has been set to SIGIGN and we are now 159 * clearing the disposition of the signal (restoring it 160 * back to its default value) then we need to clear this 161 * bit as well 162 * 163 */ 164 if (trapflg[i] & SIGIGN) 165 trapflg[i] &= ~SIGIGN; 166 167 trapflg[i] &= ~SIGMOD; 168 handle(i, sigval[i]); 169 } 170 } 171 172 void 173 done(sig) 174 { 175 register unsigned char *t; 176 int savxit; 177 178 if (t = trapcom[0]) 179 { 180 trapcom[0] = 0; 181 /* Save exit value so trap handler will not change its val */ 182 savxit = exitval; 183 execexp(t, 0); 184 exitval = savxit; /* Restore exit value */ 185 free(t); 186 } 187 else 188 chktrap(); 189 190 rmtemp(0); 191 rmfunctmp(); 192 193 #ifdef ACCT 194 doacct(); 195 #endif 196 if (flags & subsh) { 197 /* in a subshell, need to wait on foreground job */ 198 collect_fg_job(); 199 } 200 201 (void) endjobs(0); 202 if (sig) { 203 sigset_t set; 204 sigemptyset(&set); 205 sigaddset(&set, sig); 206 sigprocmask(SIG_UNBLOCK, &set, 0); 207 handle(sig, SIG_DFL); 208 kill(mypid, sig); 209 } 210 exit(exitval); 211 } 212 213 static void 214 fault(sig) 215 register int sig; 216 { 217 register int flag; 218 219 switch (sig) { 220 case SIGALRM: 221 if (sleeping) 222 return; 223 break; 224 } 225 226 if (trapcom[sig]) 227 flag = TRAPSET; 228 else if (flags & subsh) 229 done(sig); 230 else 231 flag = SIGSET; 232 233 trapnote |= flag; 234 trapflg[sig] |= flag; 235 } 236 237 int 238 handle(sig, func) 239 int sig; 240 void (*func)(); 241 { 242 int ret; 243 struct sigaction act, oact; 244 245 if (func == SIG_IGN && (trapflg[sig] & SIGIGN)) 246 return (0); 247 248 /* 249 * Ensure that sigaction is only called with valid signal numbers, 250 * we can get random values back for oact.sa_handler if the signal 251 * number is invalid 252 * 253 */ 254 if (sig > MINTRAP && sig < MAXTRAP) { 255 sigemptyset(&act.sa_mask); 256 act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0; 257 act.sa_handler = func; 258 sigaction(sig, &act, &oact); 259 } 260 261 if (func == SIG_IGN) 262 trapflg[sig] |= SIGIGN; 263 264 /* 265 * Special case for signal zero, we can not obtain the previos 266 * action by calling sigaction, instead we save it in the variable 267 * psig0_func, so we can test it next time through this code 268 * 269 */ 270 if (sig == 0) { 271 ret = (psig0_func != func); 272 psig0_func = func; 273 } else { 274 ret = (func != oact.sa_handler); 275 } 276 277 return (ret); 278 } 279 280 void 281 stdsigs() 282 { 283 register int i; 284 stack_t ss; 285 int err = 0; 286 int rtmin = (int)SIGRTMIN; 287 int rtmax = (int)SIGRTMAX; 288 289 ss.ss_size = SIGSTKSZ; 290 ss.ss_sp = sigsegv_stack; 291 ss.ss_flags = 0; 292 errno = 0; 293 if (sigaltstack(&ss, (stack_t *)NULL) == -1) { 294 err = errno; 295 failure("sigaltstack(2) failed with", strerror(err)); 296 } 297 298 for (i = 1; i < MAXTRAP; i++) { 299 if (i == rtmin) { 300 i = rtmax; 301 continue; 302 } 303 if (sigval[i] == 0) 304 continue; 305 if (i != SIGSEGV && ignoring(i)) 306 continue; 307 handle(i, sigval[i]); 308 } 309 310 /* 311 * handle all the realtime signals 312 * 313 */ 314 for (i = rtmin; i <= rtmax; i++) { 315 handle(i, done); 316 } 317 } 318 319 void 320 oldsigs() 321 { 322 register int i; 323 register unsigned char *t; 324 325 i = MAXTRAP; 326 while (i--) 327 { 328 t = trapcom[i]; 329 if (t == 0 || *t) 330 clrsig(i); 331 trapflg[i] = 0; 332 } 333 trapnote = 0; 334 } 335 336 /* 337 * check for traps 338 */ 339 340 void 341 chktrap() 342 { 343 register int i = MAXTRAP; 344 register unsigned char *t; 345 346 trapnote &= ~TRAPSET; 347 while (--i) 348 { 349 if (trapflg[i] & TRAPSET) 350 { 351 trapflg[i] &= ~TRAPSET; 352 if (t = trapcom[i]) 353 { 354 int savxit = exitval; 355 execexp(t, 0); 356 exitval = savxit; 357 exitset(); 358 } 359 } 360 } 361 } 362 363 systrap(argc, argv) 364 int argc; 365 char **argv; 366 { 367 int sig; 368 369 if (argc == 1) { 370 /* 371 * print out the current action associated with each signal 372 * handled by the shell 373 * 374 */ 375 for (sig = 0; sig < MAXTRAP; sig++) { 376 if (trapcom[sig]) { 377 prn_buff(sig); 378 prs_buff(colon); 379 prs_buff(trapcom[sig]); 380 prc_buff(NL); 381 } 382 } 383 } else { 384 /* 385 * set the action for the list of signals 386 * 387 */ 388 char *cmd = *argv, *a1 = *(argv+1); 389 BOOL noa1; 390 noa1 = (str2sig(a1, &sig) == 0); 391 if (noa1 == 0) 392 ++argv; 393 while (*++argv) { 394 if (str2sig(*argv, &sig) < 0 || 395 sig >= MAXTRAP || sig < MINTRAP || 396 sig == SIGSEGV) { 397 failure(cmd, badtrap); 398 } else if (noa1) { 399 /* 400 * no action specifed so reset the siganl 401 * to its default disposition 402 * 403 */ 404 clrsig(sig); 405 } else if (*a1) { 406 /* 407 * set the action associated with the signal 408 * to a1 409 * 410 */ 411 if (trapflg[sig] & SIGMOD || sig == 0 || 412 !ignoring(sig)) { 413 handle(sig, fault); 414 trapflg[sig] |= SIGMOD; 415 replace(&trapcom[sig], a1); 416 } 417 } else if (handle(sig, SIG_IGN)) { 418 /* 419 * set the action associated with the signal 420 * to SIG_IGN 421 * 422 */ 423 trapflg[sig] |= SIGMOD; 424 replace(&trapcom[sig], a1); 425 } 426 } 427 } 428 } 429 430 unsigned int 431 sleep(ticks) 432 unsigned int ticks; 433 { 434 sigset_t set, oset; 435 struct sigaction act, oact; 436 437 438 /* 439 * add SIGALRM to mask 440 */ 441 442 sigemptyset(&set); 443 sigaddset(&set, SIGALRM); 444 sigprocmask(SIG_BLOCK, &set, &oset); 445 446 /* 447 * catch SIGALRM 448 */ 449 450 sigemptyset(&act.sa_mask); 451 act.sa_flags = 0; 452 act.sa_handler = fault; 453 sigaction(SIGALRM, &act, &oact); 454 455 /* 456 * start alarm and wait for signal 457 */ 458 459 alarm(ticks); 460 sleeping = 1; 461 sigsuspend(&oset); 462 sleeping = 0; 463 464 /* 465 * reset alarm, catcher and mask 466 */ 467 468 alarm(0); 469 sigaction(SIGALRM, &oact, NULL); 470 sigprocmask(SIG_SETMASK, &oset, 0); 471 472 } 473 474 void 475 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap) 476 { 477 if (sip == (siginfo_t *)NULL) { 478 /* 479 * This should never happen, but if it does this is all we 480 * can do. It can only happen if sigaction(2) for SIGSEGV 481 * has been called without SA_SIGINFO being set. 482 * 483 */ 484 485 exit(ERROR); 486 } else { 487 if (sip->si_code <= 0) { 488 /* 489 * If we are here then SIGSEGV must have been sent to 490 * us from a user process NOT as a result of an 491 * internal error within the shell eg 492 * kill -SEGV $$ 493 * will bring us here. So do the normal thing. 494 * 495 */ 496 fault(sig); 497 } else { 498 /* 499 * If we are here then there must have been an internal 500 * error within the shell to generate SIGSEGV eg 501 * the stack is full and we cannot call any more 502 * functions (Remeber this signal handler is running 503 * on an alternate stack). So we just exit cleanly 504 * with an error status (no core file). 505 */ 506 exit(ERROR); 507 } 508 } 509 } 510