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,

-- 
Cristian
Index: 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

Reply via email to