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