[lxc-devel] [PATCH 4/8] Add attach support to container C API

Christian Seiler christian at iwakd.de
Tue Aug 13 21:56:16 UTC 2013


Signed-off-by: Christian Seiler <christian at iwakd.de>
---
 src/lxc/lxccontainer.c |  124 ++++++++++++++++++++++++++++--------------------
 src/lxc/lxccontainer.h |    8 +++-
 2 files changed, 80 insertions(+), 52 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 3affe22..1c77b63 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -18,6 +18,7 @@
  */
 
 #define _GNU_SOURCE
+#include <stdarg.h>
 #include <pthread.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -38,6 +39,7 @@
 #include "log.h"
 #include "bdev.h"
 #include "utils.h"
+#include "attach.h"
 #include <lxc/utils.h>
 #include <lxc/monitor.h>
 #include <sched.h>
@@ -583,51 +585,30 @@ reboot:
 static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
 {
 	va_list ap;
-	char **inargs = NULL, **temp;
-	int n_inargs = 0;
+	char **inargs = NULL;
 	bool bret = false;
 
 	/* container exists */
 	if (!c)
 		return false;
 
-	/* build array of arguments if any */
 	va_start(ap, useinit);
-	while (1) {
-		char *arg;
-		arg = va_arg(ap, char *);
-		if (!arg)
-			break;
-		n_inargs++;
-		temp = realloc(inargs, n_inargs * sizeof(*inargs));
-		if (!temp) {
-			va_end(ap);
-			goto out;
-		}
-		inargs = temp;
-		inargs[n_inargs - 1] = strdup(arg);  // not sure if it's safe not to copy
-	}
+	inargs = lxc_va_arg_list_to_argv(ap, 0, 1);
 	va_end(ap);
 
-	/* add trailing NULL */
-	if (n_inargs) {
-		n_inargs++;
-		temp = realloc(inargs, n_inargs * sizeof(*inargs));
-		if (!temp)
-			goto out;
-		inargs = temp;
-		inargs[n_inargs - 1] = NULL;
+	if (!inargs) {
+		ERROR("Memory allocation error.");
+		goto out;
 	}
 
-	bret = lxcapi_start(c, useinit, inargs);
+	/* pass NULL if no arguments were supplied */
+	bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL);
 
 out:
 	if (inargs) {
-		int i;
-		for (i = 0; i < n_inargs; i++) {
-			if (inargs[i])
-				free(inargs[i]);
-		}
+		char *arg;
+		for (arg = *inargs; arg; arg++)
+			free(arg);
 		free(inargs);
 	}
 
@@ -1133,9 +1114,8 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
 		const char *bdevtype, struct bdev_specs *specs, int flags, ...)
 {
 	bool bret = false;
-	char **args = NULL, **temp;
+	char **args = NULL;
 	va_list ap;
-	int nargs = 0;
 
 	if (!c)
 		return false;
@@ -1145,29 +1125,17 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
 	 * need to get a copy of the arguments.
 	 */
 	va_start(ap, flags);
-	while (1) {
-		char *arg;
-		arg = va_arg(ap, char *);
-		if (!arg)
-			break;
-		nargs++;
-		temp = realloc(args, (nargs+1) * sizeof(*args));
-		if (!temp) {
-			va_end(ap);
-			goto out;
-		}
-		args = temp;
-		args[nargs - 1] = arg;
-	}
+	args = lxc_va_arg_list_to_argv(ap, 0, 0);
 	va_end(ap);
-	if (args)
-		args[nargs] = NULL;
+	if (!args) {
+		ERROR("Memory allocation error.");
+		goto out;
+	}
 
 	bret = c->create(c, t, bdevtype, specs, flags, args);
 
 out:
-	if (args)
-		free(args);
+	free(args);
 	return bret;
 }
 
@@ -2000,6 +1968,57 @@ out:
 	return NULL;
 }
 
+static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
+{
+	if (!c)
+		return -1;
+
+	return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
+}
+
+static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
+{
+	lxc_attach_command_t command;
+	pid_t pid;
+	int r;
+
+	if (!c)
+		return -1;
+
+	command.program = (char*)program;
+	command.argv = (char**)argv;
+	r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);
+	if (r < 0) {
+		ERROR("ups");
+		return r;
+	}
+	return lxc_wait_for_pid_status(pid);
+}
+
+static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
+{
+	va_list ap;
+	const char **argv;
+	int ret;
+
+	if (!c)
+		return -1;
+
+	va_start(ap, arg);
+	argv = lxc_va_arg_list_to_argv_const(ap, 1);
+	va_end(ap);
+
+	if (!argv) {
+		ERROR("Memory allocation error.");
+		return -1;
+	}
+	argv[0] = arg;
+
+	ret = lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
+	free((void*)argv);
+	return ret;
+}
+
 struct lxc_container *lxc_container_new(const char *name, const char *configpath)
 {
 	struct lxc_container *c;
@@ -2086,6 +2105,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
 	c->set_config_path = lxcapi_set_config_path;
 	c->clone = lxcapi_clone;
 	c->get_ips = lxcapi_get_ips;
+	c->attach = lxcapi_attach;
+	c->attach_run_wait = lxcapi_attach_run_wait;
+	c->attach_run_waitl = lxcapi_attach_run_waitl;
 
 	/* we'll allow the caller to update these later */
 	if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 3399c7f..e0c465c 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -1,6 +1,7 @@
 #ifndef __LXC_CONTAINER_H
 #define __LXC_CONTAINER_H
 #include "lxclock.h"
+#include "attach_options.h"
 #include <stdlib.h>
 #include <malloc.h>
 
@@ -150,12 +151,17 @@ struct lxc_container {
 	int (*console)(struct lxc_container *c, int ttynum,
 		       int stdinfd, int stdoutfd, int stderrfd, int escape);
 
+	/* create subprocess and attach it to the container, run exec_function inside */
+	int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process);
+
+	/* run program in container, wait for it to exit */
+	int (*attach_run_wait)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[]);
+	int (*attach_run_waitl)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...);
 #if 0
 	bool (*commit_cgroups)(struct lxc_container *c);
 	bool (*reread_cgroups)(struct lxc_container *c);
 	// question with clone: how do we handle non-standard config file in orig?
 	struct lxc_container (*clone)(struct container *c);
-	int (*ns_attach)(struct lxc_container *c, int ns_mask);
 	// we'll need some plumbing to support lxc-console
 #endif
 };
-- 
1.7.10.4





More information about the lxc-devel mailing list