ash: optional printf builtin. +25 bytes if off, +35 if on.
by Cristian Ionescu-Idbohrn.
diff --git a/coreutils/Kbuild b/coreutils/Kbuild
index cb45439..a5a2d4c 100644
--- a/coreutils/Kbuild
+++ b/coreutils/Kbuild
@@ -54,6 +54,7 @@
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 eaaefaf..78377e6 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -61,7 +61,6 @@
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 ebe9615..b775236 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -193,6 +193,7 @@
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 @@
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 @@
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. */