move some code of start.c to new commands.c and to console.c

Signed-off-by: Michel Normand <normand@fr.ibm.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 src/lxc/Makefile.am |    2 
 src/lxc/commands.c  |  214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/commands.h  |    8 +
 src/lxc/console.c   |  117 +++++++++++++++-------------
 src/lxc/start.c     |  192 ----------------------------------------------
 5 files changed, 288 insertions(+), 245 deletions(-)
 create mode 100644 src/lxc/commands.c

Index: lxc/src/lxc/Makefile.am
===================================================================
--- lxc.orig/src/lxc/Makefile.am
+++ lxc/src/lxc/Makefile.am
@@ -19,7 +19,7 @@ pkginclude_HEADERS = \
 
 liblxc_la_SOURCES = \
 	arguments.c arguments.h \
-	commands.h \
+	commands.c commands.h \
 	create.c \
 	destroy.c \
 	start.c \
Index: lxc/src/lxc/commands.c
===================================================================
--- /dev/null
+++ lxc/src/lxc/commands.c
@@ -0,0 +1,214 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2009
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+
+#include <lxc/lxc.h>
+
+#include "commands.h"
+#include "mainloop.h"
+#include "af_unix.h"
+
+lxc_log_define(lxc_commands, lxc);
+
+/*----------------------------------------------------------------------------
+ * functions used by processes requesting command to lxc-start
+ *--------------------------------------------------------------------------*/
+static int receive_answer(int sock, struct lxc_answer *answer)
+{
+	int ret;
+
+	ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer, sizeof(*answer));
+	if (ret < 0)
+		ERROR("failed to receive answer for the command");
+
+	return ret;
+}
+
+extern int lxc_command(const char *name, struct lxc_command *command)
+{
+	struct sockaddr_un addr = { 0 };
+	int sock, ret = -1;
+	char *offset = &addr.sun_path[1];
+
+	snprintf(addr.sun_path, sizeof(addr.sun_path), "@%s", name);
+	addr.sun_path[0] = '\0';
+
+	sock = lxc_af_unix_connect(addr.sun_path);
+	if (sock < 0) {
+		WARN("failed to connect to '@%s': %s", offset, strerror(errno));
+		return -1;
+	}
+
+	ret = lxc_af_unix_send_credential(sock, &command->request,
+					sizeof(command->request));
+	if (ret < 0) {
+		SYSERROR("failed to send credentials");
+		goto out_close;
+	}
+
+	if (ret != sizeof(command->request)) {
+		SYSERROR("message only partially sent to '@%s'", offset);
+		goto out_close;
+	}
+
+	ret = receive_answer(sock, &command->answer);
+	if (ret < 0)
+		goto out_close;
+out:
+	return ret;
+out_close:
+	close(sock);
+	goto out;
+}
+
+/*----------------------------------------------------------------------------
+ * functions used by lxc-start process
+ *--------------------------------------------------------------------------*/
+extern void lxc_console_remove_fd(int fd, struct lxc_tty_info *tty_info);
+extern int lxc_console_callback(int fd, struct lxc_request *request,
+			struct lxc_handler *handler);
+
+static int trigger_command(int fd, struct lxc_request *request,
+			struct lxc_handler *handler)
+{
+	typedef int (*callback)(int, struct lxc_request *,
+				struct lxc_handler *);
+
+	callback cb[LXC_COMMAND_MAX] = {
+		[LXC_COMMAND_TTY] = lxc_console_callback,
+	};
+
+	if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
+		return -1;
+
+	return cb[request->type](fd, request, handler);
+}
+
+static void command_fd_cleanup(int fd, struct lxc_handler *handler,
+			struct lxc_epoll_descr *descr)
+{
+	lxc_console_remove_fd(fd, &handler->tty_info);
+	lxc_mainloop_del_handler(descr, fd);
+	close(fd);
+}
+
+static int command_handler(int fd, void *data,
+			      struct lxc_epoll_descr *descr)
+{
+	int ret;
+	struct lxc_request request;
+	struct lxc_handler *handler = data;
+
+	ret = lxc_af_unix_rcv_credential(fd, &request, sizeof(request));
+	if (ret < 0) {
+		SYSERROR("failed to receive data on command socket");
+		goto out_close;
+	}
+
+	if (!ret) {
+		DEBUG("peer has disconnected");
+		goto out_close;
+	}
+
+	if (ret != sizeof(request)) {
+		WARN("partial request, ignored");
+		goto out_close;
+	}
+
+	ret = trigger_command(fd, &request, handler);
+	if (ret) {
+		/* this is not an error, but only a request to close fd */
+		ret = 0;
+		goto out_close;
+	}
+
+out:
+	return ret;
+out_close:
+	command_fd_cleanup(fd, handler, descr);
+	goto out;
+}
+
+static int incoming_command_handler(int fd, void *data,
+				    struct lxc_epoll_descr *descr)
+{
+	int ret = 1, connection;
+
+	connection = accept(fd, NULL, 0);
+	if (connection < 0) {
+		SYSERROR("failed to accept connection");
+		return -1;
+	}
+
+	if (setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &ret, sizeof(ret))) {
+		SYSERROR("failed to enable credential on socket");
+		goto out_close;
+	}
+
+	ret = lxc_mainloop_add_handler(descr, connection, command_handler, data);
+	if (ret) {
+		ERROR("failed to add handler");
+		goto out_close;
+	}
+
+out:
+	return ret;
+
+out_close:
+	close(connection);
+	goto out;
+}
+
+extern int lxc_command_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
+				    struct lxc_handler *handler)
+{
+	int ret, fd;
+	struct sockaddr_un addr = { 0 };
+	char *offset = &addr.sun_path[1];
+
+	strcpy(offset, name);
+	addr.sun_path[0] = '\0';
+
+	fd = lxc_af_unix_open(addr.sun_path, SOCK_STREAM, 0);
+	if (fd < 0) {
+		ERROR("failed to create the command service point");
+		return -1;
+	}
+
+	ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler,
+					handler);
+	if (ret) {
+		ERROR("failed to add handler for command socket");
+		close(fd);
+	}
+
+	return ret;
+}
Index: lxc/src/lxc/commands.h
===================================================================
--- lxc.orig/src/lxc/commands.h
+++ lxc/src/lxc/commands.h
@@ -43,4 +43,12 @@ struct lxc_command {
 	struct lxc_answer answer;
 };
 
