#include "securebits.h"
#include "missing.h"
#include "unit-name.h"
+#include "bus-errors.h"
#define COMMENTS "#;\n"
-#define LINE_MAX 4096
-
-#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
- static int function( \
- const char *filename, \
- unsigned line, \
- const char *section, \
- const char *lvalue, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
- type *i = data, x; \
- \
- assert(filename); \
- assert(lvalue); \
- assert(rvalue); \
- assert(data); \
- \
- if ((x = name##_from_string(rvalue)) < 0) { \
- log_error("[%s:%u] " msg ": %s", filename, line, rvalue); \
- return -EBADMSG; \
- } \
- \
- *i = x; \
- \
- return 0; \
- }
static int config_parse_deps(
const char *filename,
assert(lvalue);
assert(rvalue);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t, *k;
int r;
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t, *k;
int r;
void *data,
void *userdata) {
- ExecCommand **e = data, *nce = NULL;
- char **n;
- char *w;
+ ExecCommand **e = data, *nce;
+ char *path, **n;
unsigned k;
- size_t l;
- char *state, *path = NULL;
- bool honour_argv0, write_to_path;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
+ assert(e);
/* We accept an absolute path as first argument, or
* alternatively an absolute prefixed with @ to allow
* overriding of argv[0]. */
- honour_argv0 = rvalue[0] == '@';
+ for (;;) {
+ char *w;
+ size_t l;
+ char *state;
+ bool honour_argv0, write_to_path;
- if (rvalue[honour_argv0 ? 1 : 0] != '/') {
- log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
- return -EINVAL;
- }
+ path = NULL;
+ nce = NULL;
+ n = NULL;
- k = 0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state)
- k++;
+ rvalue += strspn(rvalue, WHITESPACE);
- if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
- return -ENOMEM;
+ if (rvalue[0] == 0)
+ break;
- k = 0;
- write_to_path = honour_argv0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (write_to_path) {
- if (!(path = strndup(w+1, l-1)))
- goto fail;
- write_to_path = false;
- } else {
- if (!(n[k++] = strndup(w, l)))
- goto fail;
+ honour_argv0 = rvalue[0] == '@';
+
+ if (rvalue[honour_argv0 ? 1 : 0] != '/') {
+ log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
+ return -EINVAL;
}
- }
- n[k] = NULL;
+ k = 0;
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ if (strncmp(w, ";", l) == 0)
+ break;
- if (!n[0]) {
- log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
- strv_free(n);
- return -EINVAL;
- }
+ k++;
+ }
- if (!path)
- if (!(path = strdup(n[0])))
- goto fail;
+ if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
+ return -ENOMEM;
+
+ k = 0;
+ write_to_path = honour_argv0;
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ if (strncmp(w, ";", l) == 0)
+ break;
- assert(path_is_absolute(path));
+ if (write_to_path) {
+ if (!(path = cunescape_length(w+1, l-1)))
+ goto fail;
+ write_to_path = false;
+ } else {
+ if (!(n[k++] = cunescape_length(w, l)))
+ goto fail;
+ }
+ }
- if (!(nce = new0(ExecCommand, 1)))
- goto fail;
+ n[k] = NULL;
- nce->argv = n;
- nce->path = path;
+ if (!n[0]) {
+ log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
+ strv_free(n);
+ return -EINVAL;
+ }
- path_kill_slashes(nce->path);
+ if (!path)
+ if (!(path = strdup(n[0])))
+ goto fail;
- exec_command_append_list(e, nce);
+ assert(path_is_absolute(path));
+
+ if (!(nce = new0(ExecCommand, 1)))
+ goto fail;
+
+ nce->argv = n;
+ nce->path = path;
+
+ path_kill_slashes(nce->path);
+
+ exec_command_append_list(e, nce);
+
+ rvalue = state;
+ }
return 0;
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
static int config_parse_bindtodevice(
const char *filename,
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
static int config_parse_facility(
const char *filename,
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
unsigned cpu;
if (!(t = strndup(w, l)))
return -ENOMEM;
+ r = safe_atou(t, &cpu);
+ free(t);
+
if (!(c->cpuset))
if (!(c->cpuset = cpu_set_malloc(&c->cpuset_ncpus)))
return -ENOMEM;
- r = safe_atou(t, &cpu);
- free(t);
-
if (r < 0 || cpu >= c->cpuset_ncpus) {
log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
return -EBADMSG;
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (first_word(w, "keep-caps"))
c->secure_bits |= SECURE_KEEP_CAPS;
else if (first_word(w, "keep-caps-locked"))
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
cap_value_t cap;
size_t l;
char *state;
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
- if (!(t = strndup(w, l)))
+ if (!(t = cunescape_length(w, l)))
return -ENOMEM;
r = unit_add_cgroup_from_text(u, t);
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
static int config_parse_mount_flags(
const char *filename,
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strncmp(w, "shared", l) == 0)
flags |= MS_SHARED;
else if (strncmp(w, "slave", l) == 0)
Timer *t = data;
int r;
+ DBusError error;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ dbus_error_init(&error);
if (endswith(rvalue, ".timer")) {
log_error("[%s:%u] Unit cannot be of type timer: %s", filename, line, rvalue);
return -EINVAL;
}
- if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, &t->unit)) < 0) {
- log_error("[%s:%u] Failed to load unit: %s", filename, line, rvalue);
+ if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, NULL, &t->unit)) < 0) {
+ log_error("[%s:%u] Failed to load unit %s: %s", filename, line, rvalue, bus_error(&error, r));
+ dbus_error_free(&error);
return r;
}
Path *t = data;
int r;
+ DBusError error;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ dbus_error_init(&error);
if (endswith(rvalue, ".path")) {
log_error("[%s:%u] Unit cannot be of type path: %s", filename, line, rvalue);
return -EINVAL;
}
- if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, &t->unit)) < 0) {
- log_error("[%s:%u] Failed to load unit: %s", filename, line, rvalue);
+ if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, &error, &t->unit)) < 0) {
+ log_error("[%s:%u] Failed to load unit %s: %s", filename, line, rvalue, bus_error(&error, r));
+ dbus_error_free(&error);
return r;
}
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
#define FOLLOW_MAX 8