mirror of
git://github.com/lxc/lxc
synced 2025-09-01 08:13:45 +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:
committed by
Daniel Lezcano
parent
96fa1ff0d1
commit
724e753cb0
@@ -19,7 +19,7 @@ pkginclude_HEADERS = \
|
|||||||
|
|
||||||
liblxc_la_SOURCES = \
|
liblxc_la_SOURCES = \
|
||||||
arguments.c arguments.h \
|
arguments.c arguments.h \
|
||||||
commands.h \
|
commands.c commands.h \
|
||||||
create.c \
|
create.c \
|
||||||
destroy.c \
|
destroy.c \
|
||||||
start.c \
|
start.c \
|
||||||
|
214
src/lxc/commands.c
Normal file
214
src/lxc/commands.c
Normal 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;
|
||||||
|
}
|
@@ -43,4 +43,12 @@ struct lxc_command {
|
|||||||
struct lxc_answer answer;
|
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
|
#endif
|
||||||
|
@@ -27,62 +27,12 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include "af_unix.h"
|
#include <lxc/lxc.h>
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#include <lxc/log.h>
|
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
#include "af_unix.h"
|
||||||
|
|
||||||
lxc_log_define(lxc_console, lxc);
|
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)
|
extern int lxc_console(const char *name, int ttynum, int *fd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -90,7 +40,7 @@ extern int lxc_console(const char *name, int ttynum, int *fd)
|
|||||||
.request = { .type = LXC_COMMAND_TTY, .data = ttynum },
|
.request = { .type = LXC_COMMAND_TTY, .data = ttynum },
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = send_command(name, &command);
|
ret = lxc_command(name, &command);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ERROR("failed to send command");
|
ERROR("failed to send command");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -110,3 +60,64 @@ extern int lxc_console(const char *name, int ttynum, int *fd)
|
|||||||
INFO("tty %d allocated", ttynum);
|
INFO("tty %d allocated", ttynum);
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
192
src/lxc/start.c
192
src/lxc/start.c
@@ -133,41 +133,6 @@ static int setup_sigchld_fd(sigset_t *oldmask)
|
|||||||
return fd;
|
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,
|
static int sigchld_handler(int fd, void *data,
|
||||||
struct lxc_epoll_descr *descr)
|
struct lxc_epoll_descr *descr)
|
||||||
{
|
{
|
||||||
@@ -176,161 +141,6 @@ static int sigchld_handler(int fd, void *data,
|
|||||||
return 1;
|
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 lxc_poll(const char *name, struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
int sigfd = handler->sigfd;
|
int sigfd = handler->sigfd;
|
||||||
@@ -353,7 +163,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
|
|||||||
goto out_mainloop_open;
|
goto out_mainloop_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command_mainloop_add(name, &descr, handler))
|
if (lxc_command_mainloop_add(name, &descr, handler))
|
||||||
goto out_mainloop_open;
|
goto out_mainloop_open;
|
||||||
|
|
||||||
ret = lxc_mainloop(&descr);
|
ret = lxc_mainloop(&descr);
|
||||||
|
Reference in New Issue
Block a user