Make use of the lxc_clone function and do no longer
use the fork_ns function.

The lxc-unshare utility has been changed to always do a fork.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 src/lxc/lxc_unshare.c |  103 +++++++++++++++++++-------------------------
 src/lxc/start.c       |  116 +++++++++++++++++++++++++++++---------------------
 2 files changed, 114 insertions(+), 105 deletions(-)

Index: lxc/src/lxc/start.c
===================================================================
--- lxc.orig/src/lxc/start.c
+++ lxc/src/lxc/start.c
@@ -32,6 +32,7 @@
 #include <signal.h>
 #include <fcntl.h>
 #include <termios.h>
+#include <namespace.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/mount.h>
@@ -452,12 +453,79 @@ void lxc_abort(const char *name, struct 
 	kill(handler->pid, SIGKILL);
 }
 
+struct start_arg {
+	const char *name;
+	char *const *argv;
+	struct lxc_handler *handler;
+	int *sv;
+};
+
+static int do_start(void *arg)
+{
+	struct start_arg *start_arg = arg;
+	struct lxc_handler *handler = start_arg->handler;
+	const char *name = start_arg->name;
+	char *const *argv = start_arg->argv;
+	int *sv = start_arg->sv;
+	int err = -1, sync;
+
+	if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
+		SYSERROR("failed to set sigprocmask");
+		goto out_child;
+	}
+
+	close(sv[1]);
+
+	/* Be sure we don't inherit this after the exec */
+	fcntl(sv[0], F_SETFD, FD_CLOEXEC);
+
+	/* Tell our father he can begin to configure the container */
+	if (write(sv[0], &sync, sizeof(sync)) < 0) {
+		SYSERROR("failed to write socket");
+		goto out_child;
+	}
+
+	/* Wait for the father to finish the configuration */
+	if (read(sv[0], &sync, sizeof(sync)) < 0) {
+		SYSERROR("failed to read socket");
+		goto out_child;
+	}
+
+	/* Setup the container, ip, names, utsname, ... */
+	if (lxc_setup(name, handler->tty, &handler->tty_info)) {
+		ERROR("failed to setup the container");
+		goto out_warn_father;
+	}
+
+	if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
+		SYSERROR("failed to remove CAP_SYS_BOOT capability");
+		goto out_child;
+	}
+
+	execvp(argv[0], argv);
+	SYSERROR("failed to exec %s", argv[0]);
+
+out_warn_father:
+	/* If the exec fails, tell that to our father */
+	if (write(sv[0], &err, sizeof(err)) < 0)
+		SYSERROR("failed to write the socket");
+out_child:
+	return -1;
+}
+
 int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
 {
 	int sv[2];
 	int clone_flags;
 	int err = -1, sync;
 
+	struct start_arg start_arg = {
+		.name = name,
+		.argv = argv,
+		.handler = handler,
+		.sv = sv,
+	};
+
 	/* Synchro socketpair */
 	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
 		SYSERROR("failed to create communication socketpair");
@@ -469,58 +537,12 @@ int lxc_spawn(const char *name, struct l
 		clone_flags |= CLONE_NEWNET;
 
 	/* Create a process in a new set of namespaces */
-	handler->pid = fork_ns(clone_flags);
+	handler->pid = lxc_clone(do_start, &start_arg, clone_flags);
 	if (handler->pid < 0) {
 		SYSERROR("failed to fork into a new namespace");
 		goto out_close;
 	}
 
-	if (!handler->pid) {
-
-		if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
-			SYSERROR("failed to set sigprocmask");
-			goto out_child;
-		}
-
-		close(sv[1]);
-
-		/* Be sure we don't inherit this after the exec */
-		fcntl(sv[0], F_SETFD, FD_CLOEXEC);
-		
-		/* Tell our father he can begin to configure the container */
-		if (write(sv[0], &sync, sizeof(sync)) < 0) {
-			SYSERROR("failed to write socket");
-			goto out_child;
-		}
-
-		/* Wait for the father to finish the configuration */
-		if (read(sv[0], &sync, sizeof(sync)) < 0) {
-			SYSERROR("failed to read socket");
-			goto out_child;
-		}
-
-		/* Setup the container, ip, names, utsname, ... */
-		if (lxc_setup(name, handler->tty, &handler->tty_info)) {
-			ERROR("failed to setup the container");
-			goto out_warn_father;
-		}
-
-		if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
-			SYSERROR("failed to remove CAP_SYS_BOOT capability");
-			goto out_child;
-		}
-
-		execvp(argv[0], argv);
-		SYSERROR("failed to exec %s", argv[0]);
-
-	out_warn_father:
-		/* If the exec fails, tell that to our father */
-		if (write(sv[0], &err, sizeof(err)) < 0)
-			SYSERROR("failed to write the socket");
-	out_child:
-		exit(err);
-	}
-
 	close(sv[0]);
 	
 	/* Wait for the child to be ready */
