views:

178

answers:

2
+1  Q: 

Scanf with Signals

I have a signal that blocks SIGINT and basically says "Sorry, you can't quit.\n"

The issue is this can occur during a scanf.

When this occurs during a scanf, scanf takes in the printf as input.

How can I do a printf that will cause scanf to basically hit the enter key automatically. I don't care that I am getting bad input. I just want to programatically finish that scanf with a printf or something else.

Process:

scanf("get stuff") -> User is able to enter stuff in.

-> SIGINT occurs and goes to my handler.

-> Handler says "Blah blah blah" to stdout.

-> Scanf has taken this blah blah blah and is waiting for more input.

How do I make it so that when I return scanf is finished (don't care what it has gathered I just want it to continue without user help).

EDIT: if I send two signals then the scanf terminates. I want to emulate the ending of the scanf somehow programatically.

A: 

Don't use scanf as its buffering or retry code may get in the way. If you use a read(2) call it should return -1 with an errno of EINTR. Scanf may see that error and retry the read. You can always sscanf the data from the raw read.

This is assuming that QNX is POSIX compliant for read and you don't have the source for scanf for inspection.

msw
The issue is I am using functions I have NO choice in using. It is POSIX compliant.
jreid42
You were onto the right track. I am never using scanf again. I had to use something along this line, except I used fgets.
jreid42
Not using scanf() is a good idea; using fgets() is a lot more sensible in my experience.
Jonathan Leffler
+1  A: 

Your question suggests you are confused - or perhaps English is not your native language.

I have a signal that blocks SIGINT and basically says "Sorry, you can't quit.\n"

What you might have is a signal handler that is set to respond to SIGINT. Further, you might be using the 'signal()' function to set the handler - but you should be aiming to use the POSIX standard 'sigaction()' function to set the handler instead.

The issue is this can occur during a scanf.

In context, 'this' is presumably an interrupt signal, typed by the user who wishes to stop your program. Be cautious about stopping people exiting a program with an interrupt signal; if you don't let them do that, they will be more brutal. That might mean they'll generate SIGQUIT (and perhaps a core dump) instead; if you block that too, there are a number of other tricks they can try until they get to the ultimate 'kill -9 pid' which your program will get no chance to react to.

When this occurs during a scanf, scanf takes in the printf as input.

This is confused...you are presumably implying that the output from a 'printf()' statement (presumably the one that says "You can't quit") is then being seen as input to the 'scanf()'? Which seems pretty improbable... It would require a very, very weird setup on the I/O of the process, and I'm still not convinced it can happen.

How can I do a printf that will cause scanf to basically hit the enter key automatically. I don't care that I am getting bad input. I just want to programatically finish that scanf with a printf or something else.

There are several possibilities - it depends in part on the O/S you are using (even if it is POSIX.) I don't use 'scanf()'; I find it too difficult to control. If your system resumes the reads after the interrupt handler returns, then you will have a difficult time. Sometimes, though, 'scanf()' will stop short and return the number of items it has processed. If the 'scanf()' you have does not terminate, then you will need to think about interposing a 'sigsetjmp()' in a function that simply calls 'setjmp()' and then invokes your function that calls 'scanf()'. Then your signal handler can use 'siglongjmp()' to return to that intermediate function:

sigjmp_buf trap;

int intermediary(int argument)
{
    if (sigsetjmp(trap) == 0)
    {
         function_calling_scanf(argument);
         return 0;  // Success
    }
    // Report failure
    return -1;
}

Your description continues:

Process:

   scanf("get stuff") -> User is able to enter stuff in.

-> SIGINT occurs and goes to my handler.

-> Handler says "Blah blah blah" to stdout.

-> Scanf has taken this blah blah blah and is waiting for more input.

How do you know that scanf has read the 'blah blah blah'? It seems very, very improbable to me.

How do I make it so that when I return scanf is finished (don't care what it has gathered I just want it to continue without user help).

Use sigsetjmp().

EDIT: if I send two signals then the scanf terminates. I want to emulate the ending of the scanf somehow programmatically.

This is what indicates that you are using 'signal()' to set your signal handler and not 'sigaction()'. With 'signal()', when the interrupt occurs, the signal handler is set back to the default. With 'sigaction()', you have to request that behaviour; by default, the received signal (SIGINT) is blocked for the duraction and the signal handler remains in effect. If a second interrupt occurs while the first is running, the second is held up until the first handler returns (at which point the handler will be re-entered).

Jonathan Leffler
Thanks for the effort. My apologies. It's very late and I tried to half ass my question. I resolved it by removing scanf and resorting to fgets.
jreid42