jdm@hodge.UUCP (jdm) (09/17/89)
A number of people have requested a handler to trap Control C and Control Break key strokes. Here is a little dittie released just for that purpose from the good people at Microsoft. /*=============================> Ctrl.c <==================================*/ /* */ /* This sample program illustrates how to trap the Ctrl-C and */ /* Ctrl-Break keys. It will wait for the user to press a key. */ /* When a key is pressed it will check to see if the key is a */ /* Ctrl-C or a Ctrl-Break. If the key is a Ctrl-Break, nothing */ /* will happen. If the key is a Ctrl-C, a message is displayed */ /* and the keyboard buffer is dumped to the screen in hex values. */ /* If the key pressed is neither Ctrl-C nor Ctrl-Break than just */ /* the keyboard buffer is dumped. */ /* */ /* Copyright (c) Microsoft Corp. 1988. All rights reserved. */ /* */ /*=========================================================================*/ #include <stdio.h> #include <dos.h> #include <conio.h> #define HIBYTE(x) ( (unsigned char) (((unsigned) x >> 8) & 0x00FF) ) #define HIWORD(x) ( (unsigned) (((unsigned long) x >> 16) & 0x0000FFFF) ) #define LOBYTE(x) ( (unsigned char) ((unsigned) x & 0x00FF) ) #define LOWORD(x) ( (unsigned) ((unsigned long) x & 0x0000FFFF) ) #define BITSET(x, n) ( (((unsigned) x >> n) & 0x0001) == 1 ? 1 : 0 ) #define AND(a, b) ( a &= b ) /* a = a AND b */ #define OR(a, b) ( a |= b ) /* a = a OR b */ #define XOR(a, b) ( a ^= b ) /* a = a XOR b */ #define SEMINIT(s) ( XOR(s, s) ) #define SEMSET(s) ( s ? 1 : 0 ) /*===========================================================================*/ #define INT09 0x0009 /* Keyboard interrupt number */ #define INT1B 0x001B /* Ctrl-C interrupt number */ #define INT23 0x0023 /* Ctrl-Break interrupt number */ #define ESC 0x1B /* Ascii escape code */ #define SPACE 0x20 /* Ascii space code */ #define cScan 0x2E /* Scan code for the "C" key */ #define CtrlOff 0xFB /* Ctrl-C bit mask */ #define CtrlOn 0x04 /* Ctrl-C bit mask */ #define Value 0x001F /* replace ^C with this value */ #define KBDMEM 0x0000041C /* Keyboard buffer tail pointer address. */ #define KBDBUF 0x0000041E /* Keyboard buffer address */ #define KBDFLAG 0x00000417 /* Keyboard flag byte address */ #define KB_DATA 0x0060 /* Kbd port address */ #define ADDRESS unsigned far * /*============================================================================*/ /* Functions pointers */ void (interrupt far *KbdPtr)(void); /* points to keyboard routine. */ void (interrupt far *BrkPtr)(void); /* points to break routine. */ void (interrupt far *OldInt09)(void); /* save old kbd handler */ void (interrupt far *OldInt1B)(void); /* save old ^C handler */ void (interrupt far *OldInt23)(void); /* save old brk handler */ /*============================================================================*/ ADDRESS KbdBuf; ADDRESS KbdCtrl; ADDRESS KbdTail; void main (void); void KbdHexDump( ADDRESS str ); /*===========================================================================*/ /* Interrupt service routines */ void interrupt far Int09(void); void interrupt far Int1B(void); void interrupt far Int23(void); /*===========================================================================*/ unsigned sem; /* ^C was pressed then sem=1, else sem=0 */ unsigned ch; unsigned cell; /* Data from Kbd port 60h */ void main (void) { unsigned i; OldInt09 = _dos_getvect( INT09 ); OldInt1B = _dos_getvect( INT1B ); OldInt23 = _dos_getvect( INT23 ); KbdPtr = Int09; _dos_setvect( INT09, KbdPtr ); BrkPtr = Int1B; _dos_setvect( INT1B, BrkPtr); BrkPtr = Int23; _dos_setvect( INT23, BrkPtr ); KbdTail = (ADDRESS) KBDMEM; KbdBuf = (ADDRESS) KBDBUF; KbdCtrl = (ADDRESS) KBDFLAG; for(i = 0; i < 16; i++) KbdBuf[i] = (unsigned) (0x3900 | SPACE); SEMINIT(sem); /* clear semaphore */ XOR(ch, ch); /* ch=0 */ while( LOBYTE(ch) != ESC ) { ch = getch(); if ( SEMSET(sem) ) printf("\nCtrl-C key was pressed!\n"); KbdHexDump( KbdBuf ); } _dos_setvect( INT09, OldInt09 ); _dos_setvect( INT1B, OldInt1B ); _dos_setvect( INT23, OldInt23 ); } void KbdHexDump( ADDRESS str ) { unsigned j; printf("\n"); for( j=0; j < 16; j++ ) { if ( LOBYTE(str[j]) < 15 ) printf("0"); if ( str[j] == Value ) printf("03 "); else printf("%x ", LOBYTE(str[j])); } printf(" "); for( j=0; j < 16; j++ ) { if ( LOBYTE(str[j]) < SPACE ) printf("%c", '.'); else printf("%c", LOBYTE(str[j])); } printf("\n"); } /*============================================================================*/ /* Interrupt Service Routines. */ void interrupt far Int09( void ) { unsigned indx; _disable(); cell = inp( KB_DATA ); if ( BITSET(*KbdCtrl, 2) && LOBYTE(cell) == cScan ) { sem = 1; indx = ( *KbdTail - LOBYTE(LOWORD(KbdBuf)) ) / 2; AND( *KbdCtrl, CtrlOff ); } else XOR(sem, sem); OldInt09(); if ( SEMSET(sem) ) { OR( *KbdCtrl, CtrlOn ); KbdBuf[indx] = Value; } } void interrupt far Int1B(void) { /* New home for Ctrl-C. */ } void interrupt far Int23(void) { /* New Home for Ctrl-Break. */ }