diff options
author | Eric Andersen <andersen@codepoet.org> | 1999-12-09 06:11:36 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 1999-12-09 06:11:36 +0000 |
commit | 1792f8c48926450501e19d32e78e140bcb9661c6 (patch) | |
tree | 14d0304ebb774077e696a9c86117bf43d935d8bb | |
parent | c24db7b591870978fdd2cec8995728d1520c2fa9 (diff) | |
download | busybox-w32-1792f8c48926450501e19d32e78e140bcb9661c6.tar.gz busybox-w32-1792f8c48926450501e19d32e78e140bcb9661c6.tar.bz2 busybox-w32-1792f8c48926450501e19d32e78e140bcb9661c6.zip |
Tail now works (costs 6k). Several other updates.
-Erik
-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 @@ | |||
2 | * New Apps: ping and hostname contributed by Randolph Chung | 2 | * New Apps: ping and hostname contributed by Randolph Chung |
3 | <tausq@debian.org>. 2 items off the TODO list! | 3 | <tausq@debian.org>. 2 items off the TODO list! |
4 | * I wrote free (just calls "cat /proc/meminfo"). | 4 | * I wrote free (just calls "cat /proc/meminfo"). |
5 | * Added tail, based on tail from GNU textutils-1.19, but adjusted | ||
6 | to suit my evil purposes. Costs 6k. | ||
5 | * on reboot, init called 'umount -a -n', which caused errors | 7 | * on reboot, init called 'umount -a -n', which caused errors |
6 | when BB_MTAB was not enabled. Changed to 'umount -a', | 8 | when BB_MTAB was not enabled. Changed to 'umount -a', |
7 | which does the right thing. | 9 | which does the right thing. |
8 | * init will now try to run /sbin/getty if it is present (for easy | 10 | * init will now try to run /sbin/getty if it is present (for easy |
9 | integration with the about-to-be-released tinylogin.) | 11 | integration with the about-to-be-released tinylogin.) |
10 | * kill now behaves itself properly, added 'kill -l' to list signals | 12 | * kill now behaves itself properly, added 'kill -l' to list signals |
11 | * Began to add tail, but it doesn't work yet. | 13 | * 'ls -l' was failing on long directories, since my_getid was leaking |
12 | * my_getid was leaking file descriptors, causing 'ls -l' on long | 14 | one file descriptor per file. Oops. |
13 | directories to fail | ||
14 | 15 | ||
15 | -Erik Andrsen | 16 | -Erik Andrsen |
16 | 17 | ||
17 | |||
18 | 0.38 | 18 | 0.38 |
19 | * Fixed a segfault in 'umount -a' when a badly formed /etc/fstab | 19 | * Fixed a segfault in 'umount -a' when a badly formed /etc/fstab |
20 | file existed. | 20 | file existed. |
@@ -18,13 +18,14 @@ around to it some time. If you have any good ideas, please let me know. | |||
18 | * traceroute/nslookup/netstat | 18 | * traceroute/nslookup/netstat |
19 | * rdate | 19 | * rdate |
20 | * hwclock | 20 | * hwclock |
21 | * login/getty | ||
22 | * killall | 21 | * killall |
23 | * tee | 22 | * tee |
24 | * stty | 23 | * stty |
25 | * head/tail | 24 | * head |
26 | * sort/uniq | 25 | * sort/uniq |
27 | * wc | 26 | * wc |
28 | * tr | 27 | * tr |
29 | * expr (maybe)? | 28 | * expr (maybe)? (ash builtin?) |
29 | * login/sulogin/passwd/getty (These are actully now part of tinylogin, which | ||
30 | I've just started to maintain). | ||
30 | 31 | ||
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[] = | |||
48 | "\tcount=n\tcopy only n input blocks\n" | 48 | "\tcount=n\tcopy only n input blocks\n" |
49 | //"\tskip=n\tskip n input blocks\n" | 49 | //"\tskip=n\tskip n input blocks\n" |
50 | "\n" | 50 | "\n" |
51 | "BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; | 51 | "BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n"; |
52 | 52 | ||
53 | 53 | ||
54 | 54 | ||
55 | |||
56 | /* | ||
57 | * Read a number with a possible multiplier. | ||
58 | * Returns -1 if the number format is illegal. | ||
59 | */ | ||
60 | static long getNum (const char *cp) | ||
61 | { | ||
62 | long value; | ||
63 | |||
64 | if (!isDecimal (*cp)) | ||
65 | return -1; | ||
66 | |||
67 | value = 0; | ||
68 | |||
69 | while (isDecimal (*cp)) | ||
70 | value = value * 10 + *cp++ - '0'; | ||
71 | |||
72 | switch (*cp++) { | ||
73 | case 'k': | ||
74 | value *= 1024; | ||
75 | break; | ||
76 | |||
77 | case 'b': | ||
78 | value *= 512; | ||
79 | break; | ||
80 | |||
81 | case 'w': | ||
82 | value *= 2; | ||
83 | break; | ||
84 | |||
85 | case '\0': | ||
86 | return value; | ||
87 | |||
88 | default: | ||
89 | return -1; | ||
90 | } | ||
91 | |||
92 | if (*cp) | ||
93 | return -1; | ||
94 | |||
95 | return value; | ||
96 | } | ||
97 | |||
98 | |||
99 | extern int dd_main (int argc, char **argv) | 55 | extern int dd_main (int argc, char **argv) |
100 | { | 56 | { |
101 | const char *inFile = NULL; | 57 | 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 @@ | |||
13 | 13 | ||
14 | You should have received a copy of the GNU General Public License | 14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software | 15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | |||
18 | /* Can display any amount of data, unlike the Unix version, which uses | ||
19 | a fixed size buffer and therefore can only deliver a limited number | ||
20 | of lines. | ||
21 | |||
22 | Options: | ||
23 | -b Tail by N 512-byte blocks. | ||
24 | -c, --bytes=N[bkm] Tail by N bytes | ||
25 | [or 512-byte blocks, kilobytes, or megabytes]. | ||
26 | -f, --follow Loop forever trying to read more characters at the | ||
27 | end of the file, on the assumption that the file | ||
28 | is growing. Ignored if reading from a pipe. | ||
29 | -n, --lines=N Tail by N lines. | ||
30 | -q, --quiet, --silent Never print filename headers. | ||
31 | -v, --verbose Always print filename headers. | ||
32 | |||
33 | If a number (N) starts with a `+', begin printing with the Nth item | ||
34 | from the start of each file, instead of from the end. | ||
35 | |||
36 | Reads from standard input if no files are given or when a filename of | ||
37 | ``-'' is encountered. | ||
38 | By default, filename headers are printed only more than one file | ||
39 | is given. | ||
40 | By default, prints the last 10 lines (tail -n 10). | ||
41 | 17 | ||
42 | Original version by Paul Rubin <phr@ocf.berkeley.edu>. | 18 | Original version by Paul Rubin <phr@ocf.berkeley.edu>. |
43 | Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. | 19 | Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. |
44 | tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */ | 20 | tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. |
21 | |||
22 | Rewrote the option parser, removed locales support, | ||
23 | and generally busyboxed, Erik Andersen <andersen@lineo.com> | ||
24 | |||
25 | */ | ||
45 | 26 | ||
46 | #include "internal.h" | 27 | #include "internal.h" |
47 | 28 | ||
@@ -49,16 +30,25 @@ | |||
49 | #include <assert.h> | 30 | #include <assert.h> |
50 | #include <errno.h> | 31 | #include <errno.h> |
51 | #include <sys/types.h> | 32 | #include <sys/types.h> |
33 | #include <sys/types.h> | ||
34 | #include <sys/stat.h> | ||
35 | #include <fcntl.h> | ||
36 | #include <ctype.h> | ||
37 | |||
52 | 38 | ||
53 | 39 | ||
54 | /* Disable assertions. Some systems have broken assert macros. */ | 40 | /* Disable assertions. Some systems have broken assert macros. */ |
55 | #define NDEBUG 1 | 41 | #define NDEBUG 1 |
56 | 42 | ||
57 | 43 | ||
58 | static void error(int i, int errnum, char* fmt, const char *msg) | 44 | static void error(int i, int errnum, char* fmt, ...) |
59 | { | 45 | { |
60 | fprintf(stderr, fmt, msg); | 46 | va_list arguments; |
61 | perror( errnum); | 47 | |
48 | va_start(arguments, fmt); | ||
49 | vfprintf(stderr, fmt, arguments); | ||
50 | fprintf(stderr, "\n%s\n", strerror( errnum)); | ||
51 | va_end(arguments); | ||
62 | exit(i); | 52 | exit(i); |
63 | } | 53 | } |
64 | 54 | ||
@@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg) | |||
69 | assert ((fd) == 1); \ | 59 | assert ((fd) == 1); \ |
70 | assert ((n_bytes) >= 0); \ | 60 | assert ((n_bytes) >= 0); \ |
71 | if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ | 61 | if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ |
72 | error (EXIT_FAILURE, errno, "write error", NULL); \ | 62 | error (EXIT_FAILURE, errno, "write error"); \ |
73 | } \ | 63 | } \ |
74 | while (0) | 64 | while (0) |
75 | 65 | ||
@@ -110,7 +100,6 @@ enum header_mode | |||
110 | }; | 100 | }; |
111 | 101 | ||
112 | char *xmalloc (); | 102 | char *xmalloc (); |
113 | int safe_read (); | ||
114 | 103 | ||
115 | /* The name this program was run with. */ | 104 | /* The name this program was run with. */ |
116 | char *program_name; | 105 | char *program_name; |
@@ -118,33 +107,24 @@ char *program_name; | |||
118 | /* Nonzero if we have ever read standard input. */ | 107 | /* Nonzero if we have ever read standard input. */ |
119 | static int have_read_stdin; | 108 | static int have_read_stdin; |
120 | 109 | ||
121 | /* If nonzero, display usage information and exit. */ | ||
122 | static int show_help; | ||
123 | |||
124 | /* If nonzero, print the version on standard output then exit. */ | ||
125 | static int show_version; | ||
126 | 110 | ||
127 | static const char tail_usage[] = | 111 | static const char tail_usage[] = |
128 | "tail [OPTION]... [FILE]...\n\ | 112 | "tail [OPTION]... [FILE]...\n\ |
113 | \n\ | ||
129 | Print last 10 lines of each FILE to standard output.\n\ | 114 | Print last 10 lines of each FILE to standard output.\n\ |
130 | With more than one FILE, precede each with a header giving the file name.\n\ | 115 | With more than one FILE, precede each with a header giving the file name.\n\ |
131 | With no FILE, or when FILE is -, read standard input.\n\ | 116 | With no FILE, or when FILE is -, read standard input.\n\ |
132 | \n\ | 117 | \n\ |
133 | -c, --bytes=N output the last N bytes\n\ | 118 | -c=N[kbm] output the last N bytes\n\ |
134 | -f, --follow output appended data as the file grows\n\ | 119 | -f output appended data as the file grows\n\ |
135 | -n, --lines=N output the last N lines, instead of last 10\n\ | 120 | -n=N output the last N lines, instead of last 10\n\ |
136 | -q, --quiet, --silent never output headers giving file names\n\ | 121 | -q never output headers giving file names\n\ |
137 | -v, --verbose always output headers giving file names\n\ | 122 | -v always output headers giving file names\n\ |
138 | --help display this help and exit\n\ | 123 | --help display this help and exit\n\ |
139 | --version output version information and exit\n\ | ||
140 | \n\ | 124 | \n\ |
141 | If the first character of N (the number of bytes or lines) is a `+',\n\ | 125 | If the first character of N (bytes or lines) is a `+', output begins with \n\ |
142 | print beginning with the Nth item from the start of each file, otherwise,\n\ | 126 | the Nth item from the start of each file, otherwise, print the last N items\n\ |
143 | print the last N items in the file. N may have a multiplier suffix:\n\ | 127 | in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; |
144 | b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\ | ||
145 | or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\ | ||
146 | the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\ | ||
147 | or -c +VALUE.\n"; | ||
148 | 128 | ||
149 | static void | 129 | static void |
150 | write_header (const char *filename, const char *comment) | 130 | 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) | |||
184 | reads will be on block boundaries, which might increase efficiency. */ | 164 | reads will be on block boundaries, which might increase efficiency. */ |
185 | pos -= bytes_read; | 165 | pos -= bytes_read; |
186 | lseek (fd, pos, SEEK_SET); | 166 | lseek (fd, pos, SEEK_SET); |
187 | bytes_read = safe_read (fd, buffer, bytes_read); | 167 | bytes_read = fullRead (fd, buffer, bytes_read); |
188 | if (bytes_read == -1) | 168 | if (bytes_read == -1) |
189 | { | 169 | { |
190 | error (0, errno, "%s", filename); | 170 | error (0, errno, "%s", filename); |
@@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) | |||
220 | pos -= BUFSIZ; | 200 | pos -= BUFSIZ; |
221 | lseek (fd, pos, SEEK_SET); | 201 | lseek (fd, pos, SEEK_SET); |
222 | } | 202 | } |
223 | while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0); | 203 | while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); |
224 | if (bytes_read == -1) | 204 | if (bytes_read == -1) |
225 | { | 205 | { |
226 | error (0, errno, "%s", filename); | 206 | error (0, errno, "%s", filename); |
@@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines) | |||
255 | tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); | 235 | tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); |
256 | 236 | ||
257 | /* Input is always read into a fresh buffer. */ | 237 | /* Input is always read into a fresh buffer. */ |
258 | while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) | 238 | while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) |
259 | { | 239 | { |
260 | tmp->nlines = 0; | 240 | tmp->nlines = 0; |
261 | tmp->next = NULL; | 241 | tmp->next = NULL; |
@@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes) | |||
374 | tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); | 354 | tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); |
375 | 355 | ||
376 | /* Input is always read into a fresh buffer. */ | 356 | /* Input is always read into a fresh buffer. */ |
377 | while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) | 357 | while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) |
378 | { | 358 | { |
379 | tmp->next = NULL; | 359 | tmp->next = NULL; |
380 | 360 | ||
@@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes) | |||
453 | char buffer[BUFSIZ]; | 433 | char buffer[BUFSIZ]; |
454 | int bytes_read = 0; | 434 | int bytes_read = 0; |
455 | 435 | ||
456 | while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 436 | while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
457 | n_bytes -= bytes_read; | 437 | n_bytes -= bytes_read; |
458 | if (bytes_read == -1) | 438 | if (bytes_read == -1) |
459 | { | 439 | { |
@@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines) | |||
476 | int bytes_read = 0; | 456 | int bytes_read = 0; |
477 | int bytes_to_skip = 0; | 457 | int bytes_to_skip = 0; |
478 | 458 | ||
479 | while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 459 | while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
480 | { | 460 | { |
481 | bytes_to_skip = 0; | 461 | bytes_to_skip = 0; |
482 | while (bytes_to_skip < bytes_read) | 462 | while (bytes_to_skip < bytes_read) |
@@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd) | |||
509 | 489 | ||
510 | total = 0; | 490 | total = 0; |
511 | output: | 491 | output: |
512 | while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 492 | while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
513 | { | 493 | { |
514 | XWRITE (STDOUT_FILENO, buffer, bytes_read); | 494 | XWRITE (STDOUT_FILENO, buffer, bytes_read); |
515 | total += bytes_read; | 495 | total += bytes_read; |
@@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum) | |||
731 | int fd, errors; | 711 | int fd, errors; |
732 | struct stat stats; | 712 | struct stat stats; |
733 | 713 | ||
734 | if (!strcmp (filename, "-") | 714 | if (!strcmp (filename, "-")) |
735 | { | 715 | { |
736 | have_read_stdin = 1; | 716 | have_read_stdin = 1; |
737 | filename = "standard input"; | 717 | filename = "standard input"; |
@@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum) | |||
815 | } | 795 | } |
816 | 796 | ||
817 | extern int | 797 | extern int |
818 | tai_main (int argc, char **argv) | 798 | tail_main (int argc, char **argv) |
819 | { | 799 | { |
800 | int stopit = 0; | ||
820 | enum header_mode header_mode = multiple_files; | 801 | enum header_mode header_mode = multiple_files; |
821 | int exit_status = 0; | 802 | int exit_status = 0; |
822 | /* If from_start, the number of items to skip before printing; otherwise, | 803 | /* If from_start, the number of items to skip before printing; otherwise, |
823 | the number of items at the end of the file to print. Initially, -1 | 804 | the number of items at the end of the file to print. Initially, -1 |
824 | means the value has not been set. */ | 805 | means the value has not been set. */ |
825 | off_t n_units = -1; | 806 | off_t n_units = -1; |
826 | long int tmp_long; | ||
827 | int c; /* Option character. */ | ||
828 | int n_files; | 807 | int n_files; |
829 | char **file; | 808 | char **file; |
830 | 809 | ||
@@ -832,48 +811,38 @@ tai_main (int argc, char **argv) | |||
832 | have_read_stdin = 0; | 811 | have_read_stdin = 0; |
833 | count_lines = 1; | 812 | count_lines = 1; |
834 | forever = forever_multiple = from_start = print_headers = 0; | 813 | forever = forever_multiple = from_start = print_headers = 0; |
835 | 814 | ||
836 | if (argc > 1 | 815 | /* Parse any options */ |
837 | && ((argv[1][0] == '-' && ISDIGIT (argv[1][1])) | 816 | //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); |
838 | || (argv[1][0] == '+' && (ISDIGIT (argv[1][1]) | 817 | while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { |
839 | || argv[1][1] == 0)))) | 818 | if (**argv == '+') { |
840 | { | 819 | from_start = 1; |
841 | /* Old option syntax: a dash or plus, one or more digits (zero digits | 820 | } |
842 | are acceptable with a plus), and one or more option letters. */ | 821 | stopit = 0; |
843 | if (argv[1][0] == '+') | 822 | while (stopit == 0 && *(++(*argv))) { |
844 | from_start = 1; | 823 | switch (**argv) { |
845 | if (argv[1][1] != '\0') | ||
846 | { | ||
847 | strtol_error s_err; | ||
848 | char *p; | ||
849 | |||
850 | s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm"); | ||
851 | n_units = tmp_long; | ||
852 | if (s_err == LONGINT_OVERFLOW) | ||
853 | { | ||
854 | STRTOL_FATAL_ERROR (argv[1], "argument", s_err); | ||
855 | } | ||
856 | |||
857 | /* If a [bkm] suffix was given then count bytes, not lines. */ | ||
858 | if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm') | ||
859 | count_lines = 0; | ||
860 | |||
861 | /* Parse any appended option letters. */ | ||
862 | while (*p) | ||
863 | { | ||
864 | switch (*p) | ||
865 | { | ||
866 | case 'c': | 824 | case 'c': |
867 | /* Interpret N_UNITS as # of bytes. */ | ||
868 | count_lines = 0; | 825 | count_lines = 0; |
826 | |||
827 | if (--argc < 1) { | ||
828 | usage(tail_usage); | ||
829 | } | ||
830 | n_units = getNum(*(++argv)); | ||
831 | stopit = 1; | ||
869 | break; | 832 | break; |
870 | 833 | ||
871 | case 'f': | 834 | case 'f': |
872 | forever = 1; | 835 | forever = 1; |
873 | break; | 836 | break; |
874 | 837 | ||
875 | case 'l': | 838 | case 'n': |
876 | count_lines = 1; | 839 | count_lines = 1; |
840 | |||
841 | if (--argc < 1) { | ||
842 | usage(tail_usage); | ||
843 | } | ||
844 | n_units = atol(*(++argv)); | ||
845 | stopit = 1; | ||
877 | break; | 846 | break; |
878 | 847 | ||
879 | case 'q': | 848 | case 'q': |
@@ -885,26 +854,11 @@ tai_main (int argc, char **argv) | |||
885 | break; | 854 | break; |
886 | 855 | ||
887 | default: | 856 | default: |
888 | error (0, 0, "unrecognized option '%c'", *p); | ||
889 | usage (tail_usage); | 857 | usage (tail_usage); |
890 | } | ||
891 | ++p; | ||
892 | } | 858 | } |
893 | } | 859 | } |
894 | /* Make the options we just parsed invisible to getopt. */ | ||
895 | argv[1] = argv[0]; | ||
896 | argv++; | ||
897 | argc--; | ||
898 | } | ||
899 | |||
900 | if (show_version) | ||
901 | { | ||
902 | printf ("tail - %s\n", PACKAGE_VERSION); | ||
903 | exit (EXIT_SUCCESS); | ||
904 | } | 860 | } |
905 | 861 | ||
906 | if (show_help) | ||
907 | usage (tail_usage); | ||
908 | 862 | ||
909 | if (n_units == -1) | 863 | if (n_units == -1) |
910 | n_units = DEFAULT_N_LINES; | 864 | n_units = DEFAULT_N_LINES; |
@@ -918,8 +872,8 @@ tai_main (int argc, char **argv) | |||
918 | --n_units; | 872 | --n_units; |
919 | } | 873 | } |
920 | 874 | ||
921 | n_files = argc - optind; | 875 | n_files = argc; |
922 | file = argv + optind; | 876 | file = argv; |
923 | 877 | ||
924 | if (n_files > 1 && forever) | 878 | if (n_files > 1 && forever) |
925 | { | 879 | { |
@@ -48,54 +48,10 @@ static const char dd_usage[] = | |||
48 | "\tcount=n\tcopy only n input blocks\n" | 48 | "\tcount=n\tcopy only n input blocks\n" |
49 | //"\tskip=n\tskip n input blocks\n" | 49 | //"\tskip=n\tskip n input blocks\n" |
50 | "\n" | 50 | "\n" |
51 | "BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; | 51 | "BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n"; |
52 | 52 | ||
53 | 53 | ||
54 | 54 | ||
55 | |||
56 | /* | ||
57 | * Read a number with a possible multiplier. | ||
58 | * Returns -1 if the number format is illegal. | ||
59 | */ | ||
60 | static long getNum (const char *cp) | ||
61 | { | ||
62 | long value; | ||
63 | |||
64 | if (!isDecimal (*cp)) | ||
65 | return -1; | ||
66 | |||
67 | value = 0; | ||
68 | |||
69 | while (isDecimal (*cp)) | ||
70 | value = value * 10 + *cp++ - '0'; | ||
71 | |||
72 | switch (*cp++) { | ||
73 | case 'k': | ||
74 | value *= 1024; | ||
75 | break; | ||
76 | |||
77 | case 'b': | ||
78 | value *= 512; | ||
79 | break; | ||
80 | |||
81 | case 'w': | ||
82 | value *= 2; | ||
83 | break; | ||
84 | |||
85 | case '\0': | ||
86 | return value; | ||
87 | |||
88 | default: | ||
89 | return -1; | ||
90 | } | ||
91 | |||
92 | if (*cp) | ||
93 | return -1; | ||
94 | |||
95 | return value; | ||
96 | } | ||
97 | |||
98 | |||
99 | extern int dd_main (int argc, char **argv) | 55 | extern int dd_main (int argc, char **argv) |
100 | { | 56 | { |
101 | const char *inFile = NULL; | 57 | 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 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ | 2 | * $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ |
3 | * Mini hostname implementation for busybox | 3 | * Mini hostname implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | 5 | * 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, | |||
155 | char* filesystemType, long flags, char* string_flags); | 155 | char* filesystemType, long flags, char* string_flags); |
156 | extern void erase_mtab(const char * name); | 156 | extern void erase_mtab(const char * name); |
157 | extern int check_wildcard_match(const char* text, const char* pattern); | 157 | extern int check_wildcard_match(const char* text, const char* pattern); |
158 | extern long getNum (const char *cp); | ||
158 | 159 | ||
159 | 160 | ||
160 | #if defined BB_MTAB | 161 | #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 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: hostname.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ | 2 | * $Id: hostname.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ |
3 | * Mini hostname implementation for busybox | 3 | * Mini hostname implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | 5 | * 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 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ | 2 | * $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ |
3 | * Mini ping implementation for busybox | 3 | * Mini ping implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | 5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> |
@@ -53,6 +53,7 @@ | |||
53 | #define MAXPACKET 65468 | 53 | #define MAXPACKET 65468 |
54 | #define MAX_DUP_CHK (8 * 128) | 54 | #define MAX_DUP_CHK (8 * 128) |
55 | #define MAXWAIT 10 | 55 | #define MAXWAIT 10 |
56 | #define PINGINTERVAL 1 /* second */ | ||
56 | 57 | ||
57 | #define O_QUIET (1 << 0) | 58 | #define O_QUIET (1 << 0) |
58 | 59 | ||
@@ -155,8 +156,8 @@ static void sendping(int ign) | |||
155 | } | 156 | } |
156 | 157 | ||
157 | signal(SIGALRM, sendping); | 158 | signal(SIGALRM, sendping); |
158 | if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */ | 159 | if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ |
159 | alarm(1); | 160 | alarm(PINGINTERVAL); |
160 | } else { /* done, wait for the last ping to come back */ | 161 | } else { /* done, wait for the last ping to come back */ |
161 | /* todo, don't necessarily need to wait so long... */ | 162 | /* todo, don't necessarily need to wait so long... */ |
162 | signal(SIGALRM, pingstats); | 163 | signal(SIGALRM, pingstats); |
@@ -243,9 +244,8 @@ static void ping(char *host) | |||
243 | exit(1); | 244 | exit(1); |
244 | } | 245 | } |
245 | 246 | ||
246 | #ifdef SUID_BUSYBOX | 247 | /* drop root privs if running setuid */ |
247 | setuid(getuid()); | 248 | setuid(getuid()); |
248 | #endif | ||
249 | 249 | ||
250 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); | 250 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); |
251 | pingaddr.sin_family = AF_INET; | 251 | pingaddr.sin_family = AF_INET; |
@@ -305,35 +305,31 @@ static void ping(char *host) | |||
305 | 305 | ||
306 | extern int ping_main(int argc, char **argv) | 306 | extern int ping_main(int argc, char **argv) |
307 | { | 307 | { |
308 | char *thisarg; | ||
309 | |||
308 | argc--; | 310 | argc--; |
309 | argv++; | 311 | argv++; |
310 | options = 0; | 312 | options = 0; |
311 | /* Parse any options */ | 313 | /* Parse any options */ |
312 | if (argc < 1) usage(ping_usage); | 314 | while (argc > 1) { |
313 | 315 | if (**argv != '-') usage(ping_usage); | |
314 | while (**argv == '-') { | 316 | thisarg = *argv; thisarg++; |
315 | while (*++(*argv)) | 317 | switch (*thisarg) { |
316 | switch (**argv) { | 318 | case 'q': options |= O_QUIET; break; |
317 | case 'c': | 319 | case 'c': |
318 | argc--; argv++; | 320 | argc--; argv++; |
319 | if (argc < 1) usage(ping_usage); | 321 | pingcount = atoi(*argv); |
320 | pingcount = atoi(*argv); | 322 | break; |
321 | break; | 323 | default: |
322 | case 'q': | 324 | usage(ping_usage); |
323 | options |= O_QUIET; | 325 | } |
324 | break; | 326 | argc--; argv++; |
325 | default: | ||
326 | usage(ping_usage); | ||
327 | } | ||
328 | argc--; | ||
329 | argv++; | ||
330 | } | 327 | } |
331 | 328 | if (argc < 1) usage(ping_usage); | |
332 | if (argc < 1) usage(ping_usage); | ||
333 | 329 | ||
334 | myid = getpid() & 0xFFFF; | 330 | myid = getpid() & 0xFFFF; |
335 | ping(*(argv++)); | 331 | ping(*argv); |
336 | exit( TRUE); | 332 | exit(TRUE); |
337 | } | 333 | } |
338 | 334 | ||
339 | /* | 335 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ping.c,v 1.4 1999/12/08 23:19:36 andersen Exp $ | 2 | * $Id: ping.c,v 1.5 1999/12/09 06:11:36 andersen Exp $ |
3 | * Mini ping implementation for busybox | 3 | * Mini ping implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | 5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> |
@@ -53,6 +53,7 @@ | |||
53 | #define MAXPACKET 65468 | 53 | #define MAXPACKET 65468 |
54 | #define MAX_DUP_CHK (8 * 128) | 54 | #define MAX_DUP_CHK (8 * 128) |
55 | #define MAXWAIT 10 | 55 | #define MAXWAIT 10 |
56 | #define PINGINTERVAL 1 /* second */ | ||
56 | 57 | ||
57 | #define O_QUIET (1 << 0) | 58 | #define O_QUIET (1 << 0) |
58 | 59 | ||
@@ -155,8 +156,8 @@ static void sendping(int ign) | |||
155 | } | 156 | } |
156 | 157 | ||
157 | signal(SIGALRM, sendping); | 158 | signal(SIGALRM, sendping); |
158 | if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next */ | 159 | if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ |
159 | alarm(1); | 160 | alarm(PINGINTERVAL); |
160 | } else { /* done, wait for the last ping to come back */ | 161 | } else { /* done, wait for the last ping to come back */ |
161 | /* todo, don't necessarily need to wait so long... */ | 162 | /* todo, don't necessarily need to wait so long... */ |
162 | signal(SIGALRM, pingstats); | 163 | signal(SIGALRM, pingstats); |
@@ -243,9 +244,8 @@ static void ping(char *host) | |||
243 | exit(1); | 244 | exit(1); |
244 | } | 245 | } |
245 | 246 | ||
246 | #ifdef SUID_BUSYBOX | 247 | /* drop root privs if running setuid */ |
247 | setuid(getuid()); | 248 | setuid(getuid()); |
248 | #endif | ||
249 | 249 | ||
250 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); | 250 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); |
251 | pingaddr.sin_family = AF_INET; | 251 | pingaddr.sin_family = AF_INET; |
@@ -305,35 +305,31 @@ static void ping(char *host) | |||
305 | 305 | ||
306 | extern int ping_main(int argc, char **argv) | 306 | extern int ping_main(int argc, char **argv) |
307 | { | 307 | { |
308 | char *thisarg; | ||
309 | |||
308 | argc--; | 310 | argc--; |
309 | argv++; | 311 | argv++; |
310 | options = 0; | 312 | options = 0; |
311 | /* Parse any options */ | 313 | /* Parse any options */ |
312 | if (argc < 1) usage(ping_usage); | 314 | while (argc > 1) { |
313 | 315 | if (**argv != '-') usage(ping_usage); | |
314 | while (**argv == '-') { | 316 | thisarg = *argv; thisarg++; |
315 | while (*++(*argv)) | 317 | switch (*thisarg) { |
316 | switch (**argv) { | 318 | case 'q': options |= O_QUIET; break; |
317 | case 'c': | 319 | case 'c': |
318 | argc--; argv++; | 320 | argc--; argv++; |
319 | if (argc < 1) usage(ping_usage); | 321 | pingcount = atoi(*argv); |
320 | pingcount = atoi(*argv); | 322 | break; |
321 | break; | 323 | default: |
322 | case 'q': | 324 | usage(ping_usage); |
323 | options |= O_QUIET; | 325 | } |
324 | break; | 326 | argc--; argv++; |
325 | default: | ||
326 | usage(ping_usage); | ||
327 | } | ||
328 | argc--; | ||
329 | argv++; | ||
330 | } | 327 | } |
331 | 328 | if (argc < 1) usage(ping_usage); | |
332 | if (argc < 1) usage(ping_usage); | ||
333 | 329 | ||
334 | myid = getpid() & 0xFFFF; | 330 | myid = getpid() & 0xFFFF; |
335 | ping(*(argv++)); | 331 | ping(*argv); |
336 | exit( TRUE); | 332 | exit(TRUE); |
337 | } | 333 | } |
338 | 334 | ||
339 | /* | 335 | /* |
@@ -13,35 +13,16 @@ | |||
13 | 13 | ||
14 | You should have received a copy of the GNU General Public License | 14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software | 15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | |||
18 | /* Can display any amount of data, unlike the Unix version, which uses | ||
19 | a fixed size buffer and therefore can only deliver a limited number | ||
20 | of lines. | ||
21 | |||
22 | Options: | ||
23 | -b Tail by N 512-byte blocks. | ||
24 | -c, --bytes=N[bkm] Tail by N bytes | ||
25 | [or 512-byte blocks, kilobytes, or megabytes]. | ||
26 | -f, --follow Loop forever trying to read more characters at the | ||
27 | end of the file, on the assumption that the file | ||
28 | is growing. Ignored if reading from a pipe. | ||
29 | -n, --lines=N Tail by N lines. | ||
30 | -q, --quiet, --silent Never print filename headers. | ||
31 | -v, --verbose Always print filename headers. | ||
32 | |||
33 | If a number (N) starts with a `+', begin printing with the Nth item | ||
34 | from the start of each file, instead of from the end. | ||
35 | |||
36 | Reads from standard input if no files are given or when a filename of | ||
37 | ``-'' is encountered. | ||
38 | By default, filename headers are printed only more than one file | ||
39 | is given. | ||
40 | By default, prints the last 10 lines (tail -n 10). | ||
41 | 17 | ||
42 | Original version by Paul Rubin <phr@ocf.berkeley.edu>. | 18 | Original version by Paul Rubin <phr@ocf.berkeley.edu>. |
43 | Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. | 19 | Extensions by David MacKenzie <djm@gnu.ai.mit.edu>. |
44 | tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. */ | 20 | tail -f for multiple files by Ian Lance Taylor <ian@airs.com>. |
21 | |||
22 | Rewrote the option parser, removed locales support, | ||
23 | and generally busyboxed, Erik Andersen <andersen@lineo.com> | ||
24 | |||
25 | */ | ||
45 | 26 | ||
46 | #include "internal.h" | 27 | #include "internal.h" |
47 | 28 | ||
@@ -49,16 +30,25 @@ | |||
49 | #include <assert.h> | 30 | #include <assert.h> |
50 | #include <errno.h> | 31 | #include <errno.h> |
51 | #include <sys/types.h> | 32 | #include <sys/types.h> |
33 | #include <sys/types.h> | ||
34 | #include <sys/stat.h> | ||
35 | #include <fcntl.h> | ||
36 | #include <ctype.h> | ||
37 | |||
52 | 38 | ||
53 | 39 | ||
54 | /* Disable assertions. Some systems have broken assert macros. */ | 40 | /* Disable assertions. Some systems have broken assert macros. */ |
55 | #define NDEBUG 1 | 41 | #define NDEBUG 1 |
56 | 42 | ||
57 | 43 | ||
58 | static void error(int i, int errnum, char* fmt, const char *msg) | 44 | static void error(int i, int errnum, char* fmt, ...) |
59 | { | 45 | { |
60 | fprintf(stderr, fmt, msg); | 46 | va_list arguments; |
61 | perror( errnum); | 47 | |
48 | va_start(arguments, fmt); | ||
49 | vfprintf(stderr, fmt, arguments); | ||
50 | fprintf(stderr, "\n%s\n", strerror( errnum)); | ||
51 | va_end(arguments); | ||
62 | exit(i); | 52 | exit(i); |
63 | } | 53 | } |
64 | 54 | ||
@@ -69,7 +59,7 @@ static void error(int i, int errnum, char* fmt, const char *msg) | |||
69 | assert ((fd) == 1); \ | 59 | assert ((fd) == 1); \ |
70 | assert ((n_bytes) >= 0); \ | 60 | assert ((n_bytes) >= 0); \ |
71 | if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ | 61 | if (n_bytes > 0 && fwrite ((buffer), 1, (n_bytes), stdout) == 0) \ |
72 | error (EXIT_FAILURE, errno, "write error", NULL); \ | 62 | error (EXIT_FAILURE, errno, "write error"); \ |
73 | } \ | 63 | } \ |
74 | while (0) | 64 | while (0) |
75 | 65 | ||
@@ -110,7 +100,6 @@ enum header_mode | |||
110 | }; | 100 | }; |
111 | 101 | ||
112 | char *xmalloc (); | 102 | char *xmalloc (); |
113 | int safe_read (); | ||
114 | 103 | ||
115 | /* The name this program was run with. */ | 104 | /* The name this program was run with. */ |
116 | char *program_name; | 105 | char *program_name; |
@@ -118,33 +107,24 @@ char *program_name; | |||
118 | /* Nonzero if we have ever read standard input. */ | 107 | /* Nonzero if we have ever read standard input. */ |
119 | static int have_read_stdin; | 108 | static int have_read_stdin; |
120 | 109 | ||
121 | /* If nonzero, display usage information and exit. */ | ||
122 | static int show_help; | ||
123 | |||
124 | /* If nonzero, print the version on standard output then exit. */ | ||
125 | static int show_version; | ||
126 | 110 | ||
127 | static const char tail_usage[] = | 111 | static const char tail_usage[] = |
128 | "tail [OPTION]... [FILE]...\n\ | 112 | "tail [OPTION]... [FILE]...\n\ |
113 | \n\ | ||
129 | Print last 10 lines of each FILE to standard output.\n\ | 114 | Print last 10 lines of each FILE to standard output.\n\ |
130 | With more than one FILE, precede each with a header giving the file name.\n\ | 115 | With more than one FILE, precede each with a header giving the file name.\n\ |
131 | With no FILE, or when FILE is -, read standard input.\n\ | 116 | With no FILE, or when FILE is -, read standard input.\n\ |
132 | \n\ | 117 | \n\ |
133 | -c, --bytes=N output the last N bytes\n\ | 118 | -c=N[kbm] output the last N bytes\n\ |
134 | -f, --follow output appended data as the file grows\n\ | 119 | -f output appended data as the file grows\n\ |
135 | -n, --lines=N output the last N lines, instead of last 10\n\ | 120 | -n=N output the last N lines, instead of last 10\n\ |
136 | -q, --quiet, --silent never output headers giving file names\n\ | 121 | -q never output headers giving file names\n\ |
137 | -v, --verbose always output headers giving file names\n\ | 122 | -v always output headers giving file names\n\ |
138 | --help display this help and exit\n\ | 123 | --help display this help and exit\n\ |
139 | --version output version information and exit\n\ | ||
140 | \n\ | 124 | \n\ |
141 | If the first character of N (the number of bytes or lines) is a `+',\n\ | 125 | If the first character of N (bytes or lines) is a `+', output begins with \n\ |
142 | print beginning with the Nth item from the start of each file, otherwise,\n\ | 126 | the Nth item from the start of each file, otherwise, print the last N items\n\ |
143 | print the last N items in the file. N may have a multiplier suffix:\n\ | 127 | in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; |
144 | b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\ | ||
145 | or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\ | ||
146 | the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\ | ||
147 | or -c +VALUE.\n"; | ||
148 | 128 | ||
149 | static void | 129 | static void |
150 | write_header (const char *filename, const char *comment) | 130 | 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) | |||
184 | reads will be on block boundaries, which might increase efficiency. */ | 164 | reads will be on block boundaries, which might increase efficiency. */ |
185 | pos -= bytes_read; | 165 | pos -= bytes_read; |
186 | lseek (fd, pos, SEEK_SET); | 166 | lseek (fd, pos, SEEK_SET); |
187 | bytes_read = safe_read (fd, buffer, bytes_read); | 167 | bytes_read = fullRead (fd, buffer, bytes_read); |
188 | if (bytes_read == -1) | 168 | if (bytes_read == -1) |
189 | { | 169 | { |
190 | error (0, errno, "%s", filename); | 170 | error (0, errno, "%s", filename); |
@@ -220,7 +200,7 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos) | |||
220 | pos -= BUFSIZ; | 200 | pos -= BUFSIZ; |
221 | lseek (fd, pos, SEEK_SET); | 201 | lseek (fd, pos, SEEK_SET); |
222 | } | 202 | } |
223 | while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0); | 203 | while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0); |
224 | if (bytes_read == -1) | 204 | if (bytes_read == -1) |
225 | { | 205 | { |
226 | error (0, errno, "%s", filename); | 206 | error (0, errno, "%s", filename); |
@@ -255,7 +235,7 @@ pipe_lines (const char *filename, int fd, long int n_lines) | |||
255 | tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); | 235 | tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); |
256 | 236 | ||
257 | /* Input is always read into a fresh buffer. */ | 237 | /* Input is always read into a fresh buffer. */ |
258 | while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) | 238 | while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) |
259 | { | 239 | { |
260 | tmp->nlines = 0; | 240 | tmp->nlines = 0; |
261 | tmp->next = NULL; | 241 | tmp->next = NULL; |
@@ -374,7 +354,7 @@ pipe_bytes (const char *filename, int fd, off_t n_bytes) | |||
374 | tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); | 354 | tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); |
375 | 355 | ||
376 | /* Input is always read into a fresh buffer. */ | 356 | /* Input is always read into a fresh buffer. */ |
377 | while ((tmp->nbytes = safe_read (fd, tmp->buffer, BUFSIZ)) > 0) | 357 | while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) |
378 | { | 358 | { |
379 | tmp->next = NULL; | 359 | tmp->next = NULL; |
380 | 360 | ||
@@ -453,7 +433,7 @@ start_bytes (const char *filename, int fd, off_t n_bytes) | |||
453 | char buffer[BUFSIZ]; | 433 | char buffer[BUFSIZ]; |
454 | int bytes_read = 0; | 434 | int bytes_read = 0; |
455 | 435 | ||
456 | while (n_bytes > 0 && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 436 | while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
457 | n_bytes -= bytes_read; | 437 | n_bytes -= bytes_read; |
458 | if (bytes_read == -1) | 438 | if (bytes_read == -1) |
459 | { | 439 | { |
@@ -476,7 +456,7 @@ start_lines (const char *filename, int fd, long int n_lines) | |||
476 | int bytes_read = 0; | 456 | int bytes_read = 0; |
477 | int bytes_to_skip = 0; | 457 | int bytes_to_skip = 0; |
478 | 458 | ||
479 | while (n_lines && (bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 459 | while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
480 | { | 460 | { |
481 | bytes_to_skip = 0; | 461 | bytes_to_skip = 0; |
482 | while (bytes_to_skip < bytes_read) | 462 | while (bytes_to_skip < bytes_read) |
@@ -509,7 +489,7 @@ dump_remainder (const char *filename, int fd) | |||
509 | 489 | ||
510 | total = 0; | 490 | total = 0; |
511 | output: | 491 | output: |
512 | while ((bytes_read = safe_read (fd, buffer, BUFSIZ)) > 0) | 492 | while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) |
513 | { | 493 | { |
514 | XWRITE (STDOUT_FILENO, buffer, bytes_read); | 494 | XWRITE (STDOUT_FILENO, buffer, bytes_read); |
515 | total += bytes_read; | 495 | total += bytes_read; |
@@ -731,7 +711,7 @@ tail_file (const char *filename, off_t n_units, int filenum) | |||
731 | int fd, errors; | 711 | int fd, errors; |
732 | struct stat stats; | 712 | struct stat stats; |
733 | 713 | ||
734 | if (!strcmp (filename, "-") | 714 | if (!strcmp (filename, "-")) |
735 | { | 715 | { |
736 | have_read_stdin = 1; | 716 | have_read_stdin = 1; |
737 | filename = "standard input"; | 717 | filename = "standard input"; |
@@ -815,16 +795,15 @@ tail_file (const char *filename, off_t n_units, int filenum) | |||
815 | } | 795 | } |
816 | 796 | ||
817 | extern int | 797 | extern int |
818 | tai_main (int argc, char **argv) | 798 | tail_main (int argc, char **argv) |
819 | { | 799 | { |
800 | int stopit = 0; | ||
820 | enum header_mode header_mode = multiple_files; | 801 | enum header_mode header_mode = multiple_files; |
821 | int exit_status = 0; | 802 | int exit_status = 0; |
822 | /* If from_start, the number of items to skip before printing; otherwise, | 803 | /* If from_start, the number of items to skip before printing; otherwise, |
823 | the number of items at the end of the file to print. Initially, -1 | 804 | the number of items at the end of the file to print. Initially, -1 |
824 | means the value has not been set. */ | 805 | means the value has not been set. */ |
825 | off_t n_units = -1; | 806 | off_t n_units = -1; |
826 | long int tmp_long; | ||
827 | int c; /* Option character. */ | ||
828 | int n_files; | 807 | int n_files; |
829 | char **file; | 808 | char **file; |
830 | 809 | ||
@@ -832,48 +811,38 @@ tai_main (int argc, char **argv) | |||
832 | have_read_stdin = 0; | 811 | have_read_stdin = 0; |
833 | count_lines = 1; | 812 | count_lines = 1; |
834 | forever = forever_multiple = from_start = print_headers = 0; | 813 | forever = forever_multiple = from_start = print_headers = 0; |
835 | 814 | ||
836 | if (argc > 1 | 815 | /* Parse any options */ |
837 | && ((argv[1][0] == '-' && ISDIGIT (argv[1][1])) | 816 | //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); |
838 | || (argv[1][0] == '+' && (ISDIGIT (argv[1][1]) | 817 | while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { |
839 | || argv[1][1] == 0)))) | 818 | if (**argv == '+') { |
840 | { | 819 | from_start = 1; |
841 | /* Old option syntax: a dash or plus, one or more digits (zero digits | 820 | } |
842 | are acceptable with a plus), and one or more option letters. */ | 821 | stopit = 0; |
843 | if (argv[1][0] == '+') | 822 | while (stopit == 0 && *(++(*argv))) { |
844 | from_start = 1; | 823 | switch (**argv) { |
845 | if (argv[1][1] != '\0') | ||
846 | { | ||
847 | strtol_error s_err; | ||
848 | char *p; | ||
849 | |||
850 | s_err = xstrtol (++argv[1], &p, 0, &tmp_long, "bkm"); | ||
851 | n_units = tmp_long; | ||
852 | if (s_err == LONGINT_OVERFLOW) | ||
853 | { | ||
854 | STRTOL_FATAL_ERROR (argv[1], "argument", s_err); | ||
855 | } | ||
856 | |||
857 | /* If a [bkm] suffix was given then count bytes, not lines. */ | ||
858 | if (p[-1] == 'b' || p[-1] == 'k' || p[-1] == 'm') | ||
859 | count_lines = 0; | ||
860 | |||
861 | /* Parse any appended option letters. */ | ||
862 | while (*p) | ||
863 | { | ||
864 | switch (*p) | ||
865 | { | ||
866 | case 'c': | 824 | case 'c': |
867 | /* Interpret N_UNITS as # of bytes. */ | ||
868 | count_lines = 0; | 825 | count_lines = 0; |
826 | |||
827 | if (--argc < 1) { | ||
828 | usage(tail_usage); | ||
829 | } | ||
830 | n_units = getNum(*(++argv)); | ||
831 | stopit = 1; | ||
869 | break; | 832 | break; |
870 | 833 | ||
871 | case 'f': | 834 | case 'f': |
872 | forever = 1; | 835 | forever = 1; |
873 | break; | 836 | break; |
874 | 837 | ||
875 | case 'l': | 838 | case 'n': |
876 | count_lines = 1; | 839 | count_lines = 1; |
840 | |||
841 | if (--argc < 1) { | ||
842 | usage(tail_usage); | ||
843 | } | ||
844 | n_units = atol(*(++argv)); | ||
845 | stopit = 1; | ||
877 | break; | 846 | break; |
878 | 847 | ||
879 | case 'q': | 848 | case 'q': |
@@ -885,26 +854,11 @@ tai_main (int argc, char **argv) | |||
885 | break; | 854 | break; |
886 | 855 | ||
887 | default: | 856 | default: |
888 | error (0, 0, "unrecognized option '%c'", *p); | ||
889 | usage (tail_usage); | 857 | usage (tail_usage); |
890 | } | ||
891 | ++p; | ||
892 | } | 858 | } |
893 | } | 859 | } |
894 | /* Make the options we just parsed invisible to getopt. */ | ||
895 | argv[1] = argv[0]; | ||
896 | argv++; | ||
897 | argc--; | ||
898 | } | ||
899 | |||
900 | if (show_version) | ||
901 | { | ||
902 | printf ("tail - %s\n", PACKAGE_VERSION); | ||
903 | exit (EXIT_SUCCESS); | ||
904 | } | 860 | } |
905 | 861 | ||
906 | if (show_help) | ||
907 | usage (tail_usage); | ||
908 | 862 | ||
909 | if (n_units == -1) | 863 | if (n_units == -1) |
910 | n_units = DEFAULT_N_LINES; | 864 | n_units = DEFAULT_N_LINES; |
@@ -918,8 +872,8 @@ tai_main (int argc, char **argv) | |||
918 | --n_units; | 872 | --n_units; |
919 | } | 873 | } |
920 | 874 | ||
921 | n_files = argc - optind; | 875 | n_files = argc; |
922 | file = argv + optind; | 876 | file = argv; |
923 | 877 | ||
924 | if (n_files > 1 && forever) | 878 | if (n_files > 1 && forever) |
925 | { | 879 | { |
@@ -289,7 +289,7 @@ const char *modeString(int mode) | |||
289 | #endif | 289 | #endif |
290 | 290 | ||
291 | 291 | ||
292 | #ifdef BB_TAR | 292 | #if defined BB_TAR |
293 | /* | 293 | /* |
294 | * Return the standard ls-like time string from a time_t | 294 | * Return the standard ls-like time string from a time_t |
295 | * This is static and so is overwritten on each call. | 295 | * This is static and so is overwritten on each call. |
@@ -340,8 +340,10 @@ int fullWrite(int fd, const char *buf, int len) | |||
340 | 340 | ||
341 | return total; | 341 | return total; |
342 | } | 342 | } |
343 | #endif | ||
343 | 344 | ||
344 | 345 | ||
346 | #if defined BB_TAR || defined BB_TAIL | ||
345 | /* | 347 | /* |
346 | * Read all of the supplied buffer from a file. | 348 | * Read all of the supplied buffer from a file. |
347 | * This does multiple reads as necessary. | 349 | * This does multiple reads as necessary. |
@@ -1018,6 +1020,55 @@ extern void whine_if_fstab_is_missing() | |||
1018 | #endif | 1020 | #endif |
1019 | 1021 | ||
1020 | 1022 | ||
1023 | #if defined BB_DD || defined BB_TAIL | ||
1024 | /* | ||
1025 | * Read a number with a possible multiplier. | ||
1026 | * Returns -1 if the number format is illegal. | ||
1027 | */ | ||
1028 | extern long getNum (const char *cp) | ||
1029 | { | ||
1030 | long value; | ||
1031 | |||
1032 | if (!isDecimal (*cp)) | ||
1033 | return -1; | ||
1034 | |||
1035 | value = 0; | ||
1036 | |||
1037 | while (isDecimal (*cp)) | ||
1038 | value = value * 10 + *cp++ - '0'; | ||
1039 | |||
1040 | switch (*cp++) { | ||
1041 | case 'm': | ||
1042 | value *= 1048576; | ||
1043 | break; | ||
1044 | |||
1045 | case 'k': | ||
1046 | value *= 1024; | ||
1047 | break; | ||
1048 | |||
1049 | case 'b': | ||
1050 | value *= 512; | ||
1051 | break; | ||
1052 | |||
1053 | case 'w': | ||
1054 | value *= 2; | ||
1055 | break; | ||
1056 | |||
1057 | case '\0': | ||
1058 | return value; | ||
1059 | |||
1060 | default: | ||
1061 | return -1; | ||
1062 | } | ||
1063 | |||
1064 | if (*cp) | ||
1065 | return -1; | ||
1066 | |||
1067 | return value; | ||
1068 | } | ||
1069 | #endif | ||
1070 | |||
1071 | |||
1021 | /* END CODE */ | 1072 | /* END CODE */ |
1022 | 1073 | ||
1023 | 1074 | ||