Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C redirect stdin to keyboard

I have written a smallish C program on Mac OSX that does the following steps:

  1. reads some input from stdin and stores input into memory.
  2. runs some computations and prints the output to stdio

In between steps 1 and 2, I want to prompt the user and wait for some kind of keyboard input to signal "keep proceeding to step 2". The problem is that stdin has been redirected when the program was called using the command:

$ ./simple < input.in

I would like to redirect stdin to the keyboard after reading the file and am not sure how to do this. I have tried using

fclose(stdin);
freopen("newin", "r", stdin);

but stdin fails to read from the keyboard thereafter. Any suggestions on how to do this would be greatly appreciated.

Some further points:

  • The real program is much more involved than this but simple still illustrates my question.
  • The reason for this is that I'd like to pause my program during execution so that I have enough time to load the "simple" process into the OSX app called instruments for performance analysis.
  • If it helps, some more example code is provided below.

int main(void) {

    // STEP 1
    int array[ARRLEN];
    readinput(array, ARRLEN);


    // WAIT FOR KEYBOARD INPUT TO PROCEDE
    // redefine stdin to keyboard
    fclose(stdin);
    freopen("newin", "r", stdin);
    char c[5]; 
    char cmp[5] = ".";
    puts ("Enter text. Include a dot ('.') in a sentence to exit:");

    while (1) {
        fgets(c, sizeof(c), stdin);
        printf("c = %s\n", c);
        // if (strcmp(c, cmp))
        //     break;
        sleep(1);
    }

    // STEP 2
    // do something here
    return 0;
}
like image 562
n.dubau Avatar asked Jun 01 '14 09:06

n.dubau


1 Answers

Unless you have a file named newin that you want to use, your freopen invocation will fail. (Besides, you must not close the stream before calling freopen, since freopen expects a valid stream, which it closes as side effect.) To reopen the standard input to read from the terminal, you need to specify /dev/tty as the file name:

if (!freopen("/dev/tty", "r", stdin)) {
    perror("/dev/tty");
    exit(1);
}

If the program is under your control, there is no reason to reopen stdin to begin with - simply open /dev/tty as a separate file pointer, and use it to obtain interactive input:

FILE *tty = fopen("/dev/tty", "r");
if (!tty) {
    perror("/dev/tty");
    exit(1);
}
...
while (1) {
    fgets(c, sizeof(c), tty);
...
}

In either case, it will not be possible to automate the interactive responses using shell pipes, but that appears to be what you want. Reading from /dev/tty is standard practice in command-line programs that support both input redirection and interactive work, such as some Unix editors.

like image 174
user4815162342 Avatar answered Oct 15 '22 02:10

user4815162342