Add f-flag to tail(1) and refactor code

This commit is contained in:
FRIGN 2015-02-09 15:06:17 +01:00
parent 6b63fc2f2b
commit 2a83c2c8be

127
tail.c
View File

@ -8,58 +8,7 @@
#include "text.h"
#include "util.h"
static void dropinit(FILE *, const char *, long);
static void taketail(FILE *, const char *, long);
static void
usage(void)
{
eprintf("usage: %s [-n lines] [file]\n", argv0);
}
int
main(int argc, char *argv[])
{
long n = 10;
FILE *fp;
void (*tail)(FILE *, const char *, long) = taketail;
char *lines;
int ret = 0;
int newline, many;
ARGBEGIN {
case 'n':
lines = EARGF(usage());
n = estrtonum(lines, 0, LONG_MAX);
if (lines[0] == '+')
tail = dropinit;
break;
ARGNUM:
n = ARGNUMF();
break;
default:
usage();
} ARGEND;
if (argc == 0) {
tail(stdin, "<stdin>", n);
} else {
many = argc > 1;
for (newline = 0; argc > 0; argc--, argv++) {
if (!(fp = fopen(argv[0], "r"))) {
weprintf("fopen %s:", argv[0]);
ret = 1;
continue;
}
if (many)
printf("%s==> %s <==\n",
newline ? "\n" : "", argv[0]);
newline = 1;
tail(fp, argv[0], n);
fclose(fp);
}
}
return ret;
}
static int fflag = 0;
static void
dropinit(FILE *fp, const char *str, long n)
@ -69,8 +18,8 @@ dropinit(FILE *fp, const char *str, long n)
ssize_t len;
unsigned long i = 0;
while (i < n && ((len = getline(&buf, &size, fp)) != -1))
if (len && buf[len - 1] == '\n')
while (i < n && (len = getline(&buf, &size, fp)) != -1)
if (len > 0 && buf[len - 1] == '\n')
i++;
free(buf);
concat(fp, str, stdout, "<stdout>");
@ -97,6 +46,76 @@ taketail(FILE *fp, const char *str, long n)
free(ring[j]);
}
} while ((j = (j + 1) % n) != i);
free(ring);
free(size);
}
static void
usage(void)
{
eprintf("usage: %s [-f] [-n lines] [file ...]\n", argv0);
}
int
main(int argc, char *argv[])
{
FILE *fp;
size_t n = 10, tmpsize;
int ret = 0, newline, many;
char *lines, *tmp;
void (*tail)(FILE *, const char *, long) = taketail;
ARGBEGIN {
case 'f':
fflag = 1;
break;
case 'n':
lines = EARGF(usage());
n = estrtonum(lines, 0, LONG_MAX);
if (lines[0] == '+')
tail = dropinit;
break;
ARGNUM:
n = ARGNUMF();
break;
default:
usage();
} ARGEND;
if (argc == 0)
tail(stdin, "<stdin>", n);
else {
if ((many = argc > 1) && fflag)
usage();
for (newline = 0; argc > 0; argc--, argv++) {
if (!(fp = fopen(argv[0], "r"))) {
weprintf("fopen %s:", argv[0]);
ret = 1;
continue;
}
if (many)
printf("%s==> %s <==\n",
newline ? "\n" : "", argv[0]);
newline = 1;
tail(fp, argv[0], n);
if (fflag && argc == 1) {
for(;; tmp = NULL, tmpsize = 0) {
while (getline(&tmp, &tmpsize, fp) != -1) {
fputs(tmp, stdout);
fflush(stdout);
free(tmp);
tmp = NULL;
tmpsize = 0;
}
if (ferror(fp))
eprintf("readline '%s':", argv[0]);
clearerr(fp);
}
}
fclose(fp);
}
}
return ret;
}