Date: Mon, 20 Dec 93 22:54:49 EST From: peprbv AT cfa0 DOT harvard DOT edu (Bob Babcock) To: djgpp AT sun DOT soe DOT clarkson DOT edu Cc: peprbv AT cfa0 DOT harvard DOT edu Subject: critical error routine I've had several requests for the critical error handler I mentioned, so here it is. The basic idea is to allocate a small amount of DOS memory (one paragraph suffices), copy the code for a critical error handler into this memory, and tell DOS to use this handler. All the handler does is to save an error code and tell DOS to fail the error. One thing it does not do is to determine whether the error occurred on a block or character device. There are alternative ways a critical error handler could be implemented, in particular a real-mode callback could be used. I chose the method below because it is a close match to what I was doing in DOS code. Comments on this code are welcome. A global header file which defines LOGICAL, TRUE and FALSE is omitted, as is the error message printing routine inside the #ifdef DEBUG conditional. There's also a global variable Hard_error which is left over from my DOS critical error handler; it isn't actually needed here. ----------- #include #include /* hardgcc - critical error handler for gcc */ static char handler[16] = { 0x81, 0xe7, 0x7f, 0, /* and di,7f */ 0x47, /* inc di */ 0x2e, 0x89, 0x3e, 0xe, 0, /* mov cs:[0eh],di */ 0xb8, 3, 0, /* mov ax,3 */ 0xcf, /* iret */ 0,0 /* storage for error code */ }; static LOGICAL handler_installed = FALSE; static _go32_dpmi_seginfo new_handler_info, old_handler_info; /* hardset - install the real-mode critical error handler */ void hardset(void) { /* On first call, allocate some DOS memory and copy the handler into it */ if(!handler_installed) { handler_installed = TRUE; new_handler_info.size = old_handler_info.size = 1; _go32_dpmi_allocate_dos_memory(&new_handler_info); dosmemput(handler, 16, new_handler_info.rm_segment * 16); #ifdef DEBUG sprintf(Tempbuf, "Handler at segment %x", new_handler_info.rm_segment); error_msg(Tempbuf, 0); #endif } _go32_dpmi_get_real_mode_interrupt_vector(0x24, &old_handler_info); _go32_dpmi_set_real_mode_interrupt_vector(0x24, &new_handler_info); clear_hard_error(); return; } /* hardclear - switch back to old critical error handler */ void hardclear(void) { if(handler_installed) _go32_dpmi_set_real_mode_interrupt_vector(0x24, &old_handler_info); return; } /* clear_hard_error - clear any indication of a critical error */ void clear_hard_error(void) { short zero = 0; if(handler_installed) dosmemput(&zero, 2, new_handler_info.rm_segment * 16 + 14); Hard_error = 0; return; } /* test_hard_err - test whether a critical error has occurred and return error code (0 if none or handler never installed). */ int test_hard_err(void) { short error_code; if(handler_installed) { dosmemget(new_handler_info.rm_segment * 16 + 14, 2, &error_code); #ifdef DEBUG if(error_code) { sprintf(Tempbuf,"Critical error code is %d", error_code); error_msg(Tempbuf,0); } #endif return(error_code); } return(0); }