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 *
- *----------------------------------------------------------------------*/
-
- /*
- * C/C++ Run Time Library - Version 5.0
- *
- * Copyright (c) 1987, 1992 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 <string.h>
- #include <signal.h>
-
- #if defined( _Windows )
- #include <_win.h>
- #endif
-
- #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 unsigned char UCHAR;
-
- #if defined( _Windows )
-
- #include <windows.h>
-
- extern void (far *_FPVector)();
-
- #else // not _Windows
-
- 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);
-
- #endif // _Windows
-
- _CatcherPTR _FARFUNC signal(int, _CatcherPTR);
- int _FARFUNC raise(int);
-
- #if !defined( _Windows )
- extern _CatcherPTR (*__SignalPtr)();
- static char SignalPtrSet=0;
- #endif
-
- #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)*/
- };
-
- #ifdef _BUILDRTLDLL
- static unsigned SavedDS[6] =
- {
- 0, /* SIGINT */
- 0, /* SIGILL */
- 0, /* SIGFPE */
- 0, /* SIGSEGV */
- 0, /* SIGTERM */
- 0 /* SIGABRT */
- };
- #endif
-
- 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 */
- };
-
-
- #if !defined( _Windows )
-
- #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 */
- }
- }
-
- #endif // !_Windows
-
-
- /*+----------------------------------------------------------------------+
- | 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;
- }
-
- #ifdef _Windows
-
- extern void far _fperr( void );
-
- #endif
-
- /*+----------------------------------------------------------------------+
- | Signal() - Install new signal catchers |
- +----------------------------------------------------------------------+*/
- _CatcherPTR _Cdecl _FARFUNC signal( int sig, _CatcherPTR New )
- //void _Cdecl _FARFUNC (* _Cdecl _FARFUNC signal( int sig, _CatcherPTR New))(int)
- {
- register int Index;
- _CatcherPTR OldVal;
- #if !defined( _Windows )
- if (!SignalPtrSet) /* let _fperr() know where signal is */
- {
- __SignalPtr = signal;
- SignalPtrSet = 1;
- }
- #endif // __SignalPtr not used under Windows
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 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] = New; /* Set the NEW handler */
- #ifdef _BUILDRTLDLL
- SavedDS[Index] = _SS;
- #endif
-
- #if !defined( _Windows )
- 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
-
- #endif // !_Windows
-
- return OldVal;
- }
-
- /*+----------------------------------------------------------------------+
- | raise() - generate a software 'event' |
- +----------------------------------------------------------------------+*/
-
- #if !defined( _Windows )
-
- static void default_action( int SigType )
- {
- switch (SigType)
- {
- case SIGABRT :
- _exit(3);
- case SIGINT :
- geninterrupt( 0x23 );
- break;
- case SIGILL :
- case SIGSEGV :
- case SIGTERM :
- case SIGFPE :
- default :
- _exit(1);
- }
- }
-
- #else
-
- #define FPE_DENORMAL 0x82
-
- #define FPE_UNEMULATED 0x87
- #define FPE_SQRTNEG 0x88
- #define FPE_STACKOVERFLOW 0x8a
- #define FPE_STACKUNDERFLOW 0x8b
-
- #undef FPE_EXPLICITGEN
- #define FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */
-
- #pragma argsused
-
- void _FpeDefault( int SubType )
- {
- static char fpMsg[] = "Floating Point: Square Root of Negative Number";
- #define DIFF_LOC fpMsg + 16
-
- switch( SubType )
- {
- case FPE_INVALID:
- strcpy( DIFF_LOC, "Invalid" );
- break;
- case FPE_DENORMAL:
- strcpy( DIFF_LOC, "DeNormal" );
- break;
- case FPE_ZERODIVIDE:
- strcpy( DIFF_LOC, "Divide by Zero" );
- break;
- case FPE_OVERFLOW:
- strcpy( DIFF_LOC, "Overflow" );
- break;
- case FPE_UNDERFLOW:
- strcpy( DIFF_LOC, "Underflow" );
- break;
- case FPE_INEXACT:
- strcpy( DIFF_LOC, "Inexact" );
- break;
- case FPE_UNEMULATED:
- strcpy( DIFF_LOC, "Unemulated" );
- break;
- case FPE_SQRTNEG: // no copy here: message is already right
- break;
- case FPE_STACKOVERFLOW:
- strcpy( DIFF_LOC, "Stack Overflow" );
- break;
- case FPE_STACKUNDERFLOW:
- strcpy( DIFF_LOC, "Stack Underflow" );
- break;
- case FPE_EXPLICITGEN:
- strcpy( DIFF_LOC, "Exception Raised" );
- break;
- }
- _errorExitBox( fpMsg, 3 );
- }
-
- static void default_action( int SigType )
- {
- switch (SigType)
- {
- case SIGABRT :
- _errorExitBox( "Program Aborted", 3 );
- break;
- case SIGINT :
- geninterrupt( 0x23 );
- break;
- case SIGILL :
- _errorExitBox( "Illegal Instruction", 1 );
- break;
- case SIGSEGV :
- _errorExitBox( "Segment Violation", 1 );
- break;
- case SIGFPE :
- _errorExitBox( "Floating Point Trap", 1 );
- break;
- case SIGTERM :
- _errorExitBox( "Program Terminated", 1 );
- break;
- default :
- _errorExitBox( "Abnormal Program Termination", 1 );
- break;
- }
- }
-
- #endif // !_Windows
-
- int _FARFUNC raise(int SigType)
- {
- int Index;
- _CatcherPTR action;
- #ifdef _BUILDRTLDLL
- unsigned LocalDS;
- #endif
-
- if ((Index = GetIndex(SigType)) == BogusSignal)
- return 1;
-
- if ((action = Dispatch[Index]) != SIG_IGN)
- if (action == SIG_DFL)
- #ifdef _Windows
- if( SigType == SIGFPE )
- _FpeDefault( FPE_EXPLICITGEN );
- else
- #endif
- default_action( SigType );
- 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
-
- #ifdef _BUILDRTLDLL
- LocalDS = _DS;
- _DS = SavedDS[Index];
- #endif
- (*action)(SigType, ExplicitVal[Index]);
- #ifdef _BUILDRTLDLL
- _DS = LocalDS;
- #endif
- }
- return 0;
- }
-
- #ifdef _Windows
-
- void _FARFUNC _FpeHandler(int subcode)
- {
- register _CatcherPTR action;
- #ifdef _BUILDRTLDLL
- unsigned LocalDS;
- #endif
-
- if ((action = Dispatch[2]) != SIG_IGN)
- {
- if ((action == SIG_DFL) || (action == SIG_ERR))
- _FpeDefault(subcode);
- #ifdef ANSI_CONFORMING
- Dispatch[2] = SIG_DFL; /* Reset signal */
- #endif
- #ifdef _BUILDRTLDLL
- LocalDS = _DS;
- _DS = SavedDS[2];
- #endif
- (*action)(SIGFPE, subcode); /* Call handler */
- #ifdef _BUILDRTLDLL
- _DS = LocalDS;
- #endif
- }
- }
-
- #endif // _Windows
-
- #pragma warn .pro
-