Audit tail(1)

1) Specify default in manpage under flag.
2) Boolean and return value style fixes.
3) argv-argc-centric loop.
4) No need to check for argc == 1 before the fflag-subroutine.
5) Remove indentation.
6) Empty line before return.
This commit is contained in:
FRIGN 2015-03-17 23:24:43 +01:00
parent 3c5d0ce4ca
commit 6372a8f227
3 changed files with 35 additions and 36 deletions

2
README
View File

@ -71,7 +71,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
=*| sponge non-posix none =*| sponge non-posix none
#*| strings yes none #*| strings yes none
=*| sync non-posix none =*| sync non-posix none
=* tail yes none =*| tail yes none
=* tar non-posix none =* tar non-posix none
=*| tee yes none =*| tee yes none
=* test yes none =* test yes none

4
tail.1
View File

@ -1,4 +1,4 @@
.Dd March 5, 2015 .Dd March 17, 2015
.Dt TAIL 1 .Dt TAIL 1
.Os sbase .Os sbase
.Sh NAME .Sh NAME
@ -31,7 +31,7 @@ it is an offset from the beginning of each
.Ar file . .Ar file .
If If
.Ar num .Ar num
begins with '-' it is as if no sign was given. begins with '-' it is as if no sign was given. The default is 10 lines.
.It Fl f .It Fl f
If one If one
.Ar file .Ar file

65
tail.c
View File

@ -24,7 +24,7 @@ dropinit(FILE *fp, const char *str)
ssize_t len; ssize_t len;
if (mode == 'n') { if (mode == 'n') {
while (i < num && (len = getline(&buf, &size, fp)) != -1) while (i < num && (len = getline(&buf, &size, fp)) >= 0)
if (len > 0 && buf[len - 1] == '\n') if (len > 0 && buf[len - 1] == '\n')
i++; i++;
} else { } else {
@ -106,52 +106,51 @@ main(int argc, char *argv[])
usage(); usage();
} ARGEND; } ARGEND;
if (argc == 0) if (!argc)
tail(stdin, "<stdin>"); tail(stdin, "<stdin>");
else { else {
if ((many = argc > 1) && fflag) if ((many = argc > 1) && fflag)
usage(); usage();
for (newline = 0; argc > 0; argc--, argv++) { for (newline = 0; *argv; argc--, argv++) {
if (!(fp = fopen(argv[0], "r"))) { if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", argv[0]); weprintf("fopen %s:", *argv);
ret = 1; ret = 1;
continue; continue;
} }
if (many) if (many)
printf("%s==> %s <==\n", printf("%s==> %s <==\n", newline ? "\n" : "", *argv);
newline ? "\n" : "", argv[0]); if (stat(*argv, &st1) < 0)
if (stat(argv[0], &st1) < 0) eprintf("stat %s:", *argv);
eprintf("stat %s:", argv[0]);
if (!(S_ISFIFO(st1.st_mode) || S_ISREG(st1.st_mode))) if (!(S_ISFIFO(st1.st_mode) || S_ISREG(st1.st_mode)))
fflag = 0; fflag = 0;
newline = 1; newline = 1;
tail(fp, argv[0]); tail(fp, *argv);
if (fflag && argc == 1) { if (!fflag) {
tmp = NULL; fclose(fp);
tmpsize = 0; continue;
for (;;) { }
while (getline(&tmp, &tmpsize, fp) != -1) { for (tmp = NULL, tmpsize = 0;;) {
fputs(tmp, stdout); while (getline(&tmp, &tmpsize, fp) >= 0) {
fflush(stdout); fputs(tmp, stdout);
} fflush(stdout);
if (ferror(fp)) }
eprintf("readline %s:", argv[0]); if (ferror(fp))
clearerr(fp); eprintf("readline %s:", *argv);
/* ignore error in case file was removed, we continue clearerr(fp);
* tracking the existing open file descriptor */ /* ignore error in case file was removed, we continue
if (!stat(argv[0], &st2)) { * tracking the existing open file descriptor */
if (st2.st_size < st1.st_size) { if (!stat(*argv, &st2)) {
fprintf(stderr, "%s: file truncated\n", argv[0]); if (st2.st_size < st1.st_size) {
rewind(fp); fprintf(stderr, "%s: file truncated\n", *argv);
} rewind(fp);
st1 = st2; }
} st1 = st2;
sleep(1); }
} sleep(1);
} }
fclose(fp);
} }
} }
return ret; return ret;
} }