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 605649b..07005b8 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in @@ -603,8 +603,8 @@ config CONFIG_TEST default n help test is used to check file types and compare values, - returning an appropriate exit code. The shells (ash - and bash) have test builtin. + returning an appropriate exit code. The bash shell + has test built in, ash can build it in optionally. config CONFIG_FEATURE_TEST_64 bool "Extend test to 64 bit" diff --git a/coreutils/echo.c b/coreutils/echo.c index 0dbb32f..a673bb0 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -1,29 +1,158 @@ +/* vi: set sw=4 ts=4: */ /* - * echo applet implementation for busybox + * echo implementation for busybox * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original copyright notice is retained at the end of this file. + */ + +/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ + +/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) * + * Because of behavioral differences, implemented configurable SUSv3 + * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs. + * 1) In handling '\c' escape, the previous version only suppressed the + * trailing newline. SUSv3 specifies _no_ output after '\c'. + * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. + * The previous version version did not allow 4-digit octals. */ + #include <stdio.h> #include <string.h> #include <stdlib.h> #include "busybox.h" +int bb_echo(int ATTRIBUTE_UNUSED argc, char **argv) +{ +#ifndef CONFIG_FEATURE_FANCY_ECHO +#define eflag '\\' + ++argv; +#else + const char *p; + int nflag = 1; + int eflag = 0; + + while (*++argv && (**argv == '-')) { + /* If it appears that we are handling options, then make sure + * that all of the options specified are actually valid. + * Otherwise, the string should just be echoed. + */ + + if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ + goto just_echo; + } + + do { + if (strrchr("neE", *p) == 0) { + goto just_echo; + } + } while (*++p); + + /* All of the options in this arg are valid, so handle them. */ + p = *argv + 1; + do { + if (*p == 'n') { + nflag = 0; + } else if (*p == 'e') { + eflag = '\\'; + } else { + eflag = 0; + } + } while (*++p); + } + +just_echo: +#endif + while (*argv) { + register int c; + + while ((c = *(*argv)++)) { + if (c == eflag) { /* Check for escape seq. */ + if (**argv == 'c') { + /* '\c' means cancel newline and + * ignore all subsequent chars. */ + return 0; + } +#ifndef CONFIG_FEATURE_FANCY_ECHO + /* SUSv3 specifies that octal escapes must begin with '0'. */ + if (((unsigned int)(**argv - '1')) >= 7) +#endif + { + /* Since SUSv3 mandates a first digit of 0, 4-digit octals + * of the form \0### are accepted. */ + if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { + (*argv)++; + } + /* bb_process_escape_sequence can handle nul correctly */ + c = bb_process_escape_sequence((const char **) argv); + } + } + putchar(c); + } + + if (*++argv) { + putchar(' '); + } + } + +#ifdef CONFIG_FEATURE_FANCY_ECHO + if (nflag) { + putchar('\n'); + } +#else + putchar('\n'); +#endif + return 0; +} + int echo_main(int argc, char** argv) { (void)bb_echo(argc, argv); bb_fflush_stdout_and_exit(EXIT_SUCCESS); } + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change + * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> + * + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)echo.c 8.1 (Berkeley) 5/31/93 + */ diff --git a/coreutils/test.c b/coreutils/test.c index 2b624e3..4d92038 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -4,31 +4,19 @@ * * Copyright (c) by a whole pile of folks: * - * test(1); version 7-like -- author Erik Baalbergen - * modified by Eric Gisin to be used as built-in. - * modified by Arnold Robbins to add SVR3 compatibility - * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). - * modified by J.T. Conklin for NetBSD. - * modified by Herbert Xu to be used as built-in in ash. - * modified by Erik Andersen <andersen@codepoet.org> to be used - * in busybox. + * test(1); version 7-like -- author Erik Baalbergen + * modified by Eric Gisin to be used as built-in. + * modified by Arnold Robbins to add SVR3 compatibility + * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). + * modified by J.T. Conklin for NetBSD. + * modified by Herbert Xu to be used as built-in in ash. + * modified by Erik Andersen <andersen@codepoet.org> to be used + * in busybox. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * * Original copyright notice states: - * "This program is in the Public Domain." + * "This program is in the Public Domain." */ #include <sys/types.h> @@ -37,13 +25,14 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#include <setjmp.h> #include "busybox.h" /* test(1) accepts the following grammar: oexpr ::= aexpr | aexpr "-o" oexpr ; aexpr ::= nexpr | nexpr "-a" aexpr ; nexpr ::= primary | "!" primary - primary ::= unary-operator operand + primary ::= unary-operator operand | operand binary-operator operand | operand | "(" oexpr ")" @@ -128,7 +117,7 @@ static const struct t_op { "-t", FILTT, UNOP}, { "-z", STREZ, UNOP}, { "-n", STRNZ, UNOP}, { - "-h", FILSYM, UNOP}, /* for backwards compat */ + "-h", FILSYM, UNOP}, /* for backwards compat */ { "-O", FILUID, UNOP}, { "-G", FILGID, UNOP}, { @@ -182,36 +171,56 @@ static int test_eaccess(char *path, int mode); static int is_a_group_member(gid_t gid); static void initialize_group_array(void); -int test_main(int argc, char **argv) +static jmp_buf leaving; + +int bb_test(int argc, char **argv) { int res; - if (strcmp(bb_applet_name, "[") == 0) { - if (strcmp(argv[--argc], "]")) - bb_error_msg_and_die("missing ]"); + if (strcmp(argv[0], "[") == 0) { + if (strcmp(argv[--argc], "]")) { + bb_error_msg("missing ]"); + return 2; + } argv[argc] = NULL; - } - if (strcmp(bb_applet_name, "[[") == 0) { - if (strcmp(argv[--argc], "]]")) - bb_error_msg_and_die("missing ]]"); + } else if (strcmp(argv[0], "[[") == 0) { + if (strcmp(argv[--argc], "]]")) { + bb_error_msg("missing ]]"); + return 2; + } argv[argc] = NULL; } + + res = setjmp(leaving); + if (res) + return res; + + /* resetting ngroups is probably unnecessary. it will + * force a new call to getgroups(), which prevents using + * group data fetched during a previous call. but the + * only way the group data could be stale is if there's + * been an intervening call to setgroups(), and this + * isn't likely in the case of a shell. paranoia + * prevails... + */ + ngroups = 0; + /* Implement special cases from POSIX.2, section 4.62.4 */ switch (argc) { case 1: - exit(1); + return 1; case 2: - exit(*argv[1] == '\0'); + return *argv[1] == '\0'; case 3: if (argv[1][0] == '!' && argv[1][1] == '\0') { - exit(!(*argv[2] == '\0')); + return *argv[2] != '\0'; } break; case 4: if (argv[1][0] != '!' || argv[1][1] != '\0') { if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) { t_wp = &argv[1]; - exit(binop() == 0); + return binop() == 0; } } break; @@ -219,7 +228,7 @@ int test_main(int argc, char **argv) if (argv[1][0] == '!' && argv[1][1] == '\0') { if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) { t_wp = &argv[2]; - exit(!(binop() == 0)); + return binop() != 0; } } break; @@ -228,10 +237,21 @@ int test_main(int argc, char **argv) t_wp = &argv[1]; res = !oexpr(t_lex(*t_wp)); - if (*t_wp != NULL && *++t_wp != NULL) - bb_error_msg_and_die("%s: unknown operand", *t_wp); + if (*t_wp != NULL && *++t_wp != NULL) { + bb_error_msg("%s: unknown operand", *t_wp); + return 2; + } + return res; +} - return (res); +static void syntax(const char *op, const char *msg) +{ + if (op && *op) { + bb_error_msg("%s: %s", op, msg); + } else { + bb_error_msg("%s", msg); + } + longjmp(leaving, 2); } static arith_t oexpr(enum token n) @@ -269,18 +289,18 @@ static arith_t primary(enum token n) arith_t res; if (n == EOI) { - bb_error_msg_and_die("argument expected"); + syntax(NULL, "argument expected"); } if (n == LPAREN) { res = oexpr(t_lex(*++t_wp)); if (t_lex(*++t_wp) != RPAREN) - bb_error_msg_and_die("closing paren expected"); + syntax(NULL, "closing paren expected"); return res; } if (t_wp_op && t_wp_op->op_type == UNOP) { /* unary expression */ if (*++t_wp == NULL) - bb_error_msg_and_die(bb_msg_requires_arg, t_wp_op->op_text); + syntax(t_wp_op->op_text, "argument expected"); switch (n) { case STREZ: return strlen(*t_wp) == 0; @@ -310,7 +330,7 @@ static int binop(void) op = t_wp_op; if ((opnd2 = *++t_wp) == (char *) 0) - bb_error_msg_and_die(bb_msg_requires_arg, op->op_text); + syntax(op->op_text, "argument expected"); switch (op->op_num) { case STREQ: @@ -460,11 +480,11 @@ static arith_t getn(const char *s) #endif if (errno != 0) - bb_error_msg_and_die("%s: out of range", s); + syntax(s, "out of range"); /* p = bb_skip_whitespace(p); avoid const warning */ if (*(bb_skip_whitespace(p))) - bb_error_msg_and_die("%s: bad number", s); + syntax(s, "bad number"); return r; } @@ -516,7 +536,7 @@ static int test_eaccess(char *path, int mode) return (0); } - if (st.st_uid == euid) /* owner */ + if (st.st_uid == euid) /* owner */ mode <<= 6; else if (is_a_group_member(st.st_gid)) mode <<= 3; @@ -553,3 +573,12 @@ static int is_a_group_member(gid_t gid) return (0); } + + +/* applet entry point */ + +int test_main(int argc, char **argv) +{ + exit(bb_test(argc, argv)); +} + |