svn commit: trunk/busybox: findutils include libbb

vda at busybox.net vda at busybox.net
Mon Apr 9 21:32:30 UTC 2007


Author: vda
Date: 2007-04-09 14:32:30 -0700 (Mon, 09 Apr 2007)
New Revision: 18375

Log:
factor out NOFORK/NOEXEC code from find. Use it for xargs too.


Modified:
   trunk/busybox/findutils/find.c
   trunk/busybox/findutils/xargs.c
   trunk/busybox/include/libbb.h
   trunk/busybox/libbb/vfork_daemon_rexec.c


Changeset:
Modified: trunk/busybox/findutils/find.c
===================================================================
--- trunk/busybox/findutils/find.c	2007-04-09 21:30:53 UTC (rev 18374)
+++ trunk/busybox/findutils/find.c	2007-04-09 21:32:30 UTC (rev 18375)
@@ -238,37 +238,19 @@
 ACTF(exec)
 {
 	int i, rc;
-	char *argv[ap->exec_argc+1];
+	char *argv[ap->exec_argc + 1];
 	for (i = 0; i < ap->exec_argc; i++)
 		argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
 	argv[i] = NULL; /* terminate the list */
 
-	if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) {
-		const struct BB_applet *a = find_applet_by_name(argv[0]);
-		if (a) {
-			if (a->nofork) {
-				rc = a->main(ap->exec_argc, argv);
-				goto f;
-			}
-#ifndef BB_NOMMU
-			if (a->noexec) {
-				rc = fork();
-				if (rc) goto w;
-				current_applet = a;
-				run_current_applet_and_exit(ap->exec_argc, argv);
-			}
-#endif
-		}
-	}
-	rc = spawn(argv);
- w:
-	rc = wait4pid(rc);
+	rc = spawn_and_wait(argv);
 	if (rc < 0)
 		bb_perror_msg("%s", argv[0]);
- f:
-	for (i = 0; i < ap->exec_argc; i++)
-		free(argv[i]);
-	return rc == 0; /* return 1 if success */
+
+	i = 0;
+	while (argv[i])
+		free(argv[i++]);
+	return rc == 0; /* return 1 if exitcode 0 */
 }
 #endif
 

Modified: trunk/busybox/findutils/xargs.c
===================================================================
--- trunk/busybox/findutils/xargs.c	2007-04-09 21:30:53 UTC (rev 18374)
+++ trunk/busybox/findutils/xargs.c	2007-04-09 21:32:30 UTC (rev 18375)
@@ -48,47 +48,32 @@
    This function has special algorithm.
    Don't use fork and include to main!
 */
