aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Lammerts <busybox@lists.lammerts.org>2009-07-22 00:31:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-07-22 00:31:27 +0200
commit3b5a66444030949027dacf4c372713fe33f1d9d9 (patch)
treecde2fc60c110415d134e232d3a6e4eac810a1bde
parent997538ab586e9b061b33c24f2ddced18a0379826 (diff)
downloadbusybox-w32-3b5a66444030949027dacf4c372713fe33f1d9d9.tar.gz
busybox-w32-3b5a66444030949027dacf4c372713fe33f1d9d9.tar.bz2
busybox-w32-3b5a66444030949027dacf4c372713fe33f1d9d9.zip
tail: implement -F
function old new delta tail_main 1190 1494 +304 Signed-off-by: Eric Lammerts <busybox@lists.lammerts.org> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/Config.in2
-rw-r--r--coreutils/tail.c85
2 files changed, 66 insertions, 21 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 1bc047c9a..cacfb9661 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -635,7 +635,7 @@ config TAIL
635 from files. 635 from files.
636 636
637config FEATURE_FANCY_TAIL 637config FEATURE_FANCY_TAIL
638 bool "Enable extra tail options (-q, -s, and -v)" 638 bool "Enable extra tail options (-q, -s, -v, and -F)"
639 default y 639 default y
640 depends on TAIL 640 depends on TAIL
641 help 641 help
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 3ce6be0bd..ef1326c83 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -85,18 +85,15 @@ int tail_main(int argc, char **argv)
85 unsigned count = 10; 85 unsigned count = 10;
86 unsigned sleep_period = 1; 86 unsigned sleep_period = 1;
87 bool from_top; 87 bool from_top;
88 int header_threshhold = 1;
89 const char *str_c, *str_n; 88 const char *str_c, *str_n;
90 89
91 char *tailbuf; 90 char *tailbuf;
92 size_t tailbufsize; 91 size_t tailbufsize;
93 int taillen = 0; 92 unsigned header_threshhold = 1;
94 int newlines_seen = 0; 93 unsigned nfiles;
95 int nfiles, nread, nwrite, i, opt; 94 int i, opt;
96 unsigned seen;
97 95
98 int *fds; 96 int *fds;
99 char *s, *buf;
100 const char *fmt; 97 const char *fmt;
101 98
102#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL 99#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
@@ -110,8 +107,9 @@ int tail_main(int argc, char **argv)
110 } 107 }
111#endif 108#endif
112 109
113 IF_FEATURE_FANCY_TAIL(opt_complementary = "s+";) /* -s N */ 110 /* -s NUM, -F imlies -f */
114 opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:v"), 111 IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";)
112 opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"),
115 &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period)); 113 &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period));
116#define FOLLOW (opt & 0x1) 114#define FOLLOW (opt & 0x1)
117#define COUNT_BYTES (opt & 0x2) 115#define COUNT_BYTES (opt & 0x2)
@@ -119,8 +117,12 @@ int tail_main(int argc, char **argv)
119 if (opt & 0x2) count = eat_num(str_c); // -c 117 if (opt & 0x2) count = eat_num(str_c); // -c
120 if (opt & 0x4) count = eat_num(str_n); // -n 118 if (opt & 0x4) count = eat_num(str_n); // -n
121#if ENABLE_FEATURE_FANCY_TAIL 119#if ENABLE_FEATURE_FANCY_TAIL
122 if (opt & 0x8) header_threshhold = INT_MAX; // -q 120 /* q: make it impossible for nfiles to be > header_threshhold */
121 if (opt & 0x8) header_threshhold = UINT_MAX; // -q
123 if (opt & 0x20) header_threshhold = 0; // -v 122 if (opt & 0x20) header_threshhold = 0; // -v
123#define FOLLOW_RETRY (opt & 0x40)
124#else
125#define FOLLOW_RETRY 0
124#endif 126#endif
125 argc -= optind; 127 argc -= optind;
126 argv += optind; 128 argv += optind;
@@ -128,19 +130,21 @@ int tail_main(int argc, char **argv)
128 G.status = EXIT_SUCCESS; 130 G.status = EXIT_SUCCESS;
129 131
130 /* open all the files */ 132 /* open all the files */
131 fds = xmalloc(sizeof(int) * (argc + 1)); 133 fds = xmalloc(sizeof(fds[0]) * (argc + 1));
132 if (!argv[0]) { 134 if (!argv[0]) {
133 struct stat statbuf; 135 struct stat statbuf;
134 136
135 if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { 137 if (fstat(STDIN_FILENO, &statbuf) == 0
138 && S_ISFIFO(statbuf.st_mode)
139 ) {
136 opt &= ~1; /* clear FOLLOW */ 140 opt &= ~1; /* clear FOLLOW */
137 } 141 }
138 *argv = (char *) bb_msg_standard_input; 142 argv[0] = (char *) bb_msg_standard_input;
139 } 143 }
140 nfiles = i = 0; 144 nfiles = i = 0;
141 do { 145 do {
142 int fd = open_or_warn_stdin(argv[i]); 146 int fd = open_or_warn_stdin(argv[i]);
143 if (fd < 0) { 147 if (fd < 0 && !FOLLOW_RETRY) {
144 G.status = EXIT_FAILURE; 148 G.status = EXIT_FAILURE;
145 continue; 149 continue;
146 } 150 }
@@ -161,9 +165,18 @@ int tail_main(int argc, char **argv)
161 tailbuf = xmalloc(tailbufsize); 165 tailbuf = xmalloc(tailbufsize);
162 166
163 /* tail the files */ 167 /* tail the files */
164 fmt = header_fmt + 1; /* Skip header leading newline on first output. */ 168 fmt = header_fmt + 1; /* skip header leading newline on first output */
165 i = 0; 169 i = 0;
166 do { 170 do {
171 char *buf;
172 int taillen;
173 int newlines_seen;
174 unsigned seen;
175 int nread;
176
177 if (ENABLE_FEATURE_FANCY_TAIL && fds[i] < 0)
178 continue; /* may happen with -E */
179
167 if (nfiles > header_threshhold) { 180 if (nfiles > header_threshhold) {
168 tail_xprint_header(fmt, argv[i]); 181 tail_xprint_header(fmt, argv[i]);
169 fmt = header_fmt; 182 fmt = header_fmt;
@@ -192,13 +205,13 @@ int tail_main(int argc, char **argv)
192 newlines_seen = 0; 205 newlines_seen = 0;
193 while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { 206 while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
194 if (from_top) { 207 if (from_top) {
195 nwrite = nread; 208 int nwrite = nread;
196 if (seen < count) { 209 if (seen < count) {
197 if (COUNT_BYTES) { 210 if (COUNT_BYTES) {
198 nwrite -= (count - seen); 211 nwrite -= (count - seen);
199 seen = count; 212 seen = count;
200 } else { 213 } else {
201 s = buf; 214 char *s = buf;
202 do { 215 do {
203 --nwrite; 216 --nwrite;
204 if (*s++ == '\n' && ++seen == count) { 217 if (*s++ == '\n' && ++seen == count) {
@@ -231,6 +244,7 @@ int tail_main(int argc, char **argv)
231 taillen += nread; 244 taillen += nread;
232 } else { 245 } else {
233 int extra = (buf[nread-1] != '\n'); 246 int extra = (buf[nread-1] != '\n');
247 char *s;
234 248
235 k = newlines_seen + newlines_in_buf + extra - count; 249 k = newlines_seen + newlines_in_buf + extra - count;
236 s = tailbuf; 250 s = tailbuf;
@@ -257,23 +271,54 @@ int tail_main(int argc, char **argv)
257 } 271 }
258 } while (++i < nfiles); 272 } while (++i < nfiles);
259 273
260 buf = xrealloc(tailbuf, BUFSIZ); 274 tailbuf = xrealloc(tailbuf, BUFSIZ);
261 275
262 fmt = NULL; 276 fmt = NULL;
263 277
264 if (FOLLOW) while (1) { 278 if (FOLLOW) while (1) {
265 sleep(sleep_period); 279 sleep(sleep_period);
280
266 i = 0; 281 i = 0;
267 do { 282 do {
283 int nread;
284 const char *filename = argv[i];
285 int fd = fds[i];
286
287 if (FOLLOW_RETRY) {
288 struct stat sbuf, fsbuf;
289
290 if (fd < 0
291 || fstat(fd, &fsbuf) < 0
292 || stat(filename, &sbuf) < 0
293 || fsbuf.st_dev != sbuf.st_dev
294 || fsbuf.st_ino != sbuf.st_ino
295 ) {
296 int new_fd;
297
298 if (fd >= 0)
299 close(fd);
300 new_fd = open(filename, O_RDONLY);
301 if (new_fd >= 0) {
302 bb_error_msg("%s has %s; following end of new file",
303 filename, (fd < 0) ? "appeared" : "been replaced"
304 );
305 } else if (fd >= 0) {
306 bb_perror_msg("%s has become inaccessible", filename);
307 }
308 fds[i] = fd = new_fd;
309 }
310 }
311 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
312 continue;
268 if (nfiles > header_threshhold) { 313 if (nfiles > header_threshhold) {
269 fmt = header_fmt; 314 fmt = header_fmt;
270 } 315 }
271 while ((nread = tail_read(fds[i], buf, BUFSIZ)) > 0) { 316 while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) {
272 if (fmt) { 317 if (fmt) {
273 tail_xprint_header(fmt, argv[i]); 318 tail_xprint_header(fmt, filename);
274 fmt = NULL; 319 fmt = NULL;
275 } 320 }
276 xwrite(STDOUT_FILENO, buf, nread); 321 xwrite(STDOUT_FILENO, tailbuf, nread);
277 } 322 }
278 } while (++i < nfiles); 323 } while (++i < nfiles);
279 } 324 }