1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 
5 #include "sleep.h"
6 
7 /* Open a file, seek at the end, and store in '*len' the file length */
vi_openAtEnd(char * filename,long * len)8 static FILE *vi_openAtEnd(char *filename, long *len)
9 {
10 	FILE *fp = NULL;
11 
12 	if ((fp = fopen(filename, "rb")) == NULL) goto err; /* open */
13 	if ((fseek(fp, 0, SEEK_END)) == -1) goto err; /* seek at end */
14 	if ((*len = ftell(fp)) == -1) goto err; /* read the file length */
15 	return fp;
16 err:
17 	if (fp != NULL) fclose(fp);
18 	return NULL;
19 }
20 
21 /* Output 'len' bytes of file 'fp' starting from 'offset'.
22  * The function returns 0 on success, -1 on error. */
23 #define TAILOUT_BUFLEN 1024
vi_tailOutput(FILE * fp,long offset,long len)24 static int vi_tailOutput(FILE *fp, long offset, long len)
25 {
26 	char buf[TAILOUT_BUFLEN];
27 	if (fseek(fp, offset, SEEK_SET) == -1) return -1;
28 	while(len) {
29 		unsigned int min = (len > TAILOUT_BUFLEN) ? TAILOUT_BUFLEN : len;
30 		if (fread(buf, 1, min, fp) != min) return -1;
31 		fwrite(buf, 1, min, stdout);
32 		fflush(stdout);
33 		len -= min;
34 	}
35 	return 0;
36 }
37 
38 /* An interation for the 'tail -f' simulation. Open the
39  * file at every iteration in order to continue to work
40  * when files are rotated. */
vi_tailIteration(char * filename,long * len)41 static void vi_tailIteration(char *filename, long *len)
42 {
43 	long newlen, datalen;
44 	FILE *fp = NULL;
45 
46 	fp = vi_openAtEnd(filename, &newlen);
47 	if (fp != NULL) {
48 		if (*len == -1) {
49 			/* Initialization */
50 			*len = newlen;
51 		} else if (newlen < *len) {
52 			/* Shorter file condition */
53 			*len = 0; /* the next iteration will read
54 				     the new data */
55 		} else if (newlen > *len) {
56 			/* Data ready condition */
57 			datalen = newlen - *len;
58 			if (vi_tailOutput(fp, *len, datalen) != -1)
59 				*len = newlen;
60 		}
61 	}
62 	if (fp != NULL) fclose(fp);
63 }
64 
vi_tail(int filec,char ** filev)65 void vi_tail(int filec, char **filev)
66 {
67 	long *len;
68 	int i;
69 
70 	if (filec <= 0) {
71 		fprintf(stderr, "No files specified in tail-mode\n");
72 		exit(1);
73 	}
74 	len = malloc(filec);
75 	if (!len) {
76 		fprintf(stderr, "Out of memory\n");
77 		exit(1);
78 	}
79 	for (i = 0; i < filec; i++)
80 		len[i] = -1;
81 
82 	while(1) {
83 		for (i = 0; i < filec; i++)
84 			vi_tailIteration(filev[i], &len[i]);
85 		vi_sleep(1);
86 	}
87 }
88