2
0
mirror of git://github.com/lxc/lxc synced 2025-08-31 02:59:36 +00:00

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 <normand@fr.ibm.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
This commit is contained in:
Michel Normand
2009-10-07 16:06:08 +02:00
committed by Daniel Lezcano
parent 96fa1ff0d1
commit 724e753cb0
5 changed files with 288 additions and 245 deletions

View File

@@ -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 \

214
src/lxc/commands.c Normal file
View File

@@ -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;
}

View File

@@ -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

View File

@@ -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, 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;
}

View File

@@ -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);