[comp.sys.ibm.pc] preventing MS-DOS from printing ^C while within MS C

galvin@circle.UUCP (John Galvin) (06/29/87)

     A while ago someone asked how to prevent MS-DOS from printing ^C
when using signal() to trap Ctrl-C's.  The code below does this for
MS-DOS machines which are BIOS compatible with the IBM PC.  Through
sheer laziness I have not tested it without signal().

     When the BIOS determines that a Ctrl-C has been pressed it does
two important things.  First it sets bit 7 of 0040:0071 (labeled in
the BIOS listing as BIOS_BREAK).  Then it does an interrupt 0x1B.  The
interrupt routine that MS-DOS supplies for int 1B sticks a control C
character (0x03) into the keyboard buffer.  That is why the ^C is
printed out by MS-DOS.  The code below intercepts that interrupt so
that the ^C is not put into the buffer.  It does not, however, affect
the byte at BIOS_BREAK in any way.  if you want to prevent that flag
from being seen by DOS, just add some code to zero out that location in
the int 1B interrupt handler.

     To use these routines, just call intercept() when you want to
prevent DOS from printing ^C.  Remember to call release() before the
program exits.  Hope this is what you were looking for...
                            John

--  
John Galvin         UUCP:    ...uwvax!uwmacc!hobbes!circle!galvin
213 N. Hamilton #9  FidoNet: Sysop of 121/0, and 121/1.  (608) 258-9723
Madison, Wi  53703  AT&T:    (608) 258-9721


-------------------------------Cut Here---------------------------------

        TITLE   Intercept.asm - intercept ^C
        PAGE    66,132
;
;       Intercept.ASM
;
;       Author:  John Galvin
;       Date:    06-Jan-1987
;       Purpose: to intercept a control-C from Microsoft C
;
;       Copyright (C) 1987 by John W. Galvin.
;
;       This source code may be freely used and distributed provided that
;       it is not sold, no charge whatsoever is made for its distribution,
;       and the above copyright and authorship information remains with
;       the source code.
;
;               John Galvin - FidoNet 121/0 & 121/1
;                             UUCP ...!uwvax!uwmacc!hobbes!circle!galvin
;
;       use the following to assemble this code for the small memory model:
;               masm /ml intercep.asm;
;       for the large memory model use:
;               masm /ml /dLPROG intercep.asm;
;
;       Update History:
;           06-Jan-1987 - initial version.
;           28-Jun-1987 - threw in some comments for release.
;

ifdef LPROG
    assume CS:INTERCEP_TEXT
    INTERCEP_TEXT       segment byte    public 'CODE'
else
    assume CS:_TEXT
    _TEXT       segment byte    public 'CODE'
endif

        PUBLIC _intercept, _release


oldseg  dw      ?       ; the old segment of the break interrupt vector
oldoff  dw      ?       ; the old offset of the break interrupt vector


;----------------------------------------------------------------------------
;       Name: do_intcpt
;       
;       This is an interrupt handler for int 1B, the Keyboard Break
;       interrupt.  As it stands it just does a return from interrupt.
;       This routine is local to this file.
;
ifdef LPROG
        do_intcpt       PROC FAR
else
        do_intcpt       PROC NEAR
endif
        iret
do_intcpt       ENDP


;----------------------------------------------------------------------------
;       Name: _intercept
;
;       This routine changes the Keyboard Break interrupt handler
;       to do_intcpt.
;
ifdef LPROG
        _intercept      PROC FAR
else
        _intercept      PROC NEAR
endif
        push    bp                      ; save bp
        mov     bp, sp                  ; setup bp
        push    di                      ; save possible register variable
        push    si                      ; save possible register variable
        push    es
        mov     ax, 351Bh               ; DOS get vector service
        int     21h
        mov     ax, es                  ; segment returned in es
        mov     cs:oldseg, ax           ; save old routine's segment address
        mov     cs:oldoff, bx           ; and offset
        mov     ax, 251Bh               ; DOS set vector service
        mov     dx, offset do_intcpt    ; offset of our interrupt handler
        push    ds
        push    cs
        pop     ds                      ; get segment address of our handler
        int     21h                     ; set the vector
        pop     ds                      ; restore ds
        pop     es                      ; restore es
        pop     si                      ; restore si
        pop     di                      ; restore di
        mov     sp, bp                  ; chop stack for return to calling function
        pop     bp                      ; restore bp
        ret                             ; return to calling function
_intercept      ENDP


;----------------------------------------------------------------------------
;       Name: _release
;
;       This routine changes the Keyboard Break interrupt handler back to
;       the original MS-DOS routine.
;
ifdef LPROG
        _release        PROC FAR
else
        _release        PROC NEAR
endif
        push    bp                      ; save bp
        mov     bp, sp                  ; setup bp 
        push    di                      ; save possible register variable
        push    si                      ; save possible register variable
        push    ds
        mov     ax, 251Bh               ; DOS set vector service
        mov     dx, cs:oldoff           ; old handler's offset
        mov     bx, cs:oldseg           ; old handler's segment
        mov     ds, bx
        int     21h                     ; set the vector
        pop     ds
        pop     si                      ; restore si
        pop     di                      ; restore di
        mov     sp, bp                  ; chop stack for return to calling function
        pop     bp                      ; restore bp
        ret                             ; return to calling function
_release        ENDP

ifdef LPROG
        INTERCEP_TEXT   ENDS
else
        _TEXT   ENDS
endif

END