Quoting Dwight Engen (dwight.en...@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.en...@oracle.com>

Working great on my box - thanks.

Acked-by: Serge E. Hallyn <serge.hal...@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')

> ---
>  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@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to