aboutsummaryrefslogtreecommitdiff
path: root/coreutils/test.c
diff options
context:
space:
mode:
authorpgf <pgf@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-06-08 21:37:26 +0000
committerpgf <pgf@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-06-08 21:37:26 +0000
commitdc3b7958d75c261b988db308963da8e85792ace7 (patch)
tree5f109ab555b2e3ca7df717cd7590058ab12d54c1 /coreutils/test.c
parent0b623f284cee0ef504cda61a8c8338c2acdb0082 (diff)
downloadbusybox-w32-dc3b7958d75c261b988db308963da8e85792ace7.tar.gz
busybox-w32-dc3b7958d75c261b988db308963da8e85792ace7.tar.bz2
busybox-w32-dc3b7958d75c261b988db308963da8e85792ace7.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. git-svn-id: svn://busybox.net/trunk/busybox@15344 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'coreutils/test.c')
-rw-r--r--coreutils/test.c123
1 files changed, 76 insertions, 47 deletions
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