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 2009 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 /* 32 * UNIX shell 33 */ 34 35 #include "defs.h" 36 #include <sys/procset.h> 37 #include <siginfo.h> 38 #include <ucontext.h> 39 #include <errno.h> 40 #include <string.h> 41 42 extern void hupforegnd(void); 43 44 /* previous signal handler for signal 0 */ 45 static void (*psig0_func)() = SIG_ERR; 46 static char sigsegv_stack[SIGSTKSZ]; 47 48 static void sigsegv(int sig, siginfo_t *sip, ucontext_t *uap); 49 static void fault(); 50 static BOOL sleeping = 0; 51 static unsigned char *trapcom[MAXTRAP]; /* array of actions, one per signal */ 52 static BOOL trapflg[MAXTRAP] = 53 { 54 0, 55 0, /* hangup */ 56 0, /* interrupt */ 57 0, /* quit */ 58 0, /* illegal instr */ 59 0, /* trace trap */ 60 0, /* IOT */ 61 0, /* EMT */ 62 0, /* float pt. exp */ 63 0, /* kill */ 64 0, /* bus error */ 65 0, /* memory faults */ 66 0, /* bad sys call */ 67 0, /* bad pipe call */ 68 0, /* alarm */ 69 0, /* software termination */ 70 0, /* unassigned */ 71 0, /* unassigned */ 72 0, /* death of child */ 73 0, /* power fail */ 74 0, /* window size change */ 75 0, /* urgent IO condition */ 76 0, /* pollable event occured */ 77 0, /* stopped by signal */ 78 0, /* stopped by user */ 79 0, /* continued */ 80 0, /* stopped by tty input */ 81 0, /* stopped by tty output */ 82 0, /* virtual timer expired */ 83 0, /* profiling timer expired */ 84 0, /* exceeded cpu limit */ 85 0, /* exceeded file size limit */ 86 0, /* process's lwps are blocked */ 87 0, /* special signal used by thread library */ 88 0, /* check point freeze */ 89 0, /* check point thaw */ 90 }; 91 92 static void (*( 93 sigval[MAXTRAP]))() = 94 { 95 0, 96 done, /* hangup */ 97 fault, /* interrupt */ 98 fault, /* quit */ 99 done, /* illegal instr */ 100 done, /* trace trap */ 101 done, /* IOT */ 102 done, /* EMT */ 103 done, /* floating pt. exp */ 104 0, /* kill */ 105 done, /* bus error */ 106 sigsegv, /* memory faults */ 107 done, /* bad sys call */ 108 done, /* bad pipe call */ 109 done, /* alarm */ 110 fault, /* software termination */ 111 done, /* unassigned */ 112 done, /* unassigned */ 113 0, /* death of child */ 114 done, /* power fail */ 115 0, /* window size change */ 116 done, /* urgent IO condition */ 117 done, /* pollable event occured */ 118 0, /* uncatchable stop */ 119 0, /* foreground stop */ 120 0, /* stopped process continued */ 121 0, /* background tty read */ 122 0, /* background tty write */ 123 done, /* virtual timer expired */ 124 done, /* profiling timer expired */ 125 done, /* exceeded cpu limit */ 126 done, /* exceeded file size limit */ 127 0, /* process's lwps are blocked */ 128 0, /* special signal used by thread library */ 129 0, /* check point freeze */ 130 0, /* check point thaw */ 131 }; 132 133 static int 134 ignoring(int i) 135 { 136 struct sigaction act; 137 if (trapflg[i] & SIGIGN) 138 return (1); 139 sigaction(i, 0, &act); 140 if (act.sa_handler == SIG_IGN) { 141 trapflg[i] |= SIGIGN; 142 return (1); 143 } 144 return (0); 145 } 146 147 static void 148 clrsig(i) 149 int i; 150 { 151 if (trapcom[i] != 0) { 152 free(trapcom[i]); 153 trapcom[i] = 0; 154 } 155 156 157 if (trapflg[i] & SIGMOD) { 158 /* 159 * If the signal has been set to SIGIGN and we are now 160 * clearing the disposition of the signal (restoring it 161 * back to its default value) then we need to clear this 162 * bit as well 163 * 164 */ 165 if (trapflg[i] & SIGIGN) 166 trapflg[i] &= ~SIGIGN; 167 168 trapflg[i] &= ~SIGMOD; 169 handle(i, sigval[i]); 170 } 171 } 172 173 void 174 done(sig) 175 { 176 unsigned char *t; 177 int savxit; 178 179 if (t = trapcom[0]) { 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 205 /* 206 * If the signal is SIGHUP, then it should be delivered 207 * to the process group leader of the foreground job. 208 */ 209 if (sig == SIGHUP) 210 hupforegnd(); 211 212 sigemptyset(&set); 213 sigaddset(&set, sig); 214 sigprocmask(SIG_UNBLOCK, &set, 0); 215 handle(sig, SIG_DFL); 216 kill(mypid, sig); 217 } 218 exit(exitval); 219 } 220 221 static void 222 fault(int sig) 223 { 224 int flag; 225 226 switch (sig) { 227 case SIGALRM: 228 if (sleeping) 229 return; 230 break; 231 } 232 233 if (trapcom[sig]) 234 flag = TRAPSET; 235 else if (flags & subsh) 236 done(sig); 237 else 238 flag = SIGSET; 239 240 trapnote |= flag; 241 trapflg[sig] |= flag; 242 } 243 244 int 245 handle(sig, func) 246 int sig; 247 void (*func)(); 248 { 249 int ret; 250 struct sigaction act, oact; 251 252 if (func == SIG_IGN && (trapflg[sig] & SIGIGN)) 253 return (0); 254 255 /* 256 * Ensure that sigaction is only called with valid signal numbers, 257 * we can get random values back for oact.sa_handler if the signal 258 * number is invalid 259 * 260 */ 261 if (sig > MINTRAP && sig < MAXTRAP) { 262 sigemptyset(&act.sa_mask); 263 act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0; 264 act.sa_handler = func; 265 sigaction(sig, &act, &oact); 266 } 267 268 if (func == SIG_IGN) 269 trapflg[sig] |= SIGIGN; 270 271 /* 272 * Special case for signal zero, we can not obtain the previos 273 * action by calling sigaction, instead we save it in the variable 274 * psig0_func, so we can test it next time through this code 275 * 276 */ 277 if (sig == 0) { 278 ret = (psig0_func != func); 279 psig0_func = func; 280 } else { 281 ret = (func != oact.sa_handler); 282 } 283 284 return (ret); 285 } 286 287 void 288 stdsigs() 289 { 290 int i; 291 stack_t ss; 292 int rtmin = (int)SIGRTMIN; 293 int rtmax = (int)SIGRTMAX; 294 295 ss.ss_size = SIGSTKSZ; 296 ss.ss_sp = sigsegv_stack; 297 ss.ss_flags = 0; 298 if (sigaltstack(&ss, NULL) == -1) { 299 error("sigaltstack(2) failed"); 300 } 301 302 for (i = 1; i < MAXTRAP; i++) { 303 if (i == rtmin) { 304 i = rtmax; 305 continue; 306 } 307 if (sigval[i] == 0) 308 continue; 309 if (i != SIGSEGV && ignoring(i)) 310 continue; 311 handle(i, sigval[i]); 312 } 313 314 /* 315 * handle all the realtime signals 316 * 317 */ 318 for (i = rtmin; i <= rtmax; i++) { 319 handle(i, done); 320 } 321 } 322 323 void 324 oldsigs() 325 { 326 int i; 327 unsigned char *t; 328 329 i = MAXTRAP; 330 while (i--) { 331 t = trapcom[i]; 332 if (t == 0 || *t) 333 clrsig(i); 334 trapflg[i] = 0; 335 } 336 trapnote = 0; 337 } 338 339 /* 340 * check for traps 341 */ 342 343 void 344 chktrap() 345 { 346 int i = MAXTRAP; 347 unsigned char *t; 348 349 trapnote &= ~TRAPSET; 350 while (--i) { 351 if (trapflg[i] & TRAPSET) { 352 trapflg[i] &= ~TRAPSET; 353 if (t = trapcom[i]) { 354 int savxit = exitval; 355 356 execexp(t, 0); 357 exitval = savxit; 358 exitset(); 359 } 360 } 361 } 362 } 363 364 void 365 systrap(int argc, 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 void 431 sh_sleep(unsigned int ticks) 432 { 433 sigset_t set, oset; 434 struct sigaction act, oact; 435 436 437 /* 438 * add SIGALRM to mask 439 */ 440 441 sigemptyset(&set); 442 sigaddset(&set, SIGALRM); 443 sigprocmask(SIG_BLOCK, &set, &oset); 444 445 /* 446 * catch SIGALRM 447 */ 448 449 sigemptyset(&act.sa_mask); 450 act.sa_flags = 0; 451 act.sa_handler = fault; 452 sigaction(SIGALRM, &act, &oact); 453 454 /* 455 * start alarm and wait for signal 456 */ 457 458 alarm(ticks); 459 sleeping = 1; 460 sigsuspend(&oset); 461 sleeping = 0; 462 463 /* 464 * reset alarm, catcher and mask 465 */ 466 467 alarm(0); 468 sigaction(SIGALRM, &oact, NULL); 469 sigprocmask(SIG_SETMASK, &oset, 0); 470 471 } 472 473 void 474 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap) 475 { 476 if (sip == (siginfo_t *)NULL) { 477 /* 478 * This should never happen, but if it does this is all we 479 * can do. It can only happen if sigaction(2) for SIGSEGV 480 * has been called without SA_SIGINFO being set. 481 * 482 */ 483 484 exit(ERROR); 485 } else { 486 if (sip->si_code <= 0) { 487 /* 488 * If we are here then SIGSEGV must have been sent to 489 * us from a user process NOT as a result of an 490 * internal error within the shell eg 491 * kill -SEGV $$ 492 * will bring us here. So do the normal thing. 493 * 494 */ 495 fault(sig); 496 } else { 497 /* 498 * If we are here then there must have been an internal 499 * error within the shell to generate SIGSEGV eg 500 * the stack is full and we cannot call any more 501 * functions (Remeber this signal handler is running 502 * on an alternate stack). So we just exit cleanly 503 * with an error status (no core file). 504 */ 505 exit(ERROR); 506 } 507 } 508 } 509