blob: 058d462a5b0f93c0da048ab24e728b2b076e8aff [file] [log] [blame]
Eric Andersenabc0f4f1999-12-08 23:19:36 +00001/* tail -- output the last part of file(s)
2 Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18/* Can display any amount of data, unlike the Unix version, which uses
19 a fixed size buffer and therefore can only deliver a limited number
20 of lines.
21
22 Options:
23 -b Tail by N 512-byte blocks.
24 -c, --bytes=N[bkm] Tail by N bytes
25 [or 512-byte blocks, kilobytes, or megabytes].
26 -f, --follow Loop forever trying to read more characters at the
27 end of the file, on the assumption that the file
28 is growing. Ignored if reading from a pipe.
29 -n, --lines=N Tail by N lines.
30 -q, --quiet, --silent Never print filename headers.
31 -v, --verbose Always print filename headers.
32
33 If a number (N) starts with a `+', begin printing with the Nth item
34 from the start of each file, instead of from the end.
35
36 Reads from standard input if no files are given or when a filename of
37 ``-'' is encountered.
38 By default, filename headers are printed only more than one file
39 is given.
40 By default, prints the last 10 lines (tail -n 10).
41
42 Original version by Paul Rubin <phr@ocf.berkeley.edu>.
43 Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
44 tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */
45
46#include "internal.h"
47
48#include <stdio.h>
49#include <assert.h>
50#include <errno.h>
51#include <sys/types.h>
52
53
54/* Disable assertions. Some systems have broken assert macros. */
55#define NDEBUG 1
56
57
58static void error(int i, int errnum, char* fmt, const char *msg)
59{
60 fprintf(stderr, fmt, msg);
61 perror( errnum);
62 exit(i);
63}
64
65
66#define XWRITE(fd, buffer, n_bytes) \
67 do \
68 { \
69 assert ((fd) == 1); \
70 assert ((n_bytes) >= 0); \
71 if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \
72 error (EXIT_FAILURE, errno, "write error", NULL); \
73 } \
74 while (0)
75
76/* Number of items to tail. */
77#define DEFAULT_N_LINES 10
78
79/* Size of atomic reads. */
80#ifndef BUFSIZ
81#define BUFSIZ (512 * 8)
82#endif
83
84/* If nonzero, interpret the numeric argument as the number of lines.
85 Otherwise, interpret it as the number of bytes. */
86static int count_lines;
87
88/* If nonzero, read from the end of one file until killed. */
89static int forever;
90
91/* If nonzero, read from the end of multiple files until killed. */
92static int forever_multiple;
93
94/* Array of file descriptors if forever_multiple is 1. */
95static int *file_descs;
96
97/* Array of file sizes if forever_multiple is 1. */
98static off_t *file_sizes;
99
100/* If nonzero, count from start of file instead of end. */
101static int from_start;
102
103/* If nonzero, print filename headers. */
104static int print_headers;
105
106/* When to print the filename banners. */
107enum header_mode
108{
109 multiple_files, always, never
110};
111
112char *xmalloc ();
113int safe_read ();
114
115/* The name this program was run with. */
116char *program_name;
117
118/* Nonzero if we have ever read standard input. */
119static int have_read_stdin;
120
121/* If nonzero, display usage information and exit. */
122static int show_help;
123
124/* If nonzero, print the version on standard output then exit. */
125static int show_version;
126
127static const char tail_usage[] =
128"tail [OPTION]... [FILE]...\n\
129Print last 10 lines of each FILE to standard output.\n\
130With more than one FILE, precede each with a header giving the file name.\n\
131With no FILE, or when FILE is -, read standard input.\n\
132\n\
133 -c, --bytes=N output the last N bytes\n\
134 -f, --follow output appended data as the file grows\n\
135 -n, --lines=N output the last N lines, instead of last 10\n\
136 -q, --quiet, --silent never output headers giving file names\n\
137 -v, --verbose always output headers giving file names\n\
138 --help display this help and exit\n\
139 --version output version information and exit\n\
140\n\
141If the first character of N (the number of bytes or lines) is a `+',\n\
142print beginning with the Nth item from the start of each file, otherwise,\n\
143print the last N items in the file. N may have a multiplier suffix:\n\
144b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\
145or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\
146the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\
147or -c +VALUE.\n";
148
149static void
150write_header (const char *filename, const char *comment)
151{
152 static int first_file = 1;
153
154 printf ("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename,
155 (comment ? ": " : ""),
156 (comment ? comment : ""));
157 first_file = 0;
158}
159
160/* Print the last N_LINES lines from the end of file FD.
161 Go backward through the file, reading `BUFSIZ' bytes at a time (except
162 probably the first), until we hit the start of the file or have
163 read NUMBER newlines.
164 POS starts out as the length of the file (the offset of the last
165 byte of the file + 1).
166 Return 0 if successful, 1 if an error occurred. */
167
168static int
169file_lines (const char *filename, int fd, long int n_lines, off_t pos)
170{
171 char buffer[BUFSIZ];
172 int bytes_read;
173 int i; /* Index into `buffer' for scanning. */
174
175 if (n_lines == 0)
176 return 0;
177
178 /* Set `bytes_read' to the size of the last, probably partial, buffer;
179 0 < `bytes_read' <= `BUFSIZ'. */
180 bytes_read = pos % BUFSIZ;
181 if (bytes_read == 0)
182 bytes_read = BUFSIZ;
183 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
184 reads will be on block boundaries, which might increase efficiency. */
185 pos -= bytes_read;
186 lseek (fd, pos, SEEK_SET);
187 bytes_read = safe_read (fd, buffer, bytes_read);
188 if (bytes_read == -1)
189 {
190 error (0, errno, "%s", filename);
191 return 1;
192 }
193
194 /* Count the incomplete line on files that don't end with a newline. */
195 if (bytes_read && buffer[bytes_read - 1] != '\n')
196 --n_lines;
197
198 do
199 {
200 /* Scan backward, counting the newlines in this bufferfull. */
201 for (i = bytes_read - 1; i >= 0; i--)
202 {
203 /* Have we counted the requested number of newlines yet? */
204 if (buffer[i] == '\n' && n_lines-- == 0)
205 {
206 /* If this newline wasn't the last character in the buffer,
207 print the text after it. */
208 if (i != bytes_read - 1)
209 XWRITE (STDOUT_FILENO, &buffer[i + 1], bytes_read - (i + 1));
210 return 0;
211 }
212 }
213 /* Not enough newlines in that bufferfull. */
214 if (pos == 0)
215 {
216 /* Not enough lines in the file; print the entire file. */
217 lseek (fd, (off_t) 0, SEEK_SET);
218 return 0;
219 }
220 pos -= BUFSIZ;
221 lseek (fd, pos, SEEK_SET);
222 }
223 while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0);
224 if (bytes_read == -1)
225 {
226 error (0, errno, "%s", filename);
227 return 1;
228 }
229 return 0;
230}
231
232/* Print the last N_LINES lines from the end of the standard input,
233 open for reading as pipe FD.
234 Buffer the text as a linked list of LBUFFERs, adding them as needed.
235 Return 0 if successful, 1 if an error occured. */
236
237static int
238pipe_lines (const char *filename, int fd, long int n_lines)
239{
240 struct linebuffer
241 {
242 int nbytes, nlines;
243 char buffer[BUFSIZ];
244 struct linebuffer *next;
245 };
246 typedef struct linebuffer LBUFFER;
247 LBUFFER *first, *last, *tmp;
248 int i; /* Index into buffers. */
249 int total_lines = 0; /* Total number of newlines in all buffers. */
250 int errors = 0;
251
252 first = last = (LBUFFER *) xmalloc (sizeof (LBUFFER));
253 first->nbytes = first->nlines = 0;
254 first->next = NULL;
255 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
256
257 /* Input is always read into a fresh buffer. */
258 while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
259 {
260 tmp->nlines = 0;
261 tmp->next = NULL;
262
263 /* Count the number of newlines just read. */
264 for (i = 0; i < tmp->nbytes; i++)
265 if (tmp->buffer[i] == '\n')
266 ++tmp->nlines;
267 total_lines += tmp->nlines;
268
269 /* If there is enough room in the last buffer read, just append the new
270 one to it. This is because when reading from a pipe, `nbytes' can
271 often be very small. */
272 if (tmp->nbytes + last->nbytes < BUFSIZ)
273 {
274 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
275 last->nbytes += tmp->nbytes;
276 last->nlines += tmp->nlines;
277 }
278 else
279 {
280 /* If there's not enough room, link the new buffer onto the end of
281 the list, then either free up the oldest buffer for the next
282 read if that would leave enough lines, or else malloc a new one.
283 Some compaction mechanism is possible but probably not
284 worthwhile. */
285 last = last->next = tmp;
286 if (total_lines - first->nlines > n_lines)
287 {
288 tmp = first;
289 total_lines -= first->nlines;
290 first = first->next;
291 }
292 else
293 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER));
294 }
295 }
296 if (tmp->nbytes == -1)
297 {
298 error (0, errno, "%s", filename);
299 errors = 1;
300 free ((char *) tmp);
301 goto free_lbuffers;
302 }
303
304 free ((char *) tmp);
305
306 /* This prevents a core dump when the pipe contains no newlines. */
307 if (n_lines == 0)
308 goto free_lbuffers;
309
310 /* Count the incomplete line on files that don't end with a newline. */
311 if (last->buffer[last->nbytes - 1] != '\n')
312 {
313 ++last->nlines;
314 ++total_lines;
315 }
316
317 /* Run through the list, printing lines. First, skip over unneeded
318 buffers. */
319 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
320 total_lines -= tmp->nlines;
321
322 /* Find the correct beginning, then print the rest of the file. */
323 if (total_lines > n_lines)
324 {
325 char *cp;
326
327 /* Skip `total_lines' - `n_lines' newlines. We made sure that
328 `total_lines' - `n_lines' <= `tmp->nlines'. */
329 cp = tmp->buffer;
330 for (i = total_lines - n_lines; i; --i)
331 while (*cp++ != '\n')
332 /* Do nothing. */ ;
333 i = cp - tmp->buffer;
334 }
335 else
336 i = 0;
337 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
338
339 for (tmp = tmp->next; tmp; tmp = tmp->next)
340 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
341
342free_lbuffers:
343 while (first)
344 {
345 tmp = first->next;
346 free ((char *) first);
347 first = tmp;
348 }
349 return errors;
350}
351
352/* Print the last N_BYTES characters from the end of pipe FD.
353 This is a stripped down version of pipe_lines.
354 Return 0 if successful, 1 if an error occurred. */
355
356static int
357pipe_bytes (const char *filename, int fd, off_t n_bytes)
358{
359 struct charbuffer
360 {
361 int nbytes;
362 char buffer[BUFSIZ];
363 struct charbuffer *next;
364 };
365 typedef struct charbuffer CBUFFER;
366 CBUFFER *first, *last, *tmp;
367 int i; /* Index into buffers. */
368 int total_bytes = 0; /* Total characters in all buffers. */
369 int errors = 0;
370
371 first = last = (CBUFFER *) xmalloc (sizeof (CBUFFER));
372 first->nbytes = 0;
373 first->next = NULL;
374 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
375
376 /* Input is always read into a fresh buffer. */
377 while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0)
378 {
379 tmp->next = NULL;
380
381 total_bytes += tmp->nbytes;
382 /* If there is enough room in the last buffer read, just append the new
383 one to it. This is because when reading from a pipe, `nbytes' can
384 often be very small. */
385 if (tmp->nbytes + last->nbytes < BUFSIZ)
386 {
387 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
388 last->nbytes += tmp->nbytes;
389 }
390 else
391 {
392 /* If there's not enough room, link the new buffer onto the end of
393 the list, then either free up the oldest buffer for the next
394 read if that would leave enough characters, or else malloc a new
395 one. Some compaction mechanism is possible but probably not
396 worthwhile. */
397 last = last->next = tmp;
398 if (total_bytes - first->nbytes > n_bytes)
399 {
400 tmp = first;
401 total_bytes -= first->nbytes;
402 first = first->next;
403 }
404 else
405 {
406 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER));
407 }
408 }
409 }
410 if (tmp->nbytes == -1)
411 {
412 error (0, errno, "%s", filename);
413 errors = 1;
414 free ((char *) tmp);
415 goto free_cbuffers;
416 }
417
418 free ((char *) tmp);
419
420 /* Run through the list, printing characters. First, skip over unneeded
421 buffers. */
422 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
423 total_bytes -= tmp->nbytes;
424
425 /* Find the correct beginning, then print the rest of the file.
426 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
427 if (total_bytes > n_bytes)
428 i = total_bytes - n_bytes;
429 else
430 i = 0;
431 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
432
433 for (tmp = tmp->next; tmp; tmp = tmp->next)
434 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
435
436free_cbuffers:
437 while (first)
438 {
439 tmp = first->next;
440 free ((char *) first);
441 first = tmp;
442 }
443 return errors;
444}
445
446/* Skip N_BYTES characters from the start of pipe FD, and print
447 any extra characters that were read beyond that.
448 Return 1 on error, 0 if ok. */
449
450static int
451start_bytes (const char *filename, int fd, off_t n_bytes)
452{
453 char buffer[BUFSIZ];
454 int bytes_read = 0;
455
456 while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
457 n_bytes -= bytes_read;
458 if (bytes_read == -1)
459 {
460 error (0, errno, "%s", filename);
461 return 1;
462 }
463 else if (n_bytes < 0)
464 XWRITE (STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
465 return 0;
466}
467
468/* Skip N_LINES lines at the start of file or pipe FD, and print
469 any extra characters that were read beyond that.
470 Return 1 on error, 0 if ok. */
471
472static int
473start_lines (const char *filename, int fd, long int n_lines)
474{
475 char buffer[BUFSIZ];
476 int bytes_read = 0;
477 int bytes_to_skip = 0;
478
479 while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
480 {
481 bytes_to_skip = 0;
482 while (bytes_to_skip < bytes_read)
483 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0)
484 break;
485 }
486 if (bytes_read == -1)
487 {
488 error (0, errno, "%s", filename);
489 return 1;
490 }
491 else if (bytes_to_skip < bytes_read)
492 {
493 XWRITE (STDOUT_FILENO, &buffer[bytes_to_skip],
494 bytes_read - bytes_to_skip);
495 }
496 return 0;
497}
498
499/* Display file FILENAME from the current position in FD to the end.
500 If `forever' is nonzero, keep reading from the end of the file
501 until killed. Return the number of bytes read from the file. */
502
503static long
504dump_remainder (const char *filename, int fd)
505{
506 char buffer[BUFSIZ];
507 int bytes_read;
508 long total;
509
510 total = 0;
511output:
512 while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0)
513 {
514 XWRITE (STDOUT_FILENO, buffer, bytes_read);
515 total += bytes_read;
516 }
517 if (bytes_read == -1)
518 error (EXIT_FAILURE, errno, "%s", filename);
519 if (forever)
520 {
521 fflush (stdout);
522 sleep (1);
523 goto output;
524 }
525 else
526 {
527 if (forever_multiple)
528 fflush (stdout);
529 }
530
531 return total;
532}
533
534/* Tail NFILES (>1) files forever until killed. The file names are in
535 NAMES. The open file descriptors are in `file_descs', and the size
536 at which we stopped tailing them is in `file_sizes'. We loop over
537 each of them, doing an fstat to see if they have changed size. If
538 none of them have changed size in one iteration, we sleep for a
539 second and try again. We do this until the user interrupts us. */
540
541static void
542tail_forever (char **names, int nfiles)
543{
544 int last;
545
546 last = -1;
547
548 while (1)
549 {
550 int i;
551 int changed;
552
553 changed = 0;
554 for (i = 0; i < nfiles; i++)
555 {
556 struct stat stats;
557
558 if (file_descs[i] < 0)
559 continue;
560 if (fstat (file_descs[i], &stats) < 0)
561 {
562 error (0, errno, "%s", names[i]);
563 file_descs[i] = -1;
564 continue;
565 }
566 if (stats.st_size == file_sizes[i])
567 continue;
568
569 /* This file has changed size. Print out what we can, and
570 then keep looping. */
571
572 changed = 1;
573
574 if (stats.st_size < file_sizes[i])
575 {
576 write_header (names[i], "file truncated");
577 last = i;
578 lseek (file_descs[i], stats.st_size, SEEK_SET);
579 file_sizes[i] = stats.st_size;
580 continue;
581 }
582
583 if (i != last)
584 {
585 if (print_headers)
586 write_header (names[i], NULL);
587 last = i;
588 }
589 file_sizes[i] += dump_remainder (names[i], file_descs[i]);
590 }
591
592 /* If none of the files changed size, sleep. */
593 if (! changed)
594 sleep (1);
595 }
596}
597
598/* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
599 Return 0 if successful, 1 if an error occurred. */
600
601static int
602tail_bytes (const char *filename, int fd, off_t n_bytes)
603{
604 struct stat stats;
605
606 /* FIXME: resolve this like in dd.c. */
607 /* Use fstat instead of checking for errno == ESPIPE because
608 lseek doesn't work on some special files but doesn't return an
609 error, either. */
610 if (fstat (fd, &stats))
611 {
612 error (0, errno, "%s", filename);
613 return 1;
614 }
615
616 if (from_start)
617 {
618 if (S_ISREG (stats.st_mode))
619 lseek (fd, n_bytes, SEEK_CUR);
620 else if (start_bytes (filename, fd, n_bytes))
621 return 1;
622 dump_remainder (filename, fd);
623 }
624 else
625 {
626 if (S_ISREG (stats.st_mode))
627 {
628 off_t current_pos, end_pos;
629 size_t bytes_remaining;
630
631 if ((current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
632 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
633 {
634 off_t diff;
635 /* Be careful here. The current position may actually be
636 beyond the end of the file. */
637 bytes_remaining = (diff = end_pos - current_pos) < 0 ? 0 : diff;
638 }
639 else
640 {
641 error (0, errno, "%s", filename);
642 return 1;
643 }
644
645 if (bytes_remaining <= n_bytes)
646 {
647 /* From the current position to end of file, there are no
648 more bytes than have been requested. So reposition the
649 file pointer to the incoming current position and print
650 everything after that. */
651 lseek (fd, current_pos, SEEK_SET);
652 }
653 else
654 {
655 /* There are more bytes remaining than were requested.
656 Back up. */
657 lseek (fd, -n_bytes, SEEK_END);
658 }
659 dump_remainder (filename, fd);
660 }
661 else
662 return pipe_bytes (filename, fd, n_bytes);
663 }
664 return 0;
665}
666
667/* Output the last N_LINES lines of file FILENAME open for reading in FD.
668 Return 0 if successful, 1 if an error occurred. */
669
670static int
671tail_lines (const char *filename, int fd, long int n_lines)
672{
673 struct stat stats;
674 off_t length;
675
676 if (fstat (fd, &stats))
677 {
678 error (0, errno, "%s", filename);
679 return 1;
680 }
681
682 if (from_start)
683 {
684 if (start_lines (filename, fd, n_lines))
685 return 1;
686 dump_remainder (filename, fd);
687 }
688 else
689 {
690 /* Use file_lines only if FD refers to a regular file with
691 its file pointer positioned at beginning of file. */
692 /* FIXME: adding the lseek conjunct is a kludge.
693 Once there's a reasonable test suite, fix the true culprit:
694 file_lines. file_lines shouldn't presume that the input
695 file pointer is initially positioned to beginning of file. */
696 if (S_ISREG (stats.st_mode)
697 && lseek (fd, (off_t) 0, SEEK_CUR) == (off_t) 0)
698 {
699 length = lseek (fd, (off_t) 0, SEEK_END);
700 if (length != 0 && file_lines (filename, fd, n_lines, length))
701 return 1;
702 dump_remainder (filename, fd);
703 }
704 else
705 return pipe_lines (filename, fd, n_lines);
706 }
707 return 0;
708}
709
710/* Display the last N_UNITS units of file FILENAME, open for reading
711 in FD.
712 Return 0 if successful, 1 if an error occurred. */
713
714static int
715tail (const char *filename, int fd, off_t n_units)
716{
717 if (count_lines)
718 return tail_lines (filename, fd, (long) n_units);
719 else
720 return tail_bytes (filename, fd, n_units);
721}
722
723/* Display the last N_UNITS units of file FILENAME.
724 "-" for FILENAME means the standard input.
725 FILENUM is this file's index in the list of files the user gave.
726 Return 0 if successful, 1 if an error occurred. */
727
728static int
729tail_file (const char *filename, off_t n_units, int filenum)
730{
731 int fd, errors;
732 struct stat stats;
733
734 if (!strcmp (filename, "-")
735 {
736 have_read_stdin = 1;
737 filename = "standard input";
738 if (print_headers)
739 write_header (filename, NULL);
740 errors = tail (filename, 0, n_units);
741 if (forever_multiple)
742 {
743 if (fstat (0, &stats) < 0)
744 {
745 error (0, errno, "standard input");
746 errors = 1;
747 }
748 else if (!S_ISREG (stats.st_mode))
749 {
750 error (0, 0,
751 "standard input: cannot follow end of non-regular file");
752 errors = 1;
753 }
754 if (errors)
755 file_descs[filenum] = -1;
756 else
757 {
758 file_descs[filenum] = 0;
759 file_sizes[filenum] = stats.st_size;
760 }
761 }
762 }
763 else
764 {
765 /* Not standard input. */
766 fd = open (filename, O_RDONLY);
767 if (fd == -1)
768 {
769 if (forever_multiple)
770 file_descs[filenum] = -1;
771 error (0, errno, "%s", filename);
772 errors = 1;
773 }
774 else
775 {
776 if (print_headers)
777 write_header (filename, NULL);
778 errors = tail (filename, fd, n_units);
779 if (forever_multiple)
780 {
781 if (fstat (fd, &stats) < 0)
782 {
783 error (0, errno, "%s", filename);
784 errors = 1;
785 }
786 else if (!S_ISREG (stats.st_mode))
787 {
788 error (0, 0, "%s: cannot follow end of non-regular file",
789 filename);
790 errors = 1;
791 }
792 if (errors)
793 {
794 close (fd);
795 file_descs[filenum] = -1;
796 }
797 else
798 {
799 file_descs[filenum] = fd;
800 file_sizes[filenum] = stats.st_size;
801 }
802 }
803 else
804 {
805 if (close (fd))
806 {
807 error (0, errno, "%s", filename);
808 errors = 1;
809 }
810 }
811 }
812 }
813
814 return errors;
815}
816
817extern int
818tai_main (int argc, char **argv)
819{
820 enum header_mode header_mode = multiple_files;
821 int exit_status = 0;
822 /* If from_start, the number of items to skip before printing; otherwise,
823 the number of items at the end of the file to print. Initially, -1
824 means the value has not been set. */
825 off_t n_units = -1;
826 long int tmp_long;
827 int c; /* Option character. */
828 int n_files;
829 char **file;
830
831 program_name = argv[0];
832 have_read_stdin = 0;
833 count_lines = 1;
834 forever = forever_multiple = from_start = print_headers = 0;
835
836 if (argc > 1
837 && ((argv[1][0] == '-' && ISDIGIT (argv[1][1]))
838 || (argv[1][0] == '+' && (ISDIGIT (argv[1][1])
839 || argv[1][1] == 0))))
840 {
841 /* Old option syntax: a dash or plus, one or more digits (zero digits
842 are acceptable with a plus), and one or more option letters. */
843 if (argv[1][0] == '+')
844 from_start = 1;
845 if (argv[1][1] != '\0')
846 {
847 strtol_error s_err;
848 char *p;
849
850 s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm");
851 n_units = tmp_long;
852 if (s_err == LONGINT_OVERFLOW)
853 {
854 STRTOL_FATAL_ERROR (argv[1], "argument", s_err);
855 }
856
857 /* If a [bkm] suffix was given then count bytes, not lines. */
858 if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm')
859 count_lines = 0;
860
861 /* Parse any appended option letters. */
862 while (*p)
863 {
864 switch (*p)
865 {
866 case 'c':
867 /* Interpret N_UNITS as # of bytes. */
868 count_lines = 0;
869 break;
870
871 case 'f':
872 forever = 1;
873 break;
874
875 case 'l':
876 count_lines = 1;
877 break;
878
879 case 'q':
880 header_mode = never;
881 break;
882
883 case 'v':
884 header_mode = always;
885 break;
886
887 default:
888 error (0, 0, "unrecognized option '%c'", *p);
889 usage (tail_usage);
890 }
891 ++p;
892 }
893 }
894 /* Make the options we just parsed invisible to getopt. */
895 argv[1] = argv[0];
896 argv++;
897 argc--;
898 }
899
900 if (show_version)
901 {
902 printf ("tail - %s\n", PACKAGE_VERSION);
903 exit (EXIT_SUCCESS);
904 }
905
906 if (show_help)
907 usage (tail_usage);
908
909 if (n_units == -1)
910 n_units = DEFAULT_N_LINES;
911
912 /* To start printing with item N_UNITS from the start of the file, skip
913 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix
914 compatibility it's treated the same as `tail +1'. */
915 if (from_start)
916 {
917 if (n_units)
918 --n_units;
919 }
920
921 n_files = argc - optind;
922 file = argv + optind;
923
924 if (n_files > 1 && forever)
925 {
926 forever_multiple = 1;
927 forever = 0;
928 file_descs = (int *) xmalloc (n_files * sizeof (int));
929 file_sizes = (off_t *) xmalloc (n_files * sizeof (off_t));
930 }
931
932 if (header_mode == always
933 || (header_mode == multiple_files && n_files > 1))
934 print_headers = 1;
935
936 if (n_files == 0)
937 {
938 exit_status |= tail_file ("-", n_units, 0);
939 }
940 else
941 {
942 int i;
943 for (i = 0; i < n_files; i++)
944 exit_status |= tail_file (file[i], n_units, i);
945
946 if (forever_multiple)
947 tail_forever (file, n_files);
948 }
949
950 if (have_read_stdin && close (0) < 0)
951 error (EXIT_FAILURE, errno, "-");
952 if (fclose (stdout) == EOF)
953 error (EXIT_FAILURE, errno, "write error");
954 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
955}