#!/usr/bin/env compileAndGo # See http://Yost.com/computers/compileAndGo compiler = gcc compileAndGo /* tac.c -- Author unknown */ #include #include #include #include /* changed from LENGTH to larger number -dyost 870619 */ /* 2005-08-05 also digest old-style Mac files with \r line endings -dyost */ #define LENGTH (1000 * 1024) main(argc, argv) int argc; char **argv; { off_t off, lseek(); static char buffer[ 1 + LENGTH + LENGTH + 1 ]; char *buf; char *readerr = "Read error at offset %lu of %s\n"; int fd, any; void output(), utcopyn(); if (argc < 2) { (void) fprintf(stderr, "Usage: tac file ...\n"); exit(1); } buf = buffer; *buf++ = '\n'; any = 0; while (--argc) { register int i; { register char *filename; { struct stat st; if (stat(filename = *++argv, &st) == -1) { (void) fprintf(stderr , "Bad status for %s\n", filename); any++; continue; } if ((off = st.st_size) == 0) continue; } if ((fd = open(filename, 0)) == -1) { (void) fprintf(stderr, "Can't open %s\n", filename); any++; continue; } if ((i = off % LENGTH ) == 0) i = LENGTH; off -= i; if (lseek(fd, off, 0) < 0) { (void) fprintf(stderr, "Can't seek to end of %s\n", filename); (void) close(fd); any++; continue; } if (read(fd, buf, i) != i) { (void) fprintf(stderr, readerr, off, filename); (void) close(fd); any++; continue; } } { register char *begin; register char *end; begin = end = buf + i; if (*--begin == '\n' || *begin == '\r') end = begin; for (;;) { while (*--begin != '\n' && *begin != '\r') continue; if (begin < buf) { if (off == 0) { output(begin, end); (void) close(fd); break; } (void) lseek(fd, off -= LENGTH, 0); if ((i = end - buf) > LENGTH) { (void) fprintf(stderr, "Line too long\n"); any++; i = LENGTH; } utcopyn(begin = buf + LENGTH, buf, i); end = begin + i; if (read(fd, buf, LENGTH) != LENGTH) { (void) fprintf(stderr, readerr, off, *argv); any++; (void) close(fd); break; } continue; } output(begin, end); end = begin; } } } exit(any); } void output( register char* begin, register char* end ) { register FILE *iop = stdout; for (begin++; begin < end; ++begin) (void) putc(*begin, iop); (void) putc('\n', iop); fflush (iop); } void utcopyn(tp, fp, n) register char *tp, *fp; register int n; { while (--n >= 0) *tp++ = *fp++; return; }