| #include "lock.h" |
| #include <stdio.h> |
| #include <signal.h> |
| #include <errno.h> |
| #include <windows.h> |
| |
| #define _lock(n) (0) |
| #define _unlock(n) (0) |
| #define MAX_TRIES 10 |
| |
| //void __cdecl _unlock(int); |
| static __p_sig_fn_t ctrlc_action = SIG_DFL; /* SIGINT */ |
| static __p_sig_fn_t ctrlbreak_action = SIG_DFL; /* SIGBREAK */ |
| static __p_sig_fn_t abort_action = SIG_DFL; /* SIGABRT */ |
| static __p_sig_fn_t term_action = SIG_DFL; /* SIGTERM */ |
| //static int ConsoleCtrlHandler_Installed = 0; |
| //extern void *g_hMainThread; |
| struct _XCPT_ACTION {
|
|
|
| /*
|
| * exception code or number. defined by the host OS.
|
| */
|
| unsigned long XcptNum;
|
|
|
| /*
|
| * signal code or number. defined by the C runtime.
|
| */
|
| int SignalNumber;
|
|
|
| /*
|
| * exception action code. either a special code or the address of
|
| * a handler function. always determines how the exception filter
|
| * should dispose of the exception.
|
| */
|
| __p_sig_fn_t XcptAction;
|
| }; |
| //extern struct _XCPT_ACTION _XcptActTab[]; |
| static struct _XCPT_ACTION _XcptActTab[] = { |
| |
| /* |
| * Exceptions corresponding to the same signal (e.g., SIGFPE) must be grouped |
| * together. |
| * |
| * XcptNum SigNumber XcptAction |
| * ------------------------------------------------------------------- |
| */ |
| { (unsigned long)STATUS_ACCESS_VIOLATION, SIGSEGV, SIG_DFL }, |
| |
| { (unsigned long)STATUS_ILLEGAL_INSTRUCTION, SIGILL, SIG_DFL }, |
| |
| { (unsigned long)STATUS_PRIVILEGED_INSTRUCTION, SIGILL, SIG_DFL }, |
| |
| /* { (unsigned long)STATUS_NONCONTINUABLE_EXCEPTION, NOSIG, SIG_DIE }, |
| */ |
| /* { (unsigned long)STATUS_INVALID_DISPOSITION, NOSIG, SIG_DIE }, |
| */ |
| { (unsigned long)STATUS_FLOAT_DENORMAL_OPERAND, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_DIVIDE_BY_ZERO, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_INEXACT_RESULT, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_INVALID_OPERATION, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_OVERFLOW, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_STACK_CHECK, SIGFPE, SIG_DFL }, |
| |
| { (unsigned long)STATUS_FLOAT_UNDERFLOW, SIGFPE, SIG_DFL }, |
| |
| /* { (unsigned long)STATUS_INTEGER_DIVIDE_BY_ZERO, NOSIG, SIG_DIE }, |
| */ |
| /* { (unsigned long)STATUS_STACK_OVERFLOW, NOSIG, SIG_DIE } |
| */ |
| }; |
| static int _XcptActTabCount; |
| static void * _pxcptinfoptrs = NULL; |
| |
| #if 0 |
| static unsigned long int GetCurrentProcessOfThread(void *hThread) |
| { |
| PBYTE pData; |
| pData = (PBYTE)((DWORD)hThread & 0x1FFFFFFC) + 0x80000000; // (struct _HDATA)pData |
| pData = *(PBYTE*)(pData + 0x18); // pData == (struct Thread)pvObj |
| pData = *(PBYTE*)(pData + 0xC); // pData == (struct Process)pProc |
| pData = *(PBYTE*)(pData + 0x8); // pData == (HANDLE)hProc |
| return (DWORD)pData; |
| } |
| |
| static unsigned long int ControlCHandler()
|
| {
|
| unsigned long int *Stack;
|
| CONTEXT ctx;
|
| int tries;
|
|
|
| for(tries=0;tries<MAX_TRIES;tries++)
|
| {
|
| Sleep(1);
|
|
|
| ctx.ContextFlags = CONTEXT_FULL;
|
|
|
| if( -1 == SuspendThread((void *)GetCurrentThreadId()))
|
| {
|
| continue;
|
| }
|
| if((GetCurrentProcessId() != GetCurrentProcessOfThread((void *)GetCurrentThreadId())) )
|
| {
|
| ResumeThread((void *)GetCurrentThreadId());
|
| continue;
|
| }
|
| if(!GetThreadContext((void *)GetCurrentThreadId(), &ctx))
|
| {
|
| ResumeThread((void *)GetCurrentThreadId());
|
| continue;
|
| }
|
| break;
|
| }
|
| if(tries == MAX_TRIES)
|
| {
|
| return 0;
|
| } |
|
|
| SetThreadContext((void *)GetCurrentThreadId(), &ctx);
|
| ResumeThread((void *)GetCurrentThreadId());
|
|
|
| return 1;
|
| } |
| |
| static int ctrlevent_capture(unsigned long int CtrlType) |
| { |
| |
| /* |
| * Identify the type of event and fetch the corresponding action |
| * description. |
| */ |
| |
| if((ctrlc_action != SIG_DFL) && (ctrlc_action != SIG_IGN) ) |
| { |
| _unlock(_SIGNAL_LOCK); |
| ControlCHandler(); |
| return 1; |
| } |
| |
| if ( ctrlc_action == SIG_DFL ) { |
| /* |
| * return false, indicating the event has NOT been handled |
| */ |
| _unlock(_SIGNAL_LOCK); |
| return 0; |
| } |
| |
| /* |
| * SIG_IGN - nothing special to do except release the lock |
| */ |
| _unlock(_SIGNAL_LOCK); |
| |
| /* |
| * Return true, indicating the event has been handled (which may |
| * mean it's being ignored) |
| */ |
| return 1; |
| } |
| #endif |
| |
| static struct _XCPT_ACTION * __cdecl siglookup(int sig) |
| { |
| struct _XCPT_ACTION *pxcptact = _XcptActTab; |
| |
| /* |
| * walk thru the _xcptactab table looking for the proper entry. note |
| * that in the case where more than one exception corresponds to the |
| * same signal, the first such instance in the table is the one |
| * returned. |
| */ |
| |
| while ( (pxcptact->SignalNumber != sig) && |
| (++pxcptact < _XcptActTab + _XcptActTabCount) ) ; |
| |
| |
| if ( (pxcptact < (_XcptActTab + _XcptActTabCount)) && |
| (pxcptact->SignalNumber == sig) ) |
| /* |
| * found a table entry corresponding to the signal |
| */ |
| return(pxcptact); |
| else |
| /* |
| * found no table entry corresponding to the signal |
| */ |
| return(NULL); |
| } |
| |
| __p_sig_fn_t signal(int sig, __p_sig_fn_t act){ |
| struct _XCPT_ACTION *pxcptact;
|
| __p_sig_fn_t oldsigact = 0;
|
|
|
| /*
|
| * Check for values of sigact supported on other platforms but not
|
| * on this one. Also, make sure sigact is not SIG_DIE
|
| */
|
| if ( (act == SIG_ACK) || (act == SIG_SGE) )
|
| goto sigreterror;
|
|
|
| /*
|
| * Take care of all signals which do not correspond to exceptions
|
| * in the host OS. Those are:
|
| *
|
| * SIGINT
|
| * SIGBREAK
|
| * SIGABRT
|
| * SIGTERM
|
| *
|
| */
|
| if ( (sig == SIGINT) || (sig == SIGBREAK) || (sig == SIGABRT)
|
| || (sig == SIGTERM) ) {
|
|
|
| _lock(_SIGNAL_LOCK);
|
|
|
| /*
|
| * if SIGINT or SIGBREAK, make sure the handler is installed
|
| * to capture ^C and ^Break events.
|
| */ |
| /*
|
| if ( ((sig == SIGINT) || (sig == SIGBREAK)) &&
|
| !ConsoleCtrlHandler_Installed )
|
| if ( SetConsoleCtrlHandler(ctrlevent_capture(NULL), 1) == 1 ) ConsoleCtrlHandler_Installed = 1;
|
| else {
|
| _unlock(_SIGNAL_LOCK);
|
| goto sigreterror;
|
| }
|
| */
|
| switch (sig) {
|
|
|
| case SIGINT:
|
| oldsigact = ctrlc_action;
|
| ctrlc_action = act;
|
| break;
|
|
|
| case SIGBREAK:
|
| oldsigact = ctrlbreak_action;
|
| ctrlbreak_action = act;
|
| break;
|
|
|
| case SIGABRT:
|
| oldsigact = abort_action;
|
| abort_action = act;
|
| break;
|
|
|
| case SIGTERM:
|
| oldsigact = term_action;
|
| term_action = act;
|
| break;
|
| }
|
|
|
| _unlock(_SIGNAL_LOCK);
|
| goto sigretok;
|
| }
|
|
|
| /*
|
| * If we reach here, SignalNumber is supposed to be one the signals which
|
| * correspond to exceptions in the host OS. Those are:
|
| *
|
| * SIGFPE
|
| * SIGILL
|
| * SIGSEGV
|
| */
|
|
|
| /*
|
| * Make sure SignalNumber is one of the remaining supported signals.
|
| */
|
| if ( (sig != SIGFPE) && (sig != SIGILL) && (sig != SIGSEGV) )
|
| goto sigreterror;
|
|
|
|
|
| /*
|
| * look up the proper entry in the exception-action table. note that
|
| * if several exceptions are mapped to the same signal, this returns
|
| * the pointer to first such entry in the exception action table. it
|
| * is assumed that the other entries immediately follow this one.
|
| */
|
| if ( (pxcptact = siglookup(sig)) == NULL )
|
| goto sigreterror;
|
|
|
| /*
|
| * SIGSEGV, SIGILL and SIGFPE all have more than one exception mapped
|
| * to them. the code below depends on the exceptions corresponding to
|
| * the same signal being grouped together in the exception-action
|
| * table.
|
| */
|
|
|
| /*
|
| * store old signal action code for return value
|
| */
|
| oldsigact = pxcptact->XcptAction;
|
|
|
| /*
|
| * loop through all entries corresponding to the
|
| * given signal and update the SigAction and XcptAction
|
| * fields as appropriate
|
| */
|
| while ( pxcptact->SignalNumber == sig ) {
|
| /*
|
| * take care of the SIG_IGN and SIG_DFL action
|
| * codes
|
| */
|
| pxcptact->XcptAction = act;
|
|
|
| /*
|
| * make sure we don't run off the end of the table
|
| */
|
| if ( ++pxcptact >= (_XcptActTab + _XcptActTabCount) )
|
| break;
|
| }
|
|
|
| sigretok:
|
| return(oldsigact);
|
|
|
| sigreterror:
|
| return(SIG_ERR); |
| } |
| |
| int raise(int sig) { |
| __p_sig_fn_t sigact; |
| __p_sig_fn_t *psigact; |
| PEXCEPTION_POINTERS oldpxcptinfoptrs; |
| |
| |
| switch (sig) { |
| |
| case SIGINT: |
| sigact = *(psigact = &ctrlc_action); |
| break; |
| |
| case SIGBREAK: |
| sigact = *(psigact = &ctrlbreak_action); |
| break; |
| |
| case SIGABRT: |
| sigact = *(psigact = &abort_action); |
| break; |
| |
| case SIGTERM: |
| sigact = *(psigact = &term_action); |
| break; |
| |
| case SIGFPE: |
| case SIGILL: |
| case SIGSEGV: |
| sigact = *(psigact = &(siglookup( sig )-> |
| XcptAction)); |
| break; |
| |
| default: |
| /* |
| * unsupported signal, return an error |
| */ |
| return (-1); |
| } |
| |
| |
| /* |
| * If the current action is SIG_IGN, just return |
| */ |
| if ( sigact == SIG_IGN ) { |
| return(0); |
| } |
| |
| /* |
| * If the current action is SIG_DFL, take the default action |
| */ |
| if ( sigact == SIG_DFL ) { |
| |
| /* |
| * The current default action for all of the supported |
| * signals is to terminate with an exit code of 3. |
| * |
| */ |
| _exit(3); |
| } |
| |
| /* |
| * From here on, sigact is assumed to be a pointer to a user-supplied |
| * handler. |
| */ |
| |
| /* |
| * For signals which correspond to exceptions, set the pointer |
| * to the EXCEPTION_POINTERS structure to NULL |
| */ |
| if ( (sig == SIGFPE) || (sig == SIGSEGV) || |
| (sig == SIGILL) ) { |
| oldpxcptinfoptrs = _pxcptinfoptrs; |
| _pxcptinfoptrs = NULL; |
| } |
| |
| /* |
| * Reset the action to SIG_DFL and call the user specified handler |
| * routine. |
| */ |
| (*sigact)(sig); |
| |
| /* |
| * For signals which correspond to exceptions, restore the pointer |
| * to the EXCEPTION_POINTERS structure. |
| */ |
| if ( (sig == SIGFPE) || (sig == SIGSEGV) || |
| (sig == SIGILL) ) { |
| _pxcptinfoptrs = oldpxcptinfoptrs; |
| /* |
| * If sig is SIGFPE, also restore _fpecode |
| */ |
| } |
| return(0); |
| } |