Reading data from stdin in C
I'm trying to read from stdin
and output the data, things work, EXCEPT that it's not outputting the new incoming data. I'm not quite sure where is the issue. I'm guessing it has something to do when determining the stdin
size. Any help would be greatly appreciated! Thanks
tail -f file | my_pro开发者_开发百科g
Updated
#include <stdio.h>
#include <sys/stat.h>
long size(FILE *st_in) {
struct stat st;
if (fstat(fileno(st_in), &st) == 0)
return st.st_size;
return -1;
}
int main (){
FILE *file = stdin;
char line [ 128 ];
while ( fgets ( line, sizeof line, file ) != NULL )
fputs ( line, stdout ); /* write the line */
long s1, s2;
s1 = size(file);
for (;;) {
s2 = size (file);
if (s2 != s1) {
if (!fseek (file, s1, SEEK_SET)) {
while ( fgets ( line, sizeof line, file ) != NULL ) {
fputs ( line, stdout ); /* write the line */
}
}
s1 = s2;
usleep(300000);
}
}
return 0;
}
Edit: Fixed!
After a FILE *
has reached EOF, it stays in a state where it will read no more data until you clear the 'EOF' bit either with clearerr()
or with fseek()
. However, if standard input is connected to a terminal, then that is not a seekable device, so instead of clearing the error, it might not do anything useful:
POSIX says:
The behavior of fseek() on devices which are incapable of seeking is implementation-defined.
Your loop entry condition is suspect; you need to sleep before starting it, and you need to sleep on each iteration. Indeed, normally you write tail -f
without worrying about the file size; you sleep, try to read until the next 'EOF', reset the file EOF indicator, and repeat. Note, too, that the size of a pipe or terminal is not defined.
Separately, it is aconventional to call a FILE *
argument to a function filename
; it has completely the wrong connotations. A filename is a string.
This is not really standard C:
size(file);
Call stat() to get file information - organization type of a file, file size and permissions.
What your code does is to eventually set the file pointer to the end of the file, as it tries to read through it. Consider stat() (or fstat() on a an open file) instead.
rewind() resets the file pointer to the start of the file, fseek() will place it anywhere you need.
tail -f repeatedly tries the file at the EOF point with a short sleep in between tries.... It does not "consider" EOF to be an error. It remembers the current file offset for the EOF, then fseeks() using SEEK_END, then calls ftell(), and compares the offsets. If there is a difference it then fseek()-s back to the last known endpoint and reads the data.
This description is from old unix source. I'm sure it has been tweaked since then.
精彩评论