From: e-mail DOT address AT end DOT of DOT text (Mike Collins) Newsgroups: comp.os.msdos.djgpp Subject: One PC shadows another (Part 1) Date: 22 Jul 1997 10:25:14 GMT Organization: Storage Technology Limited Lines: 138 Message-ID: <5r21qb$3bq@news.network.com> NNTP-Posting-Host: 129.80.172.76 Mime-Version: 1.0 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk /* Folks, I am writing a database program in C, that will be used in a critical situation in real time. For disaster recovery, I wrote the code below, which causes two PCs to run the same software in parallel, so that both PCs remain identical at all times. I have incorporated it into my software and tested it, and it appears to work fine. If anybody has the same requirement, they may use it, hack it about, do whatever they want with it. There are no guarantees with it, though, and I will not spend much time supporting it. The effect is that a PC is configured as MASTER and another is configured as SLAVE. All keyboard characters on the Master go into the keyboard buffer as usual, where your fantastic program goes looking for its input. If it uses getch(), the character is input to the program, but when it uses kb_getch(), besides going to the program, the character is also sent to the serial port. Note that in these routines, only serial port COM-1 is used. If you don't like that, change the references to 0x3fa-0x3fe to something you like better. Your fantastic program is also running on the Slave system, and just as on any system, it goes looking in the keyboard buffer for its input. On the Slave system, however, any character arriving at serial COM-1 port causes an interrupt, and the interrupt routine puts the character into the keyboard buffer, where your program finds it, just as if you had typed it there. The routines in this source code come with a demonstration program which will be compiled as long as TEST is defined. The demonstration program in main() echoes any characters typed on the Master onto the screen of the Slave, but this is not a simple echo. It is the result of the same program running on both Master and Slave, and getting the same keyboard input. The program detects characters and function keys. It does not detect other two- character keys such as Arrow keys, although they are, in fact, sent to the slave system. Five routines are defined and described in kb.h (below). Read the descriptions there. The database program for which I wrote these shadowing routines, uses active help files, for which I use the kb_ungetch() and kb_ungets(). For example, at a given point in the program, I look for input. If the key pressed is A, B, C, D, F1 or F2, then the program performs a corresponding action. If the key was F1, the action is to display a help menu. The menu describes the action for each key other than F1, eg: A - Action 1 B - Action 2 C - Action 3 D - Action 4 F2 - Action 5 If Escape is pressed, the menu goes away, and a goto (yes, that's right, a GOTO!!) takes us back to the beginning of the keyboard input section, and you can press the key of your choice. Instead of making the menu go away, however, you can move the cursor down to the line of your choice (let's say the description for the F2 key) and press Return to select it. In that case, the help() routine which has just received a return from the menu() routine, does a kb_ungets("\0\x3c"); The "\0" tells kb_ungets that this is a function key (you could kb_ungets an arrow key or delete key the same way). The "\x3c" is the second character generated by the F2 key. Now when the goto is executed, the keyboard input routine finds two characters in the keyboard buffer - a zero, saying that the next character is the scancode of the key pressed, and a \x3c, exactly the same as if it had been looking for keyboard input and we had pressed the F2 key, so off it goes and does the F2 action. Prerequisites are : 1) Your program must be in 32-bit protected mode C, compilable with DJGPP. 2) All keyboard input must be done via getch(). If you use scanf(), for example, you will have some work to do before you can use these routines. How to use these routines : 1) #include kb.h // in your program.c file 2) In the initiallisation phase of your program, insert the line SetupInt(); 3) Throughout your program, change all your getch() and ungetch() statements to kb_getch() and kb_ungetch(). This can be done with a couple of #defines 4) Put kb.c into your project. 5) Compile & Link. 6) Copy your program.exe file to the slave system. 7) Connect a serial cable (pins 2, 3 and 7) between the two machines' COM-1. 8) Run the program on both machines. 9) Configure the Master by pressing (Alt-Ctl-M). 10) Configure the Slave by pressing (Alt-Ctl-S). 11) Type on the Master only. Anything typed on the Slave will go only to the Slave, so the two programs may get out of step. 12) A machine may be configured to Standalone by pressing Alt-Ctl-1. kb_getch() will then work the same as getch() would have. */ //=================FILE : KB.H====================// #define MASTER 0x32 /* ScanCode for 'M' key */ #define SLAVE 0x1f /* ScanCode for 'S' key */ #define STANDALONE 0x02 /* ScanCode for '1' key */ // set MASTER mode by pressing Alt-Ctl-M keys // set SLAVE mode by pressing Alt-Ctl-S keys // set STANDALONE by pressing Alt-Ctl-1 keys // these settings assume that the scan codes equate with English keyboard. int kb_hit(void); // tests to see if a key has been hit. More specifically, // tests whether 'next' and 'last' keyboard-buffer pointers // are equal void kb_ungetch(char ch); // puts a char back into the keyboard buffer. This // character appears to your program the same as // one that you have entered from the keyboard. char kb_getch(void); // gets a character (or function key) from the keyboard // and sends it to your program the same as getch(), but // if in MASTER mode, also sends it to serial port A, or // in SLAVE mode, gets the character from the serial line // and puts it into the keyboard buffer. The program // running on the SLAVE system sees it as keybd input. void disp_kb_bfr(int period); // displays the keyboard buffer without // modifying anything. // Shows Head & Tail as '>' & '<'. void kb_ungets(char *str); // Puts characters into kb-bfr. Use like this : // 1) ungets("\0\x3c") - put the FUNC-1 character into the keybd buffer // the leading zero specifies that this is a // function/arrow/etc. character. The second char (0x3c) is the scancode. // 2) ungets("Hello World") - must be less than 16 characters // these characters are then ready to be read by your program exactly // the same as if they had been keyed in. -- Don't just hit "reply" - my E-mail address is bogus to avoid automatic browsers from sending junk mail. Please use collim'at'anubis'dot'network'dot'com Actually, even this doesn't stop all of them ...