I have a program that runs scripts. If the user types "script
myScript.dat" the program will grab commands from the text file, verify
correctness, and begin executing the script UNTIL...
I need a way to stop the execution with user input. I was thinking
something like this:
while(user hasn't pressed 'any key'){
keepExecutingScript();
}
If you're allowed to choose which key the user uses to interrupt the
program, there's a good chance you can do this without going beyond what
the standard defines.
(This may or may not be something you'd want to do instead of using
something system-specific instead.)
Most implementations have a way to cause SIGINT to be raised in a running
program, so you can just install a handler that sets a flag indicating
it's time to stop, and check that in your main loop.
(Note that the way you arrange for SIGINT to be raised asynchronously
is entirely dependent on your system and there may not be a way at all.
(All of the systems that used nontrivially use ctrl-C by default, but
check your documentation.) So you're not actually gaining portability
to systems that don't support user-caused SIGINT, you're just gaining
not having to change the code to move between systems that do.)
--------
#include <signal.h>
volatile sig_atomic_t time_to_stop=0;
void sigint_handler(int ignored)
{
time_to_stop=1;
/*Revert to the default signal handler (usually immediate
termination) for if the user gets impatient and interrupts
again
*/
signal(SIGINT,SIG_DFL);
}
void do_main_loop(some_args args)
{
void (*old_sighandler)(int);
old_sighandler=signal(SIGINT,sigint_handler);
if(old_sighandler==SIG_IGN)
{
/*Assume it was ignored for a good reason, re-ignore*/
signal(SIGINT,SIG_IGN);
}
if(old_sighandler==SIG_ERR)
{
report_signal_installation_error();
abort_if_we_dont_want_to_continue_uninterruptible();
}
while(time_to_stop==0)
{
keep_executing_script(args);
}
do_any_cleanup_required();
/*Depending on what comes next, we may want to restore the original
handler:
*/
if(old_sighandler!=SIG_ERR)
signal(SIGINT,old_sighandler);
}
--------
Note that the things you can do in a handler for an asynchronous signal
are seriously limited. Storing a value in an object of type volatile
sig_atomic_t is guaranteed to do what you'd expect (store the value
completely and correctly and become available the next time it's checked
outside the signal handler), and using signal() to install a new handler
for the signal you're handling is also well-defined. Calling most library
functions isn't safe, examining and/or modifying most objects isn't safe,
and there's really not a whole lot that you can do without trying to do
one or the other of those.
dave