[lxc-devel] [PATCH] extend command processor to handle generic data
Dwight Engen
dwight.engen at oracle.com
Tue May 21 14:44:31 UTC 2013
On Tue, 21 May 2013 08:18:01 -0500
Serge Hallyn <serge.hallyn at ubuntu.com> wrote:
> Quoting Dwight Engen (dwight.engen at oracle.com):
> > Motivation for this change is to have the ability to get the
> > run-time configuration items from a container, which may differ
> > from its current on disk configuration, or might not be available
> > any other way (for example lxc.network.0.veth.pair). In adding this
> > ability it seemed there was room for refactoring improvements.
> >
> > Genericize the command infrastructure so that both command requests
> > and responses can have arbitrary data. Consolidate all commands
> > into command.c and name them consistently. This allows all the
> > callback routines to be made static, reducing exposure.
> >
> > Return the actual allocated tty for the console command. Don't
> > print the init pid in lxc_info if the container isn't actually
> > running. Command processing was made more thread safe by removing
> > the static buffer from receive_answer(). Refactored command
> > response code to a common routine.
> >
> > Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
>
> Working great on my box - thanks.
>
> Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
>
> It seems like a general cleanup, but I'm wondering what your
> motivation was for the get-config command? Programs using the struct
> lxc_container API or lua/python3 bindings can after all just do
>
> import lxc
> c = lxcContainer('c1', NULL);
> c.get_config_item('lxc.rootfs')
Creating a container using the API/bindings creates a new c, and
c->lxc_conf contains a parse of the on-disk configuration as it
exists at the time of the lxcContainer() call but may not reflect an
already running c1. I specifically wanted to know the veth pair name of
an already running container, and I think it may be useful to know other
configuration items of a running container which may differ from what
is currently on disk.
> > ---
> > src/lxc/Makefile.am | 1 -
> > src/lxc/cgroup.c | 70 ++----
> > src/lxc/cgroup.h | 1 -
> > src/lxc/commands.c | 648
> > +++++++++++++++++++++++++++++++++++++++++--------
> > src/lxc/commands.h | 75 +++--- src/lxc/console.c | 84
> > ------- src/lxc/lxc.h | 8 -
> > src/lxc/lxc_attach.c | 4 +-
> > src/lxc/lxc_console.c | 8 +-
> > src/lxc/lxc_info.c | 10 +-
> > src/lxc/lxc_kill.c | 2 +-
> > src/lxc/lxc_stop.c | 3 +-
> > src/lxc/lxccontainer.c | 4 +-
> > src/lxc/start.c | 88 +------
> > src/lxc/state.c | 63 +----
> > src/lxc/stop.c | 115 ---------
> > src/tests/cgpath.c | 5 +-
> > 17 files changed, 633 insertions(+), 556 deletions(-)
> > delete mode 100644 src/lxc/stop.c
> >
> > diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> > index 4a19061..f8eb41b 100644
> > --- a/src/lxc/Makefile.am
> > +++ b/src/lxc/Makefile.am
> > @@ -40,7 +40,6 @@ liblxc_so_SOURCES = \
> > bdev.c bdev.h \
> > commands.c commands.h \
> > start.c start.h \
> > - stop.c \
> > execute.c \
> > monitor.c monitor.h \
> > console.c \
> > diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> > index a8ae8c1..a3fa2c6 100644
> > --- a/src/lxc/cgroup.c
> > +++ b/src/lxc/cgroup.c
> > @@ -120,7 +120,7 @@ static int get_cgroup_mount(const char
> > *subsystem, char *mnt) while ((getmntent_r(file, &mntent_r, buf,
> > sizeof(buf)))) { if (strcmp(mntent_r.mnt_type, "cgroup") != 0)
> > continue;
> > -
> > +
> > if (subsystem) {
> > if (!hasmntopt(&mntent_r, subsystem))
> > continue;
> > @@ -215,55 +215,9 @@ fail:
> > }
> >
> > /*
> > - * Calculate a container's cgroup path for a particular
> > subsystem. This
> > - * is the cgroup path relative to the root of the cgroup
> > filesystem.
> > - * @path: A char ** into which we copy the char* containing the
> > answer
> > - * @subsystem: the cgroup subsystem of interest (i.e. freezer)
> > - * @name: container name
> > - * @lxcpath: the lxcpath in which the container is running.
> > - *
> > - * Returns 0 on success, -1 on error.
> > - *
> > - * Note that the char* copied into *path is a static
> > char[MAXPATHLEN] in
> > - * commands.c:receive_answer(). It should not be freed.
> > - */
> > -extern int lxc_get_cgpath(const char **path, const char
> > *subsystem, const char *name, const char *lxcpath) -{
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_CGROUP },
> > - };
> > -
> > - int ret, stopped = 0;
> > -
> > - ret = lxc_command(name, &command, &stopped, lxcpath);
> > - if (ret < 0) {
> > - if (!stopped)
> > - ERROR("failed to send command");
> > - return -1;
> > - }
> > -
> > - if (!ret) {
> > - WARN("'%s' has stopped before sending its state",
> > name);
> > - return -1;
> > - }
> > -
> > - if (command.answer.ret < 0 || command.answer.pathlen < 0) {
> > - ERROR("failed to get state for '%s': %s",
> > - name, strerror(-command.answer.ret));
> > - return -1;
> > - }
> > -
> > - *path = command.answer.path;
> > -
> > - return 0;
> > -}
> > -
> > -/*
> > * lxc_cgroup_path_get: determine full pathname for a cgroup
> > * file for a specific container.
> > - * @path: char ** used to return the answer. The char * will point
> > - * into the static char* retuf from cgroup_path_get() (so no need
> > - * to free it).
> > + * @path: char ** used to return the answer.
> > * @subsystem: cgroup subsystem (i.e. "freezer") for which to
> > * return an answer. If NULL, then the first cgroup entry in
> > * mtab will be used.
> > @@ -275,12 +229,16 @@ extern int lxc_get_cgpath(const char **path,
> > const char *subsystem, const char * */
> > int lxc_cgroup_path_get(char **path, const char *subsystem, const
> > char *name, const char *lxcpath) {
> > - const char *cgpath;
> > + int ret;
> > + char *cgpath;
> >
> > - if (lxc_get_cgpath(&cgpath, subsystem, name, lxcpath) < 0)
> > + cgpath = lxc_cmd_get_cgroup_path(subsystem, name, lxcpath);
> > + if (!cgpath)
> > return -1;
> >
> > - return cgroup_path_get(path, subsystem, cgpath);
> > + ret = cgroup_path_get(path, subsystem, cgpath);
> > + free(cgpath);
> > + return ret;
> > }
> >
> > /*
> > @@ -917,13 +875,17 @@ int lxc_cgroup_destroy(const char *cgpath)
> >
> > int lxc_cgroup_attach(pid_t pid, const char *name, const char
> > *lxcpath) {
> > - const char *dirpath;
> > + int ret;
> > + char *dirpath;
> >
> > - if (lxc_get_cgpath(&dirpath, NULL, name, lxcpath) < 0) {
> > + dirpath = lxc_cmd_get_cgroup_path(NULL, name, lxcpath);
> > + if (!dirpath) {
> > ERROR("Error getting cgroup for container %s: %s",
> > lxcpath, name); return -1;
> > }
> > INFO("joining pid %d to cgroup %s", pid, dirpath);
> >
> > - return lxc_cgroup_enter(dirpath, pid);
> > + ret = lxc_cgroup_enter(dirpath, pid);
> > + free(dirpath);
> > + return ret;
> > }
> > diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
> > index 937b9c9..971311e 100644
> > --- a/src/lxc/cgroup.h
> > +++ b/src/lxc/cgroup.h
> > @@ -34,5 +34,4 @@ extern char *lxc_cgroup_path_create(const char
> > *lxcgroup, const char *name); extern int lxc_cgroup_enter(const
> > char *cgpath, pid_t pid); extern int lxc_cgroup_attach(pid_t pid,
> > const char *name, const char *lxcpath); extern int
> > cgroup_path_get(char **path, const char *subsystem, const char
> > *cgpath); -extern int lxc_get_cgpath(const char **path, const char
> > *subsystem, const char *name, const char *lxcpath); #endif diff
> > --git a/src/lxc/commands.c b/src/lxc/commands.c index
> > d45ae21..3f21488 100644 --- a/src/lxc/commands.c
> > +++ b/src/lxc/commands.c
> > @@ -34,27 +34,30 @@
> > #include <stdlib.h>
> >
> > #include <lxc/log.h>
> > +#include <lxc/lxc.h>
> > #include <lxc/conf.h>
> > #include <lxc/start.h> /* for struct lxc_handler */
> > #include <lxc/utils.h>
> >
> > #include "commands.h"
> > +#include "confile.h"
> > #include "mainloop.h"
> > #include "af_unix.h"
> > #include "config.h"
> >
> > /*
> > - * This file provides the different functions to have the client
> > - * and the server to communicate
> > + * This file provides the different functions for clients to
> > + * query/command the server. The client is typically some lxc
> > + * tool and the server is typically the container (ie. lxc-start).
> > *
> > - * Each command is transactional, the client send a request to
> > - * the server and the server answer the request with a message
> > + * Each command is transactional, the clients send a request to
> > + * the server and the server answers the request with a message
> > * giving the request's status (zero or a negative errno value).
> > + * Both the request and response may contain addtional data.
> > *
> > * Each command is wrapped in a ancillary message in order to pass
> > * a credential making possible to the server to check if the
> > client
> > * is allowed to ask for this command or not.
> > - *
> > */
> >
> > lxc_log_define(lxc_commands, lxc);
> > @@ -81,66 +84,183 @@ static int fill_sock_name(char *path, int len,
> > const char *name, return 0;
> > }
> >
> > -static int receive_answer(int sock, struct lxc_answer *answer)
> > +static const char *lxc_cmd_str(lxc_cmd_t cmd)
> > {
> > - int ret;
> > - static char answerpath[MAXPATHLEN];
> > + static const char *cmdname[LXC_CMD_MAX] = {
> > + [LXC_CMD_CONSOLE] = "console",
> > + [LXC_CMD_STOP] = "stop",
> > + [LXC_CMD_GET_STATE] = "get_state",
> > + [LXC_CMD_GET_INIT_PID] = "get_init_pid",
> > + [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
> > + [LXC_CMD_GET_CGROUP] = "get_cgroup",
> > + [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
> > + };
> >
> > - ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer,
> > sizeof(*answer));
> > - if (ret < 0)
> > - ERROR("failed to receive answer for the command");
> > - if (answer->pathlen == 0)
> > + if (cmd < 0 || cmd >= LXC_CMD_MAX)
> > + return "Unknown cmd";
> > + return cmdname[cmd];
> > +}
> > +
> > +/*
> > + * lxc_cmd_rsp_recv: Receive a response to a command
> > + *
> > + * @sock : the socket connected to the container
> > + * @cmd : command to put response in
> > + *
> > + * Returns the size of the response message or < 0 on failure
> > + *
> > + * Note that if the command response datalen > 0, then data is
> > + * a malloc()ed buffer and should be free()ed by the caller. If
> > + * the response data is <= a void * worth of data, it will be
> > + * stored directly in data and datalen will be 0.
> > + *
> > + * As a special case, the response for LXC_CMD_CONSOLE is created
> > + * here as it contains an fd passed through the unix socket.
> > + */
> > +static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
> > +{
> > + int ret,rspfd;
> > + struct lxc_cmd_rsp *rsp = &cmd->rsp;
> > +
> > + ret = lxc_af_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
> > + if (ret < 0) {
> > + ERROR("command %s failed to receive response",
> > + lxc_cmd_str(cmd->req.cmd));
> > + return -1;
> > + }
> > +
> > + if (cmd->req.cmd == LXC_CMD_CONSOLE) {
> > + struct lxc_cmd_console_rsp_data *rspdata;
> > +
> > + rspdata = malloc(sizeof(*rspdata));
> > + if (!rspdata) {
> > + ERROR("command %s couldn't allocate
> > response buffer",
> > + lxc_cmd_str(cmd->req.cmd));
> > + return -1;
> > + }
> > + rspdata->fd = rspfd;
> > + rspdata->ttynum = PTR_TO_INT(rsp->data);
> > + rsp->data = rspdata;
> > + }
> > +
> > + if (rsp->datalen == 0)
> > return ret;
> > - if (answer->pathlen >= MAXPATHLEN) {
> > - ERROR("cgroup path was too long");
> > + if (rsp->datalen > LXC_CMD_DATA_MAX) {
> > + ERROR("command %s response data %d too long",
> > + lxc_cmd_str(cmd->req.cmd), rsp->datalen);
> > + errno = EFBIG;
> > return -1;
> > }
> > - ret = recv(sock, answerpath, answer->pathlen, 0);
> > - if (ret != answer->pathlen) {
> > - ERROR("failed to receive answer for the command");
> > - ret = 0;
> > - } else
> > - answer->path = answerpath;
> > +
> > + rsp->data = malloc(rsp->datalen);
> > + if (!rsp->data) {
> > + ERROR("command %s unable to allocate response
> > buffer",
> > + lxc_cmd_str(cmd->req.cmd));
> > + return -1;
> > + }
> > + ret = recv(sock, rsp->data, rsp->datalen, 0);
> > + if (ret != rsp->datalen) {
> > + ERROR("command %s failed to receive response data",
> > + lxc_cmd_str(cmd->req.cmd));
> > + if (ret >= 0)
> > + ret = -1;
> > + }
> >
> > return ret;
> > }
> >
> > -static int __lxc_command(const char *name, struct lxc_command
> > *command,
> > - int *stopped, int stay_connected, const
> > char *lxcpath) +/*
> > + * lxc_cmd_rsp_send: Send a command response
> > + *
> > + * @fd : file descriptor of socket to send response on
> > + * @rsp : response to send
> > + *
> > + * Returns 0 on success, < 0 on failure
> > + */
> > +static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
> > +{
> > + int ret;
> > +
> > + ret = send(fd, rsp, sizeof(*rsp), 0);
> > + if (ret != sizeof(*rsp)) {
> > + ERROR("failed to send command response %d %s", ret,
> > + strerror(errno));
> > + return -1;
> > + }
> > +
> > + if (rsp->datalen > 0) {
> > + ret = send(fd, rsp->data, rsp->datalen, 0);
> > + if (ret != rsp->datalen) {
> > + WARN("failed to send command response data
> > %d %s", ret,
> > + strerror(errno));
> > + return -1;
> > + }
> > + }
> > + return 0;
> > +}
> > +
> > +/*
> > + * lxc_cmd: Connect to the specified running container, send it a
> > command
> > + * request and collect the response
> > + *
> > + * @name : name of container to connect to
> > + * @cmd : command with initialized reqest to send
> > + * @stopped : output indicator if the container was not
> > running
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the size of the response message on success, < 0 on
> > failure
> > + *
> > + * Note that there is a special case for LXC_CMD_CONSOLE. For this
> > command
> > + * the fd cannot be closed because it is used as a placeholder to
> > indicate
> > + * that a particular tty slot is in use. The fd is also used as a
> > signal to
> > + * the container that when the caller dies or closes the fd, the
> > container
> > + * will notice the fd in its mainloop select and then free the
> > slot with
> > + * lxc_cmd_fd_cleanup().
> > + */
> > +static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int
> > *stopped,
> > + const char *lxcpath)
> > {
> > int sock, ret = -1;
> > char path[sizeof(((struct sockaddr_un *)0)->sun_path)] =
> > { 0 }; char *offset = &path[1];
> > int len;
> > + int stay_connected = cmd->req.cmd == LXC_CMD_CONSOLE;
> >
> > len = sizeof(path)-1;
> > if (fill_sock_name(offset, len, name, lxcpath))
> > return -1;
> >
> > sock = lxc_af_unix_connect(path);
> > - if (sock < 0 && errno == ECONNREFUSED) {
> > - *stopped = 1;
> > - return -1;
> > - }
> > -
> > if (sock < 0) {
> > - SYSERROR("failed to connect to '@%s'", offset);
> > + if (errno == ECONNREFUSED)
> > + *stopped = 1;
> > + else
> > + SYSERROR("command %s failed to connect to
> > '@%s'",
> > + lxc_cmd_str(cmd->req.cmd),
> > offset); return -1;
> > }
> >
> > - ret = lxc_af_unix_send_credential(sock, &command->request,
> > - sizeof(command->request));
> > - if (ret < 0) {
> > - SYSERROR("failed to send request to '@%s'",
> > offset);
> > + ret = lxc_af_unix_send_credential(sock, &cmd->req,
> > sizeof(cmd->req));
> > + if (ret != sizeof(cmd->req)) {
> > + SYSERROR("command %s failed to send req to '@%s'
> > %d",
> > + lxc_cmd_str(cmd->req.cmd), offset, ret);
> > + if (ret >=0)
> > + ret = -1;
> > goto out;
> > }
> >
> > - if (ret != sizeof(command->request)) {
> > - SYSERROR("message partially sent to '@%s'",
> > offset);
> > - goto out;
> > + if (cmd->req.datalen > 0) {
> > + ret = send(sock, cmd->req.data, cmd->req.datalen,
> > 0);
> > + if (ret != cmd->req.datalen) {
> > + SYSERROR("command %s failed to send
> > request data to '@%s' %d",
> > + lxc_cmd_str(cmd->req.cmd),
> > offset, ret);
> > + if (ret >=0)
> > + ret = -1;
> > + goto out;
> > + }
> > }
> >
> > - ret = receive_answer(sock, &command->answer);
> > + ret = lxc_cmd_rsp_recv(sock, cmd);
> > out:
> > if (!stay_connected || ret < 0)
> > close(sock);
> > @@ -148,114 +268,418 @@ out:
> > return ret;
> > }
> >
> > -extern int lxc_command(const char *name,
> > - struct lxc_command *command, int *stopped,
> > - const char *lxcpath)
> > +/* Implentations of the commands and their callbacks */
> > +
> > +/*
> > + * lxc_cmd_get_init_pid: Get pid of the container's init process
> > + *
> > + * @name : name of container to connect to
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the pid on success, < 0 on failure
> > + */
> > +pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
> > {
> > - return __lxc_command(name, command, stopped, 0, lxcpath);
> > + int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_GET_INIT_PID },
> > + };
> > +
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > + if (ret < 0)
> > + return ret;
> > +
> > + return PTR_TO_INT(cmd.rsp.data);
> > }
> >
> > -extern int lxc_command_connected(const char *name,
> > - struct lxc_command *command, int
> > *stopped,
> > - const char *lxcpath)
> > +static int lxc_cmd_get_init_pid_callback(int fd, struct
> > lxc_cmd_req *req,
> > + struct lxc_handler
> > *handler) {
> > - return __lxc_command(name, command, stopped, 1, lxcpath);
> > + struct lxc_cmd_rsp rsp = { .data =
> > INT_TO_PTR(handler->pid) }; +
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > }
> >
> > +/*
> > + * lxc_cmd_get_clone_flags: Get clone flags container was spawned
> > with
> > + *
> > + * @name : name of container to connect to
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the clone flags on success, < 0 on failure
> > + */
> > +int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
> > +{
> > + int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_GET_CLONE_FLAGS },
> > + };
> > +
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > + if (ret < 0)
> > + return ret;
> >
> > -pid_t get_init_pid(const char *name, const char *lxcpath)
> > + return PTR_TO_INT(cmd.rsp.data);
> > +}
> > +
> > +static int lxc_cmd_get_clone_flags_callback(int fd, struct
> > lxc_cmd_req *req,
> > + struct lxc_handler
> > *handler) {
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_PID },
> > + struct lxc_cmd_rsp rsp = { .data =
> > INT_TO_PTR(handler->clone_flags) }; +
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > +}
> > +
> > +/*
> > + * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path
> > for a
> > + * particular subsystem. This is the cgroup path relative to the
> > root
> > + * of the cgroup filesystem.
> > + *
> > + * @subsystem : the cgroup subsystem of interest (i.e. freezer)
> > + * @name : name of container to connect to
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the path on success, NULL on failure. The caller must
> > free() the
> > + * returned path.
> > + */
> > +char *lxc_cmd_get_cgroup_path(const char *subsystem, const char
> > *name,
> > + const char *lxcpath)
> > +{
> > + int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_GET_CGROUP },
> > };
> >
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > + if (ret < 0)
> > + return NULL;
> > +
> > + if (!ret) {
> > + WARN("'%s' has stopped before sending its state",
> > name);
> > + return NULL;
> > + }
> > +
> > + if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0) {
> > + ERROR("command %s failed for '%s': %s",
> > + lxc_cmd_str(cmd.req.cmd), name,
> > + strerror(-cmd.rsp.ret));
> > + return NULL;
> > + }
> > +
> > + return cmd.rsp.data;
> > +}
> > +
> > +static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req
> > *req,
> > + struct lxc_handler *handler)
> > +{
> > + struct lxc_cmd_rsp rsp = {
> > + .datalen = strlen(handler->cgroup) + 1,
> > + .data = handler->cgroup,
> > + };
> > +
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > +}
> > +
> > +/*
> > + * lxc_cmd_get_config_item: Get config item the running container
> > + *
> > + * @name : name of container to connect to
> > + * @item : the configuration item to retrieve (ex:
> > lxc.network.0.veth.pair)
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the item on success, NULL on failure. The caller must
> > free() the
> > + * returned item.
> > + */
> > +char *lxc_cmd_get_config_item(const char *name, const char *item,
> > + const char *lxcpath)
> > +{
> > + int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
> > + .data = item,
> > + .datalen = strlen(item)+1,
> > + },
> > + };
> > +
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > + if (ret < 0)
> > + return NULL;
> > +
> > + if (cmd.rsp.ret == 0)
> > + return cmd.rsp.data;
> > + return NULL;
> > +}
> > +
> > +static int lxc_cmd_get_config_item_callback(int fd, struct
> > lxc_cmd_req *req,
> > + struct lxc_handler
> > *handler) +{
> > + int cilen;
> > + struct lxc_cmd_rsp rsp;
> > + char *cidata;
> > +
> > + memset(&rsp, 0, sizeof(rsp));
> > + cilen = lxc_get_config_item(handler->conf, req->data,
> > NULL, 0);
> > + if (cilen <= 0)
> > + goto err1;
> > +
> > + cidata = alloca(cilen + 1);
> > + if (lxc_get_config_item(handler->conf, req->data, cidata,
> > cilen + 1) != cilen)
> > + goto err1;
> > + cidata[cilen] = '\0';
> > + rsp.data = cidata;
> > + rsp.datalen = cilen + 1;
> > + rsp.ret = 0;
> > + goto out;
> > +
> > +err1:
> > + rsp.ret = -1;
> > +out:
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > +}
> > +
> > +/*
> > + * lxc_cmd_get_state: Get current state of the container
> > + *
> > + * @name : name of container to connect to
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns the state on success, < 0 on failure
> > + */
> > +lxc_state_t lxc_cmd_get_state(const char *name, const char
> > *lxcpath) +{
> > int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_GET_STATE }
> > + };
> >
> > - ret = lxc_command(name, &command, &stopped, lxcpath);
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > if (ret < 0 && stopped)
> > + return STOPPED;
> > +
> > + if (ret < 0)
> > return -1;
> >
> > + if (!ret) {
> > + WARN("'%s' has stopped before sending its state",
> > name);
> > + return -1;
> > + }
> > +
> > + DEBUG("'%s' is in '%s' state", name,
> > + lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
> > + return PTR_TO_INT(cmd.rsp.data);
> > +}
> > +
> > +static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req
> > *req,
> > + struct lxc_handler *handler)
> > +{
> > + struct lxc_cmd_rsp rsp = { .data =
> > INT_TO_PTR(handler->state) }; +
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > +}
> > +
> > +/*
> > + * lxc_cmd_stop: Stop the container previously started with
> > lxc_start. All
> > + * the processes running inside this container will be killed.
> > + *
> > + * @name : name of container to connect to
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns 0 on success, < 0 on failure
> > + */
> > +int lxc_cmd_stop(const char *name, const char *lxcpath)
> > +{
> > + int ret, stopped = 0;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_STOP },
> > + };
> > +
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > if (ret < 0) {
> > - ERROR("failed to send command");
> > + if (stopped) {
> > + INFO("'%s' is already stopped", name);
> > + return 0;
> > + }
> > return -1;
> > }
> >
> > - if (command.answer.ret) {
> > - ERROR("failed to retrieve the init pid: %s",
> > - strerror(-command.answer.ret));
> > + /* we do not expect any answer, because we wait for the
> > connection to be
> > + * closed
> > + */
> > + if (ret > 0) {
> > + ERROR("failed to stop '%s': %s", name,
> > strerror(-cmd.rsp.ret)); return -1;
> > }
> >
> > - return command.answer.pid;
> > + INFO("'%s' has stopped", name);
> > + return 0;
> > }
> >
> > -int lxc_get_clone_flags(const char *name, const char *lxcpath)
> > +static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
> > + struct lxc_handler *handler)
> > {
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_CLONE_FLAGS },
> > - };
> > + struct lxc_cmd_rsp rsp;
> > + int ret;
> > + int stopsignal = SIGKILL;
> > +
> > + if (handler->conf->stopsignal)
> > + stopsignal = handler->conf->stopsignal;
> > + memset(&rsp, 0, sizeof(rsp));
> > + rsp.ret = kill(handler->pid, stopsignal);
> > + if (!rsp.ret) {
> > + ret = lxc_unfreeze_bypath(handler->cgroup);
> > + if (!ret)
> > + return 0;
> > +
> > + ERROR("failed to unfreeze container");
> > + rsp.ret = ret;
> > + }
> > +
> > + return lxc_cmd_rsp_send(fd, &rsp);
> > +}
> >
> > +/*
> > + * lxc_cmd_console: Open an fd to a tty in the container
> > + *
> > + * @name : name of container to connect to
> > + * @ttynum : in: the tty to open or -1 for next available
> > + * : out: the tty allocated
> > + * @fd : out: file descriptor for master side of pty
> > + * @lxcpath : the lxcpath in which the container is running
> > + *
> > + * Returns 0 on success, < 0 on failure
> > + */
> > +int lxc_cmd_console(const char *name, int *ttynum, int *fd, const
> > char *lxcpath) +{
> > int ret, stopped = 0;
> > + struct lxc_cmd_console_rsp_data *rspdata;
> > + struct lxc_cmd_rr cmd = {
> > + .req = { .cmd = LXC_CMD_CONSOLE, .data =
> > INT_TO_PTR(*ttynum) },
> > + };
> >
> > - ret = lxc_command(name, &command, &stopped, lxcpath);
> > - if (ret < 0 && stopped)
> > - return -1;
> > + ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
> > + if (ret < 0)
> > + return ret;
> > + if (ret == 0) {
> > + ERROR("console %d invalid or all consoles busy",
> > *ttynum);
> > + ret = -1;
> > + goto out;
> > + }
> >
> > - if (ret < 0) {
> > - ERROR("failed to send command");
> > - return -1;
> > + ret = -1;
> > + #if 1 /* FIXME: how can this happen? */
> > + if (cmd.rsp.ret) {
> > + ERROR("console access denied: %s",
> > + strerror(-cmd.rsp.ret));
> > + goto out;
> > + }
> > + #endif
> > +
> > + rspdata = cmd.rsp.data;
> > + if (rspdata->fd < 0) {
> > + ERROR("unable to allocate fd for tty %d",
> > rspdata->ttynum);
> > + goto out;
> > + }
> > +
> > + ret = 0;
> > + *fd = rspdata->fd;
> > + *ttynum = rspdata->ttynum;
> > + INFO("tty %d allocated", rspdata->ttynum);
> > +out:
> > + free(cmd.rsp.data);
> > + return ret;
> > +}
> > +
> > +static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req
> > *req,
> > + struct lxc_handler *handler)
> > +{
> > + int ttynum = PTR_TO_INT(req->data);
> > + struct lxc_tty_info *tty_info = &handler->conf->tty_info;
> > + struct lxc_cmd_rsp rsp;
> > +
> > + if (ttynum > 0) {
> > + if (ttynum > tty_info->nbtty)
> > + goto out_close;
> > +
> > + if (tty_info->pty_info[ttynum - 1].busy)
> > + goto out_close;
> > +
> > + /* the requested tty is available */
> > + goto out_send;
> > }
> >
> > - return command.answer.ret;
> > + /* search for next available tty, 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:
> > + memset(&rsp, 0, sizeof(rsp));
> > + rsp.data = INT_TO_PTR(ttynum);
> > + if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum -
> > 1].master,
> > + &rsp, sizeof(rsp)) < 0) {
> > + ERROR("failed to send tty to client");
> > + goto out_close;
> > + }
> > +
> > + tty_info->pty_info[ttynum - 1].busy = fd;
> > + return 0;
> > +
> > +out_close:
> > + /* special indicator to lxc_cmd_handler() to close the fd
> > and do
> > + * related cleanup
> > + */
> > + return 1;
> > }
> >
> > -extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
> > -extern int lxc_console_callback(int, struct lxc_request *, struct
> > lxc_handler *); -extern int lxc_stop_callback(int, struct
> > lxc_request *, struct lxc_handler *); -extern int
> > lxc_state_callback(int, struct lxc_request *, struct lxc_handler
> > *); -extern int lxc_pid_callback(int, struct lxc_request *, struct
> > lxc_handler *); -extern int lxc_clone_flags_callback(int, struct
> > lxc_request *, struct lxc_handler *); -extern int
> > lxc_cgroup_callback(int, struct lxc_request *, struct lxc_handler
> > *); -static int trigger_command(int fd, struct lxc_request
> > *request, + +static int lxc_cmd_process(int fd, struct lxc_cmd_req
> > *req, 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,
> > - [LXC_COMMAND_STOP] = lxc_stop_callback,
> > - [LXC_COMMAND_STATE] = lxc_state_callback,
> > - [LXC_COMMAND_PID] = lxc_pid_callback,
> > - [LXC_COMMAND_CLONE_FLAGS] =
> > lxc_clone_flags_callback,
> > - [LXC_COMMAND_CGROUP] = lxc_cgroup_callback,
> > + typedef int (*callback)(int, struct lxc_cmd_req *, struct
> > lxc_handler *); +
> > + callback cb[LXC_CMD_MAX] = {
> > + [LXC_CMD_CONSOLE] =
> > lxc_cmd_console_callback,
> > + [LXC_CMD_STOP] = lxc_cmd_stop_callback,
> > + [LXC_CMD_GET_STATE] =
> > lxc_cmd_get_state_callback,
> > + [LXC_CMD_GET_INIT_PID] =
> > lxc_cmd_get_init_pid_callback,
> > + [LXC_CMD_GET_CLONE_FLAGS] =
> > lxc_cmd_get_clone_flags_callback,
> > + [LXC_CMD_GET_CGROUP] =
> > lxc_cmd_get_cgroup_callback,
> > + [LXC_CMD_GET_CONFIG_ITEM] =
> > lxc_cmd_get_config_item_callback, };
> >
> > - if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
> > + if (req->cmd < 0 || req->cmd >= LXC_CMD_MAX) {
> > + ERROR("bad cmd %d recieved", req->cmd);
> > return -1;
> > -
> > - return cb[request->type](fd, request, handler);
> > + }
> > + return cb[req->cmd](fd, req, handler);
> > }
> >
> > -static void command_fd_cleanup(int fd, struct lxc_handler *handler,
> > +static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
> > struct lxc_epoll_descr *descr)
> > {
> > + extern void lxc_console_remove_fd(int, struct lxc_tty_info
> > *); lxc_console_remove_fd(fd, &handler->conf->tty_info);
> > lxc_mainloop_del_handler(descr, fd);
> > close(fd);
> > }
> >
> > -static int command_handler(int fd, void *data, struct
> > lxc_epoll_descr *descr) +static int lxc_cmd_handler(int fd, void
> > *data, struct lxc_epoll_descr *descr) {
> > int ret;
> > - struct lxc_request request;
> > + struct lxc_cmd_req req;
> > struct lxc_handler *handler = data;
> >
> > - ret = lxc_af_unix_rcv_credential(fd, &request,
> > sizeof(request));
> > + ret = lxc_af_unix_rcv_credential(fd, &req, sizeof(req));
> > if (ret == -EACCES) {
> > /* we don't care for the peer, just send and close
> > */
> > - struct lxc_answer answer = { .ret = ret };
> > - send(fd, &answer, sizeof(answer), 0);
> > + struct lxc_cmd_rsp rsp = { .ret = ret };
> > +
> > + lxc_cmd_rsp_send(fd, &rsp);
> > goto out_close;
> > }
> >
> > @@ -269,12 +693,32 @@ static int command_handler(int fd, void
> > *data, struct lxc_epoll_descr *descr) goto out_close;
> > }
> >
> > - if (ret != sizeof(request)) {
> > + if (ret != sizeof(req)) {
> > WARN("partial request, ignored");
> > + ret = -1;
> > + goto out_close;
> > + }
> > +
> > + if (req.datalen > LXC_CMD_DATA_MAX) {
> > + ERROR("cmd data length %d too large", req.datalen);
> > + ret = -1;
> > goto out_close;
> > }
> >
> > - ret = trigger_command(fd, &request, handler);
> > + if (req.datalen > 0) {
> > + void *reqdata;
> > +
> > + reqdata = alloca(req.datalen);
> > + ret = recv(fd, reqdata, req.datalen, 0);
> > + if (ret != req.datalen) {
> > + WARN("partial request, ignored");
> > + ret = -1;
> > + goto out_close;
> > + }
> > + req.data = reqdata;
> > + }
> > +
> > + ret = lxc_cmd_process(fd, &req, handler);
> > if (ret) {
> > /* this is not an error, but only a request to
> > close fd */ ret = 0;
> > @@ -284,12 +728,11 @@ static int command_handler(int fd, void
> > *data, struct lxc_epoll_descr *descr) out:
> > return ret;
> > out_close:
> > - command_fd_cleanup(fd, handler, descr);
> > + lxc_cmd_fd_cleanup(fd, handler, descr);
> > goto out;
> > }
> >
> > -static int incoming_command_handler(int fd, void *data,
> > - struct lxc_epoll_descr *descr)
> > +static int lxc_cmd_accept(int fd, void *data, struct
> > lxc_epoll_descr *descr) {
> > int opt = 1, ret = -1, connection;
> >
> > @@ -310,7 +753,7 @@ static int incoming_command_handler(int fd,
> > void *data, goto out_close;
> > }
> >
> > - ret = lxc_mainloop_add_handler(descr, connection,
> > command_handler, data);
> > + ret = lxc_mainloop_add_handler(descr, connection,
> > lxc_cmd_handler, data); if (ret) {
> > ERROR("failed to add handler");
> > goto out_close;
> > @@ -324,8 +767,8 @@ out_close:
> > goto out;
> > }
> >
> > -extern int lxc_command_init(const char *name, struct lxc_handler
> > *handler,
> > - const char *lxcpath)
> > +int lxc_cmd_init(const char *name, struct lxc_handler *handler,
> > + const char *lxcpath)
> > {
> > int fd;
> > char path[sizeof(((struct sockaddr_un *)0)->sun_path)] =
> > { 0 }; @@ -357,14 +800,13 @@ extern int lxc_command_init(const char
> > *name, struct lxc_handler *handler, return 0;
> > }
> >
> > -extern int lxc_command_mainloop_add(const char *name,
> > - struct lxc_epoll_descr *descr,
> > - struct lxc_handler *handler)
> > +int lxc_cmd_mainloop_add(const char *name,
> > + struct lxc_epoll_descr *descr,
> > + struct lxc_handler *handler)
> > {
> > int ret, fd = handler->conf->maincmd_fd;
> >
> > - ret = lxc_mainloop_add_handler(descr, fd,
> > incoming_command_handler,
> > - handler);
> > + ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept,
> > handler); if (ret) {
> > ERROR("failed to add handler for command socket");
> > close(fd);
> > diff --git a/src/lxc/commands.h b/src/lxc/commands.h
> > index 3b725fb..b5b4788 100644
> > --- a/src/lxc/commands.h
> > +++ b/src/lxc/commands.h
> > @@ -20,52 +20,67 @@
> > * License along with this library; if not, write to the Free
> > Software
> > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> > 02111-1307 USA */
> > +
> > #ifndef __commands_h
> > #define __commands_h
> >
> > -enum {
> > - LXC_COMMAND_TTY,
> > - LXC_COMMAND_STOP,
> > - LXC_COMMAND_STATE,
> > - LXC_COMMAND_PID,
> > - LXC_COMMAND_CLONE_FLAGS,
> > - LXC_COMMAND_CGROUP,
> > - LXC_COMMAND_MAX,
> > -};
> > +#include "state.h"
> > +
> > +#define LXC_CMD_DATA_MAX (MAXPATHLEN*2)
> > +
> > +/*
> > https://developer.gnome.org/glib/2.28/glib-Type-Conversion-Macros.html
> > */ +#define INT_TO_PTR(n) ((void *) (long) (n)) +#define
> > PTR_TO_INT(p) ((int) (long) (p)) +
> > +typedef enum {
> > + LXC_CMD_CONSOLE,
> > + LXC_CMD_STOP,
> > + LXC_CMD_GET_STATE,
> > + LXC_CMD_GET_INIT_PID,
> > + LXC_CMD_GET_CLONE_FLAGS,
> > + LXC_CMD_GET_CGROUP,
> > + LXC_CMD_GET_CONFIG_ITEM,
> > + LXC_CMD_MAX,
> > +} lxc_cmd_t;
> >
> > -struct lxc_request {
> > - int type;
> > - int data;
> > +struct lxc_cmd_req {
> > + lxc_cmd_t cmd;
> > + int datalen;
> > + const void *data;
> > };
> >
> > -struct lxc_answer {
> > - int fd;
> > +struct lxc_cmd_rsp {
> > int ret; /* 0 on success, -errno on failure */
> > - pid_t pid;
> > - int pathlen;
> > - const char *path;
> > + int datalen;
> > + void *data;
> > };
> >
> > -struct lxc_command {
> > - struct lxc_request request;
> > - struct lxc_answer answer;
> > +struct lxc_cmd_rr {
> > + struct lxc_cmd_req req;
> > + struct lxc_cmd_rsp rsp;
> > };
> >
> > -extern pid_t get_init_pid(const char *name, const char *lxcpath);
> > -extern int lxc_get_clone_flags(const char *name, const char
> > *lxcpath); -
> > -extern int lxc_command(const char *name, struct lxc_command
> > *command,
> > - int *stopped, const char *lxcpath);
> > +struct lxc_cmd_console_rsp_data {
> > + int fd;
> > + int ttynum;
> > +};
> >
> > -extern int lxc_command_connected(const char *name, struct
> > lxc_command *command,
> > - int *stopped, const char
> > *lxcpath); +extern int lxc_cmd_console(const char *name, int
> > *ttynum, int *fd,
> > + const char *lxcpath);
> > +extern char *lxc_cmd_get_cgroup_path(const char *subsystem,
> > + const char *name, const char
> > *lxcpath); +extern int lxc_cmd_get_clone_flags(const char *name,
> > const char *lxcpath); +extern char *lxc_cmd_get_config_item(const
> > char *name, const char *item, const char *lxcpath); +extern pid_t
> > lxc_cmd_get_init_pid(const char *name, const char *lxcpath);
> > +extern lxc_state_t lxc_cmd_get_state(const char *name, const char
> > *lxcpath); +extern int lxc_cmd_stop(const char *name, const char
> > *lxcpath); struct lxc_epoll_descr;
> > struct lxc_handler;
> >
> > -extern int lxc_command_init(const char *name, struct lxc_handler
> > *handler, +extern int lxc_cmd_init(const char *name, struct
> > lxc_handler *handler, const char *lxcpath);
> > -extern int lxc_command_mainloop_add(const char *name, struct
> > lxc_epoll_descr *descr, +extern int lxc_cmd_mainloop_add(const char
> > *name, struct lxc_epoll_descr *descr, struct lxc_handler *handler);
> >
> > -#endif
> > +#endif /* __commands_h */
> > diff --git a/src/lxc/console.c b/src/lxc/console.c
> > index 9ef62c1..93c16b5 100644
> > --- a/src/lxc/console.c
> > +++ b/src/lxc/console.c
> > @@ -46,49 +46,6 @@
> >
> > lxc_log_define(lxc_console, lxc);
> >
> > -extern int lxc_console(const char *name, int ttynum, int *fd,
> > const char *lxcpath) -{
> > - int ret, stopped = 0;
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_TTY, .data =
> > ttynum },
> > - };
> > -
> > - ret = lxc_command_connected(name, &command, &stopped,
> > lxcpath);
> > - if (ret < 0 && stopped) {
> > - ERROR("'%s' is stopped", name);
> > - return -1;
> > - }
> > -
> > - if (ret < 0) {
> > - ERROR("failed to send command");
> > - return -1;
> > - }
> > -
> > - if (!ret) {
> > - ERROR("console denied by '%s'", name);
> > - return -1;
> > - }
> > -
> > - if (command.answer.ret) {
> > - ERROR("console access denied: %s",
> > - strerror(-command.answer.ret));
> > - return -1;
> > - }
> > -
> > - *fd = command.answer.fd;
> > - if (*fd <0) {
> > - ERROR("unable to allocate fd for tty %d", ttynum);
> > - return -1;
> > - }
> > -
> > - 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;
> > @@ -104,47 +61,6 @@ extern void lxc_console_remove_fd(int fd,
> > struct lxc_tty_info *tty_info) 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->conf->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 get_default_console(char **console)
> > {
> > int fd;
> > diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
> > index 9057757..8491ff3 100644
> > --- a/src/lxc/lxc.h
> > +++ b/src/lxc/lxc.h
> > @@ -52,14 +52,6 @@ extern int lxc_start(const char *name, char
> > *const argv[], struct lxc_conf *conf const char *lxcpath);
> >
> > /*
> > - * Stop the container previously started with lxc_start, all
> > - * the processes running inside this container will be killed.
> > - * @name : the name of the container
> > - * Returns 0 on success, < 0 otherwise
> > - */
> > -extern int lxc_stop(const char *name, const char *lxcpath);
> > -
> > -/*
> > * Start the specified command inside an application container
> > * @name : the name of the container
> > * @argv : an array of char * corresponding to the commande
> > line diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
> > index e0c253b..efa7d89 100644
> > --- a/src/lxc/lxc_attach.c
> > +++ b/src/lxc/lxc_attach.c
> > @@ -296,7 +296,7 @@ int main(int argc, char *argv[])
> > if (ret)
> > return ret;
> >
> > - init_pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
> > + init_pid = lxc_cmd_get_init_pid(my_args.name,
> > my_args.lxcpath[0]); if (init_pid < 0) {
> > ERROR("failed to get the init pid");
> > return -1;
> > @@ -314,7 +314,7 @@ int main(int argc, char *argv[])
> > * by asking lxc-start
> > */
> > if (namespace_flags == -1) {
> > - namespace_flags =
> > lxc_get_clone_flags(my_args.name, my_args.lxcpath[0]);
> > + namespace_flags =
> > lxc_cmd_get_clone_flags(my_args.name, my_args.lxcpath[0]); /* call
> > failed */ if (namespace_flags == -1) {
> > ERROR("failed to automatically determine
> > the " diff --git a/src/lxc/lxc_console.c b/src/lxc/lxc_console.c
> > index 795b54c..820794a 100644
> > --- a/src/lxc/lxc_console.c
> > +++ b/src/lxc/lxc_console.c
> > @@ -43,6 +43,7 @@
> > #include "log.h"
> > #include "mainloop.h"
> > #include "arguments.h"
> > +#include "commands.h"
> >
> > lxc_log_define(lxc_console_ui, lxc_console);
> >
> > @@ -202,13 +203,14 @@ int main(int argc, char *argv[])
> > return -1;
> > }
> >
> > - err = lxc_console(my_args.name, my_args.ttynum, &master,
> > my_args.lxcpath[0]);
> > + err = lxc_cmd_console(my_args.name, &my_args.ttynum,
> > &master, my_args.lxcpath[0]); if (err)
> > goto out;
> >
> > fprintf(stderr, "\n\
> > -Type <Ctrl+%1$c q> to exit the console, \
> > -<Ctrl+%1$c Ctrl+%1$c> to enter Ctrl+%1$c itself\n",
> > +Connected to tty %1$d\n\
> > +Type <Ctrl+%2$c q> to exit the console, \
> > +<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n", my_args.ttynum,
> > 'a' + my_args.escape - 1);
> >
> > err = setsid();
> > diff --git a/src/lxc/lxc_info.c b/src/lxc/lxc_info.c
> > index f815b0f..f86626d 100644
> > --- a/src/lxc/lxc_info.c
> > +++ b/src/lxc/lxc_info.c
> > @@ -22,6 +22,7 @@
> > */
> > #include <stdio.h>
> > #include <stdbool.h>
> > +#include <stdlib.h>
> > #include <unistd.h>
> > #include <libgen.h>
> > #include <sys/types.h>
> > @@ -96,8 +97,13 @@ int main(int argc, char *argv[])
> > printf("state:%10s\n", lxc_state2str(ret));
> > }
> >
> > - if (pid)
> > - printf("pid:%10d\n", get_init_pid(my_args.name,
> > my_args.lxcpath[0]));
> > + if (pid) {
> > + pid_t initpid;
> > +
> > + initpid = lxc_cmd_get_init_pid(my_args.name,
> > my_args.lxcpath[0]);
> > + if (initpid >= 0)
> > + printf("pid:%10d\n", initpid);
> > + }
> >
> > return 0;
> > }
> > diff --git a/src/lxc/lxc_kill.c b/src/lxc/lxc_kill.c
> > index 9a24209..1fedf1d 100644
> > --- a/src/lxc/lxc_kill.c
> > +++ b/src/lxc/lxc_kill.c
> > @@ -76,7 +76,7 @@ int main(int argc, char *argv[], char *envp[])
> > } else
> > sig=SIGKILL;
> >
> > - pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
> > + pid = lxc_cmd_get_init_pid(my_args.name,
> > my_args.lxcpath[0]); if (pid < 0) {
> > ERROR("failed to get the init pid");
> > return -1;
> > diff --git a/src/lxc/lxc_stop.c b/src/lxc/lxc_stop.c
> > index d7c7283..0ed8ca0 100644
> > --- a/src/lxc/lxc_stop.c
> > +++ b/src/lxc/lxc_stop.c
> > @@ -29,6 +29,7 @@
> > #include <lxc/log.h>
> >
> > #include "arguments.h"
> > +#include "commands.h"
> > #include "utils.h"
> >
> > static const struct option my_longopts[] = {
> > @@ -58,5 +59,5 @@ int main(int argc, char *argv[])
> > my_args.progname, my_args.quiet,
> > my_args.lxcpath[0])) return -1;
> >
> > - return lxc_stop(my_args.name, my_args.lxcpath[0]);
> > + return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
> > }
> > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > index 23db6f2..01501e7 100644
> > --- a/src/lxc/lxccontainer.c
> > +++ b/src/lxc/lxccontainer.c
> > @@ -279,7 +279,7 @@ static pid_t lxcapi_init_pid(struct
> > lxc_container *c)
> > if (lxclock(c->slock, 0))
> > return -1;
> > - ret = get_init_pid(c->name, c->config_path);
> > + ret = lxc_cmd_get_init_pid(c->name, c->config_path);
> > lxcunlock(c->slock);
> > return ret;
> > }
> > @@ -517,7 +517,7 @@ static bool lxcapi_stop(struct lxc_container *c)
> > if (!c)
> > return false;
> >
> > - ret = lxc_stop(c->name, c->config_path);
> > + ret = lxc_cmd_stop(c->name, c->config_path);
> >
> > return ret == 0;
> > }
> > diff --git a/src/lxc/start.c b/src/lxc/start.c
> > index 692de44..d43d580 100644
> > --- a/src/lxc/start.c
> > +++ b/src/lxc/start.c
> > @@ -262,90 +262,6 @@ static int signal_handler(int fd, void *data,
> > return 1;
> > }
> >
> > -int lxc_pid_callback(int fd, struct lxc_request *request,
> > - struct lxc_handler *handler)
> > -{
> > - struct lxc_answer answer;
> > - int ret;
> > -
> > - memset(&answer, 0, sizeof(answer));
> > - answer.pid = handler->pid;
> > - answer.ret = 0;
> > -
> > - ret = send(fd, &answer, sizeof(answer), 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - return -1;
> > - }
> > -
> > - if (ret != sizeof(answer)) {
> > - ERROR("partial answer sent");
> > - return -1;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -int lxc_cgroup_callback(int fd, struct lxc_request *request,
> > - struct lxc_handler *handler)
> > -{
> > - struct lxc_answer answer;
> > - int ret;
> > -
> > - memset(&answer, 0, sizeof(answer));
> > - answer.pathlen = strlen(handler->cgroup) + 1;
> > - answer.path = handler->cgroup;
> > - answer.ret = 0;
> > -
> > - ret = send(fd, &answer, sizeof(answer), 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - return -1;
> > - }
> > -
> > - if (ret != sizeof(answer)) {
> > - ERROR("partial answer sent");
> > - return -1;
> > - }
> > -
> > - ret = send(fd, answer.path, answer.pathlen, 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - return -1;
> > - }
> > -
> > - if (ret != answer.pathlen) {
> > - ERROR("partial answer sent");
> > - return -1;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -int lxc_clone_flags_callback(int fd, struct lxc_request *request,
> > - struct lxc_handler *handler)
> > -{
> > - struct lxc_answer answer;
> > - int ret;
> > -
> > - memset(&answer, 0, sizeof(answer));
> > - answer.pid = 0;
> > - answer.ret = handler->clone_flags;
> > -
> > - ret = send(fd, &answer, sizeof(answer), 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - return -1;
> > - }
> > -
> > - if (ret != sizeof(answer)) {
> > - ERROR("partial answer sent");
> > - return -1;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > int lxc_set_state(const char *name, struct lxc_handler *handler,
> > lxc_state_t state) {
> > handler->state = state;
> > @@ -374,7 +290,7 @@ int lxc_poll(const char *name, struct
> > lxc_handler *handler) goto out_mainloop_open;
> > }
> >
> > - if (lxc_command_mainloop_add(name, &descr, handler)) {
> > + if (lxc_cmd_mainloop_add(name, &descr, handler)) {
> > ERROR("failed to add command handler to mainloop");
> > goto out_mainloop_open;
> > }
> > @@ -426,7 +342,7 @@ struct lxc_handler *lxc_init(const char *name,
> > struct lxc_conf *conf, const char goto out_free;
> > }
> >
> > - if (lxc_command_init(name, handler, lxcpath))
> > + if (lxc_cmd_init(name, handler, lxcpath))
> > goto out_free_name;
> >
> > if (lxc_read_seccomp_config(conf) != 0) {
> > diff --git a/src/lxc/state.c b/src/lxc/state.c
> > index 68ec00b..ed59535 100644
> > --- a/src/lxc/state.c
> > +++ b/src/lxc/state.c
> > @@ -103,75 +103,14 @@ fail:
> > return -1;
> > }
> >
> > -static lxc_state_t __lxc_getstate(const char *name, const char
> > *lxcpath) -{
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_STATE },
> > - };
> > -
> > - int ret, stopped = 0;
> > -
> > - ret = lxc_command(name, &command, &stopped, lxcpath);
> > - if (ret < 0 && stopped)
> > - return STOPPED;
> > -
> > - if (ret < 0) {
> > - ERROR("failed to send command");
> > - return -1;
> > - }
> > -
> > - if (!ret) {
> > - WARN("'%s' has stopped before sending its state",
> > name);
> > - return -1;
> > - }
> > -
> > - if (command.answer.ret < 0) {
> > - ERROR("failed to get state for '%s': %s",
> > - name, strerror(-command.answer.ret));
> > - return -1;
> > - }
> > -
> > - DEBUG("'%s' is in '%s' state", name,
> > lxc_state2str(command.answer.ret)); -
> > - return command.answer.ret;
> > -}
> > -
> > lxc_state_t lxc_getstate(const char *name, const char *lxcpath)
> > {
> > lxc_state_t state = freezer_state(name, lxcpath);
> > if (state != FROZEN && state != FREEZING)
> > - state = __lxc_getstate(name, lxcpath);
> > + state = lxc_cmd_get_state(name, lxcpath);
> > return state;
> > }
> >
> > -/*----------------------------------------------------------------------------
> > - * functions used by lxc-start mainloop
> > - * to handle above command request.
> > -
> > *--------------------------------------------------------------------------*/
> > -extern int lxc_state_callback(int fd, struct lxc_request *request,
> > - struct lxc_handler *handler)
> > -{
> > - struct lxc_answer answer;
> > - int ret;
> > -
> > - memset(&answer, 0, sizeof(answer));
> > - answer.ret = handler->state;
> > -
> > - ret = send(fd, &answer, sizeof(answer), 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - goto out;
> > - }
> > -
> > - if (ret != sizeof(answer)) {
> > - ERROR("partial answer sent");
> > - goto out;
> > - }
> > -
> > -out:
> > - return ret;
> > -}
> > -
> > static int fillwaitedstates(const char *strstates, int *states)
> > {
> > char *token, *saveptr = NULL;
> > diff --git a/src/lxc/stop.c b/src/lxc/stop.c
> > deleted file mode 100644
> > index 4fb4480..0000000
> > --- a/src/lxc/stop.c
> > +++ /dev/null
> > @@ -1,115 +0,0 @@
> > -/*
> > - * lxc: linux Container library
> > - *
> > - * (C) Copyright IBM Corp. 2007, 2008
> > - *
> > - * Authors:
> > - * Daniel Lezcano <daniel.lezcano at free.fr>
> > - *
> > - * 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 <stdlib.h>
> > -#include <string.h>
> > -#include <errno.h>
> > -#include <unistd.h>
> > -#include <sys/param.h>
> > -#include <signal.h>
> > -#include <sys/types.h>
> > -#include <sys/stat.h>
> > -#include <sys/socket.h>
> > -#include <fcntl.h>
> > -
> > -#include <lxc/log.h>
> > -#include <lxc/start.h>
> > -#include <lxc/conf.h>
> > -
> > -#include "lxc.h"
> > -#include "commands.h"
> > -
> > -lxc_log_define(lxc_stop, lxc);
> > -
> > -int lxc_stop(const char *name, const char *lxcpath)
> > -{
> > - struct lxc_command command = {
> > - .request = { .type = LXC_COMMAND_STOP },
> > - };
> > -
> > - int ret, stopped = 0;
> > -
> > - ret = lxc_command(name, &command,&stopped, lxcpath);
> > - if (ret < 0 && stopped) {
> > - INFO("'%s' is already stopped", name);
> > - return 0;
> > - }
> > -
> > - if (ret < 0) {
> > - ERROR("failed to send command");
> > - return -1;
> > - }
> > -
> > - /* we do not expect any answer, because we wait for the
> > connection to be
> > - * closed
> > - */
> > - if (ret > 0) {
> > - ERROR("failed to stop '%s': %s",
> > - name, strerror(-command.answer.ret));
> > - return -1;
> > - }
> > -
> > - INFO("'%s' has stopped", name);
> > -
> > - return 0;
> > -}
> > -
> > -/*----------------------------------------------------------------------------
> > - * functions used by lxc-start mainloop
> > - * to handle above command request.
> > -
> > *--------------------------------------------------------------------------*/
> > -extern int lxc_stop_callback(int fd, struct lxc_request *request,
> > - struct lxc_handler *handler)
> > -{
> > - struct lxc_answer answer;
> > - int ret;
> > - int stopsignal = SIGKILL;
> > -
> > - if (handler->conf->stopsignal)
> > - stopsignal = handler->conf->stopsignal;
> > - memset(&answer, 0, sizeof(answer));
> > - answer.ret = kill(handler->pid, stopsignal);
> > - if (!answer.ret) {
> > - ret = lxc_unfreeze_bypath(handler->cgroup);
> > - if (!ret)
> > - return 0;
> > -
> > - ERROR("failed to unfreeze container");
> > - answer.ret = ret;
> > - }
> > -
> > - ret = send(fd, &answer, sizeof(answer), 0);
> > - if (ret < 0) {
> > - WARN("failed to send answer to the peer");
> > - goto out;
> > - }
> > -
> > - if (ret != sizeof(answer)) {
> > - ERROR("partial answer sent");
> > - goto out;
> > - }
> > -
> > -out:
> > - return -1;
> > -}
> > -
> > diff --git a/src/tests/cgpath.c b/src/tests/cgpath.c
> > index d8c3624..b7f0885 100644
> > --- a/src/tests/cgpath.c
> > +++ b/src/tests/cgpath.c
> > @@ -137,7 +137,8 @@ int main()
> > }
> >
> > const char *dirpath;
> > - if (lxc_get_cgpath(&dirpath, NULL, c2->name,
> > c2->config_path) < 0) {
> > + dirpath = lxc_cmd_get_cgroup_path(NULL, c2->name,
> > c2->config_path);
> > + if (!dirpath) {
> > TSTERR("getting second container's cgpath");
> > goto out;
> > }
> > @@ -150,6 +151,8 @@ int main()
> >
> > retv = 0;
> > out:
> > + if (dirpath)
> > + free(dirpath);
> > if (c2) {
> > c2->stop(c2);
> > c2->destroy(c2);
> > --
> > 1.8.1.4
> >
> >
> > ------------------------------------------------------------------------------
> > AlienVault Unified Security Management (USM) platform delivers
> > complete security visibility with the essential security
> > capabilities. Easily and efficiently configure, manage, and operate
> > all of your security controls from a single console and one unified
> > framework. Download a free trial. http://p.sf.net/sfu/alienvault_d2d
> > _______________________________________________
> > Lxc-devel mailing list
> > Lxc-devel at lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-devel
mailing list