From 791e7a73a9bca8dbde19afb49f172a901ce0dd43 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 12 Jan 2018 15:31:03 +0100 Subject: [PATCH] tools: move lxc-execute to API symbols only Closes #2073. Signed-off-by: Christian Brauner --- src/lxc/Makefile.am | 14 +-- src/lxc/tools/arguments.c | 7 +- src/lxc/tools/lxc_execute.c | 65 +++++++---- src/lxc/tools/tool_utils.c | 215 ++++++++++++++++++++++++++++++++++-- src/lxc/tools/tool_utils.h | 14 +++ 5 files changed, 275 insertions(+), 40 deletions(-) diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index d7043e01b..7908f20ca 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -269,13 +269,13 @@ endif LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c -lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c -lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c -lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c -lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c -lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c -lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c -lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c +lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c tools/tool_utils.c +lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c tools/tool_utils.c +lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c tools/tool_utils.c +lxc_console_SOURCES = tools/lxc_console.c tools/arguments.c tools/tool_utils.c +lxc_destroy_SOURCES = tools/lxc_destroy.c tools/arguments.c tools/tool_utils.c +lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c tools/tool_utils.c +lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c tools/tool_utils.c lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c diff --git a/src/lxc/tools/arguments.c b/src/lxc/tools/arguments.c index f98053fec..1be7eba58 100644 --- a/src/lxc/tools/arguments.c +++ b/src/lxc/tools/arguments.c @@ -22,6 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include @@ -32,10 +33,10 @@ #include #include +#include + #include "arguments.h" -#include "utils.h" -#include "version.h" -#include "namespace.h" +#include "tool_utils.h" static int build_shortopts(const struct option *a_options, char *a_shortopts, size_t a_size) diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c index 3348d7c1c..dd58aed70 100644 --- a/src/lxc/tools/lxc_execute.c +++ b/src/lxc/tools/lxc_execute.c @@ -20,6 +20,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + #define _GNU_SOURCE #include #include @@ -35,19 +36,15 @@ #include #include "arguments.h" -#include "caps.h" -#include "conf.h" -#include "config.h" -#include "confile.h" -#include "log.h" -#include "lxc.h" -#include "start.h" -#include "utils.h" +#include "tool_list.h" +#include "tool_utils.h" static struct lxc_list defines; static int my_parser(struct lxc_arguments* args, int c, char* arg) { + int ret; + switch (c) { case 'd': args->daemonize = 1; @@ -56,7 +53,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) args->rcfile = arg; break; case 's': - return lxc_config_define_add(&defines, arg); + ret = lxc_config_define_add(&defines, arg); + if (ret < 0) + lxc_config_define_free(&defines); break; case 'u': if (lxc_safe_uint(arg, &args->uid) < 0) @@ -114,14 +113,17 @@ Options :\n\ .daemonize = 0, }; -static bool set_argv(struct lxc_conf *conf, struct lxc_arguments *args) +static bool set_argv(struct lxc_container *c, struct lxc_arguments *args) { + int ret; + char buf[TOOL_MAXPATHLEN]; char **components, **p; - if (!conf->execute_cmd) + ret = c->get_config_item(c, "lxc.execute.cmd", buf, TOOL_MAXPATHLEN); + if (ret < 0) return false; - components = lxc_string_split_quoted(conf->execute_cmd); + components = lxc_string_split_quoted(buf); if (!components) return false; @@ -156,7 +158,6 @@ int main(int argc, char *argv[]) if (lxc_log_init(&log)) exit(EXIT_FAILURE); - lxc_log_options_no_override(); /* REMOVE IN LXC 3.0 */ setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0); @@ -189,24 +190,50 @@ int main(int argc, char *argv[]) } if (my_args.argc == 0) { - if (!set_argv(c->lxc_conf, &my_args)) { + if (!set_argv(c, &my_args)) { fprintf(stderr, "missing command to execute!\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } - ret = lxc_config_define_load(&defines, c->lxc_conf); + ret = lxc_config_define_load(&defines, c); if (ret) { lxc_container_put(c); exit(EXIT_FAILURE); } - if (my_args.uid) - c->lxc_conf->init_uid = my_args.uid; + if (my_args.uid) { + char buf[256]; + + ret = snprintf(buf, 256, "%d", my_args.uid); + if (ret < 0 || (size_t)ret >= 256) { + lxc_container_put(c); + exit(EXIT_FAILURE); + } + + ret = c->set_config_item(c, "lxc.init.uid", buf); + if (ret < 0) { + lxc_container_put(c); + exit(EXIT_FAILURE); + } + } + + if (my_args.gid) { + char buf[256]; - if (my_args.gid) - c->lxc_conf->init_gid = my_args.gid; + ret = snprintf(buf, 256, "%d", my_args.gid); + if (ret < 0 || (size_t)ret >= 256) { + lxc_container_put(c); + exit(EXIT_FAILURE); + } + + ret = c->set_config_item(c, "lxc.init.gid", buf); + if (ret < 0) { + lxc_container_put(c); + exit(EXIT_FAILURE); + } + } if (!lxc_setup_shared_ns(&my_args, c)) { lxc_container_put(c); diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c index 42be4d249..b1557a18e 100644 --- a/src/lxc/tools/tool_utils.c +++ b/src/lxc/tools/tool_utils.c @@ -131,17 +131,6 @@ signed long lxc_config_parse_arch(const char *arch) return -1; } -enum { - LXC_NS_USER, - LXC_NS_MNT, - LXC_NS_PID, - LXC_NS_UTS, - LXC_NS_IPC, - LXC_NS_NET, - LXC_NS_CGROUP, - LXC_NS_MAX -}; - const static struct ns_info { const char *proc_name; int clone_flag; @@ -630,3 +619,207 @@ bool switch_to_ns(pid_t pid, const char *ns) { close(fd); return true; } + +static bool complete_word(char ***result, char *start, char *end, size_t *cap, size_t *cnt) +{ + int r; + + r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16); + if (r < 0) + return false; + (*result)[*cnt] = strndup(start, end - start); + if (!(*result)[*cnt]) + return false; + (*cnt)++; + + return true; +} + +/* + * Given a a string 'one two "three four"', split into three words, + * one, two, and "three four" + */ +char **lxc_string_split_quoted(char *string) +{ + char *nextword = string, *p, state; + char **result = NULL; + size_t result_capacity = 0; + size_t result_count = 0; + + if (!string || !*string) + return calloc(1, sizeof(char *)); + + // TODO I'm *not* handling escaped quote + state = ' '; + for (p = string; *p; p++) { + switch(state) { + case ' ': + if (isspace(*p)) + continue; + else if (*p == '"' || *p == '\'') { + nextword = p; + state = *p; + continue; + } + nextword = p; + state = 'a'; + continue; + case 'a': + if (isspace(*p)) { + complete_word(&result, nextword, p, &result_capacity, &result_count); + state = ' '; + continue; + } + continue; + case '"': + case '\'': + if (*p == state) { + complete_word(&result, nextword+1, p, &result_capacity, &result_count); + state = ' '; + continue; + } + continue; + } + } + + if (state == 'a') + complete_word(&result, nextword, p, &result_capacity, &result_count); + + return realloc(result, (result_count + 1) * sizeof(char *)); +} + +int lxc_char_left_gc(const char *buffer, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + if (buffer[i] == ' ' || + buffer[i] == '\t') + continue; + return i; + } + return 0; +} + +int lxc_char_right_gc(const char *buffer, size_t len) +{ + int i; + for (i = len - 1; i >= 0; i--) { + if (buffer[i] == ' ' || + buffer[i] == '\t' || + buffer[i] == '\n' || + buffer[i] == '\0') + continue; + return i + 1; + } + return 0; +} + +struct new_config_item *parse_line(char *buffer) +{ + char *dot, *key, *line, *linep, *value; + int ret = 0; + char *dup = buffer; + struct new_config_item *new = NULL; + + linep = line = strdup(dup); + if (!line) + return NULL; + + line += lxc_char_left_gc(line, strlen(line)); + + /* martian option - don't add it to the config itself */ + if (strncmp(line, "lxc.", 4)) + goto on_error; + + ret = -1; + dot = strchr(line, '='); + if (!dot) { + fprintf(stderr, "Invalid configuration item: %s\n", line); + goto on_error; + } + + *dot = '\0'; + value = dot + 1; + + key = line; + key[lxc_char_right_gc(key, strlen(key))] = '\0'; + + value += lxc_char_left_gc(value, strlen(value)); + value[lxc_char_right_gc(value, strlen(value))] = '\0'; + + if (*value == '\'' || *value == '\"') { + size_t len; + + len = strlen(value); + if (len > 1 && value[len - 1] == *value) { + value[len - 1] = '\0'; + value++; + } + } + + ret = -1; + new = malloc(sizeof(struct new_config_item)); + if (!new) + goto on_error; + + new->key = strdup(key); + new->val = strdup(value); + if (!new->val || !new->key) + goto on_error; + ret = 0; + +on_error: + free(linep); + if (ret < 0 && new) { + free(new->key); + free(new->val); + free(new); + new = NULL; + } + + return new; +} + +int lxc_config_define_add(struct lxc_list *defines, char *arg) +{ + struct lxc_list *dent; + + dent = malloc(sizeof(struct lxc_list)); + if (!dent) + return -1; + + dent->elem = parse_line(arg); + if (!dent->elem) + return -1; + lxc_list_add_tail(defines, dent); + return 0; +} + +int lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c) +{ + struct lxc_list *it; + int ret = 0; + + lxc_list_for_each(it, defines) { + struct new_config_item *new_item = it->elem; + ret = c->set_config_item(c, new_item->key, new_item->val); + if (ret < 0) + break; + } + + lxc_config_define_free(defines); + return ret; +} + +void lxc_config_define_free(struct lxc_list *defines) +{ + struct lxc_list *it, *next; + + lxc_list_for_each_safe(it, defines, next) { + struct new_config_item *new_item = it->elem; + free(new_item->key); + free(new_item->val); + lxc_list_del(it); + free(it); + } +} diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h index e6d922f3a..5d1e8d3e3 100644 --- a/src/lxc/tools/tool_utils.h +++ b/src/lxc/tools/tool_utils.h @@ -138,6 +138,7 @@ extern char **lxc_string_split(const char *string, char _sep); extern char **lxc_normalize_path(const char *path); extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix); +extern char **lxc_string_split_quoted(char *string); extern int mkdir_p(const char *dir, mode_t mode); extern bool file_exists(const char *f); @@ -147,4 +148,17 @@ extern char *get_template_path(const char *t); extern bool switch_to_ns(pid_t pid, const char *ns); +extern int lxc_config_define_add(struct lxc_list *defines, char *arg); +extern int lxc_config_define_load(struct lxc_list *defines, + struct lxc_container *c); +extern void lxc_config_define_free(struct lxc_list *defines); +extern int lxc_char_left_gc(const char *buffer, size_t len); +extern int lxc_char_right_gc(const char *buffer, size_t len); + +struct new_config_item { + char *key; + char *val; +}; +extern struct new_config_item *parse_line(char *buffer); + #endif /* __LXC_UTILS_H */ -- 2.47.2