diff options
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/Config.in | 4 | ||||
-rw-r--r-- | coreutils/echo.c | 153 | ||||
-rw-r--r-- | coreutils/test.c | 123 |
3 files changed, 219 insertions, 61 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 | |||