aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/Kbuild1
-rw-r--r--coreutils/chown.c1
-rw-r--r--coreutils/printf.c18
-rw-r--r--include/applets.h2
-rw-r--r--include/libbb.h9
-rw-r--r--miscutils/last.c3
-rw-r--r--miscutils/last_fancy.c3
-rw-r--r--shell/Config.in7
-rw-r--r--shell/ash.c14
9 files changed, 45 insertions, 13 deletions
diff --git a/coreutils/Kbuild b/coreutils/Kbuild
index cb4543912..a5a2d4c26 100644
--- a/coreutils/Kbuild
+++ b/coreutils/Kbuild
@@ -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
diff --git a/coreutils/chown.c b/coreutils/chown.c
index eaaefaf29..78377e6a0 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -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;
diff --git a/coreutils/printf.c b/coreutils/printf.c
index ebe961564..b7752369c 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -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. */
diff --git a/include/applets.h b/include/applets.h
index 17113dfe7..e7fc3c03c 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -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))
diff --git a/include/libbb.h b/include/libbb.h
index 947f28d79..c79cd8b20 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -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,
diff --git a/miscutils/last.c b/miscutils/last.c
index a8800bfe6..612f50488 100644
--- a/miscutils/last.c
+++ b/miscutils/last.c
@@ -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
diff --git a/miscutils/last_fancy.c b/miscutils/last_fancy.c
index 0dba9dca7..2b7fee6e5 100644
--- a/miscutils/last_fancy.c
+++ b/miscutils/last_fancy.c
@@ -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
diff --git a/shell/Config.in b/shell/Config.in
index 94ffa09f8..a6701622c 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -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
diff --git a/shell/ash.c b/shell/ash.c
index 20b93f326..31beb8671 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -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 },