On Sun, 1 Jun 2008, Denys Vlasenko wrote:
> # ./busybox ash
> /.1/usr/srcdevel/bbox/fix/busybox.t8 # printf '\c' foo
> Segmentation fault
Bummer. Wouls this hunk sort that out?
@@ -264,8 +264,11 @@
precision, "");
break;
case '\\':
- if (*++f == 'c')
- exit(EXIT_SUCCESS);
+ if (*++f == 'c') {
+ while (*argv)
+ argv++;
+ goto nomore;
+ }
bb_putchar(bb_process_escape_sequence((const char
**)&f));
f--;
break;
(included in attached patch)
> Other than that: use spaces here, otherwise indentation of "printf"
> breaks for anybody with non-4-char-wide tabs:
>
> { BUILTIN_REGULAR "printf", printfcmd },
Ok. Fixed that and a couple more similar places.
> Do not replace "return EXIT_SUCCESS;" with "return 0;" - some people
> insist on having symbolic constant there (don't know why it's so
> important, but why not?)
Alright.
Cheers,
--
CristianIndex: shell/ash.c
===================================================================
--- shell/ash.c (revision 22011)
+++ shell/ash.c (working copy)
@@ -8488,17 +8488,18 @@
* 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 @@
{ 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 @@
{ 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 },
Index: shell/Config.in
===================================================================
--- shell/Config.in (revision 22001)
+++ shell/Config.in (working copy)
@@ -114,6 +114,13 @@
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: coreutils/printf.c
===================================================================
--- coreutils/printf.c (revision 22165)
+++ coreutils/printf.c (working copy)
@@ -264,8 +264,11 @@
precision, "");
break;
case '\\':
- if (*++f == 'c')
- exit(EXIT_SUCCESS);
+ if (*++f == 'c') {
+ while (*argv)
+ argv++;
+ goto nomore;
+ }
bb_putchar(bb_process_escape_sequence((const char **)&f));
f--;
break;
@@ -273,16 +276,26 @@
bb_putchar(*f);
}
}
-
+ nomore:
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.
+ * echo_main is used from shell. Shell must correctly handle "echo 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: include/applets.h
===================================================================
--- include/applets.h (revision 22084)
+++ include/applets.h (working copy)
@@ -275,7 +275,7 @@
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: include/libbb.h
===================================================================
--- include/libbb.h (revision 22110)
+++ include/libbb.h (working copy)
@@ -882,6 +882,7 @@
int bb_cat(char** argv);
/* If shell needs them, these three "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;
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox