|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: /* signal.c:: signal handling routines */ ! 10: ! 11: ! 12: ! 13: #include "mint.h" ! 14: ! 15: ! 16: ! 17: void (*sig_routine)(); /* used in intr.s */ ! 18: ! 19: ! 20: ! 21: /* ! 22: ! 23: * killgroup(pgrp, sig): send a signal to all members of a process group ! 24: ! 25: * returns 0 on success, or an error code on failure ! 26: ! 27: */ ! 28: ! 29: ! 30: ! 31: long ! 32: ! 33: killgroup(pgrp, sig) ! 34: ! 35: int pgrp, sig; ! 36: ! 37: { ! 38: ! 39: PROC *p; ! 40: ! 41: int found = 0; ! 42: ! 43: ! 44: ! 45: TRACE("killgroup %d %d", pgrp, sig); ! 46: ! 47: ! 48: ! 49: if (pgrp < 0) ! 50: ! 51: return EINTRN; ! 52: ! 53: ! 54: ! 55: for (p = proclist; p; p = p->gl_next) { ! 56: ! 57: if (p->pgrp == pgrp) { ! 58: ! 59: post_sig(p, sig); ! 60: ! 61: found++; ! 62: ! 63: } ! 64: ! 65: } ! 66: ! 67: if (found) { ! 68: ! 69: check_sigs(); /* see if the current process is affected */ ! 70: ! 71: return 0; ! 72: ! 73: } ! 74: ! 75: else { ! 76: ! 77: DEBUG("killgroup: no processes found"); ! 78: ! 79: return EFILNF; ! 80: ! 81: } ! 82: ! 83: } ! 84: ! 85: ! 86: ! 87: /* post_sig: post a signal as being pending. It is assumed that the ! 88: ! 89: caller has already verified that "sig" is a valid signal, and ! 90: ! 91: moreover it is the caller's responsibility to call check_sigs() ! 92: ! 93: if it's possible that p == curproc ! 94: ! 95: */ ! 96: ! 97: ! 98: ! 99: void ! 100: ! 101: post_sig(p, sig) ! 102: ! 103: PROC *p; ! 104: ! 105: int sig; ! 106: ! 107: { ! 108: ! 109: ulong sigm; ! 110: ! 111: ! 112: ! 113: /* if process is ignoring this signal, do nothing ! 114: ! 115: * also: signal 0 is SIGNULL, and should never be delivered through ! 116: ! 117: * the normal channels (indeed, it's filtered out in dossig.c, ! 118: ! 119: * but the extra sanity check here is harmless). The kernel uses ! 120: ! 121: * signal 0 internally for some purposes, but it is handled ! 122: ! 123: * specially (see supexec() in xbios.c, for example). ! 124: ! 125: */ ! 126: ! 127: if (p->sighandle[sig] == SIG_IGN || sig == 0) ! 128: ! 129: return; ! 130: ! 131: ! 132: ! 133: /* if the process is already dead, do nothing */ ! 134: ! 135: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) ! 136: ! 137: return; ! 138: ! 139: ! 140: ! 141: /* mark the signal as pending */ ! 142: ! 143: sigm = (1L << (unsigned long)sig); ! 144: ! 145: p->sigpending |= sigm; ! 146: ! 147: ! 148: ! 149: /* if the signal is masked, do nothing further */ ! 150: ! 151: if ( (p->sigmask & sigm) != 0 ) ! 152: ! 153: return; ! 154: ! 155: ! 156: ! 157: /* otherwise, make sure the process is awake */ ! 158: ! 159: if (p->wait_q && p->wait_q != READY_Q) { ! 160: ! 161: rm_q(p->wait_q, p); ! 162: ! 163: add_q(READY_Q, p); ! 164: ! 165: } ! 166: ! 167: } ! 168: ! 169: ! 170: ! 171: /* ! 172: ! 173: * check_sigs: see if we have any signals pending. if so, ! 174: ! 175: * handle them. ! 176: ! 177: */ ! 178: ! 179: ! 180: ! 181: void ! 182: ! 183: check_sigs() ! 184: ! 185: { ! 186: ! 187: ulong sigs, sigm; ! 188: ! 189: ulong i; ! 190: ! 191: ! 192: ! 193: if (curproc->pid == 0) return; ! 194: ! 195: sigs = curproc->sigpending & ~(curproc->sigmask); ! 196: ! 197: if (sigs) { ! 198: ! 199: sigm = 2; ! 200: ! 201: for (i = 1; i < NSIG; i++) { ! 202: ! 203: if (sigs & sigm) { ! 204: ! 205: ulong omask; ! 206: ! 207: ! 208: ! 209: curproc->sigpending &= ~sigm; ! 210: ! 211: omask = curproc->sigmask; ! 212: ! 213: ! 214: ! 215: /* sigextra gives which extra signals should also be masked */ ! 216: ! 217: curproc->sigmask |= curproc->sigextra[i] | sigm; ! 218: ! 219: handle_sig(i); ! 220: ! 221: ! 222: ! 223: /* ! 224: ! 225: * POSIX.1-3.3.4.2(723) "If and when the user's signal handler returns ! 226: ! 227: * normally, the original signal mask is restored." ! 228: ! 229: * ! 230: ! 231: * BUG?: This unmasking could unmask a pending signal which we will not ! 232: ! 233: * see this time around (if the signal number is less than i) and which ! 234: ! 235: * was not pending when we started; should we detect this condition and ! 236: ! 237: * loop around for a second try? POSIX only guarantees delivery of ! 238: ! 239: * one signal per kernel entry, so this shouldn't really be a problem. ! 240: ! 241: */ ! 242: ! 243: curproc->sigmask = omask; /* unmask signals */ ! 244: ! 245: } ! 246: ! 247: sigm = sigm << 1; ! 248: ! 249: } ! 250: ! 251: } ! 252: ! 253: } ! 254: ! 255: ! 256: ! 257: /* ! 258: ! 259: * raise: cause a signal to be raised in the current process ! 260: ! 261: */ ! 262: ! 263: ! 264: ! 265: void ! 266: ! 267: raise(sig) ! 268: ! 269: int sig; ! 270: ! 271: { ! 272: ! 273: post_sig(curproc, sig); ! 274: ! 275: check_sigs(); ! 276: ! 277: } ! 278: ! 279: ! 280: ! 281: #ifdef EXCEPTION_SIGS ! 282: ! 283: /* exception numbers corresponding to signals */ ! 284: ! 285: char excep_num[NSIG] = ! 286: ! 287: { 0, 0, 0, 0, ! 288: ! 289: 4, /* SIGILL == illegal instruction */ ! 290: ! 291: 9, /* SIGTRAP == trace trap */ ! 292: ! 293: 4, /* pretend SIGABRT is also illegal instruction */ ! 294: ! 295: 8, /* SIGPRIV == privileged instruction exception */ ! 296: ! 297: 5, /* SIGFPE == divide by zero */ ! 298: ! 299: 0, 2, /* SIGBUS == bus error */ ! 300: ! 301: 3 /* SIGSEGV == address error */ ! 302: ! 303: /* everything else gets zeros */ ! 304: ! 305: }; ! 306: ! 307: ! 308: ! 309: /* a "0" means we don't print a message when it happens -- typically the ! 310: ! 311: user is expecting a synchronous signal, so we don't need to report it ! 312: ! 313: */ ! 314: ! 315: ! 316: ! 317: const char *signames[NSIG] = { 0, ! 318: ! 319: 0, 0, 0, "ILLEGAL INSTRUCTION", "TRACE TRAP", ! 320: ! 321: 0, "PRIVILEGE VIOLATION", "DIVISION BY ZERO", 0, "BUS ERROR", ! 322: ! 323: "ADDRESS ERROR", "BAD SYSTEM CALL", 0, 0, 0, ! 324: ! 325: 0, 0, 0, 0, 0, ! 326: ! 327: 0, 0, 0, "CPU TIME EXHAUSTED", "FILE TOO BIG", ! 328: ! 329: 0, 0, 0, 0, 0 ! 330: ! 331: }; ! 332: ! 333: ! 334: ! 335: /* ! 336: ! 337: * replaces the TOS "show bombs" routine: for now, print the name of the ! 338: ! 339: * interrupt on the console, and save info on the crash in the appropriate ! 340: ! 341: * system area ! 342: ! 343: */ ! 344: ! 345: ! 346: ! 347: void ! 348: ! 349: bombs(sig) ! 350: ! 351: int sig; ! 352: ! 353: { ! 354: ! 355: long *procinfo = (long *)0x380L; ! 356: ! 357: int i; ! 358: ! 359: CONTEXT *crash; ! 360: ! 361: ! 362: ! 363: if (signames[sig]) { ! 364: ! 365: ALERT("%s: User PC=%lx (basepage=%lx)", ! 366: ! 367: signames[sig], ! 368: ! 369: curproc->ctxt[SYSCALL].pc, curproc->base); ! 370: ! 371: ! 372: ! 373: /* save the processor state at crash time */ ! 374: ! 375: /* assumes that "crash time" is the context curproc->ctxt[SYSCALL] */ ! 376: ! 377: /* BUG: this is not true if the crash happened in the kernel; in the ! 378: ! 379: * latter case, the crash context wasn't saved anywhere. ! 380: ! 381: */ ! 382: ! 383: crash = &curproc->ctxt[SYSCALL]; ! 384: ! 385: *procinfo++ = 0x12345678; /* magic flag for valid info */ ! 386: ! 387: for (i = 0; i < 15; i++) ! 388: ! 389: *procinfo++ = crash->regs[i]; ! 390: ! 391: *procinfo++ = crash->ssp; ! 392: ! 393: *procinfo++ = ((long)excep_num[sig]) << 24L; ! 394: ! 395: *procinfo++ = crash->usp; ! 396: ! 397: ! 398: ! 399: /* we're also supposed to save some info from the supervisor stack. it's not ! 400: ! 401: * clear what we should do for MiNT, since most of the stuff that used to be ! 402: ! 403: * on the stack has been put in the CONTXT struct. Moreover, we don't want ! 404: ! 405: * to crash because of an attempt to access illegal memory. Hence, we do ! 406: ! 407: * nothing here... ! 408: ! 409: */ ! 410: ! 411: } ! 412: ! 413: } ! 414: ! 415: #endif ! 416: ! 417: ! 418: ! 419: /* ! 420: ! 421: * handle_sig: do whatever is appropriate to handle a signal ! 422: ! 423: */ ! 424: ! 425: ! 426: ! 427: static long unwound_stack = 0; ! 428: ! 429: ! 430: ! 431: void ! 432: ! 433: handle_sig(sig) ! 434: ! 435: int sig; ! 436: ! 437: { ! 438: ! 439: long oldstack, newstack; ! 440: ! 441: long *stack; ! 442: ! 443: CONTEXT *call, oldsysctxt, newcurrent; ! 444: ! 445: extern void sig_return(); ! 446: ! 447: ! 448: ! 449: if (curproc->sighandle[sig] == SIG_IGN) ! 450: ! 451: return; ! 452: ! 453: else if (curproc->sighandle[sig] == SIG_DFL) { ! 454: ! 455: _default: ! 456: ! 457: switch(sig) { ! 458: ! 459: #if 0 ! 460: ! 461: /* Note: SIGNULL is filtered out in dossig.c and is never actually ! 462: ! 463: * delivered (its only purpose for the user is to test for the existence of ! 464: ! 465: * a process, it isn't a real signal). The kernel uses SIGNULL ! 466: ! 467: * internally, but all such code does the signal handling "by hand" ! 468: ! 469: * and so no default handling is necessary. ! 470: ! 471: */ ! 472: ! 473: case SIGNULL: ! 474: ! 475: #endif ! 476: ! 477: case SIGWINCH: ! 478: ! 479: case SIGCHLD: ! 480: ! 481: return; /* do nothing */ ! 482: ! 483: case SIGSTOP: ! 484: ! 485: case SIGTSTP: ! 486: ! 487: case SIGTTIN: ! 488: ! 489: case SIGTTOU: ! 490: ! 491: stop(sig); ! 492: ! 493: return; ! 494: ! 495: case SIGCONT: ! 496: ! 497: curproc->sigpending &= ~STOPSIGS; ! 498: ! 499: return; ! 500: ! 501: ! 502: ! 503: /* here are the fatal signals. for SIGINT, we use p_term() so that ! 504: ! 505: * TOS programs that catch ^C via the vector at 0x400 will work. for ! 506: ! 507: * other signals (especially SIGKILL) we don't want that to happen; ! 508: ! 509: * TOS programs aren't prepared to deal with signals. ! 510: ! 511: */ ! 512: ! 513: case SIGINT: /* ^C */ ! 514: ! 515: if (curproc->domain == DOM_TOS) { ! 516: ! 517: curproc->sigmask &= ~(1L<<SIGINT); ! 518: ! 519: p_term(-32); ! 520: ! 521: return; ! 522: ! 523: } ! 524: ! 525: /* otherwise, fall through */ ! 526: ! 527: default: ! 528: ! 529: #ifdef EXCEPTION_SIGS ! 530: ! 531: bombs(sig); /* tell the user what happened */ ! 532: ! 533: #endif ! 534: ! 535: terminate(sig << 8, ZOMBIE_Q); ! 536: ! 537: } ! 538: ! 539: } ! 540: ! 541: else { /* user wants to handle it himself */ ! 542: ! 543: ! 544: ! 545: /* another kludge: there is one case in which the p_sigreturn mechanism ! 546: ! 547: * is invoked by the kernel, namely when the user calls Supexec() ! 548: ! 549: * or when s/he installs a handler for the GEMDOS terminate vector (#0x102) ! 550: ! 551: * and the program terminates. MiNT fakes the call to user code with ! 552: ! 553: * signal 0 (SIGNULL); programs that longjmp out of the user function ! 554: ! 555: * and are later sent back to it again (e.g. if ^C keeps getting pressed ! 556: ! 557: * and a terminate vector has been installed) will grow the stack without ! 558: ! 559: * bound unless we watch for this case. ! 560: ! 561: * ! 562: ! 563: * Solution (sort of): whenever Pterm() is called, we unwind the ! 564: ! 565: * stack; otherwise, we let it grow, so that nested Supexec() ! 566: ! 567: * calls work. ! 568: ! 569: * ! 570: ! 571: * Note that SIGNULL is thrown away when sent by user processes, ! 572: ! 573: * and the user can't mask it (it's UNMASKABLE), so there is ! 574: ! 575: * is no possibility of confusion with anything the user does. ! 576: ! 577: */ ! 578: ! 579: if (sig == 0) { ! 580: ! 581: /* p_term() sets sigmask to let us know to do Psigreturn */ ! 582: ! 583: if (curproc->sigmask & 1L) { ! 584: ! 585: p_sigreturn(); ! 586: ! 587: curproc->sigmask &= ~1L; ! 588: ! 589: } else { ! 590: ! 591: unwound_stack = 0; ! 592: ! 593: } ! 594: ! 595: } ! 596: ! 597: ! 598: ! 599: call = &curproc->ctxt[SYSCALL]; ! 600: ! 601: /* ! 602: ! 603: * what we do is build two fake stack frames; the bottom one is ! 604: ! 605: * for a call to the user function, with (long)parameter being the ! 606: ! 607: * signal number; the top one is for sig_return. ! 608: ! 609: * When the user function returns, it returns to sig_return, which ! 610: ! 611: * calls into the kernel to restore the context in prev_ctxt ! 612: ! 613: * (thus putting us back here). We can then continue on our way. ! 614: ! 615: */ ! 616: ! 617: ! 618: ! 619: /* set a new system stack, with a bit of buffer space */ ! 620: ! 621: oldstack = curproc->sysstack; ! 622: ! 623: newstack = ((long) ( (&newcurrent) - 3 )) - 12; ! 624: ! 625: ! 626: ! 627: if (newstack < (long)curproc->stack + ISTKSIZE + 256) { ! 628: ! 629: ALERT("stack overflow"); ! 630: ! 631: goto _default; ! 632: ! 633: } ! 634: ! 635: else if ((long) curproc->stack + STKSIZE < newstack) { ! 636: ! 637: FATAL("system stack not in proc structure"); ! 638: ! 639: } ! 640: ! 641: ! 642: ! 643: /* unwound_stack is set by p_sigreturn() */ ! 644: ! 645: if (sig == 0 && unwound_stack) ! 646: ! 647: curproc->sysstack = unwound_stack; ! 648: ! 649: else ! 650: ! 651: curproc->sysstack = newstack; ! 652: ! 653: oldsysctxt = *call; ! 654: ! 655: stack = (long *)(call->sr & 0x2000 ? call->ssp : ! 656: ! 657: call->usp); ! 658: ! 659: /* ! 660: ! 661: Hmmm... here's another potential problem for the signal 0 terminate ! 662: ! 663: vector: if the program keeps returning back to user mode without ! 664: ! 665: worrying about the supervisor stack, we'll eventually overflow it. ! 666: ! 667: However, if the program is in supervisor mode itself, then we don't ! 668: ! 669: want to stomp on its stack. Temporary solution: ignore the problem, ! 670: ! 671: the stack's only growing 8 bytes at a time. ! 672: ! 673: */ ! 674: ! 675: *(--stack) = (long)sig; ! 676: ! 677: *(--stack) = (long)sig_return; ! 678: ! 679: if (call->sr & 0x2000) ! 680: ! 681: call->ssp = ((long) stack); ! 682: ! 683: else ! 684: ! 685: call->usp = ((long) stack); ! 686: ! 687: call->pc = (long) curproc->sighandle[sig]; ! 688: ! 689: ! 690: ! 691: ((long *)curproc->sysstack)[1] = FRAME_MAGIC; ! 692: ! 693: ((long *)curproc->sysstack)[2] = oldstack; ! 694: ! 695: ((long *)curproc->sysstack)[3] = sig; ! 696: ! 697: ! 698: ! 699: if (save_context(&newcurrent) == 0 ) { ! 700: ! 701: /* ! 702: ! 703: * go do the signal; eventually, we'll restore this context (unless the ! 704: ! 705: * user longjmp'd out of his signal handler). while the user is handling ! 706: ! 707: * the signal, it's masked out to prevent race conditions. p_sigreturn() ! 708: ! 709: * will unmask it for us when the user is finished. ! 710: ! 711: */ ! 712: ! 713: newcurrent.regs[0] = CTXT_MAGIC; ! 714: ! 715: /* set D0 so next return is different */ ! 716: ! 717: assert(curproc->magic == CTXT_MAGIC); ! 718: ! 719: leave_kernel(); ! 720: ! 721: restore_context(call); ! 722: ! 723: } ! 724: ! 725: /* ! 726: ! 727: * OK, we get here from p_sigreturn, via the user returning from ! 728: ! 729: * the handler to sig_return. Restoring the stack and unmasking the ! 730: ! 731: * signal have been done already for us by p_sigreturn. ! 732: ! 733: * We should just restore the old system call context ! 734: ! 735: * and continue with whatever it was we were doing. ! 736: ! 737: */ ! 738: ! 739: TRACE("done handling signal"); ! 740: ! 741: curproc->ctxt[SYSCALL] = oldsysctxt; ! 742: ! 743: assert(curproc->magic == CTXT_MAGIC); ! 744: ! 745: } ! 746: ! 747: } ! 748: ! 749: ! 750: ! 751: /* ! 752: ! 753: * the p_sigreturn system call ! 754: ! 755: * When called by the user from inside a signal handler, it indicates a ! 756: ! 757: * desire to restore the old stack frame prior to a longjmp() out of ! 758: ! 759: * the handler. ! 760: ! 761: * When called from the sig_return module, it indicates that the user ! 762: ! 763: * is finished a handler, and we should not only restore the stack ! 764: ! 765: * frame but also the old context we were working in (which is on the ! 766: ! 767: * system call stack -- see handle_sig). ! 768: ! 769: * The "valid_return" variable is 0 in the first case, 1 in the second. ! 770: ! 771: */ ! 772: ! 773: ! 774: ! 775: short valid_return; ! 776: ! 777: ! 778: ! 779: long ! 780: ! 781: p_sigreturn() ! 782: ! 783: { ! 784: ! 785: CONTEXT *oldctxt; ! 786: ! 787: long *frame; ! 788: ! 789: long sig; ! 790: ! 791: ! 792: ! 793: unwound_stack = 0; ! 794: ! 795: top: ! 796: ! 797: frame = (long *)curproc->sysstack; ! 798: ! 799: frame++; /* frame should point at FRAME_MAGIC, now */ ! 800: ! 801: sig = frame[2]; ! 802: ! 803: if (*frame != FRAME_MAGIC || (sig < 0) || (sig >= NSIG)) { ! 804: ! 805: FATAL("Psigreturn: system stack corrupted"); ! 806: ! 807: } ! 808: ! 809: if (frame[1] == 0) { ! 810: ! 811: DEBUG("Psigreturn: frame at %lx points to 0", frame-1); ! 812: ! 813: return 0; ! 814: ! 815: } ! 816: ! 817: unwound_stack = curproc->sysstack; ! 818: ! 819: TRACE("Psigreturn(%d)", (int)sig); ! 820: ! 821: ! 822: ! 823: curproc->sysstack = frame[1]; /* restore frame */ ! 824: ! 825: curproc->sigmask &= ~(1L<<sig); /* unblock signal */ ! 826: ! 827: ! 828: ! 829: if (!valid_return) { ! 830: ! 831: /* here, the user is telling us that a longjmp out of a signal handler is ! 832: ! 833: * about to occur; so we should unwind *all* the signal frames ! 834: ! 835: */ ! 836: ! 837: goto top; ! 838: ! 839: } ! 840: ! 841: else { ! 842: ! 843: valid_return = 0; ! 844: ! 845: oldctxt = ((CONTEXT *)(&frame[2])) + 3; ! 846: ! 847: if (oldctxt->regs[0] != CTXT_MAGIC) { ! 848: ! 849: FATAL("p_sigreturn: corrupted context"); ! 850: ! 851: } ! 852: ! 853: assert(curproc->magic == CTXT_MAGIC); ! 854: ! 855: restore_context(oldctxt); ! 856: ! 857: return 0; /* dummy -- this isn't reached */ ! 858: ! 859: } ! 860: ! 861: } ! 862: ! 863: ! 864: ! 865: /* ! 866: ! 867: * stop a process because of signal "sig" ! 868: ! 869: */ ! 870: ! 871: ! 872: ! 873: void ! 874: ! 875: stop(sig) ! 876: ! 877: int sig; ! 878: ! 879: { ! 880: ! 881: unsigned int code; ! 882: ! 883: unsigned long oldmask; ! 884: ! 885: PROC *p; ! 886: ! 887: ! 888: ! 889: code = sig << 8; ! 890: ! 891: ! 892: ! 893: if (curproc->pid == 0) { ! 894: ! 895: ALERT("attempt to stop MiNT"); ! 896: ! 897: return; ! 898: ! 899: } ! 900: ! 901: ! 902: ! 903: /* notify parent */ ! 904: ! 905: p = pid2proc(curproc->ppid); ! 906: ! 907: if (p && !(p->sigflags[SIGCHLD] & SA_NOCLDSTOP)) { ! 908: ! 909: post_sig(p, SIGCHLD); ! 910: ! 911: } ! 912: ! 913: ! 914: ! 915: oldmask = curproc->sigmask; ! 916: ! 917: ! 918: ! 919: /* mask out most signals */ ! 920: ! 921: curproc->sigmask |= ~(UNMASKABLE | SIGTERM); ! 922: ! 923: ! 924: ! 925: /* sleep until someone signals us awake */ ! 926: ! 927: sleep(STOP_Q, (long) code | 0177); ! 928: ! 929: ! 930: ! 931: /* when we wake up, restore the signal mask */ ! 932: ! 933: curproc->sigmask = oldmask; ! 934: ! 935: ! 936: ! 937: /* and discard any signals that would cause us to stop again */ ! 938: ! 939: curproc->sigpending &= ~STOPSIGS; ! 940: ! 941: } ! 942: ! 943: ! 944: ! 945: /* ! 946: ! 947: * interrupt handlers to raise SIGBUS, SIGSEGV, etc. Note that for ! 948: ! 949: * really fatal errors we reset the handler to SIG_DFL, so that ! 950: ! 951: * a second such error kills us ! 952: ! 953: */ ! 954: ! 955: ! 956: ! 957: void ! 958: ! 959: exception(sig) ! 960: ! 961: int sig; ! 962: ! 963: { ! 964: ! 965: curproc->sighandle[sig] = SIG_DFL; ! 966: ! 967: raise(sig); ! 968: ! 969: } ! 970: ! 971: ! 972: ! 973: void ! 974: ! 975: sigbus() ! 976: ! 977: { ! 978: ! 979: exception(SIGBUS); ! 980: ! 981: } ! 982: ! 983: ! 984: ! 985: void ! 986: ! 987: sigaddr() ! 988: ! 989: { ! 990: ! 991: exception(SIGSEGV); ! 992: ! 993: } ! 994: ! 995: ! 996: ! 997: void ! 998: ! 999: sigill() ! 1000: ! 1001: { ! 1002: ! 1003: exception(SIGILL); ! 1004: ! 1005: } ! 1006: ! 1007: ! 1008: ! 1009: void ! 1010: ! 1011: sigpriv() ! 1012: ! 1013: { ! 1014: ! 1015: raise(SIGPRIV); ! 1016: ! 1017: } ! 1018: ! 1019: ! 1020: ! 1021: void ! 1022: ! 1023: sigfpe() ! 1024: ! 1025: { ! 1026: ! 1027: raise(SIGFPE); ! 1028: ! 1029: } ! 1030: ! 1031: ! 1032: ! 1033: void ! 1034: ! 1035: sigtrap() ! 1036: ! 1037: { ! 1038: ! 1039: raise(SIGTRAP); ! 1040: ! 1041: } ! 1042:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.