-static int xargs_exec(char *const *args)
+static int xargs_exec(char **args)
 {
-	pid_t p;
-	volatile int exec_errno = 0;    /* shared vfork stack */
 	int status;
 
-	p = vfork();
-	if (p < 0)
-		bb_perror_msg_and_die("vfork");
-
-	if (p == 0) {
-		/* vfork -- child */
-		BB_EXECVP(args[0], args);
-		exec_errno = errno;     /* set error to shared stack */
-		_exit(1);
-	}
-
-	/* vfork -- parent */
-	while (wait(&status) == (pid_t) -1)
-		if (errno != EINTR)
-			break;
-	if (exec_errno) {
-		errno = exec_errno;
+	status = spawn_and_wait(args);
+	if (status < 0) {
 		bb_perror_msg("%s", args[0]);
-		return exec_errno == ENOENT ? 127 : 126;
+		return errno == ENOENT ? 127 : 126;
 	}
-	if (WEXITSTATUS(status) == 255) {
+	if (status == 255) {
 		bb_error_msg("%s: exited with status 255; aborting", args[0]);
 		return 124;
 	}
+/* Huh? I think we won't see this, ever. We don't wait with WUNTRACED!
 	if (WIFSTOPPED(status)) {
 		bb_error_msg("%s: stopped by signal %d",
 			args[0], WSTOPSIG(status));
 		return 125;
 	}
-	if (WIFSIGNALED(status)) {
+*/
+	if (status >= 1000) {
 		bb_error_msg("%s: terminated by signal %d",
-			args[0], WTERMSIG(status));
+			args[0], status - 1000);
 		return 125;
 	}
-	if (WEXITSTATUS(status))
+	if (status)
 		return 123;
 	return 0;
 }

Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2007-04-09 21:30:53 UTC (rev 18374)
+++ trunk/busybox/include/libbb.h	2007-04-09 21:32:30 UTC (rev 18375)
@@ -269,17 +269,6 @@
 char *xmalloc_readlink_or_warn(const char *path);
 char *xmalloc_realpath(const char *path);
 
-/* Unlike waitpid, waits ONLY for one process,
- * It's safe to pass negative 'pids' from failed [v]fork -
- * wait4pid will return -1 and ECHILD in errno.
- * IOW: rc = wait4pid(spawn(argv));
- *      if (rc < 0) bb_perror_msg("%s", argv[0]);
- *      if (rc > 0) bb_error_msg("exit code: %d", rc);
- */
-extern int wait4pid(int pid);
-extern int wait_pid(int *wstat, int pid);
-extern int wait_nohang(int *wstat);
-//TODO: signal(sid, f) is the same? then why?
 extern void sig_catch(int,void (*)(int));
 //#define sig_ignore(s) (sig_catch((s), SIG_IGN))
 //#define sig_uncatch(s) (sig_catch((s), SIG_DFL))
@@ -288,10 +277,6 @@
 /* UNUSED: extern void sig_blocknone(void); */
 extern void sig_pause(void);
 
-#define wait_crashed(w) ((w) & 127)
-#define wait_exitcode(w) ((w) >> 8)
-#define wait_stopsig(w) ((w) >> 8)
-#define wait_stopped(w) (((w) & 127) == 127)
 
 
 void xsetgid(gid_t gid);
@@ -528,6 +513,25 @@
 /* NOMMU friendy fork+exec */
 pid_t spawn(char **argv);
 pid_t xspawn(char **argv);
+
+/* Unlike waitpid, waits ONLY for one process,
+ * It's safe to pass negative 'pids' from failed [v]fork -
+ * wait4pid will return -1 and ECHILD in errno.
+ * IOW: rc = wait4pid(spawn(argv));
+ *      if (rc < 0) bb_perror_msg("%s", argv[0]);
+ *      if (rc > 0) bb_error_msg("exit code: %d", rc);
+ */
+int wait_pid(int *wstat, int pid);
+int wait_nohang(int *wstat);
+int wait4pid(int pid);
+//TODO: signal(sid, f) is the same? then why?
+#define wait_crashed(w) ((w) & 127)
+#define wait_exitcode(w) ((w) >> 8)
+#define wait_stopsig(w) ((w) >> 8)
+#define wait_stopped(w) (((w) & 127) == 127)
+/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
+int spawn_and_wait(char **argv);
+
 /* Helpers for daemonization.
  *
  * bb_daemonize(flags) = daemonize, does not compile on NOMMU
@@ -573,6 +577,7 @@
 void bb_sanitize_stdio(void);
 
 
+// TODO: always error out?
 enum { BB_GETOPT_ERROR = 0x80000000 };
 extern const char *opt_complementary;
 #if ENABLE_GETOPT_LONG

Modified: trunk/busybox/libbb/vfork_daemon_rexec.c
===================================================================
--- trunk/busybox/libbb/vfork_daemon_rexec.c	2007-04-09 21:30:53 UTC (rev 18374)
+++ trunk/busybox/libbb/vfork_daemon_rexec.c	2007-04-09 21:32:30 UTC (rev 18375)
@@ -16,7 +16,7 @@
  */
 
 #include <paths.h>
-#include "libbb.h"
+#include "busybox.h" /* for struct BB_applet */
 
 /* This does a fork/exec in one call, using vfork().  Returns PID of new child,
  * -1 for failure.  Runs argv[0], searching path if that has no / in it. */
@@ -72,7 +72,8 @@
 	int status;
 
 	if (pid <= 0) {
-		/*errno = ECHILD; -- wrong. we expect errno to be set from failed exec */
+		/*errno = ECHILD; -- wrong. */
+		/* we expect errno to be already set from failed [v]fork/exec */
 		return -1;
 	}
 	if (waitpid(pid, &status, 0) == -1)
@@ -80,7 +81,7 @@
 	if (WIFEXITED(status))
 		return WEXITSTATUS(status);
 	if (WIFSIGNALED(status))
-		return WTERMSIG(status) + 10000;
+		return WTERMSIG(status) + 1000;
 	return 0;
 }
 
@@ -99,6 +100,41 @@
 	return r;
 }
 
+int spawn_and_wait(char **argv)
+{
+	int rc;
+
+	if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) {
+		const struct BB_applet *a = find_applet_by_name(argv[0]);
+		if (a && (a->nofork
+#ifndef BB_NOMMU
+			 || a->noexec /* NOEXEC cannot be used on NOMMU */
+#endif
+		)) {
+			int argc = 1;
+			char **pp = argv;
+			while (*++pp)
+				argc++;
+#ifdef BB_NOMMU
+			return a->main(argc, argv);
+#else
+			if (a->nofork)
+				return a->main(argc, argv);
+			/* a->noexec is true */
+			rc = fork();
+			if (rc)
+				goto w;
+			/* child */
+			current_applet = a;
+			run_current_applet_and_exit(argc, argv);
+#endif
+		}
+	}
+	rc = spawn(argv);
+ w:
+	return wait4pid(rc);
+}
+
 #if 0 //ndef BB_NOMMU
 // Die with an error message if we can't daemonize.
 void xdaemon(int nochdir, int noclose)




More information about the busybox-cvs mailing list