MS-DOS Critical Error Handler
Kent Williams
kent at ncoast.UUCP
Wed Dec 3 01:43:10 AEST 1986
s/*** REPLACE THIS LINE WITH YOUR MESSAGE ***/YOUR MESSAGE/g
The following is a MS-DOS critical error handler for C. It is written
for Microsoft C, but should work with any compiler provided that the
assembly file crit.asm is edited to conform with local segment and public
naming conventions.
A MS-DOS critical error is when an I/O error occurs that puts you at a
prompt "abort, retry, ignore". In the absence of a handler, if you select
abort, you get dumped back at the DOS prompt. With the handler, control
returns to your program if an error has occured, where it can be dealt with
more gracefully.
----------------------------CUT HERE---------------------------------------
# shell archive (shar) file utility
# V1.00 (c) 1986 SIASOFT# Unpack using PC-SHELL or some reasonable facsimile
# by using:
#
# sh < archivename
#
# FILE: crit.doc
echo unpacking crit.doc
sed s/^-// <<SHAR_EOF >crit.doc
- CRIT (2) Critical Error Handler CRIT (2)
-
-
- CRITICAL
-
- critical error handler routines for Microsoft C (et al)
-
- SYNOPSIS
-
- int setup_crit();
-
- void restore_crit();
-
-
- DESCRIPTION
-
- These two functions implement a simple critical error
- handler for Microsoft C. The setup_crit function works much
- like the standard library's setjmp function - when it is
- called initially, it returns 0. When a critical error
- occurs, control is passed to the point where setup_crit was
- called, and the function appears to return -1.
-
- If a critical error occurs, the default DOS handler is
- called, which will display the 'ABORT, RETRY, IGNORE'
- message and wait for a key to be struck. If retry or ignore
- are selected, then DOS does whatever it is it supposed to do
- in that situation. If, however, the user selects abort,
- then control is returned to your program at the point where
- the call to setup_crit was made.
-
- The whole rationale for these functions is for your program
- to be able to catch fatal errors and deal with them
- relatively gracefully. Unless they are used, DOS will
- unceremoniously abort your program, leaving you with
- dangling files and interrupt vectors.
-
- The restore_crit function restores the default DOS critical
- error handler. It is not necessary to call restore_crit
- when your program terminates, as DOS restores the critical
- error vector out of your program segment prefix. It will
- allow you to turn off catching of critical errors.
-
- CAVEATS
-
- You may call setup_crit repeatedly without calling
- restore_crit - an interlock is used so that garbage isn't
- put into the critical error interrupt vector. However, each
- call to setup_crit overwrites the context saved by previous
- calls, so they do not nest.
-
- EXAMPLES
-
- The following example calls setup_crit to catch critical
- errors. It then tries to open a file on drive A:. If you've
- left the drive door open or have an unformatted diskette in
- A:, the critical error will cause a return to the point
- where setup_crit is called.
-
-
-
-
-
- -1-
-
-
- CRIT (2) Critical Error Handler CRIT (2)
-
-
- #include <stdio.h>
- main(argc,argv)
- int argc;
- char **argv;
- {
- FILE *foo = NULL;
- static char fnamebuf[65];
- /* attempt to open the file specified by the first command line
- ** argument
- */
- sprintf(fnamebuf,"A:%s",argv[1]); /* build the file name */
- for (;foo == NULL;)
- {
- if (-1 == setup_crit()) /* set up error handler */
- {
- /* if an error occurs, you will end up here */
- fprintf(stderr,
- "Check to make sure a valid disk is drive A:\n");
- fprintf(stderr,"and that the drive door is closed\n");
- fprintf(stderr,"Hit return to continue\n");
- getchar();
- }
- foo = fopen(fnamebuf,"r");
- }
- restore_crit(); /* turn off critical error handling */
- }
-
- FILES
-
- testcrit.c, crit.asm
-
- RETURN VALUE
-
- setup_crit returns 0 when invoked to set up critical error
- catching, and -1 when a critical error occurs.
-
- SEE ALSO
-
- setjmp,longjmp
-
- NOTES
-
- These functions were written by
- Kent Williams
- 722 Rundell
- Iowa City IA 52240
- (319)338-6053
-
- They may be used freely, provided proper credit is given to
- their author. They may be freely distributed, so long as
- all components of this package (crit.asm testcrit.c and
- crit.doc) are included, and no charge be made beyond a
- nominal fee for duplication.
-
-
-
-
-
-
-
- -2-
-
SHAR_EOF
# FILE: crit.asm
echo unpacking crit.asm
sed s/^-// <<SHAR_EOF >crit.asm
-;
-; testcrit.asm - implements a 'setjmp' style critical error handler
-; for Microsoft C. Implementation with other compilers should be trivial.
-; define LARGE_CODE to compile for large code models
-;
-_TEXT segment public 'CODE'
-
-_DATA segment public 'DATA'
-_DATA ends
-
-assume cs:_TEXT,ds:_DATA
-
-old_handler label dword
-old_off dw ?
-old_seg dw ?
-
-critical equ 24H
-
-savess dw ?
-savesp dw ?
-savebp dw ?
-savesi dw ?
-savedi dw ?
-returnaddress dw ?
-ifdef LARGE_CODE
-returnsegment dw ?
-endif
-datasegment dw ?
-extrasegment dw ?
-counter dw 0
-
-; crit_handler is where the critical error vector is pointed.
-; it follows the suggestions found in the DOS technical reference handler,
-; i.e. it calls the old handler, and decides what to do on the basis of the
-; value returned in AL
- public crit_handler
-crit_handler proc near
- pushf ; push flags to simulate s/w interrupt
- call dword ptr cs:old_handler ; call the old handler
- cmp al,2 ; is this an abort?
- je do_abort ; if it is, handle abort
- iret ; if not, just iret
-do_abort:
- ; otherwise, restore environment
- cli ; disable interrupts
- ; restore all important registers to the values they had upon entry
- ; into setup_crit, set AX to -1 and return
- mov ss,cs:savess
- mov sp,cs:savesp
- mov bp,cs:savebp
- mov si,cs:savesi
- mov di,cs:savedi
- mov ds,cs:datasegment
- mov es,cs:extrasegment
- mov bx,cs:returnaddress ; pick up return address
- mov ax,-1 ; return -1
- sti ; enable interrupts
-ifdef LARGE_CODE
- jmp dword ptr cs:returnaddress
-else
- jmp bx
-endif
-crit_handler endp
-
-;
-; setup_crit - sets up the critical error handler.
-; When this is called initially it will return 0.
-; If a critical error occurs, and the user responds with 'abort'
-; to the abort, retry, ignore message, then it will return -1.
-; This is very similar to the setjmp/longjmp non-local goto interface in
-; the standard C library
-;
- public _setup_crit
-ifdef LARGE_CODE
-_setup_crit proc far
-else
-_setup_crit proc near
-endif
- ; the counter variable is an interlock - if you call setup_crit
- ; if another call to setup_crit is already pending, then restore_crit will
- ; be called in order to restore the old vector before installing the new
- ; one.
- cmp cs:counter,0 ; have we been here before?
- je continue ; if not, keep going
-ifdef LARGE_CODE
- call far ptr _restore_crit
-else
- call _restore_crit ; otherwise restore old handler 1st
-endif
-continue:
- inc cs:counter ; bump the counter
- push es ; save registers munged
- push ds ;
- push si ;
- xor ax,ax ; address interrupt vectors
- mov ds,ax
- mov bx,critical*4 ; offset of critical error handler
- les si,[bx] ; load into es:si
- mov cs:old_off,si ; save offset
- mov cs:old_seg,es ; save segment
- mov word ptr [bx],offset crit_handler ; install new handler
- mov 2[bx],cs ; handler segment
- pop si ; restore munged variables
- pop ds ;
- pop es ;
- ; save the relevant calling environment, which consists of
- ; ss,sp,bp (stack environment) si,di (possible register vars)
- ; and ds,es (data segments)
- mov cs:savess,ss
- mov cs:savesp,sp
- mov cs:savebp,bp
- mov cs:savesi,si
- mov cs:savedi,di
- mov cs:datasegment,ds
- mov cs:extrasegment,es
- xor ax,ax ; return 0
- pop bx ; get return address
- mov cs:returnaddress,bx ; save it
-ifdef LARGE_CODE
- pop bx ; get return segment
- mov cs:returnsegment,bx
- jmp dword ptr cs:returnaddress
-else
- jmp bx ; go to return address
-endif
-_setup_crit endp
-
- public _restore_crit
-ifdef LARGE_CODE
-_restore_crit proc far
-else
-_restore_crit proc near
-endif
- ; check the counter to make sure setup_crit has already been called
- cmp cs:counter,1 ; has it been called?
- je restore ; yes, restore environment
- ret ; no, do nothing
-restore:
- dec cs:counter ; make counter 0
- push es ; save registers munged
- push ds ;
- push si ;
- xor ax,ax ; address interrupt vectors
- mov ds,ax ;
- les si,cs:old_handler ; pick up old handler into es:si
- mov bx,critical*4 ; address critical vector
- mov [bx],si ; poke old handler back in
- mov 2[bx],es ;
- pop si ; restore munged registers
- pop ds ;
- pop es ;
- ret ; go away
-_restore_crit endp
-
-_TEXT ends
- end
-
SHAR_EOF
# FILE: testcrit.c
echo unpacking testcrit.c
sed s/^-// <<SHAR_EOF >testcrit.c
-#include <stdio.h>
-main(argc,argv)
-int argc;
-char **argv;
-{
- FILE *foo = NULL;
- static char fnamebuf[65];
- /* attempt to open the file specified by the first command line
- ** argument
- */
- sprintf(fnamebuf,"A:%s",argv[1]); /* build the file name */
- for (;foo == NULL;)
- {
- if (-1 == setup_crit()) /* set up error handler */
- {
- /* if an error occurs, you will end up here */
- fprintf(stderr,"Check to make sure a valid disk is drive A:\n");
- fprintf(stderr,"and that the drive door is closed\n");
- fprintf(stderr,"Hit return to continue\n");
- getchar();
- }
- foo = fopen(fnamebuf,"r");
- }
- restore_crit(); /* turn off critical error handling */
-}
SHAR_EOF
More information about the Comp.sources.unix
mailing list