146 lines
2.4 KiB
C
146 lines
2.4 KiB
C
/* tail - print the end of a file */
|
|
|
|
#include <stdio.h>
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#define BLANK ' '
|
|
#define TAB '\t'
|
|
#define NEWL '\n'
|
|
|
|
int lines, chars;
|
|
char buff[BUFSIZ];
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
char *s;
|
|
FILE *input, *fopen();
|
|
int count;
|
|
|
|
setbuf(stdout, buff);
|
|
argc--;
|
|
argv++;
|
|
lines = TRUE;
|
|
chars = FALSE;
|
|
count = -10;
|
|
|
|
if (argc == 0) {
|
|
tail(stdin, count);
|
|
exit(0);
|
|
}
|
|
s = *argv;
|
|
if (*s == '-' || *s == '+') {
|
|
s++;
|
|
if (*s >= '0' && *s <= '9') {
|
|
count = stoi(*argv);
|
|
s++;
|
|
while (*s >= '0' && *s <= '9') s++;
|
|
}
|
|
if (*s == 'c') {
|
|
chars = TRUE;
|
|
lines = FALSE;
|
|
} else if (*s != 'l' && *s != '\0') {
|
|
fprintf(stderr, "tail: unknown option %c\n", *s);
|
|
argc = 0;
|
|
}
|
|
argc--;
|
|
argv++;
|
|
}
|
|
if (argc < 0) {
|
|
fprintf(stderr, "Usage: tail [+/-[number][lc]] [files]\n");
|
|
exit(1);
|
|
}
|
|
if (argc == 0) tail(stdin, count);
|
|
|
|
else if ((input = fopen(*argv, "r")) == NULL) {
|
|
fprintf(stderr, "tail: can't open %s\n", *argv);
|
|
exit(1);
|
|
} else {
|
|
tail(input, count);
|
|
fclose(input);
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
/* Stoi - convert string to integer */
|
|
stoi(s)
|
|
char *s;
|
|
{
|
|
int n, sign;
|
|
|
|
while (*s == BLANK || *s == NEWL || *s == TAB) s++;
|
|
|
|
sign = 1;
|
|
if (*s == '+')
|
|
s++;
|
|
else if (*s == '-') {
|
|
sign = -1;
|
|
s++;
|
|
}
|
|
for (n = 0; *s >= '0' && *s <= '9'; s++) n = 10 * n + *s - '0';
|
|
return(sign * n);
|
|
}
|
|
|
|
/* Tail - print 'count' lines/chars */
|
|
|
|
#define INCR(p) if (p >= end) p=cbuf ; else p++
|
|
#define BUF_SIZE 4098
|
|
|
|
char cbuf[BUF_SIZE];
|
|
|
|
tail(in, goal)
|
|
FILE *in;
|
|
int goal;
|
|
{
|
|
int c, count;
|
|
char *start, *finish, *end;
|
|
|
|
count = 0;
|
|
|
|
if (goal > 0) { /* skip */
|
|
count++; /* start counting at 1 */
|
|
if (lines) /* lines */
|
|
while ((c = getc(in)) != EOF) {
|
|
if (c == NEWL) count++;
|
|
if (count >= goal) break;
|
|
}
|
|
else /* chars */
|
|
while (getc(in) != EOF) {
|
|
count++;
|
|
if (count >= goal) break;
|
|
}
|
|
if (count >= goal) while ((c = getc(in)) != EOF)
|
|
putc(c, stdout);
|
|
} else { /* tail */
|
|
|
|
goal = -goal;
|
|
start = finish = cbuf;
|
|
end = &cbuf[BUF_SIZE - 1];
|
|
|
|
while ((c = getc(in)) != EOF) {
|
|
*finish = c;
|
|
INCR(finish);
|
|
|
|
if (start == finish) INCR(start);
|
|
if (!lines || c == NEWL) count++;
|
|
|
|
if (count > goal) {
|
|
count = goal;
|
|
if (lines) while (*start != NEWL)
|
|
INCR(start);
|
|
INCR(start);
|
|
}
|
|
} /* end while */
|
|
|
|
while (start != finish) {
|
|
putc(*start, stdout);
|
|
INCR(start);
|
|
}
|
|
|
|
} /* end else */
|
|
|
|
} /* end tail */
|