home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------*
- * filename - signal.c *
- * *
- * function(s) signal(), raise() *
- * usage *
- * Function prototypes are in SIGNAL.H *
- * *
- * oldcatcher = signal(sig, newcatcher); *
- * void (*oldcatcher)(int) Ptr to previous signal catcher *
- * int sig Signal # to install catcher for *
- * void (*newcatcher)(int) Address of new signal catcher *
- * *
- * rc = raise(sig); *
- * int rc Return code, success=0, error=!0 *
- * int sig Signal number to raise *
- *----------------------------------------------------------------------*/
-
- /*[]------------------------------------------------------------[]*/
- /*| |*/
- /*| Turbo C Run Time Library - Version 3.0 |*/
- /*| |*/
- /*| |*/
- /*| Copyright (c) 1987,1988,1990 by Borland International |*/
- /*| All Rights Reserved. |*/
- /*| |*/
- /*[]------------------------------------------------------------[]*/
-
- #include <process.h> /* Get definition for _exit() */
- #include <errno.h>
- #include <dos.h>
- #include <float.h> /* Get definition for FPE_nn SEGV_nn ILL_nn types */
- #include <signal.h>
-
- #pragma warn -pro
-
- #undef ANSI_CONFORMING
- #undef BOUNDS_TRAP
- #undef ILLEGALOP_TRAP
-
- #define ANSI_CONFORMING
- #define BOUNDS_TRAP
- #define ILLEGALOP_TRAP
-
- /*----------------------------- NOTE ! ---------------------------------
-
- Normal ANSI operation resets ALL signals, Microsoft(R) doesn't reset SIGFPE.
- Remove ANSI_CONFORMING define for MS style SIGFPE operation.
- Remove BOUNDS_TRAP define disables SIGSEGV bound violations.
- Remove ILLEGALOP_TRAP define disables SIGILL illegal op violations.
- Default configuration is ANSI conforming SIGFPE operation.
- Default configuration enables SIGSEGV to detect BOUND violations.
- Default configuration enables SIGSILL to detect illegal operations.
-
- ----------------------------- NOTE ! -------------------------------*/
-
- typedef void _Cdecl (* CatcherPTR)();
-
- typedef unsigned char UCHAR;
-
- static void interrupt Int0Catcher(unsigned);
- static void interrupt Int4Catcher(unsigned);
-
- #ifdef BOUNDS_TRAP
- typedef unsigned U;
-
- static void interrupt (*BiosPrtScr)(); /* Old BIOS Int 5 vector */
-
- static char GotInt5 = 0;
- static void interrupt Int5Catcher(U, U, U, U, U, U, U, U, U, U, U, U);
- #endif
-
- #ifdef ILLEGALOP_TRAP
- static void interrupt Int6Catcher(unsigned);
- #endif
-
- static void interrupt Int23Catcher(void);
- static int GetIndex(int);
-
- CatcherPTR signal(int, CatcherPTR);
- int raise(int);
-
- extern CatcherPTR (*__SignalPtr)();
- static char SignalPtrSet=0;
-
- #define BogusSignal -1 /* Flags a bogus signal type */
-
- /*+----------------------------------------------------------------------+
- | Signal Dispatch, Index Generator & Signal Default Tables |
- | *** Note : Ordering of constants in these tables MUST match |
- +----------------------------------------------------------------------+*/
- #define SIGINT_INDEX 0
- #define SIGILL_INDEX 1
- #define SIGFPE_INDEX 2
- #define SIGSEGV_INDEX 3
- #define SIGTERM_INDEX 4
- #define SIGABRT_INDEX 5
-
- static CatcherPTR Dispatch[] =
- {
- (CatcherPTR)SIG_DFL, /* SIGINT (2) */
- (CatcherPTR)SIG_DFL, /* SIGILL (4) */
- (CatcherPTR)SIG_DFL, /* SIGFPE (8) */
- (CatcherPTR)SIG_DFL, /* SIGSEGV (11)*/
- (CatcherPTR)SIG_DFL, /* SIGTERM (15)*/
- (CatcherPTR)SIG_DFL /* SIGABRT (22)*/
- };
-
- static const UCHAR IxGen[] =
- {
- /* NEVER! change the ordering of these */
-
- SIGINT, /* Index 0 */
- SIGILL, /* Index 1 */
- SIGFPE, /* Index 2 */
- SIGSEGV, /* Index 3 */
- SIGTERM, /* Index 4 */
- SIGABRT /* Index 5 */
- };
-
- /*+----------------------------------------------------------------------+
- | Table of values for EXPLICITLY raised signals |
- | For SIGILL, SIGFPE & SIGSEGV explicit generation may have special |
- | meaning to applications. For the others use dummy 0's. |
- +----------------------------------------------------------------------+*/
- static const UCHAR ExplicitVal[] =
- {
- 0, /* SIGINT */
- ILL_EXPLICITGEN, /* SIGILL */
- FPE_EXPLICITGEN, /* SIGFPE */
- SEGV_EXPLICITGEN, /* SIGSEGV */
- 0, /* SIGTERM */
- 0 /* SIGABRT */
- };
-
-
- #ifdef BOUNDS_TRAP
- /*+----------------------------------------------------------------------+
- | Int5Catcher() - Int 5 catcher for detecting BOUND violations on |
- | 80188/80186/80286/80386 & NEC V Series processors. |
- | |
- | This routine is installed when any call to signal with SIGSEGV is |
- | specified. THIS ROUTINE REMAINS INSTALLED AS THE INT 5 HANDLER FOR |
- | THE REST OF THE PROGRAM DURATION. |
- | When activated this routine checks where the interrupt came from. |
- | If the return CS:IP points to a BOUND instruction it is assumed the |
- | bounds check done by that instruction failed. If the return CS:IP |
- | points to something other than a BOUND instruction then we assume |
- | that the user wanted to do a BIOS Prt-screen. We call the old BIOS |
- | handler in this case. |
- | |
- +----------------------------------------------------------------------+
- | |
- | There are some EXTREMELY rare cases where this scheme fails. |
- | One is when somebody does the following instruction sequence in |
- | their code (which I doubt has EVER been done ANYWHERE by anybody): |
- | |
- | INT 5 ; Do a prt-screen |
- | BOUND ... ; Check bounds |
- | |
- | Here the return CS:IP on the interrupt handlers stack DOES point to |
- | a BOUND instruction, but one that hasn't been executed yet! We |
- | might think the heuristic "if it's a BOUND instruction proceeded by |
- | an INT 5 then it's not a REAL violation." would serve us well here, |
- | but alas it doesn't because the following situation can exist. |
- | A program jumps to a BOUND instruction that is preceded by some |
- | DATA that happens to LOOK like an INT 5 instruction by accident ex: |
- | |
- | JMP DOBOUND |
- | SOMEDATA DB 0CDH, 5 ; Data that looks like an INT 5 |
- | DOBOUND : BOUND ... ; Check bounds |
- | |
- | In the above example the heuristic fails us completely. |
- | |
- | Thus, we're left solidly impaled on the horns of a dilemma. Do we |
- | recognize a BOUND violation where none exists, or do we ignore a |
- | possibly genuine BOUND violation? Hmm... if only Prt-Scr wasn't on |
- | INT 5. |
- | |
- | So... what do we do here, eh? |
- | For the sake of expedience we'll punt. A quick look at the |
- | instruction pointed to by the return CS:IP will be done. If we |
- | see a BOUND instruction we call the handler. |
- | |
- | Avoiding these situations amounts to putting a NOP before |
- | any BOUND instruction that is in one of these rare situations. |
- | Not exactly a tough a work around! |
- +----------------------------------------------------------------------+*/
-
- #pragma argsused
- static void interrupt Int5Catcher(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags)
- unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;
- {
- register CatcherPTR action;
-
- #define BND_OPCODE 0x62
-
- if (*(*((UCHAR far * far *)((unsigned far *)&ip))) != BND_OPCODE)
- (*BiosPrtScr)(); // Hand off Prt-Sc request
- else // Process BOUND violation
- if ((action = Dispatch[3]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _exit(1);
- Dispatch[3] = SIG_DFL; // Reset signal
- (*action)(SIGSEGV, SEGV_BOUND, &bp); // Call handler
- }
- }
- #endif /*** BOUNDS_TRAP ***/
-
- #ifdef ILLEGALOP_TRAP
- /*+----------------------------------------------------------------------+
- | Int6Catcher() - Int 6 catcher for detecting illegal operations on |
- | 80188/80186/80286/80386 & NEC V Series processors. |
- | |
- | This routine is installed when any call to signal with SIGILL is |
- | specified. THIS ROUTINE REMAINS INSTALLED AS THE INT 6 HANDLER FOR |
- | THE REST OF THE PROGRAM DURATION. |
- +----------------------------------------------------------------------+*/
- static void interrupt Int6Catcher(bp)
- unsigned bp;
- {
- register CatcherPTR action;
-
- if ((action = Dispatch[1]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _exit(1);
- Dispatch[1] = SIG_DFL; /* Reset signal */
- (*action)(SIGILL, ILL_EXECUTION, &bp); /* Call handler */
- }
- }
- #endif /*** ILLEGALOP_TRAP ***/
-
- /*+----------------------------------------------------------------------+
- | Int0Catcher() - Integer divide by zero exception handler. |
- | This routine is part of the extensions to SIGFPE |
- | handling to include integer arithmetic exceptions. |
- | ANSI doesn't restrict SIGFPE to just floats! |
- | |
- | This routine is installed when any call to signal with SIGFPE is |
- | specified. When activated this routine does the equivalent of |
- | raise(SIGFPE, ...). THIS ROUTINE REMAINS INSTALLED AS THE DIVIDE |
- | BY ZERO HANDLER FOR THE REST OF THE PROGRAM DURATION. If the |
- | application never installs a SIGFPE handler then the default action |
- | setup by the 'C' startup code will be used. If the app steals |
- | INT 0 back from us the only way the INT 0 SIGFPE code can be |
- | reactivated is signal(SIGFPE, ....) again! |
- +----------------------------------------------------------------------+*/
- static void interrupt Int0Catcher(bp)
- unsigned bp;
- {
- register CatcherPTR action;
-
- if ((action = Dispatch[2]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _exit(1);
- #ifdef ANSI_CONFORMING
- Dispatch[2] = SIG_DFL; /* Reset signal */
- #endif
- (*action)(SIGFPE, FPE_INTDIV0, &bp); /* Call handler */
- }
- }
-
- /*+----------------------------------------------------------------------+
- | Int4Catcher() - Interrupt on overflow handler. |
- | This routine is part of the extensions to SIGFPE |
- | handling to include integer arithmetic exceptions. |
- | ANSI doesn't restrict SIGFPE to just floats! |
- | |
- | This routine is installed when any call to signal with SIGFPE is |
- | specified. When activated this routine does the equivalent of |
- | raise(SIGFPE, ...). THIS ROUTINE REMAINS INSTALLED AS THE Int 4 |
- | HANDLER FOR THE REST OF THE PROGRAM DURATION. If the |
- | application never installs a SIGFPE handler then the default actions|
- | apply. If the app steals INT 4 back from us the only way the INT 4 |
- | SIGFPE code can be reactivated is call signal(SIGFPE, ....) again! |
- +----------------------------------------------------------------------+*/
- static void interrupt Int4Catcher(bp)
- unsigned bp;
- {
- register CatcherPTR action;
-
- if ((action = Dispatch[2]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _exit(1);
- #ifdef ANSI_CONFORMING
- Dispatch[2] = SIG_DFL; /* Reset signal */
- #endif
- (*action)(SIGFPE, FPE_INTOVFLOW, &bp); /* Call handler */
- }
- }
-
- /*+----------------------------------------------------------------------+
- | Routine intercepts int 23H and routes to user handler |
- +----------------------------------------------------------------------+*/
- static void interrupt Int23Catcher()
- {
- register CatcherPTR action;
-
- if ((action = Dispatch[0]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _exit(1);
- Dispatch[0] = SIG_DFL; /* Reset signal */
- (*action)(SIGINT); /* Call handler */
- }
- }
-
- /*+----------------------------------------------------------------------+
- | GetIndex() Get a DispatchTable index for specified signal type |
- +----------------------------------------------------------------------+*/
- static int GetIndex(int SigType)
- {
- register int i;
-
- for (i = 0; i < sizeof(IxGen); i++)
- if (IxGen[i] == SigType)
- return i;
- return -1;
- }
-
- /*+----------------------------------------------------------------------+
- | Signal() - Install new signal catchers |
- +----------------------------------------------------------------------+*/
- void (* _Cdecl signal(sig, New))(int)
- int sig;
- CatcherPTR New;
-
- /* CatcherPTR signal(register int sig, CatcherPTR New) */
- {
- register int Index;
- CatcherPTR OldVal;
-
- if (!SignalPtrSet) /* let _fperr() know where signal is */
- {
- __SignalPtr = signal;
- SignalPtrSet = 1;
- }
-
- #define DISPATCH_SETTING New
-
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Get an index for the signal type, if its bad exit.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- if ((Index = GetIndex(sig)) == BogusSignal)
- {
- errno = EINVAL; /* Bogus 'sig' parm was passed */
- return SIG_ERR;
- }
-
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Install handler (SIGINT, SIGFPE & SIGSEGV are special)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- OldVal = Dispatch[Index]; /* Save the OLD handler */
- Dispatch[Index] = DISPATCH_SETTING; /* Set the NEW handler */
- if (sig == SIGINT)
- {
- setvect(0x23, Int23Catcher); /* Take INT 23H */
- }
- else if (sig == SIGFPE)
- {
- setvect(0, Int0Catcher); /* Take INT 0 */
- setvect(4, Int4Catcher); /* Take INT 4 */
- }
- #ifdef BOUNDS_TRAP
- else if (sig == SIGSEGV)
- if (!GotInt5)
- {
- BiosPrtScr = getvect(5); /* Save old INT 5 */
- setvect(5, Int5Catcher); /* Take INT 5 */
- GotInt5 = 1;
- } else;
- #endif
- #ifdef ILLEGALOP_TRAP
- else if (sig == SIGILL)
- {
- setvect(6, Int6Catcher); /* Take INT 6 */
- }
- #endif
-
- return OldVal;
- }
-
- /*+----------------------------------------------------------------------+
- | raise() - generate a software 'event' |
- +----------------------------------------------------------------------+*/
- int raise(int SigType)
- {
- int Index;
- CatcherPTR action;
-
- if ((Index = GetIndex(SigType)) == BogusSignal)
- return 1;
-
- if ((action = Dispatch[Index]) != SIG_IGN)
- if (action == SIG_DFL)
- switch (SigType)
- {
- case SIGABRT :
- _exit(3);
- case SIGINT :
- geninterrupt( 0x23 );
- break;
- case SIGILL :
- case SIGSEGV :
- case SIGTERM :
- case SIGFPE :
- default :
- _exit(1);
- }
- else
- { /*
- Call user routine. Add optional parameter
- specifing that the signal was raised explicitly
- rather than asynchronously.
- */
- #ifdef ANSI_CONFORMING
- Dispatch[Index] = SIG_DFL; /* Always default (ANSI) */
- #else
- if (SigType != SIGFPE) /* Maybe default (MS) */
- Dispatch[Index] = SIG_DFL;
- #endif
- (*action)(SigType, ExplicitVal[Index]);
- }
- return 0;
- }
-
- #pragma warn .pro
-
-