]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
extend command processor to handle generic data
authorDwight Engen <dwight.engen@oracle.com>
Fri, 17 May 2013 22:29:12 +0000 (18:29 -0400)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Tue, 21 May 2013 15:16:00 +0000 (10:16 -0500)
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@oracle.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
17 files changed:
src/lxc/Makefile.am
src/lxc/cgroup.c
src/lxc/cgroup.h
src/lxc/commands.c
src/lxc/commands.h
src/lxc/console.c
src/lxc/lxc.h
src/lxc/lxc_attach.c
src/lxc/lxc_console.c
src/lxc/lxc_info.c
src/lxc/lxc_kill.c
src/lxc/lxc_stop.c
src/lxc/lxccontainer.c
src/lxc/start.c
src/lxc/state.c
src/lxc/stop.c [deleted file]
src/tests/cgpath.c

index 4a19061017c81e7ec91a67a7faeebbf405120a4d..f8eb41b8db62eb4d83a45386e3cbede1cb7996e6 100644 (file)
@@ -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 \
index c2f0a2da45437c1ccaa496cf3cce6eba30cdf903..44266de622736d9b49188245730ad7d7f3d53458 100644 (file)
@@ -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;
@@ -214,56 +214,10 @@ fail:
        return -1;
 }
 
-/*
- * 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;
 }
index 937b9c92fbe6653e6cf1b595f786b82ca361e75d..971311ece2ec4698d1455183a48e3d2a811d1cf8 100644 (file)
@@ -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
index d45ae21122751051a068f0cdd35a6fa0dd4d4479..3f2148858d54ba36115fc564dff24a296eb4ef9d 100644 (file)
 #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);
index 3b725fbbf818f2c0bafe8fd9346b85e83187c1d3..b5b478878d201cfba9d66a7583d53803f361066a 100644 (file)
  * 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 */
index 9ef62c1024843721ef2bb4327887f2b80aa6911f..93c16b5faa65e549e7d1a5c6a7fbe98ed590013d 100644 (file)
 
 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;
index 9057757c520af4bd023d02b0b3b179ad89132a8f..8491ff3dac6f3accb628c6a39ed87881f239deeb 100644 (file)
@@ -51,14 +51,6 @@ struct lxc_arguments;
 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
index e0c253b4b81ac6920fdca97a3c2d61140c7b3b75..efa7d89da21145cba08c6c71bfbac44ee8f7541f 100644 (file)
@@ -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 "
index 795b54c245481a3bdae6638612127e89cf8f5472..820794ab961aa68156c4eff86dc25d477f27e55d 100644 (file)
@@ -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();
index f815b0f47a00d7cccb914f3db155ce2f1eec87f1..f86626d9787e5044f6e6a0ebeb900cadfcaa8704 100644 (file)
@@ -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;
 }
index 9a24209dd619a088eda93618a07baf899c8012ae..1fedf1d085eeccb9bf54fb4699a31779d646d69a 100644 (file)
@@ -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;
index d7c7283736d9c1b9371f77dbfa0d4bcee41b278a..0ed8ca06658c628969eeeb6daab0fb986bd68b68 100644 (file)
@@ -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]);
 }
index 4a6f774b2dd156d0da5f3ab83b39f346c84ea7dd..7ce25c6d85be25c29b9697f0bb845530c77e184a 100644 (file)
@@ -283,7 +283,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;
 }
@@ -521,7 +521,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;
 }
index 692de44590d4ad498730f1534f402f99138616fd..d43d580731904548b4e88a3495c0ffca8ff6d5b7 100644 (file)
@@ -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) {
index 68ec00ba012b12b997dc46f5d091a64f333a2072..ed595351157925a41f483fb7682d6b32bdc27817 100644 (file)
@@ -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 (file)
index 4fb4480..0000000
+++ /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;
-}
-
index d8c36248ed934fbee11a4c4b5fca69476f6f489e..b7f08856336ca21becb03d7701b8a008912aec7c 100644 (file)
@@ -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);