How to Trap CTRL+C and CTRL+BREAK KeystrokesID: Q86558
|
The program below demonstrates how to revector interrupts to your own service routine. Also, it shows how to stop the ^C character from appearing on the screen when CTRL+C is pressed.
The sample program shows how to trap the CTRL+C and CTRL+BREAK key combinations. The program waits for a keystroke. When a key is pressed, the program checks to see if the keystroke is a CTRL+C or CTRL+BREAK key combination. If the keystroke is CTRL+BREAK, nothing happens. If the keystroke is CTRL+C, a message is displayed and the keyboard buffer is dumped to the screen in hexadecimal values. If the keystroke is neither CTRL+C nor CTRL+BREAK, just the keyboard buffer is dumped to the screen.
/* Compile options needed: None
*/
#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 /* Keyboard port address */
#define ADDRESS unsigned far *
/*========================================================*/
/* Functions pointers */
void (interrupt far *KbdPtr)(void); /* Points to keybrd 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 interrupt far Int1B();
void interrupt far Int23();
/*=========================================================*/
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 */
}
Additional query words: kbinf 5.10 6.00 6.00a 6.00ax 7.00 1.00 1.50
Keywords : kb16bitonly
Version :
Platform :
Issue type :
Last Reviewed: July 30, 1999