Both unshare and nsenter use similar code to fork and have the parent
wait for child's completion. Move it to a common library function.

function                                             old     new   delta
continue_as_child                                      -     105    +105
unshare_main                                        1066    1004     -62
nsenter_main                                         850     753     -97
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/2 up/down: 105/-159)          Total: -54 bytes
   text    data     bss     dec     hex filename
 829552    4486    9120  843158   cdd96 busybox_old
 829498    4486    9120  843104   cdd60 busybox_unstripped

Signed-off-by: Bartosz Golaszewski <bartekg...@gmail.com>
---
 util-linux/namespace.c | 34 ++++++++++++++++++++++++++++++++++
 util-linux/namespace.h |  7 +++++++
 util-linux/nsenter.c   | 20 ++------------------
 util-linux/unshare.c   | 19 ++-----------------
 4 files changed, 45 insertions(+), 35 deletions(-)
 create mode 100644 util-linux/namespace.c

diff --git a/util-linux/namespace.c b/util-linux/namespace.c
new file mode 100644
index 0000000..1cfa1ae
--- /dev/null
+++ b/util-linux/namespace.c
@@ -0,0 +1,34 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski <bartekg...@gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_UNSHARE) += namespace.o
+//kbuild:lib-$(CONFIG_NSENTER) += namespace.o
+
+#include "libbb.h"
+#include "namespace.h"
+
+void continue_as_child(void)
+{
+       int exit_status, rv;
+       pid_t pid;
+
+       pid = xfork();
+       if (pid > 0) {
+               rv = safe_waitpid(pid, &exit_status, WUNTRACED);
+               if (rv < 0)
+                       bb_perror_msg_and_die("waitpid");
+
+               if (WIFEXITED(exit_status))
+                       exit(WEXITSTATUS(exit_status));
+               else if (WIFSIGNALED(exit_status))
+                       kill(getpid(), WTERMSIG(exit_status));
+
+               bb_error_msg_and_die("child exit failed");
+       } /* Child continues. */
+}
diff --git a/util-linux/namespace.h b/util-linux/namespace.h
index da79fd9..42e8361 100644
--- a/util-linux/namespace.h
+++ b/util-linux/namespace.h
@@ -17,4 +17,11 @@
  */
 #define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
 
+/*
+ * Fork and wait for the child process to finish. Exit with the child process'
+ * exit status or deliver the signal which killed the child to the parent.
+ * Exit if fork() or waitpid() fails.
+ */
+void continue_as_child(void);
+
 #endif /* __BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 7beaddb..8e9247a 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -318,24 +318,8 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
         * Entering the pid namespace implies forking unless it's been
         * explicitly requested by the user not to.
         */
-       if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
-               int exit_status;
-               pid_t pid;
-
-               pid = xfork();
-               if (pid > 0) {
-                       status = safe_waitpid(pid, &exit_status, 0);
-                       if (status < 0)
-                               bb_perror_msg_and_die("waitpid");
-
-                       if (WIFEXITED(exit_status))
-                               return WEXITSTATUS(exit_status);
-                       else if (WIFSIGNALED(exit_status))
-                               kill(getpid(), WTERMSIG(exit_status));
-
-                       bb_error_msg_and_die("child exit failed");
-               } /* Child continues. */
-       }
+       if (!(opts & OPT_nofork) && (opts & OPT_pid))
+               continue_as_child();
 
        if (opts & OPT_setgid) {
                status = setgroups(0, NULL);
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index b6146e3..637ff2a 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -386,23 +386,8 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
         * child. The user may want to use this option to spawn a new process
         * that'll become PID 1 in this new namespace.
         */
-       if (opts & OPT_fork) {
-               int exit_status;
-
-               pid = xfork();
-               if (pid > 0) {
-                       status = safe_waitpid(pid, &exit_status, 0);
-                       if (status < 0)
-                               bb_perror_msg_and_die("waitpid");
-
-                       if (WIFEXITED(exit_status))
-                               return WEXITSTATUS(exit_status);
-                       else if (WIFSIGNALED(exit_status))
-                               kill(getpid(), WTERMSIG(exit_status));
-
-                       bb_error_msg_and_die("child exit failed");
-               } /* Child continues. */
-       }
+       if (opts & OPT_fork)
+               continue_as_child();
 
        if (opts & OPT_map_root) {
                char uidmap_buf[sizeof(unsigned int) * 3 + sizeof(" 0 1")];
-- 
2.1.4

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to