aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>1999-12-09 06:11:36 +0000
committerEric Andersen <andersen@codepoet.org>1999-12-09 06:11:36 +0000
commit1792f8c48926450501e19d32e78e140bcb9661c6 (patch)
tree14d0304ebb774077e696a9c86117bf43d935d8bb
parentc24db7b591870978fdd2cec8995728d1520c2fa9 (diff)
downloadbusybox-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--Changelog8
-rw-r--r--TODO7
-rw-r--r--coreutils/dd.c46
-rw-r--r--coreutils/tail.c176
-rw-r--r--dd.c46
-rw-r--r--hostname.c2
-rw-r--r--internal.h1
-rw-r--r--networking/hostname.c2
-rw-r--r--networking/ping.c50
-rw-r--r--ping.c50
-rw-r--r--tail.c176
-rw-r--r--utility.c53
12 files changed, 241 insertions, 376 deletions
diff --git a/Changelog b/Changelog
index 62a317123..99963cef9 100644
--- a/Changelog
+++ b/Changelog
@@ -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
180.38 180.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.
diff --git a/TODO b/TODO
index 668338299..08b2fd736 100644
--- a/TODO
+++ b/TODO
@@ -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 */
60static 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
99extern int dd_main (int argc, char **argv) 55extern 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
58static void error(int i, int errnum, char* fmt, const char *msg) 44static 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
112char *xmalloc (); 102char *xmalloc ();
113int safe_read ();
114 103
115/* The name this program was run with. */ 104/* The name this program was run with. */
116char *program_name; 105char *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. */
119static int have_read_stdin; 108static int have_read_stdin;
120 109
121/* If nonzero, display usage information and exit. */
122static int show_help;
123
124/* If nonzero, print the version on standard output then exit. */
125static int show_version;
126 110
127static const char tail_usage[] = 111static const char tail_usage[] =
128"tail [OPTION]... [FILE]...\n\ 112"tail [OPTION]... [FILE]...\n\
113\n\
129Print last 10 lines of each FILE to standard output.\n\ 114Print last 10 lines of each FILE to standard output.\n\
130With more than one FILE, precede each with a header giving the file name.\n\ 115With more than one FILE, precede each with a header giving the file name.\n\
131With no FILE, or when FILE is -, read standard input.\n\ 116With 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\
141If the first character of N (the number of bytes or lines) is a `+',\n\ 125If the first character of N (bytes or lines) is a `+', output begins with \n\
142print beginning with the Nth item from the start of each file, otherwise,\n\ 126the Nth item from the start of each file, otherwise, print the last N items\n\
143print the last N items in the file. N may have a multiplier suffix:\n\ 127in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
144b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\
145or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\
146the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\
147or -c +VALUE.\n";
148 128
149static void 129static void
150write_header (const char *filename, const char *comment) 130write_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;
511output: 491output:
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
817extern int 797extern int
818tai_main (int argc, char **argv) 798tail_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 {
diff --git a/dd.c b/dd.c
index b37038748..90c1004fa 100644
--- a/dd.c
+++ b/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 */
60static 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
99extern int dd_main (int argc, char **argv) 55extern 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);
156extern void erase_mtab(const char * name); 156extern void erase_mtab(const char * name);
157extern int check_wildcard_match(const char* text, const char* pattern); 157extern int check_wildcard_match(const char* text, const char* pattern);
158extern 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
306extern int ping_main(int argc, char **argv) 306extern 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/*
diff --git a/ping.c b/ping.c
index 45f3c20aa..4176ab390 100644
--- a/ping.c
+++ b/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
306extern int ping_main(int argc, char **argv) 306extern 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/*
diff --git a/tail.c b/tail.c
index 058d462a5..7a64c4ca3 100644
--- a/tail.c
+++ b/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
58static void error(int i, int errnum, char* fmt, const char *msg) 44static 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
112char *xmalloc (); 102char *xmalloc ();
113int safe_read ();
114 103
115/* The name this program was run with. */ 104/* The name this program was run with. */
116char *program_name; 105char *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. */
119static int have_read_stdin; 108static int have_read_stdin;
120 109
121/* If nonzero, display usage information and exit. */
122static int show_help;
123
124/* If nonzero, print the version on standard output then exit. */
125static int show_version;
126 110
127static const char tail_usage[] = 111static const char tail_usage[] =
128"tail [OPTION]... [FILE]...\n\ 112"tail [OPTION]... [FILE]...\n\
113\n\
129Print last 10 lines of each FILE to standard output.\n\ 114Print last 10 lines of each FILE to standard output.\n\
130With more than one FILE, precede each with a header giving the file name.\n\ 115With more than one FILE, precede each with a header giving the file name.\n\
131With no FILE, or when FILE is -, read standard input.\n\ 116With 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\
141If the first character of N (the number of bytes or lines) is a `+',\n\ 125If the first character of N (bytes or lines) is a `+', output begins with \n\
142print beginning with the Nth item from the start of each file, otherwise,\n\ 126the Nth item from the start of each file, otherwise, print the last N items\n\
143print the last N items in the file. N may have a multiplier suffix:\n\ 127in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
144b for 512, k for 1024, m for 1048576 (1 Meg). A first OPTION of -VALUE\n\
145or +VALUE is treated like -n VALUE or -n +VALUE unless VALUE has one of\n\
146the [bkm] suffix multipliers, in which case it is treated like -c VALUE\n\
147or -c +VALUE.\n";
148 128
149static void 129static void
150write_header (const char *filename, const char *comment) 130write_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;
511output: 491output:
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
817extern int 797extern int
818tai_main (int argc, char **argv) 798tail_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 {
diff --git a/utility.c b/utility.c
index 469275f2d..de7a0fbfc 100644
--- a/utility.c
+++ b/utility.c
@@ -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 */
1028extern 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