+extern int lxc_command(const char *name, struct lxc_command *command);
+
+struct lxc_epoll_descr;
+struct lxc_handler;
+
+extern int lxc_command_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
+				    struct lxc_handler *handler);
+
 #endif
Index: lxc/src/lxc/console.c
===================================================================
--- lxc.orig/src/lxc/console.c
+++ lxc/src/lxc/console.c
@@ -27,62 +27,12 @@
 #include <sys/types.h>
 #include <sys/un.h>
 
-#include "af_unix.h"
-#include "error.h"
-
-#include <lxc/log.h>
+#include <lxc/lxc.h>
 #include "commands.h"
+#include "af_unix.h"
 
 lxc_log_define(lxc_console, lxc);
 
-static int receive_answer(int sock, struct lxc_answer *answer)
-{
-	int ret;
-
-	ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer, sizeof(*answer));
-	if (ret < 0)
-		ERROR("failed to receive answer for the command");
-
-	return ret;
-}
-
-static int send_command(const char *name, struct lxc_command *command)
-{
-	struct sockaddr_un addr = { 0 };
-	int sock, ret = -1;
-	char *offset = &addr.sun_path[1];
-
-	snprintf(addr.sun_path, sizeof(addr.sun_path), "@%s", name);
-	addr.sun_path[0] = '\0';
-
-	sock = lxc_af_unix_connect(addr.sun_path);
-	if (sock < 0) {
-		WARN("failed to connect to '@%s': %s", offset, strerror(errno));
-		return -1;
-	}
-
-	ret = lxc_af_unix_send_credential(sock, &command->request,
-					sizeof(command->request));
-	if (ret < 0) {
-		SYSERROR("failed to send credentials");
-		goto out_close;
-	}
-
-	if (ret != sizeof(command->request)) {
-		SYSERROR("message only partially sent to '@%s'", offset);
-		goto out_close;
-	}
-
-	ret = receive_answer(sock, &command->answer);
-	if (ret < 0)
-		goto out_close;
-out:
-	return ret;
-out_close:
-	close(sock);
-	goto out;
-}
-
 extern int lxc_console(const char *name, int ttynum, int *fd)
 {
 	int ret;
@@ -90,7 +40,7 @@ extern int lxc_console(const char *name,
 		.request = { .type = LXC_COMMAND_TTY, .data = ttynum },
 	};
 
-	ret = send_command(name, &command);
+	ret = lxc_command(name, &command);
 	if (ret < 0) {
 		ERROR("failed to send command");
 		return -1;
@@ -110,3 +60,64 @@ extern int lxc_console(const char *name,
 	INFO("tty %d allocated", ttynum);
 	return 0;
 }
+
+/*----------------------------------------------------------------------------
+ * functions used by lxc-start mainloop
+ * to handle above command request.
+ *--------------------------------------------------------------------------*/
+extern void lxc_console_remove_fd(int fd, struct lxc_tty_info *tty_info)
+{
+	int i;
+
+	for (i = 0; i < tty_info->nbtty; i++) {
+
+		if (tty_info->pty_info[i].busy != fd)
+			continue;
+
+		tty_info->pty_info[i].busy = 0;
+	}
+
+	return;
+}
+
+extern int lxc_console_callback(int fd, struct lxc_request *request,
+			struct lxc_handler *handler)
+{
+	int ttynum = request->data;
+	struct lxc_tty_info *tty_info = &handler->tty_info;
+
+	if (ttynum > 0) {
+		if (ttynum > tty_info->nbtty)
+			goto out_close;
+
+		if (tty_info->pty_info[ttynum - 1].busy)
+			goto out_close;
+
+		goto out_send;
+	}
+
+	/* fixup index tty1 => [0] */
+	for (ttynum = 1;
+	     ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
+	     ttynum++);
+
+	/* we didn't find any available slot for tty */
+	if (ttynum > tty_info->nbtty)
+		goto out_close;
+
+out_send:
+	if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum - 1].master,
+				&ttynum, sizeof(ttynum)) < 0) {
+		ERROR("failed to send tty to client");
+		goto out_close;
+	}
+
+	tty_info->pty_info[ttynum - 1].busy = fd;
+
+	return 0;
+
+out_close:
+	/* the close fd and related cleanup will be done by caller */
+	return 1;
+}
+
Index: lxc/src/lxc/start.c
===================================================================
--- lxc.orig/src/lxc/start.c
+++ lxc/src/lxc/start.c
@@ -133,41 +133,6 @@ static int setup_sigchld_fd(sigset_t *ol
 	return fd;
 }
 
