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. */
}