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