3

In the following snippet, no matter how long of an input I put in (EDIT: I'm copy and pasting in a random string), say a string with 9998 characters, read() stops when i = 4095. It states it read in an EOF character, but my string does not have an EOF character (for example I tried a string of 9998 'a's). The return value also suggests there is no error from read(). Why does read() only read in only 4095 bytes?

#include <unistd.h>
#include <stdio.h>

int main() {
  char temp;
  char buf[10000];
  int i = 0;
  while(read(STDIN_FILENO, &temp, 1) > 0) {
    buf[i] = temp;
    i++;
  }
  printf("%d\n", i);
}

Edit: To clarify, read() doesn't literally state that it read in an EOF character, per https://linux.die.net/man/2/read read() returns 0 when it moves past the EOF.

Poptart
  • 331
  • 4
  • 16
  • "*It states it read in an EOF character,*" Huh? What is the "it" you are talking about? And what is an "EOF character"? – David Schwartz Nov 29 '16 at 02:21
  • 2
    How are you using the program? – Frederik Deweerdt Nov 29 '16 at 02:23
  • @FrederikDeweerdt apparently if he reads in EOF then no way the last `printf` would print out anything – artm Nov 29 '16 at 02:27
  • @DavidSchwartz When read() reads in an EOF file character it returns 0. – Poptart Nov 29 '16 at 02:27
  • @FrederikDeweerdt I'm just trying to test the read() function and trying to read byte by byte from stdin and store it into a character array. – Poptart Nov 29 '16 at 02:28
  • How do you invoke the program? Can you paste the command line? – Frederik Deweerdt Nov 29 '16 at 02:28
  • @FrederikDeweerdt It's called foo.c and I call `make foo` then run `./foo` and then copy and paste in an arbitrary string of length 9998 characters that I randomly generate using some online generator into stdin. – Poptart Nov 29 '16 at 02:30
  • EOF is not a character, and `read` didn't state that it has just "read in an EOF character" – phuclv Nov 29 '16 at 02:30
  • @Cat i suspect there's something wrong with how you pass the string, here's the program in my system: `$ for i in $(seq 1 5000); do echo -n a; done | ./foo`. It correctly says `5000` – Frederik Deweerdt Nov 29 '16 at 02:32
  • 1
    @Cat: I'd be suspicious of a problem in your copy'n'paste (say, a system level copy buffer limit). Trying saving that random string to a file, checking that it's the expected length with `wc nameoffile`, then trying `./foo < nameoffile`. – ShadowRanger Nov 29 '16 at 02:36
  • @FrederikDeweerdt Ah, it works for me too, so the problem is how I'm copy and pasting the string... I'm using right click to copy and paste. – Poptart Nov 29 '16 at 02:36
  • @ShadowRanger You're right, it's the copy and paste. I copy and pasted with echo into a .txt file and redirected that into ./foo and it worked! – Poptart Nov 29 '16 at 02:37
  • @Cat No, it doesn't. When `read` reaches the actual end of a file it returns zero. – David Schwartz Nov 29 '16 at 02:54
  • @DavidSchwartz My bad, you're right, misunderstood the man page! – Poptart Nov 29 '16 at 02:55

1 Answers1

2

You're most likely seeing the terminal buffer limit -- terminals can only read a limited number of characters on a single line, and if you type in more than that (or simulate typing with a pseudo-terminal or cut-n-paste) without entering an NL, EOL, or EOL2 character, you'll get an error, which the terminal indicates with an EOF (read returning 0).

You can generally avoid this problem by putting the terminal into non-canonical mode (where it doesn't try to buffer lines to allow backspacing).

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Terminals can also limit [number of lines](http://superuser.com/q/82087/556135) or total paste size I believe. – ShadowRanger Nov 29 '16 at 02:38
  • So why does copy and pasting the large string not hit the terminal buffer limit if I copy paste after typing in `echo` and then putting single quotes around the copy pasted string and then redirecting that output into a .txt file? – Poptart Nov 29 '16 at 02:52
  • 1
    You're probably using a shell that puts the terminal in non-canonical mode when its the foreground process, so it can do its own, more complex, line editing. – Chris Dodd Nov 29 '16 at 02:55