ash: optional printf builtin. +25 bytes if off, +35 if on.
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 1 Jun 2008 22:36:39 +0000 (22:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 1 Jun 2008 22:36:39 +0000 (22:36 -0000)
by Cristian Ionescu-Idbohrn.

coreutils/Kbuild
coreutils/chown.c
coreutils/printf.c
include/applets.h
include/libbb.h
miscutils/last.c
miscutils/last_fancy.c
shell/Config.in
shell/ash.c

index cb4543912c23ab3287e2366c616d0aa08d728b44..a5a2d4c26f8a4813bd7235d3979f04761e8725e1 100644 (file)
@@ -54,6 +54,7 @@ lib-$(CONFIG_NOHUP)     += nohup.o
 lib-$(CONFIG_OD)        += od.o
 lib-$(CONFIG_PRINTENV)  += printenv.o
 lib-$(CONFIG_PRINTF)    += printf.o
+lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
 lib-$(CONFIG_PWD)       += pwd.o
 lib-$(CONFIG_READLINK)  += readlink.o
 lib-$(CONFIG_REALPATH)  += realpath.o
index eaaefaf292b93366d8318da3de0368c566bcb517..78377e6a029b85d7a90207768f28f5da2d86d665 100644 (file)
@@ -61,7 +61,6 @@ static int fileAction(const char *fileName, struct stat *statbuf,
        return FALSE;
 }
 
-int chown_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int chown_main(int argc ATTRIBUTE_UNUSED, char **argv)
 {
        int retval = EXIT_SUCCESS;
index ebe961564f7e9980c9939fbbac5d24a54843c5d1..b7752369c56089c7b286b8c7951ef24fa949f1c9 100644 (file)
@@ -193,6 +193,7 @@ static char **print_formatted(char *f, char **argv)
        unsigned direc_length;  /* Length of % directive.  */
        int field_width;        /* Arg to first '*', or -1 if none.  */
        int precision;          /* Arg to second '*', or -1 if none.  */
+       char **saved_argv = argv;
 
        for (; *f; ++f) {
                switch (*f) {
@@ -264,8 +265,9 @@ static char **print_formatted(char *f, char **argv)
                                                        precision, "");
                        break;
                case '\\':
-                       if (*++f == 'c')
-                               exit(EXIT_SUCCESS);
+                       if (*++f == 'c') {
+                               return saved_argv; /* causes main() to exit */
+                       }
                        bb_putchar(bb_process_escape_sequence((const char **)&f));
                        f--;
                        break;
@@ -277,12 +279,22 @@ static char **print_formatted(char *f, char **argv)
        return argv;
 }
 
-int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int printf_main(int argc ATTRIBUTE_UNUSED, char **argv)
 {
        char *format;
        char **argv2;
 
+       /* We must check that stdout is not closed.
+        * The reason for this is highly non-obvious. printf_main is used from shell.
+        * Shell must correctly handle 'printf "%s" foo'
+        * if stdout is closed. With stdio, output gets shoveled into
+        * stdout buffer, and even fflush cannot clear it out. It seems that
+        * even if libc receives EBADF on write attempts, it feels determined
+        * to output data no matter what. So it will try later,
+        * and possibly will clobber future output. Not good. */
+       if (dup2(1, 1) != 1)
+               return -1;
+
        /* bash builtin errors out on "printf '-%s-\n' foo",
         * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo".
         * We will mimic coreutils. */
index 17113dfe79efc36bfe9a6c46f54dcaa891784114..e7fc3c03c1fbb180c158ddd1ab1ae03d0bc5defa 100644 (file)
@@ -275,7 +275,7 @@ USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER, pkill))
 USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff))
 USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
-USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_PRINTF(APPLET_NOFORK(printf, printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER, printf))
 USE_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_PSCAN(APPLET(pscan, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_PWD(APPLET_NOFORK(pwd, pwd, _BB_DIR_BIN, _BB_SUID_NEVER, pwd))
index 947f28d79ac3595b4d417c61ccabbff1825ca0e4..c79cd8b205f79dd87cb0fae1dc348e5b6097085a 100644 (file)
@@ -878,13 +878,16 @@ extern void bb_verror_msg(const char *s, va_list p, const char *strerr);
 #endif
 
 
-/* applets which are useful from another applets */
+/* Applets which are useful from another applets */
 int bb_cat(char** argv);
-/* If shell needs them, these three "exist" even if not enabled as applets */
+/* If shell needs them, they exist even if not enabled as applets */
 int echo_main(int argc, char** argv) USE_ECHO(MAIN_EXTERNALLY_VISIBLE);
+int printf_main(int argc, char **argv) USE_PRINTF(MAIN_EXTERNALLY_VISIBLE);
 int test_main(int argc, char **argv) USE_TEST(MAIN_EXTERNALLY_VISIBLE);
 int kill_main(int argc, char **argv) USE_KILL(MAIN_EXTERNALLY_VISIBLE);
-int chown_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+/* Similar, but used by chgrp, not shell */
+int chown_main(int argc, char **argv) USE_CHOWN(MAIN_EXTERNALLY_VISIBLE);
+/* Don't need USE_xxx() guard for these */
 int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int bbunpack(char **argv,
index a8800bfe64da97566d108023f273c745c3e69a8d..612f50488228c7d04410221e1c4081ecda7b82a8 100644 (file)
@@ -10,6 +10,9 @@
 #include "libbb.h"
 #include <utmp.h>
 
+/* NB: ut_name and ut_user are the same field, use only one name (ut_user)
+ * to reduce confusion */
+
 #ifndef SHUTDOWN_TIME
 #  define SHUTDOWN_TIME 254
 #endif
index 0dba9dca71ac6566281d169b1f01d5a3733c7b00..2b7fee6e58430e4e76aba2c6a357d62937f160c6 100644 (file)
@@ -10,6 +10,9 @@
 #include "libbb.h"
 #include <utmp.h>
 
+/* NB: ut_name and ut_user are the same field, use only one name (ut_user)
+ * to reduce confusion */
+
 #ifndef SHUTDOWN_TIME
 #  define SHUTDOWN_TIME 254
 #endif
index 94ffa09f870c384f9dc777437b0e1112bd6fd04e..a6701622c8004967fadceca067654045c8f2e168 100644 (file)
@@ -114,6 +114,13 @@ config ASH_BUILTIN_ECHO
        help
          Enable support for echo, builtin to ash.
 
+config ASH_BUILTIN_PRINTF
+       bool "Builtin version of 'printf'"
+       default y
+       depends on ASH
+       help
+         Enable support for printf, builtin to ash.
+
 config ASH_BUILTIN_TEST
        bool "Builtin version of 'test'"
        default y
index 20b93f326fa804970dbf582a18cf9ff05a5e0efc..31beb8671968d97e3db1cad66aef17084b6a7d84 100644 (file)
@@ -8488,17 +8488,18 @@ static int ulimitcmd(int, char **);
  * Apart from the above, [[ expr ]] should work as [ expr ]
  */
 
-#define testcmd test_main
-#define echocmd echo_main
+#define echocmd   echo_main
+#define printfcmd printf_main
+#define testcmd   test_main
 
 /* Keep these in proper order since it is searched via bsearch() */
 static const struct builtincmd builtintab[] = {
        { BUILTIN_SPEC_REG      ".", dotcmd },
        { BUILTIN_SPEC_REG      ":", truecmd },
 #if ENABLE_ASH_BUILTIN_TEST
-       { BUILTIN_REGULAR       "[", testcmd },
+       { BUILTIN_REGULAR       "[", testcmd },
 #if ENABLE_ASH_BASH_COMPAT
-       { BUILTIN_REGULAR       "[[", testcmd },
+       { BUILTIN_REGULAR       "[[", testcmd },
 #endif
 #endif
 #if ENABLE_ASH_ALIAS
@@ -8540,6 +8541,9 @@ static const struct builtincmd builtintab[] = {
        { BUILTIN_NOSPEC        "let", letcmd },
 #endif
        { BUILTIN_ASSIGN        "local", localcmd },
+#if ENABLE_ASH_BUILTIN_PRINTF
+       { BUILTIN_REGULAR       "printf", printfcmd },
+#endif
        { BUILTIN_NOSPEC        "pwd", pwdcmd },
        { BUILTIN_REGULAR       "read", readcmd },
        { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
@@ -8548,7 +8552,7 @@ static const struct builtincmd builtintab[] = {
        { BUILTIN_SPEC_REG      "shift", shiftcmd },
        { BUILTIN_SPEC_REG      "source", dotcmd },
 #if ENABLE_ASH_BUILTIN_TEST
-       { BUILTIN_REGULAR       "test", testcmd },
+       { BUILTIN_REGULAR       "test", testcmd },
 #endif
        { BUILTIN_SPEC_REG      "times", timescmd },
        { BUILTIN_SPEC_REG      "trap", trapcmd },