]> git.ipfire.org Git - thirdparty/util-linux.git/blob - text-utils/tailf.c
Imported from util-linux-2.12 tarball.
[thirdparty/util-linux.git] / text-utils / tailf.c
1 /* tailf.c -- tail a log file and then follow it
2 * Created: Tue Jan 9 15:49:21 1996 by faith@acm.org
3 * Copyright 1996, 2003 Rickard E. Faith (faith@acm.org)
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * less -F and tail -f cause a disk access every five seconds. This
24 * program avoids this problem by waiting for the file size to change.
25 * Hence, the file is not accessed, and the access time does not need to be
26 * flushed back to disk. This is sort of a "stealth" tail.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <malloc.h>
33 #include <sys/stat.h>
34 #include "nls.h"
35
36 static size_t filesize(const char *filename)
37 {
38 struct stat sb;
39
40 if (!stat(filename, &sb)) return sb.st_size;
41 return 0;
42 }
43
44 static void tailf(const char *filename, int lines)
45 {
46 char **buffer;
47 int head = 0;
48 int tail = 0;
49 FILE *str;
50 int i;
51
52 if (!(str = fopen(filename, "r"))) {
53 fprintf(stderr, _("Cannot open \"%s\" for read\n"), filename);
54 perror("");
55 exit(1);
56 }
57
58 buffer = malloc(lines * sizeof(*buffer));
59 for (i = 0; i < lines; i++) buffer[i] = malloc(BUFSIZ + 1);
60
61 while (fgets(buffer[tail], BUFSIZ, str)) {
62 if (++tail >= lines) {
63 tail = 0;
64 head = 1;
65 }
66 }
67
68 if (head) {
69 for (i = tail; i < lines; i++) fputs(buffer[i], stdout);
70 for (i = 0; i < tail; i++) fputs(buffer[i], stdout);
71 } else {
72 for (i = head; i < tail; i++) fputs(buffer[i], stdout);
73 }
74 fflush(stdout);
75
76 for (i = 0; i < lines; i++) free(buffer[i]);
77 free(buffer);
78 }
79
80 int main(int argc, char **argv)
81 {
82 char buffer[BUFSIZ];
83 size_t osize, nsize;
84 FILE *str;
85 const char *filename;
86 int count;
87
88 setlocale(LC_ALL, "");
89 bindtextdomain(PACKAGE, LOCALEDIR);
90 textdomain(PACKAGE);
91
92 if (argc != 2) {
93 fprintf(stderr, _("Usage: tailf logfile\n"));
94 exit(1);
95 }
96
97 filename = argv[1];
98
99 tailf(filename, 10);
100
101 for (osize = filesize(filename);;) {
102 nsize = filesize(filename);
103 if (nsize != osize) {
104 if (!(str = fopen(filename, "r"))) {
105 fprintf(stderr, _("Cannot open \"%s\" for read\n"), filename);
106 perror(argv[0]);
107 exit(1);
108 }
109 if (!fseek(str, osize, SEEK_SET))
110 while ((count = fread(buffer, 1, sizeof(buffer), str)) > 0)
111 fwrite(buffer, 1, count, stdout);
112 fflush(stdout);
113 fclose(str);
114 osize = nsize;
115 }
116 usleep(250000); /* 250mS */
117 }
118 return 0;
119 }