How to terminate scanf after a few seconds?

Viewed 192

I'm using signals in C language. The program consists in wait a few seconds for a user keyboard input if the time ends, the program terminates. However, I always have to enter text although time was over if not the program never ends. Is there any way to avoid scanf?

Here is my code

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#define NSECS 10
#define TRUE 1
#define FALSE 0
# define BELLS "\007\007\007"

int alarm_flag = FALSE;

void bye(){
    printf("Good bye...");
}

void setflag(){
    alarm_flag = TRUE;
}

int main() {
char name[20];
    do {
        

        printf("File name: \n"); 
        scanf("%s", name);

        signal(SIGALRM, setflag);
        alarm(NSECS);
        
        if (alarm_flag == TRUE){
            printf(BELLS);
            atexit(adios); 
            return 0;
        } // if the user enters a file name, the program continues 

           
1 Answers

You are almost there—set the alarm first, and call scanf afterwards. The signal will interrupt the call to read() inside scanf(), which causes scanf() to return immediately.

volatile int alarm_flag = 0;
void setflag(int sig) {
    alarm_flag = 1;
}

...

struct sigaction act = {};
act.sa_handler = set_flag;
sigaction(SIGALRM, &act, NULL);

...

    alarm(NSECS);
    scanf("%s", name);
    if (alarm_flag) {
        ...

A couple notes:

  • alarm_flag should be volatile.

  • setflag should take one int parameter.

  • Declare your functions as func(void) not func(). Declaring a function as func() is an old-fashioned style from before 1990 or so and there is no benefit to using it today. (Note that C++ is different.)

More notes:

  • You should not use == TRUE or == FALSE. In this particular case it may work fine, but there are cases where it doesn’t. So I would almost never use == TRUE.

  • As an exercise this code with alarm is reasonable, but if you want to do this kind of thing in a production application you would probably use something like libuv instead of alarm(). It’s not that there’s something wrong with this approach, just that using non-blocking IO and libuv would probably be easier to deal with.

Related