Closes #2073.
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <lxc/version.h>
+
#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)
* 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 <errno.h>
#include <libgen.h>
#include <lxc/lxccontainer.h>
#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;
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)
.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;
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);
}
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);
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;
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);
+ }
+}
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);
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 */