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 23 /* 24 * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 /* 34 * UNIX shell 35 */ 36 37 #include "defs.h" 38 #include <sys/procset.h> 39 #include <siginfo.h> 40 #include <ucontext.h> 41 #include <errno.h> 42 #include <string.h> 43 44 static void (*psig0_func)() = SIG_ERR; /* previous signal handler for signal 0 */ 45 static char sigsegv_stack[SIGSTKSZ]; 46 47 static void sigsegv(int sig, siginfo_t *sip, ucontext_t *uap); 48 static void fault(); 49 static BOOL sleeping = 0; 50 static unsigned char *trapcom[MAXTRAP]; /* array of actions, one per signal */ 51 static BOOL trapflg[MAXTRAP] = 52 { 53 0, 54 0, /* hangup */ 55 0, /* interrupt */ 56 0, /* quit */ 57 0, /* illegal instr */ 58 0, /* trace trap */ 59 0, /* IOT */ 60 0, /* EMT */ 61 0, /* float pt. exp */ 62 0, /* kill */ 63 0, /* bus error */ 64 0, /* memory faults */ 65 0, /* bad sys call */ 66 0, /* bad pipe call */ 67 0, /* alarm */ 68 0, /* software termination */ 69 0, /* unassigned */ 70 0, /* unassigned */ 71 0, /* death of child */ 72 0, /* power fail */ 73 0, /* window size change */ 74 0, /* urgent IO condition */ 75 0, /* pollable event occured */ 76 0, /* stopped by signal */ 77 0, /* stopped by user */ 78 0, /* continued */ 79 0, /* stopped by tty input */ 80 0, /* stopped by tty output */ 81 0, /* virtual timer expired */ 82 0, /* profiling timer expired */ 83 0, /* exceeded cpu limit */ 84 0, /* exceeded file size limit */ 85 0, /* process's lwps are blocked */ 86 0, /* special signal used by thread library */ 87 0, /* check point freeze */ 88 0, /* check point thaw */ 89 }; 90 91 static void (*( 92 sigval[MAXTRAP]))() = 93 { 94 0, 95 done, /* hangup */ 96 fault, /* interrupt */ 97 fault, /* quit */ 98 done, /* illegal instr */ 99 done, /* trace trap */ 100 done, /* IOT */ 101 done, /* EMT */ 102 done, /* floating pt. exp */ 103 0, /* kill */ 104 done, /* bus error */ 105 sigsegv, /* memory faults */ 106 done, /* bad sys call */ 107 done, /* bad pipe call */ 108 done, /* alarm */ 109 fault, /* software termination */ 110 done, /* unassigned */ 111 done, /* unassigned */ 112 0, /* death of child */ 113 done, /* power fail */ 114 0, /* window size change */ 115 done, /* urgent IO condition */ 116 done, /* pollable event occured */ 117 0, /* uncatchable stop */ 118 0, /* foreground stop */ 119 0, /* stopped process continued */ 120 0, /* background tty read */ 121 0, /* background tty write */ 122 done, /* virtual timer expired */ 123 done, /* profiling timer expired */ 124 done, /* exceeded cpu limit */ 125 done, /* exceeded file size limit */ 126 0, /* process's lwps are blocked */ 127 0, /* special signal used by thread library */ 128 0, /* check point freeze */ 129 0, /* check point thaw */ 130 }; 131 132 static int 133 ignoring(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 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(int sig) 215 { 216 int flag; 217 218 switch (sig) { 219 case SIGALRM: 220 if (sleeping) 221 return; 222 break; 223 } 224 225 if (trapcom[sig]) 226 flag = TRAPSET; 227 else if (flags & subsh) 228 done(sig); 229 else 230 flag = SIGSET; 231 232 trapnote |= flag; 233 trapflg[sig] |= flag; 234 } 235 236 int 237 handle(sig, func) 238 int sig; 239 void (*func)(); 240 { 241 int ret; 242 struct sigaction act, oact; 243 244 if (func == SIG_IGN && (trapflg[sig] & SIGIGN)) 245 return (0); 246 247 /* 248 * Ensure that sigaction is only called with valid signal numbers, 249 * we can get random values back for oact.sa_handler if the signal 250 * number is invalid 251 * 252 */ 253 if (sig > MINTRAP && sig < MAXTRAP) { 254 sigemptyset(&act.sa_mask); 255 act.sa_flags = (sig == SIGSEGV) ? (SA_ONSTACK | SA_SIGINFO) : 0; 256 act.sa_handler = func; 257 sigaction(sig, &act, &oact); 258 } 259 260 if (func == SIG_IGN) 261 trapflg[sig] |= SIGIGN; 262 263 /* 264 * Special case for signal zero, we can not obtain the previos 265 * action by calling sigaction, instead we save it in the variable 266 * psig0_func, so we can test it next time through this code 267 * 268 */ 269 if (sig == 0) { 270 ret = (psig0_func != func); 271 psig0_func = func; 272 } else { 273 ret = (func != oact.sa_handler); 274 } 275 276 return (ret); 277 } 278 279 void 280 stdsigs() 281 { 282 int i; 283 stack_t ss; 284 int err = 0; 285 int rtmin = (int)SIGRTMIN; 286 int rtmax = (int)SIGRTMAX; 287 288 ss.ss_size = SIGSTKSZ; 289 ss.ss_sp = sigsegv_stack; 290 ss.ss_flags = 0; 291 errno = 0; 292 if (sigaltstack(&ss, (stack_t *)NULL) == -1) { 293 err = errno; 294 failure("sigaltstack(2) failed with", strerror(err)); 295 } 296 297 for (i = 1; i < MAXTRAP; i++) { 298 if (i == rtmin) { 299 i = rtmax; 300 continue; 301 } 302 if (sigval[i] == 0) 303 continue; 304 if (i != SIGSEGV && ignoring(i)) 305 continue; 306 handle(i, sigval[i]); 307 } 308 309 /* 310 * handle all the realtime signals 311 * 312 */ 313 for (i = rtmin; i <= rtmax; i++) { 314 handle(i, done); 315 } 316 } 317 318 void 319 oldsigs() 320 { 321 int i; 322 unsigned char *t; 323 324 i = MAXTRAP; 325 while (i--) 326 { 327 t = trapcom[i]; 328 if (t == 0 || *t) 329 clrsig(i); 330 trapflg[i] = 0; 331 } 332 trapnote = 0; 333 } 334 335 /* 336 * check for traps 337 */ 338 339 void 340 chktrap() 341 { 342 int i = MAXTRAP; 343 unsigned char *t; 344 345 trapnote &= ~TRAPSET; 346 while (--i) 347 { 348 if (trapflg[i] & TRAPSET) 349 { 350 trapflg[i] &= ~TRAPSET; 351 if (t = trapcom[i]) 352 { 353 int savxit = exitval; 354 execexp(t, 0); 355 exitval = savxit; 356 exitset(); 357 } 358 } 359 } 360 } 361 362 void 363 systrap(int argc, char **argv) 364 { 365 int sig; 366 367 if (argc == 1) { 368 /* 369 * print out the current action associated with each signal 370 * handled by the shell 371 * 372 */ 373 for (sig = 0; sig < MAXTRAP; sig++) { 374 if (trapcom[sig]) { 375 prn_buff(sig); 376 prs_buff(colon); 377 prs_buff(trapcom[sig]); 378 prc_buff(NL); 379 } 380 } 381 } else { 382 /* 383 * set the action for the list of signals 384 * 385 */ 386 char *cmd = *argv, *a1 = *(argv+1); 387 BOOL noa1; 388 noa1 = (str2sig(a1, &sig) == 0); 389 if (noa1 == 0) 390 ++argv; 391 while (*++argv) { 392 if (str2sig(*argv, &sig) < 0 || 393 sig >= MAXTRAP || sig < MINTRAP || 394 sig == SIGSEGV) { 395 failure(cmd, badtrap); 396 } else if (noa1) { 397 /* 398 * no action specifed so reset the siganl 399 * to its default disposition 400 * 401 */ 402 clrsig(sig); 403 } else if (*a1) { 404 /* 405 * set the action associated with the signal 406 * to a1 407 * 408 */ 409 if (trapflg[sig] & SIGMOD || sig == 0 || 410 !ignoring(sig)) { 411 handle(sig, fault); 412 trapflg[sig] |= SIGMOD; 413 replace(&trapcom[sig], a1); 414 } 415 } else if (handle(sig, SIG_IGN)) { 416 /* 417 * set the action associated with the signal 418 * to SIG_IGN 419 * 420 */ 421 trapflg[sig] |= SIGMOD; 422 replace(&trapcom[sig], a1); 423 } 424 } 425 } 426 } 427 428 void 429 sh_sleep(unsigned int ticks) 430 { 431 sigset_t set, oset; 432 struct sigaction act, oact; 433 434 435 /* 436 * add SIGALRM to mask 437 */ 438 439 sigemptyset(&set); 440 sigaddset(&set, SIGALRM); 441 sigprocmask(SIG_BLOCK, &set, &oset); 442 443 /* 444 * catch SIGALRM 445 */ 446 447 sigemptyset(&act.sa_mask); 448 act.sa_flags = 0; 449 act.sa_handler = fault; 450 sigaction(SIGALRM, &act, &oact); 451 452 /* 453 * start alarm and wait for signal 454 */ 455 456 alarm(ticks); 457 sleeping = 1; 458 sigsuspend(&oset); 459 sleeping = 0; 460 461 /* 462 * reset alarm, catcher and mask 463 */ 464 465 alarm(0); 466 sigaction(SIGALRM, &oact, NULL); 467 sigprocmask(SIG_SETMASK, &oset, 0); 468 469 } 470 471 void 472 sigsegv(int sig, siginfo_t *sip, ucontext_t *uap) 473 { 474 if (sip == (siginfo_t *)NULL) { 475 /* 476 * This should never happen, but if it does this is all we 477 * can do. It can only happen if sigaction(2) for SIGSEGV 478 * has been called without SA_SIGINFO being set. 479 * 480 */ 481 482 exit(ERROR); 483 } else { 484 if (sip->si_code <= 0) { 485 /* 486 * If we are here then SIGSEGV must have been sent to 487 * us from a user process NOT as a result of an 488 * internal error within the shell eg 489 * kill -SEGV $$ 490 * will bring us here. So do the normal thing. 491 * 492 */ 493 fault(sig); 494 } else { 495 /* 496 * If we are here then there must have been an internal 497 * error within the shell to generate SIGSEGV eg 498 * the stack is full and we cannot call any more 499 * functions (Remeber this signal handler is running 500 * on an alternate stack). So we just exit cleanly 501 * with an error status (no core file). 502 */ 503 exit(ERROR); 504 } 505 } 506 } 507