Index: lxc/src/lxc/lxc_unshare.c
===================================================================
--- lxc.orig/src/lxc/lxc_unshare.c
+++ lxc/src/lxc/lxc_unshare.c
@@ -40,7 +40,6 @@ void usage(char *cmd)
 {
 	fprintf(stderr, "%s <options> [command]\n", basename(cmd));
 	fprintf(stderr, "Options are:\n");
-	fprintf(stderr, "\t -f      : fork and unshare (automatic when unsharing the pids)\n");
 	fprintf(stderr, "\t -s flags: Ored list of flags to unshare:\n" \
 			"\t           MOUNT, PID, UTSNAME, IPC, USER, NETWORK\n");
 	fprintf(stderr, "\t -u <id> : new id to be set if -s USER is specified\n");
@@ -101,7 +100,7 @@ static int lxc_namespace_2_cloneflag(cha
 	return -1;
 }
 
-static int lxc_fill_namespace_flags(char *flaglist, long *flags)
+static int lxc_fill_namespace_flags(char *flaglist, int *flags)
 {
 	char *token, *saveptr = NULL;
 	int aflag;
@@ -125,17 +124,48 @@ static int lxc_fill_namespace_flags(char
 	return 0;
 }
 
+
+struct start_arg {
+	char ***args;
+	int *flags;
+	uid_t *uid;
+};
+
+static int do_start(void *arg)
+{
+	struct start_arg *start_arg = arg;
+	char **args = *start_arg->args;
+	int flags = *start_arg->flags;
+	uid_t uid = *start_arg->uid;
+
+	if (flags & CLONE_NEWUSER && setuid(uid)) {
+		ERROR("failed to set uid %d: %s", uid, strerror(errno));
+		exit(1);
+	}
+
+	execvp(args[0], args);
+
+	ERROR("failed to exec: '%s': %s", args[0], strerror(errno));
+	return 1;
+}
+
 int main(int argc, char *argv[])
 {
-	int opt, status = 1, hastofork = 0;
+	int opt, status;
 	int ret;
 	char *namespaces = NULL;
 	char **args;
-	long flags = 0;
+	int flags = 0;
 	uid_t uid = -1; /* valid only if (flags & CLONE_NEWUSER) */
 	pid_t pid;
 
-	while ((opt = getopt(argc, argv, "fs:u:")) != -1) {
+	struct start_arg start_arg = {
+		.args = &args,
+		.uid = &uid,
+		.flags = &flags,
+	};
+
+	while ((opt = getopt(argc, argv, "s:u:")) != -1) {
 		switch (opt) {
 		case 's':
 			namespaces = optarg;
@@ -144,74 +174,31 @@ int main(int argc, char *argv[])
 			uid = lookup_user(optarg);
 			if (uid == -1)
 				return 1;
-		case 'f':
-			hastofork = 1;
-			break;
 		}
 	}
 
 	args = &argv[optind];
 
         ret = lxc_fill_namespace_flags(namespaces, &flags);
-	if (ret)
+ 	if (ret)
 		usage(argv[0]);
 
 	if (!(flags & CLONE_NEWUSER) && uid != -1) {
-		ERROR("-u <uid> need -s USER option");
-		return 1;
-	}
-
-	if ((flags & CLONE_NEWPID) || hastofork) {
-
-		if (!argv[optind] || !strlen(argv[optind]))
-			usage(argv[0]);
-
-		pid = fork_ns(flags);
-
-		if (pid < 0) {
-			ERROR("failed to fork into a new namespace: %s",
-				strerror(errno));
-			return 1;
-		}
-
-		if (!pid) {
-			if (flags & CLONE_NEWUSER && setuid(uid)) {
-				ERROR("failed to set uid %d: %s",
-					uid, strerror(errno));
-				exit(1);
-			}
-
-			execvp(args[0], args);
-			ERROR("failed to exec: '%s': %s",
-				argv[0], strerror(errno));
-			exit(1);
-		}
-		
-		if (waitpid(pid, &status, 0) < 0)
-			ERROR("failed to wait for '%d'", pid);
-		
-		return status;
-	}
-
-	if (unshare_ns(flags)) {
-		ERROR("failed to unshare the current process: %s",
-			strerror(errno));
+		ERROR("-u <uid> needs -s USER option");
 		return 1;
 	}
 
-	if (flags & CLONE_NEWUSER && setuid(uid)) {
-		ERROR("failed to set uid %d: %s",
-			uid, strerror(errno));
-		return 1;
+	pid = lxc_clone(do_start, &start_arg, flags);
+	if (pid < 0) {
+		ERROR("failed to clone");
+		return -1;
 	}
 
-	if (argv[optind] && strlen(argv[optind])) {
-		execvp(args[0], args);
-		ERROR("failed to exec: '%s': %s",
-			argv[0], strerror(errno));
-		return 1;
+	if (waitpid(pid, &status, 0) < 0) {
+		ERROR("failed to wait for '%d'", pid);
+		return -1;
 	}
 
-	return 0;
+	return status;
 }
 



