diff options
-rw-r--r-- | Changelog | 8 | ||||
-rw-r--r-- | TODO | 7 | ||||
-rw-r--r-- | coreutils/dd.c | 46 | ||||
-rw-r--r-- | coreutils/tail.c | 176 | ||||
-rw-r--r-- | dd.c | 46 | ||||
-rw-r--r-- | hostname.c | 2 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | networking/hostname.c | 2 | ||||
-rw-r--r-- | networking/ping.c | 50 | ||||
-rw-r--r-- | ping.c | 50 | ||||
-rw-r--r-- | tail.c | 176 | ||||
-rw-r--r-- | utility.c | 53 |
12 files changed, 241 insertions, 376 deletions
@@ -2,19 +2,19 @@ * New Apps: ping and hostname contributed by Randolph Chung <tausq@debian.org>. 2 items off the TODO list! * I wrote free (just calls "cat /proc/meminfo"). + * Added tail, based on tail from GNU textutils-1.19, but adjusted + to suit my evil purposes. Costs 6k. * on reboot, init called 'umount -a -n', which caused errors when BB_MTAB was not enabled. Changed to 'umount -a', which does the right thing. * init will now try to run /sbin/getty if it is present (for easy integration with the about-to-be-released tinylogin.) * kill now behaves itself properly, added 'kill -l' to list signals - * Began to add tail, but it doesn't work yet. - * my_getid was leaking file descriptors, causing 'ls -l' on long - directories to fail + * 'ls -l' was failing on long directories, since my_getid was leaking + one file descriptor per file. Oops. -Erik Andrsen - 0.38 * Fixed a segfault in 'umount -a' when a badly formed /etc/fstab file existed. @@ -18,13 +18,14 @@ around to it some time. If you have any good ideas, please let me know. * traceroute/nslookup/netstat * rdate * hwclock -* login/getty * killall * tee * stty -* head/tail +* head * sort/uniq * wc * tr -* expr (maybe)? +* expr (maybe)? (ash builtin?) +* login/sulogin/passwd/getty (These are actully now part of tinylogin, which + I've just started to maintain). diff --git a/coreutils/dd.c b/coreutils/dd.c index b37038748..90c1004fa 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -48,54 +48,10 @@ static const char dd_usage[] = "\tcount=n\tcopy only n input blocks\n" //"\tskip=n\tskip n input blocks\n" "\n" -"BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; +"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n"; - -/* - * Read a number with a possible multiplier. - * Returns -1 if the number format is illegal. - */ -static long getNum (const char *cp) -{ - long value; - - if (!isDecimal (*cp)) - return -1; - - value = 0; - - while (isDecimal (*cp)) - value = value * 10 + *cp++ - '0'; - - switch (*cp++) { - case 'k': - value *= 1024; - break; - - case 'b': - value *= 512; - break; - - case 'w': - value *= 2; - break; - - case '\0': - return value; - - default: - return -1; - } - - if (*cp) - return -1; - - return value; -} - - extern int dd_main (int argc, char **argv) { const char *inFile = NULL; diff --git a/coreutils/tail.c b/coreutils/tail.c index 058d462a5..7a64c4ca3 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -13,35 +13,16 @@ 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. */ - -/* Can display any amount of data, unlike the Unix version, which uses - a fixed size buffer and therefore can only deliver a limited number - of lines. - - Options: - -b Tail by N 512-byte blocks. - -c, --bytes=N[bkm] Tail by N bytes - [or 512-byte blocks, kilobytes, or megabytes]. - -f, --follow Loop forever trying to read more characters at the - end of the file, on the assumption that the file - is growing. Ignored if reading from a pipe. - -n, --lines=N Tail by N lines. - -q, --quiet, --silent Never print filename headers. - -v, --verbose Always print filename headers. - - If a number (N) starts with a `+', begin printing with the Nth item - from the start of each file, instead of from the end. - - Reads from standard input if no files are given or when a filename of - ``-'' is encountered. - By default, filename headers are printed only more than one file - is given. - By default, prints the last 10 lines (tail -n 10). + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Original version by Paul Rubin <phr@ocf.berkeley.edu>. Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. - tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */ + tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. + + Rewrote the option parser, removed locales support, + and generally busyboxed, Erik Andersen <andersen@lineo.com> + + */ #include "internal.h" @@ -49,16 +30,25 @@ #include <assert.h> #include <errno.h> #include <sys/types.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> + /* Disable assertions. Some systems have broken assert macros. */ #define NDEBUG 1 -static void error(int i, int errnum, char* fmt, const char *msg) +static void error(int i, int errnum, char* fmt, ...) { - fprintf(stderr, fmt, msg); - perror( errnum); + va_list arguments; + + va_start(arguments, fmt); + vfprintf(stderr, fmt, arguments); + fprintf(stderr, "\n%s\n", strerror( errnum)); + va_end(arguments); exit(i); } @@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg) assert ((fd) == 1); \ assert ((n_bytes) >= 0); \ if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ - error (EXIT_FAILURE, errno, "write error", NULL); \ + error (EXIT_FAILURE, errno, "write error"); \ } \ while (0) @@ -110,7 +100,6 @@ enum header_mode }; char *xmalloc (); -int safe_read (); /* The name this program was run with. */ char *program_name; @@ -118,33 +107,24 @@ char *program_name; /* Nonzero if we have ever read standard input. */ static int have_read_stdin; -/* If nonzero, display usage information and exit. */ -static int show_help; - -/* If nonzero, print the version on standard output then exit. */ -static int show_version; static const char tail_usage[] = "tail [OPTION]... [FILE]...\n\ +\n\ Print last 10 lines of each FILE to standard output.\n\ With more than one FILE, precede each with a header giving the file name.\n\ With no FILE, or when FILE is -, read standard input.\n\ \n\ - -c, --bytes=N output the last N bytes\n\ - -f, --follow output appended data as the file grows\n\ - -n, --lines=N output the last N lines, instead of last 10\n\ - -q, --quiet, --silent never output headers giving file names\n\ - -v, --verbose always output headers giving file names\n\ - --help display this help and exit\n\ - --version output version information and exit\n\ + -c=N[kbm] output the last N bytes\n\ + -f output appended data as the file grows\n\ + -n=N output the last N lines, instead of last 10\n\ + -q never output headers giving file names\n\ + -v always output headers giving file names\n\ + --help display this help and exit\n\ \n\ -If the first character of N (the number of bytes or lines) is a `+',\n\ -print beginning with the Nth item from the start of each file, otherwise,\n\ -print the last N items in the file. N may have a multiplier suffix:\n\ -b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\ -or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\ -the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\ -or -c +VALUE.\n"; +If the first character of N (bytes or lines) is a `+', output begins with \n\ +the Nth item from the start of each file, otherwise, print the last N items\n\ +in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; static void write_header (const char *filename, const char *comment) @@ -184,7 +164,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) reads will be on block boundaries, which might increase efficiency. */ pos -= bytes_read; lseek (fd, pos, SEEK_SET); - bytes_read = safe_read (fd, buffer, bytes_read); + bytes_read = fullRead (fd, buffer, bytes_read); if (bytes_read == -1) { error (0, errno, "%s", filename); @@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) pos -= BUFSIZ; lseek (fd, pos, SEEK_SET); } - while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0); + while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); if (bytes_read == -1) { error (0, errno, "%s", filename); @@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines) tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); /* Input is always read into a fresh buffer. */ - while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) + while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) { tmp->nlines = 0; tmp->next = NULL; @@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes) tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); /* Input is always read into a fresh buffer. */ - while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) + while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) { tmp->next = NULL; @@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes) char buffer[BUFSIZ]; int bytes_read = 0; - while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) n_bytes -= bytes_read; if (bytes_read == -1) { @@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines) int bytes_read = 0; int bytes_to_skip = 0; - while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) { bytes_to_skip = 0; while (bytes_to_skip < bytes_read) @@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd) total = 0; output: - while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) { XWRITE (STDOUT_FILENO, buffer, bytes_read); total += bytes_read; @@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum) int fd, errors; struct stat stats; - if (!strcmp (filename, "-") + if (!strcmp (filename, "-")) { have_read_stdin = 1; filename = "standard input"; @@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum) } extern int -tai_main (int argc, char **argv) +tail_main (int argc, char **argv) { + int stopit = 0; enum header_mode header_mode = multiple_files; int exit_status = 0; /* If from_start, the number of items to skip before printing; otherwise, the number of items at the end of the file to print. Initially, -1 means the value has not been set. */ off_t n_units = -1; - long int tmp_long; - int c; /* Option character. */ int n_files; char **file; @@ -832,48 +811,38 @@ tai_main (int argc, char **argv) have_read_stdin = 0; count_lines = 1; forever = forever_multiple = from_start = print_headers = 0; - - if (argc > 1 - && ((argv[1][0] == '-' && ISDIGIT (argv[1][1])) - || (argv[1][0] == '+' && (ISDIGIT (argv[1][1]) - || argv[1][1] == 0)))) - { - /* Old option syntax: a dash or plus, one or more digits (zero digits - are acceptable with a plus), and one or more option letters. */ - if (argv[1][0] == '+') - from_start = 1; - if (argv[1][1] != '\0') - { - strtol_error s_err; - char *p; - - s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm"); - n_units = tmp_long; - if (s_err == LONGINT_OVERFLOW) - { - STRTOL_FATAL_ERROR (argv[1], "argument", s_err); - } - - /* If a [bkm] suffix was given then count bytes, not lines. */ - if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm') - count_lines = 0; - - /* Parse any appended option letters. */ - while (*p) - { - switch (*p) - { + + /* Parse any options */ + //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); + while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { + if (**argv == '+') { + from_start = 1; + } + stopit = 0; + while (stopit == 0 && *(++(*argv))) { + switch (**argv) { case 'c': - /* Interpret N_UNITS as # of bytes. */ count_lines = 0; + + if (--argc < 1) { + usage(tail_usage); + } + n_units = getNum(*(++argv)); + stopit = 1; break; case 'f': forever = 1; break; - case 'l': + case 'n': count_lines = 1; + + if (--argc < 1) { + usage(tail_usage); + } + n_units = atol(*(++argv)); + stopit = 1; break; case 'q': @@ -885,26 +854,11 @@ tai_main (int argc, char **argv) break; default: - error (0, 0, "unrecognized option '%c'", *p); usage (tail_usage); - } - ++p; } } - /* Make the options we just parsed invisible to getopt. */ - argv[1] = argv[0]; - argv++; - argc--; - } - - if (show_version) - { - printf ("tail - %s\n", PACKAGE_VERSION); - exit (EXIT_SUCCESS); } - if (show_help) - usage (tail_usage); if (n_units == -1) n_units = DEFAULT_N_LINES; @@ -918,8 +872,8 @@ tai_main (int argc, char **argv) --n_units; } - n_files = argc - optind; - file = argv + optind; + n_files = argc; + file = argv; if (n_files > 1 && forever) { @@ -48,54 +48,10 @@ static const char dd_usage[] = "\tcount=n\tcopy only n input blocks\n" //"\tskip=n\tskip n input blocks\n" "\n" -"BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; +"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n"; - -/* - * Read a number with a possible multiplier. - * Returns -1 if the number format is illegal. - */ -static long getNum (const char *cp) -{ - long value; - - if (!isDecimal (*cp)) - return -1; - - value = 0; - - while (isDecimal (*cp)) - value = value * 10 + *cp++ - '0'; - - switch (*cp++) { - case 'k': - value *= 1024; - break; - - case 'b': - value *= 512; - break; - - case 'w': - value *= 2; - break; - - case '\0': - return value; - - default: - return -1; - } - - if (*cp) - return -1; - - return value; -} - - extern int dd_main (int argc, char **argv) { const char *inFile = NULL; diff --git a/hostname.c b/hostname.c index be49de395..20e174187 100644 --- a/hostname.c +++ b/hostname.c @@ -1,5 +1,5 @@ /* - * $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ + * $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ * Mini hostname implementation for busybox * * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> diff --git a/internal.h b/internal.h index 48bad0c69..42c6b93ab 100644 --- a/internal.h +++ b/internal.h @@ -155,6 +155,7 @@ extern void write_mtab(char* blockDevice, char* directory, char* filesystemType, long flags, char* string_flags); extern void erase_mtab(const char * name); extern int check_wildcard_match(const char* text, const char* pattern); +extern long getNum (const char *cp); #if defined BB_MTAB diff --git a/networking/hostname.c b/networking/hostname.c index be49de395..20e174187 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -1,5 +1,5 @@ /* - * $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ + * $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ * Mini hostname implementation for busybox * * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> diff --git a/networking/ping.c b/networking/ping.c index 45f3c20aa..4176ab390 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -1,5 +1,5 @@ /* - * $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ + * $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ * Mini ping implementation for busybox * * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> @@ -53,6 +53,7 @@ #define MAXPACKET 65468 #define MAX_DUP_CHK (8 * 128) #define MAXWAIT 10 +#define PINGINTERVAL 1 /* second */ #define O_QUIET (1 << 0) @@ -155,8 +156,8 @@ static void sendping(int ign) } signal(SIGALRM, sendping); - if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */ - alarm(1); + if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ + alarm(PINGINTERVAL); } else { /* done, wait for the last ping to come back */ /* todo, don't necessarily need to wait so long... */ signal(SIGALRM, pingstats); @@ -243,9 +244,8 @@ static void ping(char *host) exit(1); } -#ifdef SUID_BUSYBOX + /* drop root privs if running setuid */ setuid(getuid()); -#endif memset(&pingaddr, 0, sizeof(struct sockaddr_in)); pingaddr.sin_family = AF_INET; @@ -305,35 +305,31 @@ static void ping(char *host) extern int ping_main(int argc, char **argv) { + char *thisarg; + argc--; argv++; options = 0; /* Parse any options */ - if (argc < 1) usage(ping_usage); - - while (**argv == '-') { - while (*++(*argv)) - switch (**argv) { - case 'c': - argc--; argv++; - if (argc < 1) usage(ping_usage); - pingcount = atoi(*argv); - break; - case 'q': - options |= O_QUIET; - break; - default: - usage(ping_usage); - } - argc--; - argv++; + while (argc > 1) { + if (**argv != '-') usage(ping_usage); + thisarg = *argv; thisarg++; + switch (*thisarg) { + case 'q': options |= O_QUIET; break; + case 'c': + argc--; argv++; + pingcount = atoi(*argv); + break; + default: + usage(ping_usage); + } + argc--; argv++; } - - if (argc < 1) usage(ping_usage); + if (argc < 1) usage(ping_usage); myid = getpid() & 0xFFFF; - ping(*(argv++)); - exit( TRUE); + ping(*argv); + exit(TRUE); } /* @@ -1,5 +1,5 @@ /* - * $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ + * $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ * Mini ping implementation for busybox * * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> @@ -53,6 +53,7 @@ #define MAXPACKET 65468 #define MAX_DUP_CHK (8 * 128) #define MAXWAIT 10 +#define PINGINTERVAL 1 /* second */ #define O_QUIET (1 << 0) @@ -155,8 +156,8 @@ static void sendping(int ign) } signal(SIGALRM, sendping); - if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */ - alarm(1); + if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ + alarm(PINGINTERVAL); } else { /* done, wait for the last ping to come back */ /* todo, don't necessarily need to wait so long... */ signal(SIGALRM, pingstats); @@ -243,9 +244,8 @@ static void ping(char *host) exit(1); } -#ifdef SUID_BUSYBOX + /* drop root privs if running setuid */ setuid(getuid()); -#endif memset(&pingaddr, 0, sizeof(struct sockaddr_in)); pingaddr.sin_family = AF_INET; @@ -305,35 +305,31 @@ static void ping(char *host) extern int ping_main(int argc, char **argv) { + char *thisarg; + argc--; argv++; options = 0; /* Parse any options */ - if (argc < 1) usage(ping_usage); - - while (**argv == '-') { - while (*++(*argv)) - switch (**argv) { - case 'c': - argc--; argv++; - if (argc < 1) usage(ping_usage); - pingcount = atoi(*argv); - break; - case 'q': - options |= O_QUIET; - break; - default: - usage(ping_usage); - } - argc--; - argv++; + while (argc > 1) { + if (**argv != '-') usage(ping_usage); + thisarg = *argv; thisarg++; + switch (*thisarg) { + case 'q': options |= O_QUIET; break; + case 'c': + argc--; argv++; + pingcount = atoi(*argv); + break; + default: + usage(ping_usage); + } + argc--; argv++; } - - if (argc < 1) usage(ping_usage); + if (argc < 1) usage(ping_usage); myid = getpid() & 0xFFFF; - ping(*(argv++)); - exit( TRUE); + ping(*argv); + exit(TRUE); } /* @@ -13,35 +13,16 @@ 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. */ - -/* Can display any amount of data, unlike the Unix version, which uses - a fixed size buffer and therefore can only deliver a limited number - of lines. - - Options: - -b Tail by N 512-byte blocks. - -c, --bytes=N[bkm] Tail by N bytes - [or 512-byte blocks, kilobytes, or megabytes]. - -f, --follow Loop forever trying to read more characters at the - end of the file, on the assumption that the file - is growing. Ignored if reading from a pipe. - -n, --lines=N Tail by N lines. - -q, --quiet, --silent Never print filename headers. - -v, --verbose Always print filename headers. - - If a number (N) starts with a `+', begin printing with the Nth item - from the start of each file, instead of from the end. - - Reads from standard input if no files are given or when a filename of - ``-'' is encountered. - By default, filename headers are printed only more than one file - is given. - By default, prints the last 10 lines (tail -n 10). + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Original version by Paul Rubin <phr@ocf.berkeley.edu>. Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. - tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */ + tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. + + Rewrote the option parser, removed locales support, + and generally busyboxed, Erik Andersen <andersen@lineo.com> + + */ #include "internal.h" @@ -49,16 +30,25 @@ #include <assert.h> #include <errno.h> #include <sys/types.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> + /* Disable assertions. Some systems have broken assert macros. */ #define NDEBUG 1 -static void error(int i, int errnum, char* fmt, const char *msg) +static void error(int i, int errnum, char* fmt, ...) { - fprintf(stderr, fmt, msg); - perror( errnum); + va_list arguments; + + va_start(arguments, fmt); + vfprintf(stderr, fmt, arguments); + fprintf(stderr, "\n%s\n", strerror( errnum)); + va_end(arguments); exit(i); } @@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg) assert ((fd) == 1); \ assert ((n_bytes) >= 0); \ if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ - error (EXIT_FAILURE, errno, "write error", NULL); \ + error (EXIT_FAILURE, errno, "write error"); \ } \ while (0) @@ -110,7 +100,6 @@ enum header_mode }; char *xmalloc (); -int safe_read (); /* The name this program was run with. */ char *program_name; @@ -118,33 +107,24 @@ char *program_name; /* Nonzero if we have ever read standard input. */ static int have_read_stdin; -/* If nonzero, display usage information and exit. */ -static int show_help; - -/* If nonzero, print the version on standard output then exit. */ -static int show_version; static const char tail_usage[] = "tail [OPTION]... [FILE]...\n\ +\n\ Print last 10 lines of each FILE to standard output.\n\ With more than one FILE, precede each with a header giving the file name.\n\ With no FILE, or when FILE is -, read standard input.\n\ \n\ - -c, --bytes=N output the last N bytes\n\ - -f, --follow output appended data as the file grows\n\ - -n, --lines=N output the last N lines, instead of last 10\n\ - -q, --quiet, --silent never output headers giving file names\n\ - -v, --verbose always output headers giving file names\n\ - --help display this help and exit\n\ - --version output version information and exit\n\ + -c=N[kbm] output the last N bytes\n\ + -f output appended data as the file grows\n\ + -n=N output the last N lines, instead of last 10\n\ + -q never output headers giving file names\n\ + -v always output headers giving file names\n\ + --help display this help and exit\n\ \n\ -If the first character of N (the number of bytes or lines) is a `+',\n\ -print beginning with the Nth item from the start of each file, otherwise,\n\ -print the last N items in the file. N may have a multiplier suffix:\n\ -b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\ -or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\ -the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\ -or -c +VALUE.\n"; +If the first character of N (bytes or lines) is a `+', output begins with \n\ +the Nth item from the start of each file, otherwise, print the last N items\n\ +in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; static void write_header (const char *filename, const char *comment) @@ -184,7 +164,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) reads will be on block boundaries, which might increase efficiency. */ pos -= bytes_read; lseek (fd, pos, SEEK_SET); - bytes_read = safe_read (fd, buffer, bytes_read); + bytes_read = fullRead (fd, buffer, bytes_read); if (bytes_read == -1) { error (0, errno, "%s", filename); @@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) pos -= BUFSIZ; lseek (fd, pos, SEEK_SET); } - while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0); + while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); if (bytes_read == -1) { error (0, errno, "%s", filename); @@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines) tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); /* Input is always read into a fresh buffer. */ - while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) + while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) { tmp->nlines = 0; tmp->next = NULL; @@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes) tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); /* Input is always read into a fresh buffer. */ - while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) + while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) { tmp->next = NULL; @@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes) char buffer[BUFSIZ]; int bytes_read = 0; - while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) n_bytes -= bytes_read; if (bytes_read == -1) { @@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines) int bytes_read = 0; int bytes_to_skip = 0; - while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) { bytes_to_skip = 0; while (bytes_to_skip < bytes_read) @@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd) total = 0; output: - while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) + while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) { XWRITE (STDOUT_FILENO, buffer, bytes_read); total += bytes_read; @@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum) int fd, errors; struct stat stats; - if (!strcmp (filename, "-") + if (!strcmp (filename, "-")) { have_read_stdin = 1; filename = "standard input"; @@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum) } extern int -tai_main (int argc, char **argv) +tail_main (int argc, char **argv) { + int stopit = 0; enum header_mode header_mode = multiple_files; int exit_status = 0; /* If from_start, the number of items to skip before printing; otherwise, the number of items at the end of the file to print. Initially, -1 means the value has not been set. */ off_t n_units = -1; - long int tmp_long; - int c; /* Option character. */ int n_files; char **file; @@ -832,48 +811,38 @@ tai_main (int argc, char **argv) have_read_stdin = 0; count_lines = 1; forever = forever_multiple = from_start = print_headers = 0; - - if (argc > 1 - && ((argv[1][0] == '-' && ISDIGIT (argv[1][1])) - || (argv[1][0] == '+' && (ISDIGIT (argv[1][1]) - || argv[1][1] == 0)))) - { - /* Old option syntax: a dash or plus, one or more digits (zero digits - are acceptable with a plus), and one or more option letters. */ - if (argv[1][0] == '+') - from_start = 1; - if (argv[1][1] != '\0') - { - strtol_error s_err; - char *p; - - s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm"); - n_units = tmp_long; - if (s_err == LONGINT_OVERFLOW) - { - STRTOL_FATAL_ERROR (argv[1], "argument", s_err); - } - - /* If a [bkm] suffix was given then count bytes, not lines. */ - if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm') - count_lines = 0; - - /* Parse any appended option letters. */ - while (*p) - { - switch (*p) - { + + /* Parse any options */ + //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); + while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { + if (**argv == '+') { + from_start = 1; + } + stopit = 0; + while (stopit == 0 && *(++(*argv))) { + switch (**argv) { case 'c': - /* Interpret N_UNITS as # of bytes. */ count_lines = 0; + + if (--argc < 1) { + usage(tail_usage); + } + n_units = getNum(*(++argv)); + stopit = 1; break; case 'f': forever = 1; break; - case 'l': + case 'n': count_lines = 1; + + if (--argc < 1) { + usage(tail_usage); + } + n_units = atol(*(++argv)); + stopit = 1; break; case 'q': @@ -885,26 +854,11 @@ tai_main (int argc, char **argv) break; default: - error (0, 0, "unrecognized option '%c'", *p); usage (tail_usage); - } - ++p; } } - /* Make the options we just parsed invisible to getopt. */ - argv[1] = argv[0]; - argv++; - argc--; - } - - if (show_version) - { - printf ("tail - %s\n", PACKAGE_VERSION); - exit (EXIT_SUCCESS); } - if (show_help) - usage (tail_usage); if (n_units == -1) n_units = DEFAULT_N_LINES; @@ -918,8 +872,8 @@ tai_main (int argc, char **argv) --n_units; } - n_files = argc - optind; - file = argv + optind; + n_files = argc; + file = argv; if (n_files > 1 && forever) { @@ -289,7 +289,7 @@ const char *modeString(int mode) #endif -#ifdef BB_TAR +#if defined BB_TAR /* * Return the standard ls-like time string from a time_t * This is static and so is overwritten on each call. @@ -340,8 +340,10 @@ int fullWrite(int fd, const char *buf, int len) return total; } +#endif +#if defined BB_TAR || defined BB_TAIL /* * Read all of the supplied buffer from a file. * This does multiple reads as necessary. @@ -1018,6 +1020,55 @@ extern void whine_if_fstab_is_missing() #endif +#if defined BB_DD || defined BB_TAIL +/* + * Read a number with a possible multiplier. + * Returns -1 if the number format is illegal. + */ +extern long getNum (const char *cp) +{ + long value; + + if (!isDecimal (*cp)) + return -1; + + value = 0; + + while (isDecimal (*cp)) + value = value * 10 + *cp++ - '0'; + + switch (*cp++) { + case 'm': + value *= 1048576; + break; + + case 'k': + value *= 1024; + break; + + case 'b': + value *= 512; + break; + + case 'w': + value *= 2; + break; + + case '\0': + return value; + + default: + return -1; + } + + if (*cp) + return -1; + + return value; +} +#endif + + /* END CODE */ |