0

I have a program x, which I want to cleanly terminate. You can run it by simply doing ./x and use the terminal to write lines to stdin directly and terminate it by writing exit.

However, if you use: cat file.txt | ./x, the stdin is now piped from the file and therefore you can never type exit.

The best way to end this program would be for it to automatically terminate once the last line was read from the file.

Alternatively, I'd like to re-route stdin back to the terminal if that is at all possible, to further allow manual input as before.

Here is some sample code:

int main() {
  // ...
  while (ongoing) {

    size_t n = 0;
    char* ln = NULL;

    getline(&ln, &n, stdin);

    strtok(ln, "\n");
    strtok(ln, "\r");

    if (strcmp("exit", ln) == 0) {
      break;
    }
    //...
  }
}
AgentM
  • 406
  • 4
  • 18
  • 1
    reading the MAN page for `getline()` it contains: *Both functions return -1 on failure to read a line (including end-of- file condition). In the event of an error, errno is set to indicate the cause.* Therefore, the call to `getline()` should be in the `while()` statement, the definition of the `ln` and `n` (not very meaningful names) should be before the `while()` statement and the bottom of the loop should call `free( ln );` and `n = 0; similar to: `size_t n = 0; char* ln = NULL; while( getline(&ln, &n, stdin) != -1) { ... free( ln ); ln=NULL; n = 0; }` – user3629249 Mar 07 '19 at 20:29

2 Answers2

2

you're using getline to read your input. getline returns -1 on EOF. This makes it easy.

if (-1==getline(...))
   break;
Joshua
  • 40,822
  • 8
  • 72
  • 132
1

When you have read all the input from a pipe, EOF will be raised up to indicate that the full input has been reached. In your example, this will be rougly equivalent with exit, so you can also check the return value of getline to see if the EOF has reached (in which case -1 will be returned).

Pim
  • 135
  • 1
  • 2
  • 13
  • Using `feof()` is rarely necessary — see [`while (!feof(file))` is always wrong](https://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). – Jonathan Leffler Mar 07 '19 at 17:45
  • Using `feof` fits perfectly in this program, since it requires only a single additional comparision in the if statement. Further, the pipe is in a controlled environment where it is known to return EOF always after EOF (more a less). But indeed, when carrying about reading files in C, `feof` is indeed wrong. – Pim Mar 07 '19 at 18:19
  • Since you've not shown code, I can't guess why you think `feof()` is appropriate. The code in the question is broken because it does not test the result from `getline()` before using it. While it would be possible to use `if (feof(stdin)) break;` immediately after the call to `getline()`, that is not as idiomatic C as using `if (getline(&ln, &n, stdin) == -1) break;` (and, sadly, `getline()` does return `-1` and not `EOF`). I stand by my comment: _'Using `feof()` is rarely necessary'._ It doesn't say "never"; it says "rarely". I don't think this is a place where it's useful, though. – Jonathan Leffler Mar 07 '19 at 18:24
  • this answer is wrong, amongst other reasons, because `getline()` returns -1 not EOF – user3629249 Mar 07 '19 at 20:32
  • The overal idea of the answer is not really wrong; checking for EOF is still the idea, and I never mentioned where to check for `feof`. I removed the reference to `feof` and suggested to check for the return value of `getline`. – Pim Mar 07 '19 at 20:54