Reputation: 158
I have a log file and I want to write a program in C to read that log file and wait for new data if EOF is reached.
I do not want to use tail -f
in my code.
I tried the following code but it is not working:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>
#define PATH "/home/sanket/demo.txt"
int main(void)
{
FILE * fp;
int fd;
char * line = NULL;
size_t len = 0;
ssize_t read1;
int notify_fd;
int wd,length ,i=0;
char buffer[EVENT_BUF_LEN];
fp = fopen(PATH, "r");
if (fp == NULL)
exit(EXIT_FAILURE);
fd = fileno(fp);
while (1)
{
read1 = getline(&line, &len, fp);
if(read1 != -1)
printf("%s",line);
else
{
lseek(fd,0,SEEK_DATA);
}
}
if (line)
free(line);
exit(EXIT_SUCCESS);
}
Upvotes: 0
Views: 2038
Reputation: 753675
When you reach the first end of file, the input stream flag for EOF is set. That has to be cleared before you can resume operations (clearerr(fp)
). You should normally sleep, too. (Using lseek()
on the file descriptor associated with the stream won't help.)
Here's a program based on your code — I had to change the value of PATH (which isn't a particularly good name):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define PATH "demo.txt"
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
fp = fopen(PATH, "r");
if (fp == NULL)
{
perror(PATH);
exit(EXIT_FAILURE);
}
while (1)
{
if (getline(&line, &len, fp) != -1)
printf("%s",line);
else
{
printf("EOF\n");
sleep(1);
clearerr(fp);
}
}
if (line)
free(line);
return(EXIT_SUCCESS);
}
If you have a program that generates data to a file, you can test with it. I have a program dribbler
that does that:
$ dribbler -f demo.txt -s 1.5 -r 0.5 &
[1] 20678
$ cat demo.txt
0: message written to file
1: message written to file
2: message written to file
$ tail11
0: message written to file
1: message written to file
2: message written to file
3: message written to file
4: message written to file
5: message written to file
EOF
6: message written to file
EOF
EOF
7: message written to file
EOF
8: message written to file
EOF
EOF
9: message written to file
EOF
10: message written to file
EOF
11: message written to file
EOF
EOF
^C
$
The options to dribbler
are:
Usage: dribbler [-hlntV][-s nap.time][-r std.dev][-f outfile][-i infile][-m message][-o openstr][-F format]
-V Print version information and exit
-f outfile Write to named file (dribbler.out)
-h Print this help message and exit
-i infile Read lines from input file
-l Loop back to start of input file on EOF
-m message Write message on each line of output
-n Number lines read from input file
-o openstr Flags passed to fopen() (a+)
-s nap.time Sleep for given interval between writes (1.000 second)
-r std.dev Randomize the time (Gaussian around nap.time with std.dev)
-t Write to standard output instead of file
-F format Printf format to use instead of %zu
So, it was writing to the file demo.txt
at a mean time of 1.5 seconds, with a Gaussian random distribution with 0.5 seconds standard deviation.
That's why there were sometimes 2 EOF
messsages between successive lines of output.
Upvotes: 4