From: Michel Normand Date: Wed, 7 Oct 2009 14:06:08 +0000 (+0200) Subject: repackage previous code to new commands.c X-Git-Tag: lxc_0_6_4~87 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=724e753cb0055b84f896522e8c5ec45ad996c195;p=thirdparty%2Flxc.git repackage previous code to new commands.c move some code of start.c to new commands.c and to console.c Signed-off-by: Michel Normand Signed-off-by: Daniel Lezcano --- diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 269c618d9..641abf6cb 100644 --- a/src/lxc/Makefile.am +++ b/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 \ diff --git a/src/lxc/commands.c b/src/lxc/commands.c new file mode 100644 index 000000000..98e6121d8 --- /dev/null +++ b/src/lxc/commands.c @@ -0,0 +1,214 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2009 + * + * Authors: + * Daniel Lezcano + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; +} diff --git a/src/lxc/commands.h b/src/lxc/commands.h index 66dd6998f..b6c76c1f4 100644 --- a/src/lxc/commands.h +++ b/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 diff --git a/src/lxc/console.c b/src/lxc/console.c index 18946e1fb..d32941c16 100644 --- a/src/lxc/console.c +++ b/src/lxc/console.c @@ -27,62 +27,12 @@ #include #include -#include "af_unix.h" -#include "error.h" - -#include +#include #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, int ttynum, int *fd) .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, int ttynum, int *fd) 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; +} + diff --git a/src/lxc/start.c b/src/lxc/start.c index c96dfb3af..3c705111f 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -133,41 +133,6 @@ static int setup_sigchld_fd(sigset_t *oldmask) 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 *data, 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 lxc_handler *handler) 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);