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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 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(int i) 133 { 134 struct sigaction act; 135 if (trapflg[i] & SIGIGN) 136 return (1); 137 sigaction(i, 0, &act); 138 if (act.sa_handler == SIG_IGN) { 139 trapflg[i] |= SIGIGN; 140 return (1); 141 } 142 return (0); 143 } 144 145 static void 146 clrsig(i) 147 int i; 148 { 149 if (trapcom[i] != 0) { 150 free(trapcom[i]); 151 trapcom[i] = 0; 152 } 153 154 155 if (trapflg[i] & SIGMOD) { 156 /* 157 * If the signal has been set to SIGIGN and we are now 158 * clearing the disposition of the signal (restoring it 159 * back to its default value) then we need to clear this 160 * bit as well 161 * 162 */ 163 if (trapflg[i] & SIGIGN) 164 trapflg[i] &= ~SIGIGN; 165 166 trapflg[i] &= ~SIGMOD; 167 handle(i, sigval[i]); 168 } 169 } 170 171 void 172 done(sig) 173 { 174 unsigned char *t; 175 int savxit; 176 177 if (t = trapcom[0]) 178 { 179 trapcom[0] = 0; 180 /* Save exit value so trap handler will not change its val */ 181 savxit = exitval; 182 execexp(t, 0); 183 exitval = savxit; /* Restore exit value */ 184 free(t); 185 } 186 else 187 chktrap(); 188 189 rmtemp(0); 190 rmfunctmp(); 191 192 #ifdef ACCT 193 doacct(); 194 #endif 195 if (flags & subsh) { 196 /* in a subshell, need to wait on foreground job */ 197 collect_fg_job(); 198 } 199 200 (void) endjobs(0); 201 if (sig) { 202 sigset_t set; 203 sigemptyset(&set); 204 sigaddset(&set, sig); 205 sigprocmask(SIG_UNBLOCK, &set, 0); 206 handle(sig, SIG_DFL); 207 kill(mypid, sig); 208 } 209 exit(exitval); 210 } 211 212 static void 213 fault(int sig) 214 { 215 int flag; 216 217 switch (sig) { 218 case SIGALRM: 219 if (sleeping) 220 return; 221 break; 222 } 223 224 if (trapcom[sig]) 225 flag = TRAPSET; 226 else if (flags & subsh) 227 done(sig); 228 else 229 flag = SIGSET; 230 231 trapnote |= flag; 232 trapflg[sig] |= flag; 233 } 234 235 int 236 handle(sig, func) 237 int sig; 238 void (*func)(); 239 { 240 int ret; 241 struct sigaction act, oact; 242 243 if (func == SIG_IGN && (trapflg[sig] & SIGIGN)) 244 return (0); 245 246 /* 247 * Ensure that sigaction is only called with valid signal numbers, 248 * we can get random values back for oact.sa_handler if the signal 249 * number is invalid 250 * 251 */ 252 if (sig > MINTRAP && sig < MAXTRAP) { 253 sigemptyset(&act.sa_mask); 254 act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0; 255 act.sa_handler = func; 256 sigaction(sig, &act, &oact); 257 } 258 259 if (func == SIG_IGN) 260 trapflg[sig] |= SIGIGN; 261 262 /* 263 * Special case for signal zero, we can not obtain the previos 264 * action by calling sigaction, instead we save it in the variable 265 * psig0_func, so we can test it next time through this code 266 * 267 */ 268 if (sig == 0) { 269 ret = (psig0_func != func); 270 psig0_func = func; 271 } else { 272 ret = (func != oact.sa_handler); 273 } 274 275 return (ret); 276 } 277 278 void 279 stdsigs() 280 { 281 int i; 282 stack_t ss; 283 int rtmin = (int)SIGRTMIN; 284 int rtmax = (int)SIGRTMAX; 285 286 ss.ss_size = SIGSTKSZ; 287 ss.ss_sp = sigsegv_stack; 288 ss.ss_flags = 0; 289 if (sigaltstack(&ss, NULL) == -1) { 290 error("sigaltstack(2) failed"); 291 } 292 293 for (i = 1; i < MAXTRAP; i++) { 294 if (i == rtmin) { 295 i = rtmax; 296 continue; 297 } 298 if (sigval[i] == 0) 299 continue; 300 if (i != SIGSEGV && ignoring(i)) 301 continue; 302 handle(i, sigval[i]); 303 } 304 305 /* 306 * handle all the realtime signals 307 * 308 */ 309 for (i = rtmin; i <= rtmax; i++) { 310 handle(i, done); 311 } 312 } 313 314 void 315 oldsigs() 316 { 317 int i; 318 unsigned char *t; 319 320 i = MAXTRAP; 321 while (i--) 322 { 323 t = trapcom[i]; 324 if (t == 0 || *t) 325 clrsig(i); 326 trapflg[i] = 0; 327 } 328 trapnote = 0; 329 } 330 331 /* 332 * check for traps 333 */ 334 335 void 336 chktrap() 337 { 338 int i = MAXTRAP; 339 unsigned char *t; 340 341 trapnote &= ~TRAPSET; 342 while (--i) 343 { 344 if (trapflg[i] & TRAPSET) 345 { 346 trapflg[i] &= ~TRAPSET; 347 if (t = trapcom[i]) 348 { 349 int savxit = exitval; 350 execexp(t, 0); 351 exitval = savxit; 352 exitset(); 353 } 354 } 355 } 356 } 357 358 void 359 systrap(int argc, char **argv) 360 { 361 int sig; 362 363 if (argc == 1) { 364 /* 365 * print out the current action associated with each signal 366 * handled by the shell 367 * 368 */ 369 for (sig = 0; sig < MAXTRAP; sig++) { 370 if (trapcom[sig]) { 371 prn_buff(sig); 372 prs_buff(colon); 373 prs_buff(trapcom[sig]); 374 prc_buff(NL); 375 } 376 } 377 } else { 378 /* 379 * set the action for the list of signals 380 * 381 */ 382 char *cmd = *argv, *a1 = *(argv+1); 383 BOOL noa1; 384 noa1 = (str2sig(a1, &sig) == 0); 385 if (noa1 == 0) 386 ++argv; 387 while (*++argv) { 388 if (str2sig(*argv, &sig) < 0 || 389 sig >= MAXTRAP || sig < MINTRAP || 390 sig == SIGSEGV) { 391 failure(cmd, badtrap); 392 } else if (noa1) { 393 /* 394 * no action specifed so reset the siganl 395 * to its default disposition 396 * 397 */ 398 clrsig(sig); 399 } else if (*a1) { 400 /* 401 * set the action associated with the signal 402 * to a1 403 * 404 */ 405 if (trapflg[sig] & SIGMOD || sig == 0 || 406 !ignoring(sig)) { 407 handle(sig, fault); 408 trapflg[sig] |= SIGMOD; 409 replace(&trapcom[sig], a1); 410 } 411 } else if (handle(sig, SIG_IGN)) { 412 /* 413 * set the action associated with the signal 414 * to SIG_IGN 415 * 416 */ 417 trapflg[sig] |= SIGMOD; 418 replace(&trapcom[sig], a1); 419 } 420 } 421 } 422 } 423 424 void 425 sh_sleep(unsigned int ticks) 426 { 427 sigset_t set, oset; 428 struct sigaction act, oact; 429 430 431 /* 432 * add SIGALRM to mask 433 */ 434 435 sigemptyset(&set); 436 sigaddset(&set, SIGALRM); 437 sigprocmask(SIG_BLOCK, &set, &oset); 438 439 /* 440 * catch SIGALRM 441 */ 442 443 sigemptyset(&act.sa_mask); 444 act.sa_flags = 0; 445 act.sa_handler = fault; 446 sigaction(SIGALRM, &act, &oact); 447 448 /* 449 * start alarm and wait for signal 450 */ 451 452 alarm(ticks); 453 sleeping = 1; 454 sigsuspend(&oset); 455 sleeping = 0; 456 457 /* 458 * reset alarm, catcher and mask 459 */ 460 461 alarm(0); 462 sigaction(SIGALRM, &oact, NULL); 463 sigprocmask(SIG_SETMASK, &oset, 0); 464 465 } 466 467 void 468 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap) 469 { 470 if (sip == (siginfo_t *)NULL) { 471 /* 472 * This should never happen, but if it does this is all we 473 * can do. It can only happen if sigaction(2) for SIGSEGV 474 * has been called without SA_SIGINFO being set. 475 * 476 */ 477 478 exit(ERROR); 479 } else { 480 if (sip->si_code <= 0) { 481 /* 482 * If we are here then SIGSEGV must have been sent to 483 * us from a user process NOT as a result of an 484 * internal error within the shell eg 485 * kill -SEGV $$ 486 * will bring us here. So do the normal thing. 487 * 488 */ 489 fault(sig); 490 } else { 491 /* 492 * If we are here then there must have been an internal 493 * error within the shell to generate SIGSEGV eg 494 * the stack is full and we cannot call any more 495 * functions (Remeber this signal handler is running 496 * on an alternate stack). So we just exit cleanly 497 * with an error status (no core file). 498 */ 499 exit(ERROR); 500 } 501 } 502 } 503