Updates to a number of apps to remove warnings/compile errors under libc5.
[platform/upstream/busybox.git] / coreutils / tail.c
1 /* vi: set sw=4 ts=4: */
2 #include "internal.h"
3
4 /* This file contains _two_ implementations of tail.  One is
5  * a bit more full featured, but costs 6k.  The other (i.e. the
6  * SIMPLE_TAIL one) is less capable, but is good enough for about
7  * 99% of the things folks want to use tail for, and only costs 2k.
8  */
9
10
11 #ifdef BB_FEATURE_SIMPLE_TAIL
12
13 /* tail -- output the last part of file(s)
14    Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 2, or (at your option)
19    any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program; if not, write to the Free Software
28    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
30    Original version by Paul Rubin <phr@ocf.berkeley.edu>.
31    Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
32    tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.  
33
34    Rewrote the option parser, removed locales support,
35     and generally busyboxed, Erik Andersen <andersen@lineo.com>
36
37    Removed superfluous options and associated code ("-c", "-n", "-q").
38    Removed "tail -f" support for multiple files.
39    Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.
40
41  */
42
43
44 #include <stdio.h>
45 #include <stdarg.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <ctype.h>
50 #define BB_DECLARE_EXTERN
51 #define bb_need_help
52 #include "messages.c"
53
54
55 #define XWRITE(fd, buffer, n_bytes)                                     \
56   do {                                                                  \
57       if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0)  \
58           errorMsg("write error");                                      \
59   } while (0)
60
61 /* Number of items to tail.  */
62 #define DEFAULT_N_LINES 10
63
64 /* Size of atomic reads.  */
65 #ifndef BUFSIZ
66 #define BUFSIZ (512 * 8)
67 #endif
68
69 /* If nonzero, read from the end of one file until killed.  */
70 static int forever;
71
72 /* If nonzero, print filename headers.  */
73 static int print_headers;
74
75 const char tail_usage[] =
76         "tail [OPTION] [FILE]...\n"
77 #ifndef BB_FEATURE_TRIVIAL_HELP
78         "\nPrint last 10 lines of each FILE to standard output.\n"
79         "With more than one FILE, precede each with a header giving the\n"
80         "file name. With no FILE, or when FILE is -, read standard input.\n\n"
81         "Options:\n"
82         "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
83
84         "\t-f\t\tOutput data as the file grows.  This version\n"
85         "\t\t\tof 'tail -f' supports only one file at a time.\n"
86 #endif
87         ;
88
89
90 static void write_header(const char *filename)
91 {
92         static int first_file = 1;
93
94         printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
95         first_file = 0;
96 }
97
98 /* Print the last N_LINES lines from the end of file FD.
99    Go backward through the file, reading `BUFSIZ' bytes at a time (except
100    probably the first), until we hit the start of the file or have
101    read NUMBER newlines.
102    POS starts out as the length of the file (the offset of the last
103    byte of the file + 1).
104    Return 0 if successful, 1 if an error occurred.  */
105
106 static int
107 file_lines(const char *filename, int fd, long int n_lines, off_t pos)
108 {
109         char buffer[BUFSIZ];
110         int bytes_read;
111         int i;                                          /* Index into `buffer' for scanning.  */
112
113         if (n_lines == 0)
114                 return 0;
115
116         /* Set `bytes_read' to the size of the last, probably partial, buffer;
117            0 < `bytes_read' <= `BUFSIZ'.  */
118         bytes_read = pos % BUFSIZ;
119         if (bytes_read == 0)
120                 bytes_read = BUFSIZ;
121         /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
122            reads will be on block boundaries, which might increase efficiency.  */
123         pos -= bytes_read;
124         lseek(fd, pos, SEEK_SET);
125         bytes_read = fullRead(fd, buffer, bytes_read);
126         if (bytes_read == -1)
127                 errorMsg("read error");
128
129         /* Count the incomplete line on files that don't end with a newline.  */
130         if (bytes_read && buffer[bytes_read - 1] != '\n')
131                 --n_lines;
132
133         do {
134                 /* Scan backward, counting the newlines in this bufferfull.  */
135                 for (i = bytes_read - 1; i >= 0; i--) {
136                         /* Have we counted the requested number of newlines yet?  */
137                         if (buffer[i] == '\n' && n_lines-- == 0) {
138                                 /* If this newline wasn't the last character in the buffer,
139                                    print the text after it.  */
140                                 if (i != bytes_read - 1)
141                                         XWRITE(STDOUT_FILENO, &buffer[i + 1],
142                                                    bytes_read - (i + 1));
143                                 return 0;
144                         }
145                 }
146                 /* Not enough newlines in that bufferfull.  */
147                 if (pos == 0) {
148                         /* Not enough lines in the file; print the entire file.  */
149                         lseek(fd, (off_t) 0, SEEK_SET);
150                         return 0;
151                 }
152                 pos -= BUFSIZ;
153                 lseek(fd, pos, SEEK_SET);
154         }
155         while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
156         if (bytes_read == -1)
157                 errorMsg("read error");
158
159         return 0;
160 }
161
162 /* Print the last N_LINES lines from the end of the standard input,
163    open for reading as pipe FD.
164    Buffer the text as a linked list of LBUFFERs, adding them as needed.
165    Return 0 if successful, 1 if an error occured.  */
166
167 static int pipe_lines(const char *filename, int fd, long int n_lines)
168 {
169         struct linebuffer {
170                 int nbytes, nlines;
171                 char buffer[BUFSIZ];
172                 struct linebuffer *next;
173         };
174         typedef struct linebuffer LBUFFER;
175         LBUFFER *first, *last, *tmp;
176         int i;                                          /* Index into buffers.  */
177         int total_lines = 0;            /* Total number of newlines in all buffers.  */
178         int errors = 0;
179
180         first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
181         first->nbytes = first->nlines = 0;
182         first->next = NULL;
183         tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
184
185         /* Input is always read into a fresh buffer.  */
186         while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
187                 tmp->nlines = 0;
188                 tmp->next = NULL;
189
190                 /* Count the number of newlines just read.  */
191                 for (i = 0; i < tmp->nbytes; i++)
192                         if (tmp->buffer[i] == '\n')
193                                 ++tmp->nlines;
194                 total_lines += tmp->nlines;
195
196                 /* If there is enough room in the last buffer read, just append the new
197                    one to it.  This is because when reading from a pipe, `nbytes' can
198                    often be very small.  */
199                 if (tmp->nbytes + last->nbytes < BUFSIZ) {
200                         memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
201                         last->nbytes += tmp->nbytes;
202                         last->nlines += tmp->nlines;
203                 } else {
204                         /* If there's not enough room, link the new buffer onto the end of
205                            the list, then either free up the oldest buffer for the next
206                            read if that would leave enough lines, or else malloc a new one.
207                            Some compaction mechanism is possible but probably not
208                            worthwhile.  */
209                         last = last->next = tmp;
210                         if (total_lines - first->nlines > n_lines) {
211                                 tmp = first;
212                                 total_lines -= first->nlines;
213                                 first = first->next;
214                         } else
215                                 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
216                 }
217         }
218         if (tmp->nbytes == -1)
219                 errorMsg("read error");
220
221         free((char *) tmp);
222
223         /* This prevents a core dump when the pipe contains no newlines.  */
224         if (n_lines == 0)
225                 goto free_lbuffers;
226
227         /* Count the incomplete line on files that don't end with a newline.  */
228         if (last->buffer[last->nbytes - 1] != '\n') {
229                 ++last->nlines;
230                 ++total_lines;
231         }
232
233         /* Run through the list, printing lines.  First, skip over unneeded
234            buffers.  */
235         for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
236                 total_lines -= tmp->nlines;
237
238         /* Find the correct beginning, then print the rest of the file.  */
239         if (total_lines > n_lines) {
240                 char *cp;
241
242                 /* Skip `total_lines' - `n_lines' newlines.  We made sure that
243                    `total_lines' - `n_lines' <= `tmp->nlines'.  */
244                 cp = tmp->buffer;
245                 for (i = total_lines - n_lines; i; --i)
246                         while (*cp++ != '\n')
247                                 /* Do nothing.  */ ;
248                 i = cp - tmp->buffer;
249         } else
250                 i = 0;
251         XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
252
253         for (tmp = tmp->next; tmp; tmp = tmp->next)
254                 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
255
256   free_lbuffers:
257         while (first) {
258                 tmp = first->next;
259                 free((char *) first);
260                 first = tmp;
261         }
262         return errors;
263 }
264
265 /* Display file FILENAME from the current position in FD to the end.
266    If `forever' is nonzero, keep reading from the end of the file
267    until killed.  Return the number of bytes read from the file.  */
268
269 static long dump_remainder(const char *filename, int fd)
270 {
271         char buffer[BUFSIZ];
272         int bytes_read;
273         long total;
274
275         total = 0;
276   output:
277         while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
278                 XWRITE(STDOUT_FILENO, buffer, bytes_read);
279                 total += bytes_read;
280         }
281         if (bytes_read == -1)
282                 errorMsg("read error");
283         if (forever) {
284                 fflush(stdout);
285                 sleep(1);
286                 goto output;
287         }
288
289         return total;
290 }
291
292 /* Output the last N_LINES lines of file FILENAME open for reading in FD.
293    Return 0 if successful, 1 if an error occurred.  */
294
295 static int tail_lines(const char *filename, int fd, long int n_lines)
296 {
297         struct stat stats;
298         off_t length;
299
300         if (print_headers)
301                 write_header(filename);
302
303         if (fstat(fd, &stats))
304                 errorMsg("fstat error");
305
306         /* Use file_lines only if FD refers to a regular file with
307            its file pointer positioned at beginning of file.  */
308         /* FIXME: adding the lseek conjunct is a kludge.
309            Once there's a reasonable test suite, fix the true culprit:
310            file_lines.  file_lines shouldn't presume that the input
311            file pointer is initially positioned to beginning of file.  */
312         if (S_ISREG(stats.st_mode)
313                 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
314                 length = lseek(fd, (off_t) 0, SEEK_END);
315                 if (length != 0 && file_lines(filename, fd, n_lines, length))
316                         return 1;
317                 dump_remainder(filename, fd);
318         } else
319                 return pipe_lines(filename, fd, n_lines);
320
321         return 0;
322 }
323
324 /* Display the last N_UNITS lines of file FILENAME.
325    "-" for FILENAME means the standard input.
326    Return 0 if successful, 1 if an error occurred.  */
327
328 static int tail_file(const char *filename, off_t n_units)
329 {
330         int fd, errors;
331
332         if (!strcmp(filename, "-")) {
333                 filename = "standard input";
334                 errors = tail_lines(filename, 0, (long) n_units);
335         } else {
336                 /* Not standard input.  */
337                 fd = open(filename, O_RDONLY);
338                 if (fd == -1)
339                         perror(filename);
340
341                 errors = tail_lines(filename, fd, (long) n_units);
342                 close(fd);
343         }
344
345         return errors;
346 }
347
348 extern int tail_main(int argc, char **argv)
349 {
350         int exit_status = 0;
351         int n_units = DEFAULT_N_LINES;
352         int n_tmp, i;
353         char opt;
354
355         forever = print_headers = 0;
356
357         /* parse argv[] */
358         for (i = 1; i < argc; i++) {
359                 if (argv[i][0] == '-') {
360                         opt = argv[i][1];
361                         switch (opt) {
362                         case 'f':
363                                 forever = 1;
364                                 break;
365                         case 'n':
366                                 n_tmp = 0;
367                                 if (++i < argc)
368                                         n_tmp = atoi(argv[i]);
369                                 if (n_tmp < 1)
370                                         usage(tail_usage);
371                                 n_units = n_tmp;
372                                 break;
373                         case '-':
374                         case 'h':
375                                 usage(tail_usage);
376                         default:
377                                 if ((n_units = atoi(&argv[i][1])) < 1) {
378                                         fprintf(stderr, "tail: invalid option -- %c\n", opt);
379                                         usage(tail_usage);
380                                 }
381                         }
382                 } else {
383                         break;
384                 }
385         }
386
387         if (i + 1 < argc) {
388                 if (forever) {
389                         fprintf(stderr,
390                                         "tail: option -f is invalid with multiple files\n");
391                         usage(tail_usage);
392                 }
393                 print_headers = 1;
394         }
395
396         if (i >= argc) {
397                 exit_status |= tail_file("-", n_units);
398         } else {
399                 for (; i < argc; i++)
400                         exit_status |= tail_file(argv[i], n_units);
401         }
402
403         return(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
404 }
405
406
407 #else
408 // Here follows the code for the full featured tail code
409
410
411 /* tail -- output the last part of file(s)
412    Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
413
414    This program is free software; you can redistribute it and/or modify
415    it under the terms of the GNU General Public License as published by
416    the Free Software Foundation; either version 2, or (at your option)
417    any later version.
418
419    This program is distributed in the hope that it will be useful,
420    but WITHOUT ANY WARRANTY; without even the implied warranty of
421    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
422    GNU General Public License for more details.
423
424    You should have received a copy of the GNU General Public License
425    along with this program; if not, write to the Free Software
426    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
427
428    Original version by Paul Rubin <phr@ocf.berkeley.edu>.
429    Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
430    tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.  
431
432    Rewrote the option parser, removed locales support,
433     and generally busyboxed, Erik Andersen <andersen@lineo.com>
434  
435  */
436
437 #include "internal.h"
438
439 #include <stdio.h>
440 #include <stdarg.h>
441 #include <assert.h>
442 #include <errno.h>
443 #include <sys/types.h>
444 #include <sys/types.h>
445 #include <sys/stat.h>
446 #include <fcntl.h>
447 #include <ctype.h>
448
449
450
451 /* Disable assertions.  Some systems have broken assert macros.  */
452 #define NDEBUG 1
453
454
455 static void detailed_error(int i, int errnum, char *fmt, ...)
456                           __attribute__ ((format (printf, 3, 4)));
457 static void detailed_error(int i, int errnum, char *fmt, ...)
458 {
459         va_list arguments;
460
461         va_start(arguments, fmt);
462         vfprintf(stderr, fmt, arguments);
463         fprintf(stderr, "\n%s\n", strerror(errnum));
464         va_end(arguments);
465         exit(i);
466 }
467
468
469 #define XWRITE(fd, buffer, n_bytes)                                     \
470   do                                                                    \
471     {                                                                   \
472       assert ((fd) == 1);                                               \
473       assert ((n_bytes) >= 0);                                          \
474       if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0)  \
475         detailed_error (EXIT_FAILURE, errno, "write error");                    \
476     }                                                                   \
477   while (0)
478
479 /* Number of items to tail.  */
480 #define DEFAULT_N_LINES 10
481
482 /* Size of atomic reads.  */
483 #ifndef BUFSIZ
484 #define BUFSIZ (512 * 8)
485 #endif
486
487 /* If nonzero, interpret the numeric argument as the number of lines.
488    Otherwise, interpret it as the number of bytes.  */
489 static int count_lines;
490
491 /* If nonzero, read from the end of one file until killed.  */
492 static int forever;
493
494 /* If nonzero, read from the end of multiple files until killed.  */
495 static int forever_multiple;
496
497 /* Array of file descriptors if forever_multiple is 1.  */
498 static int *file_descs;
499
500 /* Array of file sizes if forever_multiple is 1.  */
501 static off_t *file_sizes;
502
503 /* If nonzero, count from start of file instead of end.  */
504 static int from_start;
505
506 /* If nonzero, print filename headers.  */
507 static int print_headers;
508
509 /* When to print the filename banners.  */
510 enum header_mode {
511         multiple_files, always, never
512 };
513
514 /* The name this program was run with.  */
515 char *program_name;
516
517 /* Nonzero if we have ever read standard input.  */
518 static int have_read_stdin;
519
520
521 static const char tail_usage[] = "tail [OPTION]... [FILE]...\n"
522 #ifndef BB_FEATURE_TRIVIAL_HELP
523 "\nPrint last 10 lines of each FILE to standard output.\n\
524 With more than one FILE, precede each with a header giving the file name.\n\
525 With no FILE, or when FILE is -, read standard input.\n\
526 \n\
527   -c=N[kbm]       output the last N bytes\n\
528   -f              output appended data as the file grows\n\
529   -n=N            output the last N lines, instead of last 10\n\
530   -q              never output headers giving file names\n\
531   -v              always output headers giving file names\n\
532 \n\
533 If the first character of N (bytes or lines) is a `+', output begins with \n\
534 the Nth item from the start of each file, otherwise, print the last N items\n\
535 in the file.  N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n"
536 #endif
537 ;
538
539 static void write_header(const char *filename, const char *comment)
540 {
541         static int first_file = 1;
542
543         printf("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename,
544                    (comment ? ": " : ""), (comment ? comment : ""));
545         first_file = 0;
546 }
547
548 /* Print the last N_LINES lines from the end of file FD.
549    Go backward through the file, reading `BUFSIZ' bytes at a time (except
550    probably the first), until we hit the start of the file or have
551    read NUMBER newlines.
552    POS starts out as the length of the file (the offset of the last
553    byte of the file + 1).
554    Return 0 if successful, 1 if an error occurred.  */
555
556 static int
557 file_lines(const char *filename, int fd, long int n_lines, off_t pos)
558 {
559         char buffer[BUFSIZ];
560         int bytes_read;
561         int i;                                          /* Index into `buffer' for scanning.  */
562
563         if (n_lines == 0)
564                 return 0;
565
566         /* Set `bytes_read' to the size of the last, probably partial, buffer;
567            0 < `bytes_read' <= `BUFSIZ'.  */
568         bytes_read = pos % BUFSIZ;
569         if (bytes_read == 0)
570                 bytes_read = BUFSIZ;
571         /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
572            reads will be on block boundaries, which might increase efficiency.  */
573         pos -= bytes_read;
574         lseek(fd, pos, SEEK_SET);
575         bytes_read = fullRead(fd, buffer, bytes_read);
576         if (bytes_read == -1) {
577                 detailed_error(0, errno, "%s", filename);
578                 return 1;
579         }
580
581         /* Count the incomplete line on files that don't end with a newline.  */
582         if (bytes_read && buffer[bytes_read - 1] != '\n')
583                 --n_lines;
584
585         do {
586                 /* Scan backward, counting the newlines in this bufferfull.  */
587                 for (i = bytes_read - 1; i >= 0; i--) {
588                         /* Have we counted the requested number of newlines yet?  */
589                         if (buffer[i] == '\n' && n_lines-- == 0) {
590                                 /* If this newline wasn't the last character in the buffer,
591                                    print the text after it.  */
592                                 if (i != bytes_read - 1)
593                                         XWRITE(STDOUT_FILENO, &buffer[i + 1],
594                                                    bytes_read - (i + 1));
595                                 return 0;
596                         }
597                 }
598                 /* Not enough newlines in that bufferfull.  */
599                 if (pos == 0) {
600                         /* Not enough lines in the file; print the entire file.  */
601                         lseek(fd, (off_t) 0, SEEK_SET);
602                         return 0;
603                 }
604                 pos -= BUFSIZ;
605                 lseek(fd, pos, SEEK_SET);
606         }
607         while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
608         if (bytes_read == -1) {
609                 detailed_error(0, errno, "%s", filename);
610                 return 1;
611         }
612         return 0;
613 }
614
615 /* Print the last N_LINES lines from the end of the standard input,
616    open for reading as pipe FD.
617    Buffer the text as a linked list of LBUFFERs, adding them as needed.
618    Return 0 if successful, 1 if an error occured.  */
619
620 static int pipe_lines(const char *filename, int fd, long int n_lines)
621 {
622         struct linebuffer {
623                 int nbytes, nlines;
624                 char buffer[BUFSIZ];
625                 struct linebuffer *next;
626         };
627         typedef struct linebuffer LBUFFER;
628         LBUFFER *first, *last, *tmp;
629         int i;                                          /* Index into buffers.  */
630         int total_lines = 0;            /* Total number of newlines in all buffers.  */
631         int errors = 0;
632
633         first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
634         first->nbytes = first->nlines = 0;
635         first->next = NULL;
636         tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
637
638         /* Input is always read into a fresh buffer.  */
639         while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
640                 tmp->nlines = 0;
641                 tmp->next = NULL;
642
643                 /* Count the number of newlines just read.  */
644                 for (i = 0; i < tmp->nbytes; i++)
645                         if (tmp->buffer[i] == '\n')
646                                 ++tmp->nlines;
647                 total_lines += tmp->nlines;
648
649                 /* If there is enough room in the last buffer read, just append the new
650                    one to it.  This is because when reading from a pipe, `nbytes' can
651                    often be very small.  */
652                 if (tmp->nbytes + last->nbytes < BUFSIZ) {
653                         memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
654                         last->nbytes += tmp->nbytes;
655                         last->nlines += tmp->nlines;
656                 } else {
657                         /* If there's not enough room, link the new buffer onto the end of
658                            the list, then either free up the oldest buffer for the next
659                            read if that would leave enough lines, or else malloc a new one.
660                            Some compaction mechanism is possible but probably not
661                            worthwhile.  */
662                         last = last->next = tmp;
663                         if (total_lines - first->nlines > n_lines) {
664                                 tmp = first;
665                                 total_lines -= first->nlines;
666                                 first = first->next;
667                         } else
668                                 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
669                 }
670         }
671         if (tmp->nbytes == -1) {
672                 detailed_error(0, errno, "%s", filename);
673                 errors = 1;
674                 free((char *) tmp);
675                 goto free_lbuffers;
676         }
677
678         free((char *) tmp);
679
680         /* This prevents a core dump when the pipe contains no newlines.  */
681         if (n_lines == 0)
682                 goto free_lbuffers;
683
684         /* Count the incomplete line on files that don't end with a newline.  */
685         if (last->buffer[last->nbytes - 1] != '\n') {
686                 ++last->nlines;
687                 ++total_lines;
688         }
689
690         /* Run through the list, printing lines.  First, skip over unneeded
691            buffers.  */
692         for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
693                 total_lines -= tmp->nlines;
694
695         /* Find the correct beginning, then print the rest of the file.  */
696         if (total_lines > n_lines) {
697                 char *cp;
698
699                 /* Skip `total_lines' - `n_lines' newlines.  We made sure that
700                    `total_lines' - `n_lines' <= `tmp->nlines'.  */
701                 cp = tmp->buffer;
702                 for (i = total_lines - n_lines; i; --i)
703                         while (*cp++ != '\n')
704                                 /* Do nothing.  */ ;
705                 i = cp - tmp->buffer;
706         } else
707                 i = 0;
708         XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
709
710         for (tmp = tmp->next; tmp; tmp = tmp->next)
711                 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
712
713   free_lbuffers:
714         while (first) {
715                 tmp = first->next;
716                 free((char *) first);
717                 first = tmp;
718         }
719         return errors;
720 }
721
722 /* Print the last N_BYTES characters from the end of pipe FD.
723    This is a stripped down version of pipe_lines.
724    Return 0 if successful, 1 if an error occurred.  */
725
726 static int pipe_bytes(const char *filename, int fd, off_t n_bytes)
727 {
728         struct charbuffer {
729                 int nbytes;
730                 char buffer[BUFSIZ];
731                 struct charbuffer *next;
732         };
733         typedef struct charbuffer CBUFFER;
734         CBUFFER *first, *last, *tmp;
735         int i;                                          /* Index into buffers.  */
736         int total_bytes = 0;            /* Total characters in all buffers.  */
737         int errors = 0;
738
739         first = last = (CBUFFER *) xmalloc(sizeof(CBUFFER));
740         first->nbytes = 0;
741         first->next = NULL;
742         tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
743
744         /* Input is always read into a fresh buffer.  */
745         while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
746                 tmp->next = NULL;
747
748                 total_bytes += tmp->nbytes;
749                 /* If there is enough room in the last buffer read, just append the new
750                    one to it.  This is because when reading from a pipe, `nbytes' can
751                    often be very small.  */
752                 if (tmp->nbytes + last->nbytes < BUFSIZ) {
753                         memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
754                         last->nbytes += tmp->nbytes;
755                 } else {
756                         /* If there's not enough room, link the new buffer onto the end of
757                            the list, then either free up the oldest buffer for the next
758                            read if that would leave enough characters, or else malloc a new
759                            one.  Some compaction mechanism is possible but probably not
760                            worthwhile.  */
761                         last = last->next = tmp;
762                         if (total_bytes - first->nbytes > n_bytes) {
763                                 tmp = first;
764                                 total_bytes -= first->nbytes;
765                                 first = first->next;
766                         } else {
767                                 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
768                         }
769                 }
770         }
771         if (tmp->nbytes == -1) {
772                 detailed_error(0, errno, "%s", filename);
773                 errors = 1;
774                 free((char *) tmp);
775                 goto free_cbuffers;
776         }
777
778         free((char *) tmp);
779
780         /* Run through the list, printing characters.  First, skip over unneeded
781            buffers.  */
782         for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
783                 total_bytes -= tmp->nbytes;
784
785         /* Find the correct beginning, then print the rest of the file.
786            We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'.  */
787         if (total_bytes > n_bytes)
788                 i = total_bytes - n_bytes;
789         else
790                 i = 0;
791         XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
792
793         for (tmp = tmp->next; tmp; tmp = tmp->next)
794                 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
795
796   free_cbuffers:
797         while (first) {
798                 tmp = first->next;
799                 free((char *) first);
800                 first = tmp;
801         }
802         return errors;
803 }
804
805 /* Skip N_BYTES characters from the start of pipe FD, and print
806    any extra characters that were read beyond that.
807    Return 1 on error, 0 if ok.  */
808
809 static int start_bytes(const char *filename, int fd, off_t n_bytes)
810 {
811         char buffer[BUFSIZ];
812         int bytes_read = 0;
813
814         while (n_bytes > 0 && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0)
815                 n_bytes -= bytes_read;
816         if (bytes_read == -1) {
817                 detailed_error(0, errno, "%s", filename);
818                 return 1;
819         } else if (n_bytes < 0)
820                 XWRITE(STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
821         return 0;
822 }
823
824 /* Skip N_LINES lines at the start of file or pipe FD, and print
825    any extra characters that were read beyond that.
826    Return 1 on error, 0 if ok.  */
827
828 static int start_lines(const char *filename, int fd, long int n_lines)
829 {
830         char buffer[BUFSIZ];
831         int bytes_read = 0;
832         int bytes_to_skip = 0;
833
834         while (n_lines && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
835                 bytes_to_skip = 0;
836                 while (bytes_to_skip < bytes_read)
837                         if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0)
838                                 break;
839         }
840         if (bytes_read == -1) {
841                 detailed_error(0, errno, "%s", filename);
842                 return 1;
843         } else if (bytes_to_skip < bytes_read) {
844                 XWRITE(STDOUT_FILENO, &buffer[bytes_to_skip],
845                            bytes_read - bytes_to_skip);
846         }
847         return 0;
848 }
849
850 /* Display file FILENAME from the current position in FD to the end.
851    If `forever' is nonzero, keep reading from the end of the file
852    until killed.  Return the number of bytes read from the file.  */
853
854 static long dump_remainder(const char *filename, int fd)
855 {
856         char buffer[BUFSIZ];
857         int bytes_read;
858         long total;
859
860         total = 0;
861   output:
862         while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
863                 XWRITE(STDOUT_FILENO, buffer, bytes_read);
864                 total += bytes_read;
865         }
866         if (bytes_read == -1)
867                 detailed_error(EXIT_FAILURE, errno, "%s", filename);
868         if (forever) {
869                 fflush(stdout);
870                 sleep(1);
871                 goto output;
872         } else {
873                 if (forever_multiple)
874                         fflush(stdout);
875         }
876
877         return total;
878 }
879
880 /* Tail NFILES (>1) files forever until killed.  The file names are in
881    NAMES.  The open file descriptors are in `file_descs', and the size
882    at which we stopped tailing them is in `file_sizes'.  We loop over
883    each of them, doing an fstat to see if they have changed size.  If
884    none of them have changed size in one iteration, we sleep for a
885    second and try again.  We do this until the user interrupts us.  */
886
887 static void tail_forever(char **names, int nfiles)
888 {
889         int last;
890
891         last = -1;
892
893         while (1) {
894                 int i;
895                 int changed;
896
897                 changed = 0;
898                 for (i = 0; i < nfiles; i++) {
899                         struct stat stats;
900
901                         if (file_descs[i] < 0)
902                                 continue;
903                         if (fstat(file_descs[i], &stats) < 0) {
904                                 detailed_error(0, errno, "%s", names[i]);
905                                 file_descs[i] = -1;
906                                 continue;
907                         }
908                         if (stats.st_size == file_sizes[i])
909                                 continue;
910
911                         /* This file has changed size.  Print out what we can, and
912                            then keep looping.  */
913
914                         changed = 1;
915
916                         if (stats.st_size < file_sizes[i]) {
917                                 write_header(names[i], "file truncated");
918                                 last = i;
919                                 lseek(file_descs[i], stats.st_size, SEEK_SET);
920                                 file_sizes[i] = stats.st_size;
921                                 continue;
922                         }
923
924                         if (i != last) {
925                                 if (print_headers)
926                                         write_header(names[i], NULL);
927                                 last = i;
928                         }
929                         file_sizes[i] += dump_remainder(names[i], file_descs[i]);
930                 }
931
932                 /* If none of the files changed size, sleep.  */
933                 if (!changed)
934                         sleep(1);
935         }
936 }
937
938 /* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
939    Return 0 if successful, 1 if an error occurred.  */
940
941 static int tail_bytes(const char *filename, int fd, off_t n_bytes)
942 {
943         struct stat stats;
944
945         /* FIXME: resolve this like in dd.c.  */
946         /* Use fstat instead of checking for errno == ESPIPE because
947            lseek doesn't work on some special files but doesn't return an
948            error, either.  */
949         if (fstat(fd, &stats)) {
950                 detailed_error(0, errno, "%s", filename);
951                 return 1;
952         }
953
954         if (from_start) {
955                 if (S_ISREG(stats.st_mode))
956                         lseek(fd, n_bytes, SEEK_CUR);
957                 else if (start_bytes(filename, fd, n_bytes))
958                         return 1;
959                 dump_remainder(filename, fd);
960         } else {
961                 if (S_ISREG(stats.st_mode)) {
962                         off_t current_pos, end_pos;
963                         size_t bytes_remaining;
964
965                         if ((current_pos = lseek(fd, (off_t) 0, SEEK_CUR)) != -1
966                                 && (end_pos = lseek(fd, (off_t) 0, SEEK_END)) != -1) {
967                                 off_t diff;
968
969                                 /* Be careful here.  The current position may actually be
970                                    beyond the end of the file.  */
971                                 bytes_remaining = (diff =
972                                                                    end_pos - current_pos) < 0 ? 0 : diff;
973                         } else {
974                                 detailed_error(0, errno, "%s", filename);
975                                 return 1;
976                         }
977
978                         if (bytes_remaining <= n_bytes) {
979                                 /* From the current position to end of file, there are no
980                                    more bytes than have been requested.  So reposition the
981                                    file pointer to the incoming current position and print
982                                    everything after that.  */
983                                 lseek(fd, current_pos, SEEK_SET);
984                         } else {
985                                 /* There are more bytes remaining than were requested.
986                                    Back up.  */
987                                 lseek(fd, -n_bytes, SEEK_END);
988                         }
989                         dump_remainder(filename, fd);
990                 } else
991                         return pipe_bytes(filename, fd, n_bytes);
992         }
993         return 0;
994 }
995
996 /* Output the last N_LINES lines of file FILENAME open for reading in FD.
997    Return 0 if successful, 1 if an error occurred.  */
998
999 static int tail_lines(const char *filename, int fd, long int n_lines)
1000 {
1001         struct stat stats;
1002         off_t length;
1003
1004         if (fstat(fd, &stats)) {
1005                 detailed_error(0, errno, "%s", filename);
1006                 return 1;
1007         }
1008
1009         if (from_start) {
1010                 if (start_lines(filename, fd, n_lines))
1011                         return 1;
1012                 dump_remainder(filename, fd);
1013         } else {
1014                 /* Use file_lines only if FD refers to a regular file with
1015                    its file pointer positioned at beginning of file.  */
1016                 /* FIXME: adding the lseek conjunct is a kludge.
1017                    Once there's a reasonable test suite, fix the true culprit:
1018                    file_lines.  file_lines shouldn't presume that the input
1019                    file pointer is initially positioned to beginning of file.  */
1020                 if (S_ISREG(stats.st_mode)
1021                         && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
1022                         length = lseek(fd, (off_t) 0, SEEK_END);
1023                         if (length != 0 && file_lines(filename, fd, n_lines, length))
1024                                 return 1;
1025                         dump_remainder(filename, fd);
1026                 } else
1027                         return pipe_lines(filename, fd, n_lines);
1028         }
1029         return 0;
1030 }
1031
1032 /* Display the last N_UNITS units of file FILENAME, open for reading
1033    in FD.
1034    Return 0 if successful, 1 if an error occurred.  */
1035
1036 static int tail(const char *filename, int fd, off_t n_units)
1037 {
1038         if (count_lines)
1039                 return tail_lines(filename, fd, (long) n_units);
1040         else
1041                 return tail_bytes(filename, fd, n_units);
1042 }
1043
1044 /* Display the last N_UNITS units of file FILENAME.
1045    "-" for FILENAME means the standard input.
1046    FILENUM is this file's index in the list of files the user gave.
1047    Return 0 if successful, 1 if an error occurred.  */
1048
1049 static int tail_file(const char *filename, off_t n_units, int filenum)
1050 {
1051         int fd, errors;
1052         struct stat stats;
1053
1054         if (!strcmp(filename, "-")) {
1055                 have_read_stdin = 1;
1056                 filename = "standard input";
1057                 if (print_headers)
1058                         write_header(filename, NULL);
1059                 errors = tail(filename, 0, n_units);
1060                 if (forever_multiple) {
1061                         if (fstat(0, &stats) < 0) {
1062                                 detailed_error(0, errno, "standard input");
1063                                 errors = 1;
1064                         } else if (!S_ISREG(stats.st_mode)) {
1065                                 detailed_error(0, 0,
1066                                                            "standard input: cannot follow end of non-regular file");
1067                                 errors = 1;
1068                         }
1069                         if (errors)
1070                                 file_descs[filenum] = -1;
1071                         else {
1072                                 file_descs[filenum] = 0;
1073                                 file_sizes[filenum] = stats.st_size;
1074                         }
1075                 }
1076         } else {
1077                 /* Not standard input.  */
1078                 fd = open(filename, O_RDONLY);
1079                 if (fd == -1) {
1080                         if (forever_multiple)
1081                                 file_descs[filenum] = -1;
1082                         detailed_error(0, errno, "%s", filename);
1083                         errors = 1;
1084                 } else {
1085                         if (print_headers)
1086                                 write_header(filename, NULL);
1087                         errors = tail(filename, fd, n_units);
1088                         if (forever_multiple) {
1089                                 if (fstat(fd, &stats) < 0) {
1090                                         detailed_error(0, errno, "%s", filename);
1091                                         errors = 1;
1092                                 } else if (!S_ISREG(stats.st_mode)) {
1093                                         detailed_error(0, 0,
1094                                                                    "%s: cannot follow end of non-regular file",
1095                                                                    filename);
1096                                         errors = 1;
1097                                 }
1098                                 if (errors) {
1099                                         close(fd);
1100                                         file_descs[filenum] = -1;
1101                                 } else {
1102                                         file_descs[filenum] = fd;
1103                                         file_sizes[filenum] = stats.st_size;
1104                                 }
1105                         } else {
1106                                 if (close(fd)) {
1107                                         detailed_error(0, errno, "%s", filename);
1108                                         errors = 1;
1109                                 }
1110                         }
1111                 }
1112         }
1113
1114         return errors;
1115 }
1116
1117 extern int tail_main(int argc, char **argv)
1118 {
1119         int stopit = 0;
1120         enum header_mode header_mode = multiple_files;
1121         int exit_status = 0;
1122
1123         /* If from_start, the number of items to skip before printing; otherwise,
1124            the number of items at the end of the file to print.  Initially, -1
1125            means the value has not been set.  */
1126         off_t n_units = -1;
1127         int n_files;
1128         char **file;
1129
1130         program_name = argv[0];
1131         have_read_stdin = 0;
1132         count_lines = 1;
1133         forever = forever_multiple = from_start = print_headers = 0;
1134
1135         /* Parse any options */
1136         //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
1137         while (--argc > 0 && (**(++argv) == '-' || **argv == '+')) {
1138                 if (**argv == '+') {
1139                         from_start = 1;
1140                 }
1141                 stopit = 0;
1142                 while (stopit == 0 && *(++(*argv))) {
1143                         switch (**argv) {
1144                         case 'c':
1145                                 count_lines = 0;
1146
1147                                 if (--argc < 1) {
1148                                         usage(tail_usage);
1149                                 }
1150                                 n_units = getNum(*(++argv));
1151                                 stopit = 1;
1152                                 break;
1153
1154                         case 'f':
1155                                 forever = 1;
1156                                 break;
1157
1158                         case 'n':
1159                                 count_lines = 1;
1160
1161                                 if (--argc < 1) {
1162                                         usage(tail_usage);
1163                                 }
1164                                 n_units = atol(*(++argv));
1165                                 stopit = 1;
1166                                 break;
1167
1168                         case 'q':
1169                                 header_mode = never;
1170                                 break;
1171
1172                         case 'v':
1173                                 header_mode = always;
1174                                 break;
1175
1176                         default:
1177                                 usage(tail_usage);
1178                         }
1179                 }
1180         }
1181
1182
1183         if (n_units == -1)
1184                 n_units = DEFAULT_N_LINES;
1185
1186         /* To start printing with item N_UNITS from the start of the file, skip
1187            N_UNITS - 1 items.  `tail +0' is actually meaningless, but for Unix
1188            compatibility it's treated the same as `tail +1'.  */
1189         if (from_start) {
1190                 if (n_units)
1191                         --n_units;
1192         }
1193
1194         n_files = argc;
1195         file = argv;
1196
1197         if (n_files > 1 && forever) {
1198                 forever_multiple = 1;
1199                 forever = 0;
1200                 file_descs = (int *) xmalloc(n_files * sizeof(int));
1201
1202                 file_sizes = (off_t *) xmalloc(n_files * sizeof(off_t));
1203         }
1204
1205         if (header_mode == always
1206                 || (header_mode == multiple_files && n_files > 1))
1207                 print_headers = 1;
1208
1209         if (n_files == 0) {
1210                 exit_status |= tail_file("-", n_units, 0);
1211         } else {
1212                 int i;
1213
1214                 for (i = 0; i < n_files; i++)
1215                         exit_status |= tail_file(file[i], n_units, i);
1216
1217                 if (forever_multiple)
1218                         tail_forever(file, n_files);
1219         }
1220
1221         if (have_read_stdin && close(0) < 0)
1222                 detailed_error(EXIT_FAILURE, errno, "-");
1223         if (fclose(stdout) == EOF)
1224                 detailed_error(EXIT_FAILURE, errno, "write error");
1225         exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1226 }
1227
1228
1229 #endif