tailf: remove deprecated utility
March 2017 is gone, it is time to remove this utility as scheduled in
earlier commit, and promised in manual page.
Reference: 3f8478a71c
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
parent
eff2c9a426
commit
70ca1a7772
|
@ -156,7 +156,6 @@ ylwrap
|
|||
/swapoff
|
||||
/swapon
|
||||
/switch_root
|
||||
/tailf
|
||||
/taskset
|
||||
/test_*
|
||||
/tunelp
|
||||
|
|
|
@ -13,11 +13,6 @@ why: Output printed by --compare option was nonesense.
|
|||
|
||||
--------------------------
|
||||
|
||||
what: tailf
|
||||
why: "tail -f" is better nowadays, tailf has unfixed bugs
|
||||
|
||||
--------------------------
|
||||
|
||||
what: sfdisk --show-size
|
||||
why: this does not belong to fdisk, use "blockdev --getsz"
|
||||
|
||||
|
|
|
@ -90,9 +90,6 @@ endif
|
|||
if BUILD_SETSID
|
||||
dist_bashcompletion_DATA += bash-completion/setsid
|
||||
endif
|
||||
if BUILD_TAILF
|
||||
dist_bashcompletion_DATA += bash-completion/tailf
|
||||
endif
|
||||
if BUILD_WHEREIS
|
||||
dist_bashcompletion_DATA += bash-completion/whereis
|
||||
endif
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
_tailf_module()
|
||||
{
|
||||
local cur prev OPTS
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
case $prev in
|
||||
'-n'|'--lines')
|
||||
COMPREPLY=( $(compgen -W "number" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'-h'|'--help'|'-V'|'--version')
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
case $cur in
|
||||
-*)
|
||||
OPTS="--lines --version --help"
|
||||
COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -- $cur) )
|
||||
return 0
|
||||
}
|
||||
complete -F _tailf_module tailf
|
|
@ -1644,13 +1644,6 @@ AM_CONDITIONAL([BUILD_HEXDUMP], [test "x$build_hexdump" = xyes])
|
|||
UL_BUILD_INIT([rev], [yes])
|
||||
AM_CONDITIONAL([BUILD_REV], [test "x$build_rev" = xyes])
|
||||
|
||||
AC_ARG_ENABLE([tailf],
|
||||
AS_HELP_STRING([--enable-tailf], [build tailf (deprecated)]),
|
||||
[], [UL_DEFAULT_ENABLE([tailf], [no])]
|
||||
)
|
||||
UL_BUILD_INIT([tailf])
|
||||
AM_CONDITIONAL([BUILD_TAILF], [test "x$build_tailf" = xyes])
|
||||
|
||||
|
||||
AC_ARG_ENABLE([tunelp],
|
||||
AS_HELP_STRING([--enable-tunelp], [build tunelp]),
|
||||
|
|
|
@ -88,7 +88,6 @@ TS_CMD_SETSID=${TS_CMD_SETSID-"$top_builddir/setsid"}
|
|||
TS_CMD_SWAPLABEL=${TS_CMD_SWAPLABEL:-"$top_builddir/swaplabel"}
|
||||
TS_CMD_SWAPOFF=${TS_CMD_SWAPOFF:-"$top_builddir/swapoff"}
|
||||
TS_CMD_SWAPON=${TS_CMD_SWAPON:-"$top_builddir/swapon"}
|
||||
TS_CMD_TAILF=${TS_CMD_TAILF-"$top_builddir/tailf"}
|
||||
TS_CMD_UL=${TS_CMD_UL-"$top_builddir/ul"}
|
||||
TS_CMD_UMOUNT=${TS_CMD_UMOUNT:-"$top_builddir/umount"}
|
||||
TS_CMD_UTMPDUMP=${TS_CMD_UTMPDUMP-"$top_builddir/utmpdump"}
|
||||
|
|
|
@ -101,7 +101,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
tunelp:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -112,5 +112,4 @@ line:
|
|||
more: libtinfo
|
||||
pg: libncursesw libtinfo
|
||||
rev:
|
||||
tailf:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -101,7 +101,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
tunelp:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -101,7 +101,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
tunelp:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -119,5 +119,4 @@ line:
|
|||
more: libtinfo
|
||||
pg: libncursesw libtinfo
|
||||
rev:
|
||||
tailf:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -101,7 +101,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
tunelp:
|
||||
ul: libtinfo
|
||||
|
|
|
@ -76,7 +76,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -85,7 +85,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -60,7 +60,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -77,7 +77,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -91,7 +91,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: libselinux rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -98,7 +98,6 @@ setterm: libtinfo
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
unshare:
|
||||
|
|
|
@ -104,7 +104,6 @@ sfdisk.static: STATIC
|
|||
su: libpam libpam_misc
|
||||
sulogin: rypt
|
||||
switch_root:
|
||||
tailf:
|
||||
taskset:
|
||||
ul: libtinfo
|
||||
umount.static: STATIC
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This file is part of util-linux.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
TS_TOPDIR="${0%/*}/../.."
|
||||
TS_DESC="simple"
|
||||
|
||||
. $TS_TOPDIR/functions.sh
|
||||
ts_init "$*"
|
||||
|
||||
ts_check_test_command "$TS_CMD_TAILF"
|
||||
|
||||
# This test is unsafe for some filesystems and for case non-inotify. We don't
|
||||
# fix it since tailf is deprecated. Just keep this test for the test log.
|
||||
TS_KNOWN_FAIL="yes"
|
||||
|
||||
INPUT=$TS_OUTDIR/$TS_TESTNAME.input
|
||||
|
||||
rm -f $INPUT
|
||||
echo {a..z} > $INPUT
|
||||
|
||||
$TS_CMD_TAILF $INPUT > $TS_OUTPUT 2>&1 &
|
||||
|
||||
sleep 0.5
|
||||
echo {0..9} >> $INPUT
|
||||
sleep 0.5
|
||||
|
||||
rm -f $INPUT
|
||||
|
||||
ts_finalize
|
|
@ -43,13 +43,6 @@ dist_man_MANS += text-utils/rev.1
|
|||
rev_SOURCES = text-utils/rev.c
|
||||
endif
|
||||
|
||||
if BUILD_TAILF
|
||||
usrbin_exec_PROGRAMS += tailf
|
||||
dist_man_MANS += text-utils/tailf.1
|
||||
tailf_SOURCES = text-utils/tailf.c
|
||||
tailf_LDADD = $(LDADD) libcommon.la
|
||||
endif
|
||||
|
||||
if BUILD_LINE
|
||||
usrbin_exec_PROGRAMS += line
|
||||
line_SOURCES = text-utils/line.c
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
.\" tailf.1 -- man page for tailf
|
||||
.\" Copyright 1996, 2003 Rickard E. Faith (faith@acm.org)
|
||||
.\"
|
||||
.\" Permission is granted to make and distribute verbatim copies of this
|
||||
.\" manual provided the copyright notice and this permission notice are
|
||||
.\" preserved on all copies.
|
||||
.\"
|
||||
.\" Permission is granted to copy and distribute modified versions of this
|
||||
.\" manual under the conditions for verbatim copying, provided that the
|
||||
.\" entire resulting derived work is distributed under the terms of a
|
||||
.\" permission notice identical to this one.
|
||||
.\"
|
||||
.\" Since the Linux kernel and libraries are constantly changing, this
|
||||
.\" manual page may be incorrect or out-of-date. The author(s) assume no
|
||||
.\" responsibility for errors or omissions, or for damages resulting from
|
||||
.\" the use of the information contained herein. The author(s) may not
|
||||
.\" have taken the same level of care in the production of this manual,
|
||||
.\" which is licensed free of charge, as they might when working
|
||||
.\" professionally.
|
||||
.\"
|
||||
.\" Formatted or processed versions of this manual, if unaccompanied by
|
||||
.\" the source, must acknowledge the copyright and authors of this work.
|
||||
.\"
|
||||
.TH TAILF 1 "March 2015" "util-linux" "User Commands"
|
||||
.SH NAME
|
||||
tailf \- follow the growth of a log file
|
||||
.SH SYNOPSIS
|
||||
.B tailf
|
||||
[option]
|
||||
.I file
|
||||
.SH DESCRIPTION
|
||||
.B tailf is deprecated.
|
||||
It may have unfixed bugs and will be removed from util-linux in March 2017.
|
||||
Nowadays it's safe to use
|
||||
.B tail -f
|
||||
(from coreutils), in contrast to what the original documentation below says.
|
||||
.PP
|
||||
.B tailf
|
||||
will print out the last 10 lines of the given \fIfile\fR and then wait
|
||||
for this \fIfile\fR to grow. It is similar to
|
||||
.B tail -f
|
||||
but does not access the file when it is not growing. This has the side
|
||||
effect of not updating the access time for the file, so a filesystem flush
|
||||
does not occur periodically when no log activity is happening.
|
||||
.PP
|
||||
.B tailf
|
||||
is extremely useful for monitoring log files on a laptop when logging is
|
||||
infrequent and the user wishes the hard disk to spin down to conserve
|
||||
battery life.
|
||||
.TP
|
||||
.BR \-n , " -\-lines=\fInumber\fR" , " \-\fInumber\fR"
|
||||
Output the last
|
||||
.I number
|
||||
lines, instead of the last 10.
|
||||
.TP
|
||||
\fB\-V\fR, \fB\-\-version
|
||||
Display version information and exit.
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help
|
||||
Display help text and exit.
|
||||
|
||||
.SH AUTHOR
|
||||
This program was originally written by Rik Faith (faith@acm.org) and may be freely
|
||||
distributed under the terms of the X11/MIT License. There is ABSOLUTELY
|
||||
NO WARRANTY for this program.
|
||||
|
||||
The latest inotify-based implementation was written by Karel Zak (kzak@redhat.com).
|
||||
.SH "SEE ALSO"
|
||||
.BR less (1),
|
||||
.BR tail (1)
|
||||
.SH AVAILABILITY
|
||||
The tailf command is part of the util-linux package and is available from
|
||||
https://www.kernel.org/pub/linux/utils/util-linux/.
|
|
@ -1,295 +0,0 @@
|
|||
/* tailf.c -- tail a log file and then follow it
|
||||
* Created: Tue Jan 9 15:49:21 1996 by faith@acm.org
|
||||
* Copyright 1996, 2003 Rickard E. Faith (faith@acm.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This command is deprecated. The utility is in maintenance mode,
|
||||
* meaning we keep them in source tree for backward compatibility
|
||||
* only. Do not waste time making this command better, unless the
|
||||
* fix is about security or other very critical issue.
|
||||
*
|
||||
* See Documentation/deprecated.txt for more information.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/mman.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_INOTIFY_INIT
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
|
||||
#include "nls.h"
|
||||
#include "xalloc.h"
|
||||
#include "strutils.h"
|
||||
#include "c.h"
|
||||
#include "closestream.h"
|
||||
|
||||
#define DEFAULT_LINES 10
|
||||
|
||||
/* st->st_size has to be greater than zero and smaller or equal to SIZE_MAX! */
|
||||
static void tailf(const char *filename, size_t lines, struct stat *st)
|
||||
{
|
||||
int fd;
|
||||
size_t i;
|
||||
char *data;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
err(EXIT_FAILURE, _("cannot open %s"), filename);
|
||||
data = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
i = (size_t) st->st_size - 1;
|
||||
|
||||
/* humans do not think last new line in a file should be counted,
|
||||
* in that case do off by one from counter point of view */
|
||||
if (data[i] == '\n')
|
||||
lines++;
|
||||
while (i) {
|
||||
if (data[i] == '\n' && --lines == 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
fwrite(data + i, st->st_size - i, 1, stdout);
|
||||
|
||||
munmap(data, st->st_size);
|
||||
close(fd);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void roll_file(const char *filename, struct stat *old)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int fd;
|
||||
struct stat st;
|
||||
off_t pos;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
err(EXIT_FAILURE, _("cannot open %s"), filename);
|
||||
|
||||
if (fstat(fd, &st) == -1)
|
||||
err(EXIT_FAILURE, _("stat of %s failed"), filename);
|
||||
|
||||
if (st.st_size == old->st_size) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lseek(fd, old->st_size, SEEK_SET) != (off_t)-1) {
|
||||
ssize_t rc, wc;
|
||||
|
||||
while ((rc = read(fd, buf, sizeof(buf))) > 0) {
|
||||
wc = write(STDOUT_FILENO, buf, rc);
|
||||
if (rc != wc)
|
||||
warnx(_("incomplete write to \"%s\" (written %zd, expected %zd)\n"),
|
||||
filename, wc, rc);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
pos = lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
/* If we've successfully read something, use the file position, this
|
||||
* avoids data duplication. If we read nothing or hit an error, reset
|
||||
* to the reported size, this handles truncated files.
|
||||
*/
|
||||
old->st_size = (pos != -1 && pos != old->st_size) ? pos : st.st_size;
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void watch_file(const char *filename, struct stat *old)
|
||||
{
|
||||
do {
|
||||
roll_file(filename, old);
|
||||
xusleep(250000);
|
||||
} while(1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_INOTIFY_INIT
|
||||
|
||||
#define EVENTS (IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)
|
||||
#define NEVENTS 4
|
||||
|
||||
static int watch_file_inotify(const char *filename, struct stat *old)
|
||||
{
|
||||
char buf[ NEVENTS * sizeof(struct inotify_event) ];
|
||||
int fd, ffd, e;
|
||||
ssize_t len;
|
||||
|
||||
fd = inotify_init();
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
ffd = inotify_add_watch(fd, filename, EVENTS);
|
||||
if (ffd == -1) {
|
||||
if (errno == ENOSPC)
|
||||
errx(EXIT_FAILURE, _("%s: cannot add inotify watch "
|
||||
"(limit of inotify watches was reached)."),
|
||||
filename);
|
||||
|
||||
err(EXIT_FAILURE, _("%s: cannot add inotify watch."), filename);
|
||||
}
|
||||
|
||||
while (ffd >= 0) {
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
continue;
|
||||
if (len < 0)
|
||||
err(EXIT_FAILURE,
|
||||
_("%s: cannot read inotify events"), filename);
|
||||
|
||||
for (e = 0; e < len; ) {
|
||||
struct inotify_event *ev = (struct inotify_event *) &buf[e];
|
||||
|
||||
if (ev->mask & IN_MODIFY)
|
||||
roll_file(filename, old);
|
||||
else {
|
||||
close(ffd);
|
||||
ffd = -1;
|
||||
break;
|
||||
}
|
||||
e += sizeof(struct inotify_event) + ev->len;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_INOTIFY_INIT */
|
||||
|
||||
static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
||||
{
|
||||
fputs(USAGE_HEADER, out);
|
||||
fprintf(out, _(" %s [option] <file>\n"), program_invocation_short_name);
|
||||
|
||||
fputs(USAGE_SEPARATOR, out);
|
||||
fputs(_("Follow the growth of a log file.\n"), out);
|
||||
|
||||
fputs(USAGE_OPTIONS, out);
|
||||
fputs(_(" -n, --lines <number> output the last <number> lines\n"), out);
|
||||
fputs(_(" -<number> same as '-n <number>'\n"), out);
|
||||
|
||||
fputs(USAGE_SEPARATOR, out);
|
||||
fputs(USAGE_HELP, out);
|
||||
fputs(USAGE_VERSION, out);
|
||||
fprintf(out, USAGE_MAN_TAIL("tailf(1)"));
|
||||
fputs(_("Warning: use of 'tailf' is deprecated, use 'tail -f' instead.\n"), out);
|
||||
|
||||
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* parses -N option */
|
||||
static long old_style_option(int *argc, char **argv, size_t *lines)
|
||||
{
|
||||
int i = 1, nargs = *argc, ret = 0;
|
||||
|
||||
while(i < nargs) {
|
||||
if (argv[i][0] == '-' && isdigit(argv[i][1])) {
|
||||
*lines = strtoul_or_err(argv[i] + 1,
|
||||
_("failed to parse number of lines"));
|
||||
nargs--;
|
||||
ret = 1;
|
||||
if (nargs - i)
|
||||
memmove(argv + i, argv + i + 1,
|
||||
sizeof(char *) * (nargs - i));
|
||||
} else
|
||||
i++;
|
||||
}
|
||||
*argc = nargs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *filename;
|
||||
size_t lines;
|
||||
int ch;
|
||||
struct stat st;
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{ "lines", required_argument, NULL, 'n' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
atexit(close_stdout);
|
||||
|
||||
if (!old_style_option(&argc, argv, &lines))
|
||||
lines = DEFAULT_LINES;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "n:N:Vh", longopts, NULL)) != -1)
|
||||
switch ((char)ch) {
|
||||
case 'n':
|
||||
case 'N':
|
||||
lines = strtoul_or_err(optarg,
|
||||
_("failed to parse number of lines"));
|
||||
break;
|
||||
case 'V':
|
||||
printf(UTIL_LINUX_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'h':
|
||||
usage(stdout);
|
||||
default:
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (argc == optind)
|
||||
errx(EXIT_FAILURE, _("no input file specified"));
|
||||
|
||||
filename = argv[optind];
|
||||
|
||||
if (stat(filename, &st) != 0)
|
||||
err(EXIT_FAILURE, _("stat of %s failed"), filename);
|
||||
if (!S_ISREG(st.st_mode))
|
||||
errx(EXIT_FAILURE, _("%s: is not a file"), filename);
|
||||
|
||||
/* mmap is based on size_t */
|
||||
if (st.st_size > 0 && (uintmax_t) st.st_size <= (uintmax_t) SIZE_MAX)
|
||||
tailf(filename, lines, &st);
|
||||
|
||||
#ifdef HAVE_INOTIFY_INIT
|
||||
if (!watch_file_inotify(filename, &st))
|
||||
#endif
|
||||
watch_file(filename, &st);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue