diff options
-rw-r--r-- | coreutils/Config.in | 4 | ||||
-rw-r--r-- | coreutils/echo.c | 153 | ||||
-rw-r--r-- | coreutils/test.c | 123 | ||||
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/Makefile.in | 2 | ||||
-rw-r--r-- | libbb/bb_echo.c | 151 | ||||
-rw-r--r-- | shell/Config.in | 38 | ||||
-rw-r--r-- | shell/ash.c | 30 |
8 files changed, 270 insertions, 232 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in index 605649baf..07005b81a 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in | |||
@@ -603,8 +603,8 @@ config CONFIG_TEST | |||
603 | default n | 603 | default n |
604 | help | 604 | help |
605 | test is used to check file types and compare values, | 605 | test is used to check file types and compare values, |
606 | returning an appropriate exit code. The shells (ash | 606 | returning an appropriate exit code. The bash shell |
607 | and bash) have test builtin. | 607 | has test built in, ash can build it in optionally. |
608 | 608 | ||
609 | config CONFIG_FEATURE_TEST_64 | 609 | config CONFIG_FEATURE_TEST_64 |
610 | bool "Extend test to 64 bit" | 610 | bool "Extend test to 64 bit" |
diff --git a/coreutils/echo.c b/coreutils/echo.c index 0dbb32f28..a673bb07a 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c | |||
@@ -1,29 +1,158 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
1 | /* | 2 | /* |
2 | * echo applet implementation for busybox | 3 | * echo implementation for busybox |
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * Copyright (c) 1991, 1993 |
5 | * it under the terms of the GNU General Public License as published by | 6 | * The Regents of the University of California. All rights reserved. |
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | 7 | * |
9 | * This program is distributed in the hope that it will be useful, | 8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | 9 | * |
14 | * You should have received a copy of the GNU General Public License | 10 | * Original copyright notice is retained at the end of this file. |
15 | * along with this program; if not, write to the Free Software | 11 | */ |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 12 | |
13 | /* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ | ||
14 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ | ||
15 | |||
16 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
17 | * | 17 | * |
18 | * Because of behavioral differences, implemented configurable SUSv3 | ||
19 | * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs. | ||
20 | * 1) In handling '\c' escape, the previous version only suppressed the | ||
21 | * trailing newline. SUSv3 specifies _no_ output after '\c'. | ||
22 | * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. | ||
23 | * The previous version version did not allow 4-digit octals. | ||
18 | */ | 24 | */ |
19 | 25 | ||
26 | |||
20 | #include <stdio.h> | 27 | #include <stdio.h> |
21 | #include <string.h> | 28 | #include <string.h> |
22 | #include <stdlib.h> | 29 | #include <stdlib.h> |
23 | #include "busybox.h" | 30 | #include "busybox.h" |
24 | 31 | ||
32 | int bb_echo(int ATTRIBUTE_UNUSED argc, char **argv) | ||
33 | { | ||
34 | #ifndef CONFIG_FEATURE_FANCY_ECHO | ||
35 | #define eflag '\\' | ||
36 | ++argv; | ||
37 | #else | ||
38 | const char *p; | ||
39 | int nflag = 1; | ||
40 | int eflag = 0; | ||
41 | |||
42 | while (*++argv && (**argv == '-')) { | ||
43 | /* If it appears that we are handling options, then make sure | ||
44 | * that all of the options specified are actually valid. | ||
45 | * Otherwise, the string should just be echoed. | ||
46 | */ | ||
47 | |||
48 | if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ | ||
49 | goto just_echo; | ||
50 | } | ||
51 | |||
52 | do { | ||
53 | if (strrchr("neE", *p) == 0) { | ||
54 | goto just_echo; | ||
55 | } | ||
56 | } while (*++p); | ||
57 | |||
58 | /* All of the options in this arg are valid, so handle them. */ | ||
59 | p = *argv + 1; | ||
60 | do { | ||
61 | if (*p == 'n') { | ||
62 | nflag = 0; | ||
63 | } else if (*p == 'e') { | ||
64 | eflag = '\\'; | ||
65 | } else { | ||
66 | eflag = 0; | ||
67 | } | ||
68 | } while (*++p); | ||
69 | } | ||
70 | |||
71 | just_echo: | ||
72 | #endif | ||
73 | while (*argv) { | ||
74 | register int c; | ||
75 | |||
76 | while ((c = *(*argv)++)) { | ||
77 | if (c == eflag) { /* Check for escape seq. */ | ||
78 | if (**argv == 'c') { | ||
79 | /* '\c' means cancel newline and | ||
80 | * ignore all subsequent chars. */ | ||
81 | return 0; | ||
82 | } | ||
83 | #ifndef CONFIG_FEATURE_FANCY_ECHO | ||
84 | /* SUSv3 specifies that octal escapes must begin with '0'. */ | ||
85 | if (((unsigned int)(**argv - '1')) >= 7) | ||
86 | #endif | ||
87 | { | ||
88 | /* Since SUSv3 mandates a first digit of 0, 4-digit octals | ||
89 | * of the form \0### are accepted. */ | ||
90 | if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { | ||
91 | (*argv)++; | ||
92 | } | ||
93 | /* bb_process_escape_sequence can handle nul correctly */ | ||
94 | c = bb_process_escape_sequence((const char **) argv); | ||
95 | } | ||
96 | } | ||
97 | putchar(c); | ||
98 | } | ||
99 | |||
100 | if (*++argv) { | ||
101 | putchar(' '); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | #ifdef CONFIG_FEATURE_FANCY_ECHO | ||
106 | if (nflag) { | ||
107 | putchar('\n'); | ||
108 | } | ||
109 | #else | ||
110 | putchar('\n'); | ||
111 | #endif | ||
112 | return 0; | ||
113 | } | ||
114 | |||
25 | int echo_main(int argc, char** argv) | 115 | int echo_main(int argc, char** argv) |
26 | { | 116 | { |
27 | (void)bb_echo(argc, argv); | 117 | (void)bb_echo(argc, argv); |
28 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); | 118 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); |
29 | } | 119 | } |
120 | |||
121 | /*- | ||
122 | * Copyright (c) 1991, 1993 | ||
123 | * The Regents of the University of California. All rights reserved. | ||
124 | * | ||
125 | * This code is derived from software contributed to Berkeley by | ||
126 | * Kenneth Almquist. | ||
127 | * | ||
128 | * Redistribution and use in source and binary forms, with or without | ||
129 | * modification, are permitted provided that the following conditions | ||
130 | * are met: | ||
131 | * 1. Redistributions of source code must retain the above copyright | ||
132 | * notice, this list of conditions and the following disclaimer. | ||
133 | * 2. Redistributions in binary form must reproduce the above copyright | ||
134 | * notice, this list of conditions and the following disclaimer in the | ||
135 | * documentation and/or other materials provided with the distribution. | ||
136 | * | ||
137 | * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change | ||
138 | * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> | ||
139 | * | ||
140 | * California, Berkeley and its contributors. | ||
141 | * 4. Neither the name of the University nor the names of its contributors | ||
142 | * may be used to endorse or promote products derived from this software | ||
143 | * without specific prior written permission. | ||
144 | * | ||
145 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
146 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
147 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
148 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
149 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
150 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
151 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
152 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
153 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
154 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
155 | * SUCH DAMAGE. | ||
156 | * | ||
157 | * @(#)echo.c 8.1 (Berkeley) 5/31/93 | ||
158 | */ | ||
diff --git a/coreutils/test.c b/coreutils/test.c index 2b624e308..4d920380d 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -4,31 +4,19 @@ | |||
4 | * | 4 | * |
5 | * Copyright (c) by a whole pile of folks: | 5 | * Copyright (c) by a whole pile of folks: |
6 | * | 6 | * |
7 | * test(1); version 7-like -- author Erik Baalbergen | 7 | * test(1); version 7-like -- author Erik Baalbergen |
8 | * modified by Eric Gisin to be used as built-in. | 8 | * modified by Eric Gisin to be used as built-in. |
9 | * modified by Arnold Robbins to add SVR3 compatibility | 9 | * modified by Arnold Robbins to add SVR3 compatibility |
10 | * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). | 10 | * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). |
11 | * modified by J.T. Conklin for NetBSD. | 11 | * modified by J.T. Conklin for NetBSD. |
12 | * modified by Herbert Xu to be used as built-in in ash. | 12 | * modified by Herbert Xu to be used as built-in in ash. |
13 | * modified by Erik Andersen <andersen@codepoet.org> to be used | 13 | * modified by Erik Andersen <andersen@codepoet.org> to be used |
14 | * in busybox. | 14 | * in busybox. |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify | 16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
24 | * General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
29 | * | 17 | * |
30 | * Original copyright notice states: | 18 | * Original copyright notice states: |
31 | * "This program is in the Public Domain." | 19 | * "This program is in the Public Domain." |
32 | */ | 20 | */ |
33 | 21 | ||
34 | #include <sys/types.h> | 22 | #include <sys/types.h> |
@@ -37,13 +25,14 @@ | |||
37 | #include <errno.h> | 25 | #include <errno.h> |
38 | #include <stdlib.h> | 26 | #include <stdlib.h> |
39 | #include <string.h> | 27 | #include <string.h> |
28 | #include <setjmp.h> | ||
40 | #include "busybox.h" | 29 | #include "busybox.h" |
41 | 30 | ||
42 | /* test(1) accepts the following grammar: | 31 | /* test(1) accepts the following grammar: |
43 | oexpr ::= aexpr | aexpr "-o" oexpr ; | 32 | oexpr ::= aexpr | aexpr "-o" oexpr ; |
44 | aexpr ::= nexpr | nexpr "-a" aexpr ; | 33 | aexpr ::= nexpr | nexpr "-a" aexpr ; |
45 | nexpr ::= primary | "!" primary | 34 | nexpr ::= primary | "!" primary |
46 | primary ::= unary-operator operand | 35 | primary ::= unary-operator operand |
47 | | operand binary-operator operand | 36 | | operand binary-operator operand |
48 | | operand | 37 | | operand |
49 | | "(" oexpr ")" | 38 | | "(" oexpr ")" |
@@ -128,7 +117,7 @@ static const struct t_op { | |||
128 | "-t", FILTT, UNOP}, { | 117 | "-t", FILTT, UNOP}, { |
129 | "-z", STREZ, UNOP}, { | 118 | "-z", STREZ, UNOP}, { |
130 | "-n", STRNZ, UNOP}, { | 119 | "-n", STRNZ, UNOP}, { |
131 | "-h", FILSYM, UNOP}, /* for backwards compat */ | 120 | "-h", FILSYM, UNOP}, /* for backwards compat */ |
132 | { | 121 | { |
133 | "-O", FILUID, UNOP}, { | 122 | "-O", FILUID, UNOP}, { |
134 | "-G", FILGID, UNOP}, { | 123 | "-G", FILGID, UNOP}, { |
@@ -182,36 +171,56 @@ static int test_eaccess(char *path, int mode); | |||
182 | static int is_a_group_member(gid_t gid); | 171 | static int is_a_group_member(gid_t gid); |
183 | static void initialize_group_array(void); | 172 | static void initialize_group_array(void); |
184 | 173 | ||
185 | int test_main(int argc, char **argv) | 174 | static jmp_buf leaving; |
175 | |||
176 | int bb_test(int argc, char **argv) | ||
186 | { | 177 | { |
187 | int res; | 178 | int res; |
188 | 179 | ||
189 | if (strcmp(bb_applet_name, "[") == 0) { | 180 | if (strcmp(argv[0], "[") == 0) { |
190 | if (strcmp(argv[--argc], "]")) | 181 | if (strcmp(argv[--argc], "]")) { |
191 | bb_error_msg_and_die("missing ]"); | 182 | bb_error_msg("missing ]"); |
183 | return 2; | ||
184 | } | ||
192 | argv[argc] = NULL; | 185 | argv[argc] = NULL; |
193 | } | 186 | } else if (strcmp(argv[0], "[[") == 0) { |
194 | if (strcmp(bb_applet_name, "[[") == 0) { | 187 | if (strcmp(argv[--argc], "]]")) { |
195 | if (strcmp(argv[--argc], "]]")) | 188 | bb_error_msg("missing ]]"); |
196 | bb_error_msg_and_die("missing ]]"); | 189 | return 2; |
190 | } | ||
197 | argv[argc] = NULL; | 191 | argv[argc] = NULL; |
198 | } | 192 | } |
193 | |||
194 | res = setjmp(leaving); | ||
195 | if (res) | ||
196 | return res; | ||
197 | |||
198 | /* resetting ngroups is probably unnecessary. it will | ||
199 | * force a new call to getgroups(), which prevents using | ||
200 | * group data fetched during a previous call. but the | ||
201 | * only way the group data could be stale is if there's | ||
202 | * been an intervening call to setgroups(), and this | ||
203 | * isn't likely in the case of a shell. paranoia | ||
204 | * prevails... | ||
205 | */ | ||
206 | ngroups = 0; | ||
207 | |||
199 | /* Implement special cases from POSIX.2, section 4.62.4 */ | 208 | /* Implement special cases from POSIX.2, section 4.62.4 */ |
200 | switch (argc) { | 209 | switch (argc) { |
201 | case 1: | 210 | case 1: |
202 | exit(1); | 211 | return 1; |
203 | case 2: | 212 | case 2: |
204 | exit(*argv[1] == '\0'); | 213 | return *argv[1] == '\0'; |
205 | case 3: | 214 | case 3: |
206 | if (argv[1][0] == '!' && argv[1][1] == '\0') { | 215 | if (argv[1][0] == '!' && argv[1][1] == '\0') { |
207 | exit(!(*argv[2] == '\0')); | 216 | return *argv[2] != '\0'; |
208 | } | 217 | } |
209 | break; | 218 | break; |
210 | case 4: | 219 | case 4: |
211 | if (argv[1][0] != '!' || argv[1][1] != '\0') { | 220 | if (argv[1][0] != '!' || argv[1][1] != '\0') { |
212 | if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) { | 221 | if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) { |
213 | t_wp = &argv[1]; | 222 | t_wp = &argv[1]; |
214 | exit(binop() == 0); | 223 | return binop() == 0; |
215 | } | 224 | } |
216 | } | 225 | } |
217 | break; | 226 | break; |
@@ -219,7 +228,7 @@ int test_main(int argc, char **argv) | |||
219 | if (argv[1][0] == '!' && argv[1][1] == '\0') { | 228 | if (argv[1][0] == '!' && argv[1][1] == '\0') { |
220 | if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) { | 229 | if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) { |
221 | t_wp = &argv[2]; | 230 | t_wp = &argv[2]; |
222 | exit(!(binop() == 0)); | 231 | return binop() != 0; |
223 | } | 232 | } |
224 | } | 233 | } |
225 | break; | 234 | break; |
@@ -228,10 +237,21 @@ int test_main(int argc, char **argv) | |||
228 | t_wp = &argv[1]; | 237 | t_wp = &argv[1]; |
229 | res = !oexpr(t_lex(*t_wp)); | 238 | res = !oexpr(t_lex(*t_wp)); |
230 | 239 | ||
231 | if (*t_wp != NULL && *++t_wp != NULL) | 240 | if (*t_wp != NULL && *++t_wp != NULL) { |
232 | bb_error_msg_and_die("%s: unknown operand", *t_wp); | 241 | bb_error_msg("%s: unknown operand", *t_wp); |
242 | return 2; | ||
243 | } | ||
244 | return res; | ||
245 | } | ||
233 | 246 | ||
234 | return (res); | 247 | static void syntax(const char *op, const char *msg) |
248 | { | ||
249 | if (op && *op) { | ||
250 | bb_error_msg("%s: %s", op, msg); | ||
251 | } else { | ||
252 | bb_error_msg("%s", msg); | ||
253 | } | ||
254 | longjmp(leaving, 2); | ||
235 | } | 255 | } |
236 | 256 | ||
237 | static arith_t oexpr(enum token n) | 257 | static arith_t oexpr(enum token n) |
@@ -269,18 +289,18 @@ static arith_t primary(enum token n) | |||
269 | arith_t res; | 289 | arith_t res; |
270 | 290 | ||
271 | if (n == EOI) { | 291 | if (n == EOI) { |
272 | bb_error_msg_and_die("argument expected"); | 292 | syntax(NULL, "argument expected"); |
273 | } | 293 | } |
274 | if (n == LPAREN) { | 294 | if (n == LPAREN) { |
275 | res = oexpr(t_lex(*++t_wp)); | 295 | res = oexpr(t_lex(*++t_wp)); |
276 | if (t_lex(*++t_wp) != RPAREN) | 296 | if (t_lex(*++t_wp) != RPAREN) |
277 | bb_error_msg_and_die("closing paren expected"); | 297 | syntax(NULL, "closing paren expected"); |
278 | return res; | 298 | return res; |
279 | } | 299 | } |
280 | if (t_wp_op && t_wp_op->op_type == UNOP) { | 300 | if (t_wp_op && t_wp_op->op_type == UNOP) { |
281 | /* unary expression */ | 301 | /* unary expression */ |
282 | if (*++t_wp == NULL) | 302 | if (*++t_wp == NULL) |
283 | bb_error_msg_and_die(bb_msg_requires_arg, t_wp_op->op_text); | 303 | syntax(t_wp_op->op_text, "argument expected"); |
284 | switch (n) { | 304 | switch (n) { |
285 | case STREZ: | 305 | case STREZ: |
286 | return strlen(*t_wp) == 0; | 306 | return strlen(*t_wp) == 0; |
@@ -310,7 +330,7 @@ static int binop(void) | |||
310 | op = t_wp_op; | 330 | op = t_wp_op; |
311 | 331 | ||
312 | if ((opnd2 = *++t_wp) == (char *) 0) | 332 | if ((opnd2 = *++t_wp) == (char *) 0) |
313 | bb_error_msg_and_die(bb_msg_requires_arg, op->op_text); | 333 | syntax(op->op_text, "argument expected"); |
314 | 334 | ||
315 | switch (op->op_num) { | 335 | switch (op->op_num) { |
316 | case STREQ: | 336 | case STREQ: |
@@ -460,11 +480,11 @@ static arith_t getn(const char *s) | |||
460 | #endif | 480 | #endif |
461 | 481 | ||
462 | if (errno != 0) | 482 | if (errno != 0) |
463 | bb_error_msg_and_die("%s: out of range", s); | 483 | syntax(s, "out of range"); |
464 | 484 | ||
465 | /* p = bb_skip_whitespace(p); avoid const warning */ | 485 | /* p = bb_skip_whitespace(p); avoid const warning */ |
466 | if (*(bb_skip_whitespace(p))) | 486 | if (*(bb_skip_whitespace(p))) |
467 | bb_error_msg_and_die("%s: bad number", s); | 487 | syntax(s, "bad number"); |
468 | 488 | ||
469 | return r; | 489 | return r; |
470 | } | 490 | } |
@@ -516,7 +536,7 @@ static int test_eaccess(char *path, int mode) | |||
516 | return (0); | 536 | return (0); |
517 | } | 537 | } |
518 | 538 | ||
519 | if (st.st_uid == euid) /* owner */ | 539 | if (st.st_uid == euid) /* owner */ |
520 | mode <<= 6; | 540 | mode <<= 6; |
521 | else if (is_a_group_member(st.st_gid)) | 541 | else if (is_a_group_member(st.st_gid)) |
522 | mode <<= 3; | 542 | mode <<= 3; |
@@ -553,3 +573,12 @@ static int is_a_group_member(gid_t gid) | |||
553 | 573 | ||
554 | return (0); | 574 | return (0); |
555 | } | 575 | } |
576 | |||
577 | |||
578 | /* applet entry point */ | ||
579 | |||
580 | int test_main(int argc, char **argv) | ||
581 | { | ||
582 | exit(bb_test(argc, argv)); | ||
583 | } | ||
584 | |||
diff --git a/include/libbb.h b/include/libbb.h index accc08ddf..b93b7a618 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -118,6 +118,7 @@ extern void bb_verror_msg(const char *s, va_list p) __attribute__ ((format (prin | |||
118 | extern void bb_vperror_msg(const char *s, va_list p) __attribute__ ((format (printf, 1, 0))); | 118 | extern void bb_vperror_msg(const char *s, va_list p) __attribute__ ((format (printf, 1, 0))); |
119 | 119 | ||
120 | extern int bb_echo(int argc, char** argv); | 120 | extern int bb_echo(int argc, char** argv); |
121 | extern int bb_test(int argc, char** argv); | ||
121 | 122 | ||
122 | extern const char *bb_mode_string(int mode); | 123 | extern const char *bb_mode_string(int mode); |
123 | extern int is_directory(const char *name, int followLinks, struct stat *statBuf); | 124 | extern int is_directory(const char *name, int followLinks, struct stat *statBuf); |
diff --git a/libbb/Makefile.in b/libbb/Makefile.in index f05b8ec16..0324ec041 100644 --- a/libbb/Makefile.in +++ b/libbb/Makefile.in | |||
@@ -35,7 +35,7 @@ LIBBB-y:= \ | |||
35 | getopt_ulflags.c default_error_retval.c wfopen_input.c speed_table.c \ | 35 | getopt_ulflags.c default_error_retval.c wfopen_input.c speed_table.c \ |
36 | perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c bb_askpass.c \ | 36 | perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c bb_askpass.c \ |
37 | warn_ignoring_args.c concat_subpath_file.c vfork_daemon_rexec.c \ | 37 | warn_ignoring_args.c concat_subpath_file.c vfork_daemon_rexec.c \ |
38 | bb_echo.c bb_do_delay.c | 38 | bb_do_delay.c |
39 | 39 | ||
40 | # conditionally compiled objects: | 40 | # conditionally compiled objects: |
41 | LIBBB-$(CONFIG_FEATURE_SHADOWPASSWDS)+=pwd2spwd.c | 41 | LIBBB-$(CONFIG_FEATURE_SHADOWPASSWDS)+=pwd2spwd.c |
diff --git a/libbb/bb_echo.c b/libbb/bb_echo.c deleted file mode 100644 index 0c5a94766..000000000 --- a/libbb/bb_echo.c +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * echo implementation for busybox | ||
4 | * | ||
5 | * Copyright (c) 1991, 1993 | ||
6 | * The Regents of the University of California. All rights reserved. | ||
7 | * | ||
8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
9 | * | ||
10 | * Original copyright notice is retained at the end of this file. | ||
11 | */ | ||
12 | |||
13 | /* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ | ||
14 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ | ||
15 | |||
16 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
17 | * | ||
18 | * Because of behavioral differences, implemented configurable SUSv3 | ||
19 | * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs. | ||
20 | * 1) In handling '\c' escape, the previous version only suppressed the | ||
21 | * trailing newline. SUSv3 specifies _no_ output after '\c'. | ||
22 | * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. | ||
23 | * The previous version version did not allow 4-digit octals. | ||
24 | */ | ||
25 | |||
26 | |||
27 | #include <stdio.h> | ||
28 | #include <string.h> | ||
29 | #include "libbb.h" | ||
30 | |||
31 | int bb_echo(int ATTRIBUTE_UNUSED argc, char **argv) | ||
32 | { | ||
33 | #ifndef CONFIG_FEATURE_FANCY_ECHO | ||
34 | #define eflag '\\' | ||
35 | ++argv; | ||
36 | #else | ||
37 | const char *p; | ||
38 | int nflag = 1; | ||
39 | int eflag = 0; | ||
40 | |||
41 | while (*++argv && (**argv == '-')) { | ||
42 | /* If it appears that we are handling options, then make sure | ||
43 | * that all of the options specified are actually valid. | ||
44 | * Otherwise, the string should just be echoed. | ||
45 | */ | ||
46 | |||
47 | if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ | ||
48 | goto just_echo; | ||
49 | } | ||
50 | |||
51 | do { | ||
52 | if (strrchr("neE", *p) == 0) { | ||
53 | goto just_echo; | ||
54 | } | ||
55 | } while (*++p); | ||
56 | |||
57 | /* All of the options in this arg are valid, so handle them. */ | ||
58 | p = *argv + 1; | ||
59 | do { | ||
60 | if (*p == 'n') { | ||
61 | nflag = 0; | ||
62 | } else if (*p == 'e') { | ||
63 | eflag = '\\'; | ||
64 | } else { | ||
65 | eflag = 0; | ||
66 | } | ||
67 | } while (*++p); | ||
68 | } | ||
69 | |||
70 | just_echo: | ||
71 | #endif | ||
72 | while (*argv) { | ||
73 | register int c; | ||
74 | |||
75 | while ((c = *(*argv)++)) { | ||
76 | if (c == eflag) { /* Check for escape seq. */ | ||
77 | if (**argv == 'c') { | ||
78 | /* '\c' means cancel newline and | ||
79 | * ignore all subsequent chars. */ | ||
80 | return 0; | ||
81 | } | ||
82 | #ifndef CONFIG_FEATURE_FANCY_ECHO | ||
83 | /* SUSv3 specifies that octal escapes must begin with '0'. */ | ||
84 | if (((unsigned int)(**argv - '1')) >= 7) | ||
85 | #endif | ||
86 | { | ||
87 | /* Since SUSv3 mandates a first digit of 0, 4-digit octals | ||
88 | * of the form \0### are accepted. */ | ||
89 | if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { | ||
90 | (*argv)++; | ||
91 | } | ||
92 | /* bb_process_escape_sequence can handle nul correctly */ | ||
93 | c = bb_process_escape_sequence((const char **) argv); | ||
94 | } | ||
95 | } | ||
96 | putchar(c); | ||
97 | } | ||
98 | |||
99 | if (*++argv) { | ||
100 | putchar(' '); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | #ifdef CONFIG_FEATURE_FANCY_ECHO | ||
105 | if (nflag) { | ||
106 | putchar('\n'); | ||
107 | } | ||
108 | #else | ||
109 | putchar('\n'); | ||
110 | #endif | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /*- | ||
115 | * Copyright (c) 1991, 1993 | ||
116 | * The Regents of the University of California. All rights reserved. | ||
117 | * | ||
118 | * This code is derived from software contributed to Berkeley by | ||
119 | * Kenneth Almquist. | ||
120 | * | ||
121 | * Redistribution and use in source and binary forms, with or without | ||
122 | * modification, are permitted provided that the following conditions | ||
123 | * are met: | ||
124 | * 1. Redistributions of source code must retain the above copyright | ||
125 | * notice, this list of conditions and the following disclaimer. | ||
126 | * 2. Redistributions in binary form must reproduce the above copyright | ||
127 | * notice, this list of conditions and the following disclaimer in the | ||
128 | * documentation and/or other materials provided with the distribution. | ||
129 | * | ||
130 | * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change | ||
131 | * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> | ||
132 | * | ||
133 | * California, Berkeley and its contributors. | ||
134 | * 4. Neither the name of the University nor the names of its contributors | ||
135 | * may be used to endorse or promote products derived from this software | ||
136 | * without specific prior written permission. | ||
137 | * | ||
138 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
139 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
140 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
141 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
142 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
143 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
144 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
145 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
146 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
147 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
148 | * SUCH DAMAGE. | ||
149 | * | ||
150 | * @(#)echo.c 8.1 (Berkeley) 5/31/93 | ||
151 | */ | ||
diff --git a/shell/Config.in b/shell/Config.in index dde8fd1dd..8f2f98e68 100644 --- a/shell/Config.in +++ b/shell/Config.in | |||
@@ -95,12 +95,28 @@ config CONFIG_ASH_MATH_SUPPORT_64 | |||
95 | large numbers. | 95 | large numbers. |
96 | 96 | ||
97 | config CONFIG_ASH_GETOPTS | 97 | config CONFIG_ASH_GETOPTS |
98 | bool "Enable getopts builtin to parse positional parameters" | 98 | bool "Builtin getopt to parse positional parameters" |
99 | default n | 99 | default n |
100 | depends on CONFIG_ASH | 100 | depends on CONFIG_ASH |
101 | help | 101 | help |
102 | Enable getopts builtin in the ash shell. | 102 | Enable getopts builtin in the ash shell. |
103 | 103 | ||
104 | config CONFIG_ASH_BUILTIN_ECHO | ||
105 | bool "Builtin version of 'echo'" | ||
106 | default y | ||
107 | select CONFIG_ECHO | ||
108 | depends on CONFIG_ASH | ||
109 | help | ||
110 | Enable support for echo, built in to ash. | ||
111 | |||
112 | config CONFIG_ASH_BUILTIN_TEST | ||
113 | bool "Builtin version of 'test'" | ||
114 | default y | ||
115 | select CONFIG_TEST | ||
116 | depends on CONFIG_ASH | ||
117 | help | ||
118 | Enable support for test, built in to ash. | ||
119 | |||
104 | config CONFIG_ASH_CMDCMD | 120 | config CONFIG_ASH_CMDCMD |
105 | bool "Enable cmdcmd to override shell builtins" | 121 | bool "Enable cmdcmd to override shell builtins" |
106 | default n | 122 | default n |
@@ -110,21 +126,6 @@ config CONFIG_ASH_CMDCMD | |||
110 | you to run the specified command with the specified arguments, | 126 | you to run the specified command with the specified arguments, |
111 | even when there is an ash builtin command with the same name. | 127 | even when there is an ash builtin command with the same name. |
112 | 128 | ||
113 | config CONFIG_ASH_BUILTIN_ECHO | ||
114 | bool "Enable builtin version of 'echo'" | ||
115 | default n | ||
116 | depends on CONFIG_ASH | ||
117 | help | ||
118 | Enable support for echo, built in to ash. | ||
119 | |||
120 | # this entry also appears in coreutils/Config.in, next to the echo applet | ||
121 | config CONFIG_FEATURE_FANCY_ECHO | ||
122 | bool "Enable echo options (-n and -e)" | ||
123 | default y | ||
124 | depends on CONFIG_ASH_BUILTIN_ECHO | ||
125 | help | ||
126 | This adds options (-n and -e) to echo. | ||
127 | |||
128 | config CONFIG_ASH_MAIL | 129 | config CONFIG_ASH_MAIL |
129 | bool "Check for new mail on interactive shells" | 130 | bool "Check for new mail on interactive shells" |
130 | default y | 131 | default y |
@@ -229,6 +230,11 @@ config CONFIG_FEATURE_SH_STANDALONE_SHELL | |||
229 | is generally used when creating a statically linked version of busybox | 230 | is generally used when creating a statically linked version of busybox |
230 | for use as a rescue shell, in the event that you screw up your system. | 231 | for use as a rescue shell, in the event that you screw up your system. |
231 | 232 | ||
233 | Note that this will *also* cause applets to take precedence | ||
234 | over shell builtins of the same name. So turning this on will | ||
235 | eliminate any performance gained by turning on the builtin "echo" | ||
236 | and "test" commands in ash. | ||
237 | |||
232 | Note that when using this option, the shell will attempt to directly | 238 | Note that when using this option, the shell will attempt to directly |
233 | run '/bin/busybox'. If you do not have the busybox binary sitting in | 239 | run '/bin/busybox'. If you do not have the busybox binary sitting in |
234 | that exact location with that exact name, this option will not work at | 240 | that exact location with that exact name, this option will not work at |
diff --git a/shell/ash.c b/shell/ash.c index 962813dbd..713898a9f 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -1225,6 +1225,9 @@ static int evalcmd(int, char **); | |||
1225 | #ifdef CONFIG_ASH_BUILTIN_ECHO | 1225 | #ifdef CONFIG_ASH_BUILTIN_ECHO |
1226 | static int echocmd(int, char **); | 1226 | static int echocmd(int, char **); |
1227 | #endif | 1227 | #endif |
1228 | #ifdef CONFIG_ASH_BUILTIN_TEST | ||
1229 | static int testcmd(int, char **); | ||
1230 | #endif | ||
1228 | static int execcmd(int, char **); | 1231 | static int execcmd(int, char **); |
1229 | static int exitcmd(int, char **); | 1232 | static int exitcmd(int, char **); |
1230 | static int exportcmd(int, char **); | 1233 | static int exportcmd(int, char **); |
@@ -1286,10 +1289,15 @@ struct builtincmd { | |||
1286 | 1289 | ||
1287 | 1290 | ||
1288 | #define COMMANDCMD (builtincmd + 5 + \ | 1291 | #define COMMANDCMD (builtincmd + 5 + \ |
1289 | ENABLE_ASH_ALIAS + ENABLE_ASH_JOB_CONTROL) | 1292 | 2 * ENABLE_ASH_BUILTIN_TEST + \ |
1293 | ENABLE_ASH_ALIAS + \ | ||
1294 | ENABLE_ASH_JOB_CONTROL) | ||
1290 | #define EXECCMD (builtincmd + 7 + \ | 1295 | #define EXECCMD (builtincmd + 7 + \ |
1291 | ENABLE_ASH_CMDCMD + ENABLE_ASH_ALIAS + \ | 1296 | 2 * ENABLE_ASH_BUILTIN_TEST + \ |
1292 | ENABLE_ASH_BUILTIN_ECHO + ENABLE_ASH_JOB_CONTROL) | 1297 | ENABLE_ASH_ALIAS + \ |
1298 | ENABLE_ASH_JOB_CONTROL + \ | ||
1299 | ENABLE_ASH_CMDCMD + \ | ||
1300 | ENABLE_ASH_BUILTIN_ECHO) | ||
1293 | 1301 | ||
1294 | #define BUILTIN_NOSPEC "0" | 1302 | #define BUILTIN_NOSPEC "0" |
1295 | #define BUILTIN_SPECIAL "1" | 1303 | #define BUILTIN_SPECIAL "1" |
@@ -1307,6 +1315,10 @@ struct builtincmd { | |||
1307 | static const struct builtincmd builtincmd[] = { | 1315 | static const struct builtincmd builtincmd[] = { |
1308 | { BUILTIN_SPEC_REG ".", dotcmd }, | 1316 | { BUILTIN_SPEC_REG ".", dotcmd }, |
1309 | { BUILTIN_SPEC_REG ":", truecmd }, | 1317 | { BUILTIN_SPEC_REG ":", truecmd }, |
1318 | #ifdef CONFIG_ASH_BUILTIN_TEST | ||
1319 | { BUILTIN_REGULAR "[", testcmd }, | ||
1320 | { BUILTIN_REGULAR "[[", testcmd }, | ||
1321 | #endif | ||
1310 | #ifdef CONFIG_ASH_ALIAS | 1322 | #ifdef CONFIG_ASH_ALIAS |
1311 | { BUILTIN_REG_ASSG "alias", aliascmd }, | 1323 | { BUILTIN_REG_ASSG "alias", aliascmd }, |
1312 | #endif | 1324 | #endif |
@@ -1353,6 +1365,9 @@ static const struct builtincmd builtincmd[] = { | |||
1353 | { BUILTIN_SPEC_REG "set", setcmd }, | 1365 | { BUILTIN_SPEC_REG "set", setcmd }, |
1354 | { BUILTIN_SPEC_REG "source", dotcmd }, | 1366 | { BUILTIN_SPEC_REG "source", dotcmd }, |
1355 | { BUILTIN_SPEC_REG "shift", shiftcmd }, | 1367 | { BUILTIN_SPEC_REG "shift", shiftcmd }, |
1368 | #ifdef CONFIG_ASH_BUILTIN_TEST | ||
1369 | { BUILTIN_REGULAR "test", testcmd }, | ||
1370 | #endif | ||
1356 | { BUILTIN_SPEC_REG "times", timescmd }, | 1371 | { BUILTIN_SPEC_REG "times", timescmd }, |
1357 | { BUILTIN_SPEC_REG "trap", trapcmd }, | 1372 | { BUILTIN_SPEC_REG "trap", trapcmd }, |
1358 | { BUILTIN_REGULAR "true", truecmd }, | 1373 | { BUILTIN_REGULAR "true", truecmd }, |
@@ -8143,6 +8158,15 @@ echocmd(int argc, char **argv) | |||
8143 | return bb_echo(argc, argv); | 8158 | return bb_echo(argc, argv); |
8144 | } | 8159 | } |
8145 | #endif | 8160 | #endif |
8161 | |||
8162 | #ifdef CONFIG_ASH_BUILTIN_TEST | ||
8163 | static int | ||
8164 | testcmd(int argc, char **argv) | ||
8165 | { | ||
8166 | return bb_test(argc, argv); | ||
8167 | } | ||
8168 | #endif | ||
8169 | |||
8146 | /* memalloc.c */ | 8170 | /* memalloc.c */ |
8147 | 8171 | ||
8148 | /* | 8172 | /* |