aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fox <pgf@brightstareng.com>2006-06-08 21:37:26 +0000
committerPaul Fox <pgf@brightstareng.com>2006-06-08 21:37:26 +0000
commit6ab037872fa294d20d1f84403d1ac4dd4b8cbd86 (patch)
tree5f109ab555b2e3ca7df717cd7590058ab12d54c1
parent176f2df69b70ad53d4e2f893d9d8fe1c254e405d (diff)
downloadbusybox-w32-6ab037872fa294d20d1f84403d1ac4dd4b8cbd86.tar.gz
busybox-w32-6ab037872fa294d20d1f84403d1ac4dd4b8cbd86.tar.bz2
busybox-w32-6ab037872fa294d20d1f84403d1ac4dd4b8cbd86.zip
made "test" an ash built-in.
moved the contents of libbb/bb_echo.c back into coreutils/echo.c, which is a more reasonable place for them than libbb. this forces anyone who wants echo and test to be builtin to ash to also have them available as applets. their cost is very small, and the number of people who wouldn't want them as applets is also very small. added warning about shell builtins vs. CONFIG_FEATURE_SH_STANDALONE_SHELL, which conflicts with their use. thanks to nathanael copa for debugging help. some string size optimization in test.c may have been lost with this commit, but this is a good new baseline.
-rw-r--r--coreutils/Config.in4
-rw-r--r--coreutils/echo.c153
-rw-r--r--coreutils/test.c123
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/Makefile.in2
-rw-r--r--libbb/bb_echo.c151
-rw-r--r--shell/Config.in38
-rw-r--r--shell/ash.c30
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
609config CONFIG_FEATURE_TEST_64 609config 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
32int 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
71just_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
25int echo_main(int argc, char** argv) 115int 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);
182static int is_a_group_member(gid_t gid); 171static int is_a_group_member(gid_t gid);
183static void initialize_group_array(void); 172static void initialize_group_array(void);
184 173
185int test_main(int argc, char **argv) 174static jmp_buf leaving;
175
176int 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); 247static 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
237static arith_t oexpr(enum token n) 257static 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
580int 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
118extern void bb_vperror_msg(const char *s, va_list p) __attribute__ ((format (printf, 1, 0))); 118extern void bb_vperror_msg(const char *s, va_list p) __attribute__ ((format (printf, 1, 0)));
119 119
120extern int bb_echo(int argc, char** argv); 120extern int bb_echo(int argc, char** argv);
121extern int bb_test(int argc, char** argv);
121 122
122extern const char *bb_mode_string(int mode); 123extern const char *bb_mode_string(int mode);
123extern int is_directory(const char *name, int followLinks, struct stat *statBuf); 124extern 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:
41LIBBB-$(CONFIG_FEATURE_SHADOWPASSWDS)+=pwd2spwd.c 41LIBBB-$(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
31int 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
70just_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
97config CONFIG_ASH_GETOPTS 97config 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
104config 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
112config 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
104config CONFIG_ASH_CMDCMD 120config 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
113config 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
121config 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
128config CONFIG_ASH_MAIL 129config 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
1226static int echocmd(int, char **); 1226static int echocmd(int, char **);
1227#endif 1227#endif
1228#ifdef CONFIG_ASH_BUILTIN_TEST
1229static int testcmd(int, char **);
1230#endif
1228static int execcmd(int, char **); 1231static int execcmd(int, char **);
1229static int exitcmd(int, char **); 1232static int exitcmd(int, char **);
1230static int exportcmd(int, char **); 1233static 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 {
1307static const struct builtincmd builtincmd[] = { 1315static 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
8163static int
8164testcmd(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/*