/* Delete input prefix, keeping only the last few lines. Usage: ./tail {line_count} < input.txt > output.txt Where {line_count} is the number of lines. Sign is ignored, so "-10" is interpreted the same as "10". This tool basically implements a subset of the standard tail(1) tool, except we optimize for code size. */ #include #include #include int main(int argc, char **argv) { int line_count, i, c; int capacity = 0, size = 0, eof = 0; char *buffer = NULL; if( argc != 2 ) return printf("%s {line_count}\n", *argv); line_count = abs(atoi(argv[1])); while( !eof ) { /* Extend input buffer. */ if( size == capacity ) { capacity = (capacity != 0 ? capacity * 2 : 256); if( (buffer = (char*)realloc(buffer, capacity)) == NULL ) { fprintf(stderr, "Out of memory (need %d)\n", capacity); return 1; } } size += fread(buffer + size, 1, capacity - size, stdin); eof = size < capacity; if( size > 0 ) { /* Scan backwards until we got enough lines. */ c = 0; i = size - 1; if( buffer[i] != '\n' ) c++; for(; i >= 0; i--) { if( buffer[i] == '\n' ) { c++; if( c > line_count ) break; } } /* Discard prefix, keeping only the suffix that has enough lines. */ i++; if( i > 0 ) memmove(buffer, buffer + i, size -= i); } } /* Write output. */ fwrite(buffer, size, 1, stdout); free(buffer); return 0; }