Ctrl+D in bash shows unexpected result inside a C program

Viewed 44

I am learning c programming using this tutorial on building your own lisp.

Right now I am in chapter 4 where they make an interactive prompt. I did the first step to make a program that does print out user input repeatedly.

Here is the code for that:

#include <stdio.h>

static char input[2048];

int main(int argc, char** argv) {
  puts("Went Version 0.0.0.0.1");
  puts("Press Ctrl+c to Exit\n");
  while(1){
    fputs("went> ", stdout);
    fgets(input, 2048, stdin);
    printf("%s", input);
  }
  return 0;
}

And it worked as expected

~$ ./main
Went Version 0.0.0.0.1
Press Ctrl+c to Exit

went> hello
hello
went>

But when I tried to end it with Ctrl+d instead of Ctrl+c it does something weird.

went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went>^C

It runs like this until I kill it with Ctrl+C.

It's not an issue or something, just curious to know why this happens.

1 Answers

This is what basically happens here:

Ctrl+D triggers an end of file on stdin. After that, all attemps to read from stdin will result in fgets returning NULL (and feof(stdin) returning true, which is not relevant here).

As you don't check anything in your loop, there is no reason your loop stops. This is what happens:

  1. you press Ctrl+D which triggers an end of file
  2. you read from stdin with fgets which now returns NULL and leaves the input buffer unchanged.
  3. you dispay the content of the input buffer
  4. you goto 2 etc.

This has nothing to do with bash.

You need to check for the EOF (end of file) condition:

#include <stdio.h>

static char input[2048];

int main(int argc, char** argv) {
  puts("Went Version 0.0.0.0.1");
  puts("Press Ctrl+c to Exit\n");
  while(1){
    fputs("went> ", stdout);

    if (fgets(input, 2048, stdin) == NULL)  // change here
      break;                                //

    printf("%s", input);
  }
  return 0;
}
Related