aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/Config.in4
-rw-r--r--coreutils/echo.c153
-rw-r--r--coreutils/test.c123
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
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