PDA

View Full Version : keyboard capturing



xlnk
01-17-2003, 06:36 PM
How do I capture keyboard presses in C/C++?

Like to exit the program when ctrl-c is pressed.

Thanks!

orbitz
01-18-2003, 07:59 PM
What OS is this? If it is *NIX, the OS kills your app when you hit ^C.

mray
01-20-2003, 06:31 AM
#include <signal.h>
#include <stdio.h>

void catch_ctrlC(int c) {
puts("no exit for you !");
sleep(5);
}

int main() {

signal(SIGINT,catch_ctrlC);
while(1) puts("hehe");
}



Basically, with the call to signal(2) we are replacing the original signal handler for an Interrupt(CTRL+C) with out own, you can't CTRL+C out of the program now..

orbitz
01-21-2003, 08:50 AM
I think he is asking how to exit the program when ^C is pressed instead of NOT exit.

That1Guy
01-31-2003, 01:02 PM
I can't tell what the orginal poster had in mind when asking about signals, but since ^C's default behavior is to exit, It's probably safe to assume that the poster wanted to do something in particular before and in additon to exiting.

While mray's example will work (and I use the word "work" loosely here and with no disrespect to mray), there are a couple of issues that should be understood when dealing with signals. Since it's obvious the original poster doesn't have any experience with signals, let's get started on the right foot. These examples are for UNIX, but should give you enough information to find what you'll need for Windows as well.


Originally posted by mray



#include <signal.h>
#include <stdio.h>

void catch_ctrlC(int c) {
puts("no exit for you !");
sleep(5);
}

int main() {

signal(SIGINT,catch_ctrlC);
while(1) puts("hehe");
}



The signal() function should be avoided for several reasons, but mainly because it's completely unreliable. It can't determine the current disposition of a signal without actually changing the disposition of the signal. Absolutely worthless!

If that's not enough to convince you, then consider that signal() is a one-hit wonder when it comes to trapping a signal. When a signal occurs, it's delivered and then reset to the default action for that signal! The programmer is generally forced to give another signal() call as the first line in the handler thereby perpetually resetting the action for that signal! Are you dizzy yet? But wait, there's more!

Give some though to the fact that this perpetual resetting of the signals can cause signals to disappear *Poof* or worse! The "or worse" comes in when the signal is a showstopper like SIGINT or SIGQUIT. These problems are a reality because there is a very tiny window of time in between the reset and the handler's call of the signal() function where the signal could occur again and here's the core of the problem: In that tiny window, your program is handling the signal in the default fashion and will not be handled by your handler and that's a Bad Thing.

Well, so now we know why sigaction() should be avoided when at all possible. What do we do now? Say 'ello to my liddle frien'... sigaction()!

The sigaction() call is only slighly more complex and takes care of the issues I've described above. I'm going to leave it up to you to do a little reading on your own to completely figure this out, but here's a quick example to get you started on handling a SIGINT (Control+C).

Recommended reading: Advanced Programming in the Unix Environment by Rich Stevens. ISBN 0-201-56317-7



#include <stdio.h>
#include <signal.h> /* signals goodies */

void catch_sigint(int signum);

int main(void)
{
/* these structures hold the masking and handling info */
struct sigaction sa_new, sa_old;

/* this sets the function to be called when the signal is caught */
sa_new.sa_handler = catch_sigint;

/* this blocks all signals while inside your handler so your
* handler isn't interrupted while it's handling the signal
* you've set it to handle with sigaction().
*/
sigfillset(&sa_new);

/* read about this, but know you'll probably always set to zero */
sa_new.sa_flags = 0;

/* this replaces the signal call. It says when you encounter a
* SIGINT, call the handler I've described in sa_new and save
* the old information in sa_old.
*/
sigaction(SIGINT, &sa_new, &sa_old);

printf("Now my program catches SIGINT!\n");
sleep(30);

return 0;
}

void catch_sigint(int signum)
{
printf("\nI received SIGINT!\n");
}


There is generally no return statement in a signal handler. You'll either be returning to a reentrant function (make sure you understand what a NON-reentrant function is) or you'll be using siglongjmp() to return control to a safe area of your code. These are very important issues to understand.

Do yourself a big favor and read a chapter on signals in a good book (I mentioned the best already). You'll save yourself a lot of trouble and I truly mean it when I say it's not that hard. You can learn the majority of what you need to know in one chapter and an afternoon.

Good luck!

-That1Guy