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