X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=tail.c;h=ff77bde77e69b0ea206d9bea8a270cd850dd72a6;hb=e5f39576650933770153e82c63a46f27fcd72b0e;hp=4a1aa8436254d5ccb8018fb410525d376e4e2381;hpb=98bbd688a80627ec4071b7c819ee2116f5ecc6d4;p=oweals%2Fbusybox.git diff --git a/tail.c b/tail.c index 4a1aa8436..ff77bde77 100644 --- a/tail.c +++ b/tail.c @@ -1,320 +1,247 @@ /* vi: set sw=4 ts=4: */ -/* tail -- output the last part of file(s) - Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - Original version by Paul Rubin . - Extensions by David MacKenzie . - tail -f for multiple files by Ian Lance Taylor . - - Rewrote the option parser, removed locales support, - and generally busyboxed, Erik Andersen - - Removed superfluous options and associated code ("-c", "-n", "-q"). - Removed "tail -f" support for multiple files. - Both changes by Friedrich Vedder . +/* + * Mini tail implementation for busybox + * + * + * Copyright (C) 2001 by Matt Kraai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ - Compleate Rewrite to correctly support "-NUM", "+NUM", and "-s" by - E.Allen Soard (esp@espsw.net). - */ -#include -#include #include -#include +#include +#include #include #include -#include -#include -#include "internal.h" +#include +#include "busybox.h" -#define STDIN "standard input" -#define LINES 0 -#define BYTES 1 +static const struct suffix_mult tail_suffixes[] = { + { "b", 512 }, + { "k", 1024 }, + { "m", 1048576 }, + { NULL, 0 } +}; -static int n_files = 0; -static char **files = NULL; +static const int BYTES = 0; +static const int LINES = 1; -static char follow=0; +static char *tailbuf; +static int taillen; +static int newline; -#ifdef BB_FEATURE_SIMPLE_TAIL -static const char unit_type=LINES; -static const char sleep_int=1; -#else -static char unit_type=LINES; -static int sleep_int=1; -static char verbose = 0; -#endif - -//static off_t units=-11; -static off_t units=0; - -int tail_stream(int file_id) +static void tailbuf_append(char *buf, int len) { - int fd; - ssize_t bytes_read=0; - ssize_t bs=BUFSIZ; - ssize_t startpoint=bs; - ssize_t endpoint=0; - ssize_t count=0; - ssize_t filesize=0; - ssize_t filelocation=0; - char direction=1; - char * buffer; - char pipe; - - - if (!strcmp(files[file_id], STDIN)) - fd = 0; - else - fd = open(files[file_id], O_RDONLY); - if (fd == -1) - fatalError("Unable to open file %s.\n", files[file_id]); - - buffer=malloc(bs); - - filesize=lseek(fd, -1, SEEK_END)+1; - pipe=(filesize<=0); + tailbuf = xrealloc(tailbuf, taillen + len); + memcpy(tailbuf + taillen, buf, len); + taillen += len; +} - if(units>=0) - lseek(fd,0,SEEK_SET); - else { - direction=-1; - count=1; - } - while(units != 0) { - if (pipe) { - char * line; - ssize_t f_size=0; +static void tailbuf_trunc() +{ + char *s; + s = memchr(tailbuf, '\n', taillen); + memmove(tailbuf, s + 1, taillen - ((s + 1) - tailbuf)); + taillen -= (s + 1) - tailbuf; + newline = 0; +} - bs=BUFSIZ; - line=malloc(bs); - while(1) { - bytes_read=read(fd,line,bs); - if(bytes_read<=0) - break; - buffer=realloc(buffer,f_size+bytes_read); - memcpy(&buffer[f_size],line,bytes_read); - filelocation=f_size+=bytes_read; - } - bs=f_size; - if(direction<0) - bs--; - if (line) - free(line); - } else { - filelocation = lseek(fd, 0, SEEK_CUR); - if(direction<0) { - if(filelocation 0) { + switch (opt) { + case 'f': + follow = 1; break; - bs=bytes_read; - } - startpoint=bs; - if(direction>0) { - endpoint=startpoint; - startpoint=0; - } - for(;startpoint!=endpoint;startpoint+=direction) { #ifndef BB_FEATURE_SIMPLE_TAIL - if(unit_type==BYTES) - count++; - else + case 'c': + units = BYTES; + /* FALLS THROUGH */ #endif - if(buffer[startpoint-1]=='\n') - count++; - if (!pipe) - filelocation=lseek(fd,0,SEEK_CUR); - if(count==abs(units)) + case 'n': + count = parse_number(optarg, tail_suffixes); + if (count < 0) + count = -count; + if (optarg[0] == '+') + from_top = 1; break; - } - if((count==abs(units)) | pipe) - break; - if(direction<0){ - filelocation = lseek(fd, -bytes_read, SEEK_CUR); - if(filelocation==0) +#ifndef BB_FEATURE_SIMPLE_TAIL + case 'q': + hide_headers = 1; + break; + case 's': + sleep_period = parse_number(optarg, 0); + break; + case 'v': + show_headers = 1; break; +#endif + default: + show_usage(); } } - if(pipe && (direction<0)) - bs++; - bytes_read=bs-startpoint; - memcpy(&buffer[0],&buffer[startpoint],bytes_read); - bs=BUFSIZ; - while (1) { - if((filelocation>0 || pipe)){ - write(1,buffer,bytes_read); - } - bytes_read = read(fd, buffer, bs); - filelocation+=bytes_read; - if (bytes_read <= 0) { - if (!follow) { - close(fd); - break; + /* open all the files */ + fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1)); + if (argc == optind) { + fds[nfiles++] = STDIN_FILENO; + argv[optind] = "standard input"; + } else { + for (i = optind; i < argc; i++) { + if (strcmp(argv[i], "-") == 0) { + fds[nfiles++] = STDIN_FILENO; + argv[i] = "standard input"; + } else if ((fds[nfiles++] = open(argv[i], O_RDONLY)) < 0) { + perror_msg("%s", argv[i]); + status = EXIT_FAILURE; } - sleep(sleep_int); } - usleep(sleep_int * 1000); } - if (buffer) - free(buffer); - return 0; -} + +#ifndef BB_FEATURE_SIMPLE_TAIL + /* tail the files */ + if (!from_top && units == BYTES) + tailbuf = xmalloc(count); +#endif -void add_file(char *name) -{ - ++n_files; - files = realloc(files, n_files); - files[n_files - 1] = (char *) malloc(strlen(name) + 1); - strcpy(files[n_files - 1], name); -} + for (i = 0; i < nfiles; i++) { + if (fds[i] == -1) + continue; + seen = 0; + if (show_headers || (!hide_headers && nfiles > 1)) + printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]); + while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { + if (from_top) { +#ifndef BB_FEATURE_SIMPLE_TAIL + if (units == BYTES) { + if (count - 1 <= seen) + nwrite = nread; + else if (count - 1 <= seen + nread) + nwrite = nread + seen - (count - 1); + else + nwrite = 0; + seen += nread; + } else { +#else + { +#endif + if (count - 1 <= seen) + nwrite = nread; + else { + nwrite = 0; + for (s = memchr(buf, '\n', nread); s != NULL; + s = memchr(s+1, '\n', nread - (s + 1 - buf))) { + if (count - 1 <= ++seen) { + nwrite = nread - (s + 1 - buf); + break; + } + } + } + } + if (full_write(STDOUT_FILENO, buf + nread - nwrite, + nwrite) < 0) { + perror_msg("write"); + status = EXIT_FAILURE; + break; + } + } else { +#ifndef BB_FEATURE_SIMPLE_TAIL + if (units == BYTES) { + if (nread < count) { + memmove(tailbuf, tailbuf + nread, count - nread); + memcpy(tailbuf + count - nread, buf, nread); + } else { + memcpy(tailbuf, buf + nread - count, count); + } + seen += nread; + } else { +#else + { +#endif + for (start = buf, end = memchr(buf, '\n', nread); + end != NULL; start = end+1, + end = memchr(start, '\n', nread - (start - buf))) { + if (newline && count <= seen) + tailbuf_trunc(); + tailbuf_append(start, end - start + 1); + seen++; + newline = 1; + } + if (newline && count <= seen && nread - (start - buf) > 0) + tailbuf_trunc(); + tailbuf_append(start, nread - (start - buf)); + } + } + } + if (nread < 0) { + perror_msg("read"); + status = EXIT_FAILURE; + } -int tail_main(int argc, char **argv) -{ - int show_headers = 1; - int test; - int c; - int nargs=0; - char **argn=NULL; +#ifndef BB_FEATURE_SIMPLE_TAIL + if (!from_top && units == BYTES) { + if (count < seen) + seen = count; + if (full_write(STDOUT_FILENO, tailbuf + count - seen, seen) < 0) { + perror_msg("write"); + status = EXIT_FAILURE; + } + } +#endif - opterr = 0; - - for(c=0;c'9') { - switch (optarg[strlen(optarg)-1]) { - case 'b': - test *= 512; - break; - case 'k': - test *= 1024; - break; - case 'm': - test *= (1024 * 1024); - break; - default: - fprintf(stderr,"Size must be b,k, or m."); - usage(tail_usage); - } + if ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { + if (show_headers || (!hide_headers && nfiles > 1)) + printf("\n==> %s <==\n", argv[optind + i]); + + do { + full_write(STDOUT_FILENO, buf, nread); + } while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0); + } + + if (nread < 0) { + perror_msg("read"); + status = EXIT_FAILURE; } - if(optarg[0]=='+') - units=test+1; - else - units=-(test+1); - break; - case 'q': - show_headers = 0; - break; - case 's': - sleep_int = atoi(optarg); - if(sleep_int<1) - sleep_int=1; - break; - case 'v': - verbose = 1; - break; -#endif - case 'f': - follow = 1; - break; - case 'h': - usage(tail_usage); - break; - case 'n': - test = atoi(optarg); - if (test) { - if (optarg[0] == '+') - units = test; - else - units = -(test+1); - } else - usage(tail_usage); - break; - default: - errorMsg("\nUnknown arg: %c.\n\n",c); - usage(tail_usage); } } - while (optind < nargs) { - if (!strcmp(argn[optind], "-")) - add_file(STDIN); - else - add_file(argn[optind]); - optind++; - } - if(units==0) - units=-11; - if(units>0) - units--; - if (n_files == 0) - add_file(STDIN); - if (n_files == 1) -#ifndef BB_FEATURE_SIMPLE_TAIL - if (!verbose) -#endif - show_headers = 0; - for (test = 0; test < n_files; test++) { - if (show_headers) - printf("==> %s <==\n", files[test]); - tail_stream(test); - } - if(files) - free(files); - if(argn) - free(argn); - return 0; -} -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ + return status; +}