I'm assuming this is for DOS since in XP this would all be a mute point.
There is no way possible for me to explain everything necessary for writing a well-behaved TSR program and what you should do, can do, shouldn't do, or can't do.
The keyboard interrupt problem is an age old one that has about a trillion sites on the net specifically dedicated to explaining how to hook it.
The best way to do it is to save the old interrupt handler, put your new one into the chain, and at shutdown - remove yours from the chain and put the old one back. I'm also not going to be able to explain how to extract all of the keycodes in this post. Needless to say the keyboard is a complex beasty - there are several websites that will show you how to do this - google it.
But here is some code to start with.
Code:
//Keyboard handler stub
#include <dos.h>
#include <process.h>
#include <stdio.h>
#include <errno.h>
typedef unsigned char BYTE;
#define GETKEY 0x7F
#define DOWN 0x01
#define UP 0x00
#define QUERY_HANDLER 0xFF
#define KEYBOARD 0x09
void interrupt (*OldHandler)(...)=0;
void interrupt NewHandler(...)
{
static BYTE keys[255];
//Check for GETKEY status
if (_AX==GETKEY)
{
if (keys[_BX]==DOWN)
{
_AX=DOWN;
} else _AX=UP;
}
if (_AX==QUERY_HANDLER) _AX=0x2F2F;
BYTE key=inp(0x60);
if (key<128)
{
keys[key]=DOWN;
} else keys[key-128]=UP;
OldHandler();
outp(0x20,0x20);
}
int main(void)
{
//Test to see if we are there or not
REGS regs;
regs.x.ax=0xFF;
int86(KEYBOARD,®s,®s);
if (_AX=0x2F2F)
{
printf("
//Install the new keyboard handler
printf("Saving current keyboard interrupt handler\n");
OldHandler=getvect(KEYBOARD);
printf("Installing new keyboard interrupt handler\n");
setvect(KEYBOARD,NewHandler);
printf("Success.\n");
char *path=_argv[1];
printf("Executing program %s\n",path);
int program=spawnl(P_WAIT,path,NULL);
if (program!=0)
{
printf("Program %s aborted - cannot run child process.\n",path);
printf("DOS exit code %d\n",program);
if (program==-1)
{
switch(errno)
{
case E2BIG: printf("Argument list too long\n");break;
case EINVAL: printf("Invalid argument\n");break;
case ENOENT: printf("Path or file name not found\n");break;
case ENOEXEC: printf("Exec format error\n");break;
case ENOMEM: printf("Not enough core memory\n");break;
}
}
}
else
{
printf("Program terminated normally\n");
printf("Restoring keyboard interrupt vector\n");
}
setvect(KEYBOARD,OldHandler);
return(0);
}
DJGPP 32-bit C protected-mode keyboard handler
Code:
//DJGPP keyboard interrupt handler
#include "keyboard.h"
BOOL keydown[255];
_go32_dpmi_seginfo oh, nh;
BOOL GetKey(int scancode)
{
return keydown[scancode];
}
void KeyHandler(void)
{
asm ("cli; pusha");
unsigned char al=0,ah=0;
int lastkey=inportb(0x60);
if (lastkey<128)
{
keydown[lastkey]=1;
} else keydown[lastkey-128]=0;
al=inportb(0x61);
al|=0x82;
outportb(0x61,al);
al&=0x7f;
outportb(0x61,al);
outportb(0x20,0x20);
asm("popa; sti");
}
void StartKeyboard(void)
{
nh.pm_offset=(int)KeyHandler;
nh.pm_selector=_go32_my_cs();
_go32_dpmi_get_protected_mode_interrupt_vector(0x09,&oh);
_go32_dpmi_allocate_iret_wrapper(&nh);
_go32_dpmi_set_protected_mode_interrupt_vector(0x09,&nh);
}
void StopKeyboard(void)
{
_go32_dpmi_free_iret_wrapper(&nh);
_go32_dpmi_set_protected_mode_interrupt_vector(0x09,&oh);
}
DJGPP header
Code:
#ifndef _KEYBOARD_
#define _KEYBOARD_
#include <go32.h>
#include <dpmi.h>
#include <pc.h>
typedef unsigned char BOOL;
void StartKeyboard(void);
void StopKeyboard(void);
BOOL GetKey(int scancode);
#endif
Old header that has the key codes to scan for
Code:
#ifndef _KEYBOARD_
#define _KEYBOARD_
//Keyboard header file
#include <dos.h>
#include <stdlib.h>
#define VK_ESC 1
#define VK_1 2
#define VK_! 2
#define VK_2 3
#define VK_@ 3
#define VK_3 4
#define VK_# 4
#define VK_4 5
#define VK_$ 5
#define VK_5 6
#define VK_% 6
#define VK_6 7
#define VK_^ 7
#define VK_7 8
#define VK_& 8
#define VK_8 9
#define VK_* 9
#define VK_9 10
#define VK_( 10
#define VK_0 11
#define VK_) 11
#define VK_- 12
#define VK__ 12
#define VK_= 13
#define VK_+ 13
#define VK_BACKSP 14
#define VK_TAB 15
#define VK_Q 16
#define VK_W 17
#define VK_E 18
#define VK_R 19
#define VK_T 20
#define VK_Y 21
#define VK_U 22
#define VK_I 23
#define VK_O 24
#define VK_P 25
#define VK_[ 26
#define VK_{ 26
#define VK_] 27
#define VK_} 27
#define VK_ENTER 28
#define VK_RETURN 28
#define VK_CTRL 29
#define VK_A 30
#define VK_S 31
#define VK_D 32
#define VK_F 33
#define VK_G 34
#define VK_H 35
#define VK_J 36
#define VK_K 37
#define VK_L 38
#define VK_; 39
#define VK_: 39
#define VK_' 40
#define VK_" 40
#define VK_` 41
#define VK_~ 41
#define VK_LSHFT 42
#define VK_\ 43
#define VK_| 43
#define VK_Z 44
#define VK_X 45
#define VK_C 46
#define VK_V 47
#define VK_B 48
#define VK_N 49
#define VK_M 50
#define VK_< 51
#define VK_, 51
#define VK_> 52
#define VK_. 52
#define VK_? 53
#define VK_/ 53
#define VK_RSHFT 54
#define VK_PRTSC 55
#define VK_ALT 56
#define VK_SPACE 57
#define VK_CAPS 58
#define VK_F1 59
#define VK_F2 60
#define VK_F3 61
#define VK_F4 62
#define VK_F5 63
#define VK_F6 64
#define VK_F7 65
#define VK_F8 66
#define VK_F9 67
#define VK_F10 68
#define VK_F11 133
#define VK_F12 134
#define VK_NUMLK 69
#define VK_SCRLLK 70
#define VK_HOME 71
#define VK_NUM7 71
#define VK_UP 72
#define VK_NUM8 72
#define VK_PGUP 73
#define VK_NUM9 73
#define VK_GRAY- 74
#define VK_LEFT 75
#define VK_NUM4 75
#define VK_CENTER 76
#define VK_NUM5 76
#define VK_RIGHT 77
#define VK_NUM6 77
#define VK_GRAY+ 78
#define VK_END 79
#define VK_NUM1 79
#define VK_DOWN 80
#define VK_NUM2 80
#define VK_PGDN 81
#define VK_NUM3 81
#define VK_INS 82
#define VK_NUM0 82
#define VK_DEL 83
#define VK_NUM. 83
//Pointer to original interrupt handler
void interrupt (*OldKeyboard)(...);
void StartKeyboard(void); //Called to install handler
void EndKeyboard(void); //Uninstalls handler
#endif //End of keyboard.h
That should be enough to get you started.