-static int incoming_command_handler(int fd, void *data,
-			      struct lxc_epoll_descr *descr);
-
-static int command_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
-			     struct lxc_handler *handler)
-{
-	int ret, fd;
-	struct sockaddr_un addr = { 0 };
-	char *offset = &addr.sun_path[1];
-
-	strcpy(offset, name);
-	addr.sun_path[0] = '\0';
-
-	fd = lxc_af_unix_open(addr.sun_path, SOCK_STREAM, 0);
-	if (fd < 0) {
-		ERROR("failed to create the command service point");
-		return -1;
-	}
-
-	if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
-		SYSERROR("failed to close-on-exec flag");
-		close(fd);
-		return -1;
-	}
-
-	ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler,
-					handler);
-	if (ret) {
-		ERROR("failed to add handler for command socket");
-		close(fd);
-	}
-
-	return ret;
-}
-
 static int sigchld_handler(int fd, void *data, 
 			   struct lxc_epoll_descr *descr)
 {
@@ -176,161 +141,6 @@ static int sigchld_handler(int fd, void 
 	return 1;
 }
 
-static int command_handler(int fd, void *data,
-			      struct lxc_epoll_descr *descr);
-static int trigger_command(int fd, struct lxc_request *request,
-			struct lxc_handler *handler,
-			struct lxc_epoll_descr *descr);
-
-static int incoming_command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
-{
-	int ret = 1, connection;
-
-	connection = accept(fd, NULL, 0);
-	if (connection < 0) {
-		SYSERROR("failed to accept connection");
-		return -1;
-	}
-
-	if (setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &ret, sizeof(ret))) {
-		SYSERROR("failed to enable credential on socket");
-		goto out_close;
-	}
-
-	ret = lxc_mainloop_add_handler(descr, connection, command_handler, data);
-	if (ret) {
-		ERROR("failed to add handler");
-		goto out_close;
-	}
-
-out:
-	return ret;
-
-out_close:
-	close(connection);
-	goto out;
-}
-
-static void ttyinfo_remove_fd(int fd, struct lxc_tty_info *tty_info)
-{
-	int i;
-
-	for (i = 0; i < tty_info->nbtty; i++) {
-
-		if (tty_info->pty_info[i].busy != fd)
-			continue;
-
-		tty_info->pty_info[i].busy = 0;
-	}
-
-	return;
-}
-
-static void command_fd_cleanup(int fd, struct lxc_handler *handler,
-			struct lxc_epoll_descr *descr)
-{
-	ttyinfo_remove_fd(fd, &handler->tty_info);
-	lxc_mainloop_del_handler(descr, fd);
-	close(fd);
-}
-
-static int command_handler(int fd, void *data,
-			      struct lxc_epoll_descr *descr)
-{
-	int ret;
-	struct lxc_request request;
-	struct lxc_handler *handler = data;
-
-	ret = lxc_af_unix_rcv_credential(fd, &request, sizeof(request));
-	if (ret < 0) {
-		SYSERROR("failed to receive data on command socket");
-		goto out_close;
-	}
-
-	if (!ret) {
-		DEBUG("peer has disconnected");
-		goto out_close;
-	}
-
-	if (ret != sizeof(request)) {
-		WARN("partial request, ignored");
-		goto out_close;
-	}
-
-	ret = trigger_command(fd, &request, handler, descr);
-	if (ret) {
-		/* this is not an error, but only a request to close fd */
-		ret = 0;
-		goto out_close;
-	}
-
-out:
-	return ret;
-out_close:
-	command_fd_cleanup(fd, handler, descr);
-	goto out;
-}
-
-static int ttyservice_handler(int fd, struct lxc_request *request,
-			struct lxc_handler *handler,
-			struct lxc_epoll_descr *descr)
-{
-	int ttynum = request->data;
-	struct lxc_tty_info *tty_info = &handler->tty_info;
-
-	if (ttynum > 0) {
-		if (ttynum > tty_info->nbtty)
-			goto out_close;
-
-		if (tty_info->pty_info[ttynum - 1].busy)
-			goto out_close;
-
-		goto out_send;
-	}
-
-	/* fixup index tty1 => [0] */
-	for (ttynum = 1;
-	     ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
-	     ttynum++);
-
-	/* we didn't find any available slot for tty */
-	if (ttynum > tty_info->nbtty)
-		goto out_close;
-
-out_send:
-	if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum - 1].master,
-				&ttynum, sizeof(ttynum)) < 0) {
-		ERROR("failed to send tty to client");
-		goto out_close;
-	}
-
-	tty_info->pty_info[ttynum - 1].busy = fd;
-
-	return 0;
-
-out_close:
-	/* the close fd and related cleanup will be done by caller */
-	return 1;
-}
-
-static int trigger_command(int fd, struct lxc_request *request,
-			struct lxc_handler *handler,
-			struct lxc_epoll_descr *descr)
-{
-	typedef int (*callback)(int, struct lxc_request *,
-				struct lxc_handler *,
-				struct lxc_epoll_descr *descr);
-
-	callback cb[LXC_COMMAND_MAX] = {
-		[LXC_COMMAND_TTY] = ttyservice_handler,
-	};
-
-	if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
-		return -1;
-
-	return cb[request->type](fd, request, handler, descr);
-}
-
 int lxc_poll(const char *name, struct lxc_handler *handler)
 {
 	int sigfd = handler->sigfd;
@@ -353,7 +163,7 @@ int lxc_poll(const char *name, struct lx
 		goto out_mainloop_open;
 	}
 
-	if (command_mainloop_add(name, &descr, handler))
+	if (lxc_command_mainloop_add(name, &descr, handler))
 		goto out_mainloop_open;
 
 	ret = lxc_mainloop(&descr);



