[systemd-devel] [PATCH 2/2] [PoC][RFC] Add issues to objects state

Oleksii Shevchuk alxchk at gmail.com
Mon Apr 1 00:17:05 PDT 2013


As for now there is no way to get important warnings (like configuration
ones) without looking to journal. For example, you make mistake in unit,
start it, that mistake ignored as non fatal, unit started and then you
kill hours to find out what is going wrong.

I have the proposition. Let's add something like strv to objects like
units or server states to collect really important data, even if logging
is absent.

Example:

> LC_ALL=C dctl status null.target
null.target - NYAN
	 Loaded: loaded (/home/avatar/.config/systemd/user/null.target; disabled)
	 Active: active since Mon 2013-04-01 10:12:46 EEST; 2s ago
  	 Issues: Warning: [/home/alxchk/.config/systemd/user/null.target:3]: Unknown lvalue 'SomeError' in section 'Unit'
  	         Warning: [/home/alxchk/.config/systemd/user/null.target.d/install.conf:3]: Unknown lvalue 'After!' in section 'Unit'
---
 src/bootchart/bootchart.c                          |   2 +-
 src/core/dbus-unit.c                               |   1 +
 src/core/load-dropin.c                             |   3 +-
 src/core/load-fragment.c                           | 301 ++++++++++++---------
 src/core/load-fragment.h                           | 100 +++----
 src/core/main.c                                    |  20 +-
 src/core/unit.c                                    |   4 +
 src/core/unit.h                                    |   2 +
 src/journal/journald-server.c                      |   8 +-
 src/journal/journald-server.h                      |   6 +-
 src/login/logind-action.h                          |   2 +-
 src/login/logind.c                                 |   2 +-
 src/shared/conf-parser.c                           | 162 ++++++-----
 src/shared/conf-parser.h                           |  56 ++--
 src/shared/install.c                               |   9 +-
 src/shared/install.h                               |   2 +
 src/systemctl/systemctl.c                          |  37 +++
 src/test/test-unit-file.c                          |  20 +-
 .../tty-ask-password-agent.c                       |   2 +-
 19 files changed, 442 insertions(+), 297 deletions(-)

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 208c452..6c068b9 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -121,7 +121,7 @@ static void parse_conf(void) {
                 return;
 
         r = config_parse(BOOTCHART_CONF, f,
-                         NULL, config_item_table_lookup, (void*) items, true, NULL);
+                         NULL, config_item_table_lookup, (void*) items, true, NULL, NULL);
         if (r < 0)
                 log_warning("Failed to parse configuration file: %s", strerror(-r));
 
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index dc7d1f1..8535a4d 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1278,6 +1278,7 @@ const BusProperty bus_unit_properties[] = {
         { "ReloadPropagatedFrom", bus_unit_append_dependencies,      "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]),  true },
         { "RequiresMountsFor",    bus_property_append_strv,          "as", offsetof(Unit, requires_mounts_for),                        true },
         { "Documentation",        bus_property_append_strv,          "as", offsetof(Unit, documentation),                              true },
+        { "Issues",               bus_property_append_strv,          "as", offsetof(Unit, issues),                                     true },
         { "Description",          bus_unit_append_description,        "s", 0 },
         { "LoadState",            bus_unit_append_load_state,         "s", offsetof(Unit, load_state)                         },
         { "ActiveState",          bus_unit_append_active_state,       "s", 0 },
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 95c9a38..7c6208d 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -178,7 +178,8 @@ int unit_load_dropin(Unit *u) {
                 }
 
                 STRV_FOREACH(f, files) {
-                        r = config_parse(*f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
+                        r = config_parse(*f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup,
+                                         (void*) load_fragment_gperf_lookup, false, u, &u->issues);
                         if (r < 0)
                                 return r;
                 }
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 65a2a39..ff69beb 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -50,6 +50,11 @@
 #include "syscall-list.h"
 #include "env-util.h"
 
+#define LOG_WARN_UNIT_SPEC(i,f,l,r)                                     \
+        log_syntax(i, f, l, false,                                      \
+                   "Failed to resolve unit specifiers on %s. Ignoring.", \
+                   r);
+
 #ifndef HAVE_SYSV_COMPAT
 int config_parse_warn_compat(
                 const char *filename,
@@ -59,9 +64,10 @@ int config_parse_warn_compat(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
-        log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue);
+        log_syntax(issues, filename, line, true, "Support for option %s= has been disabled at compile time and is ignored", lvalue);
         return 0;
 }
 #endif
@@ -74,7 +80,8 @@ int config_parse_unit_deps(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         UnitDependency d = ltype;
         Unit *u = userdata;
@@ -100,8 +107,8 @@ int config_parse_unit_deps(
 
                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
                 if (r < 0)
-                        log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
-                                  filename, line, k, strerror(-r));
+                        log_syntax(issues, filename, line, false, "Failed to add dependency on %s, ignoring: %s",
+                                  k, strerror(-r));
         }
 
         return 0;
@@ -115,7 +122,8 @@ int config_parse_unit_string_printf(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
@@ -127,10 +135,9 @@ int config_parse_unit_string_printf(
 
         k = unit_full_printf(u, rvalue);
         if (!k)
-                log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                          filename, line, rvalue);
+                LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
-        return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
+        return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata, issues);
 }
 
 int config_parse_unit_strv_printf(
@@ -141,7 +148,8 @@ int config_parse_unit_strv_printf(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
@@ -153,10 +161,9 @@ int config_parse_unit_strv_printf(
 
         k = unit_full_printf(u, rvalue);
         if (!k)
-                log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                          filename, line, rvalue);
+                LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
-        return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
+        return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata, issues);
 }
 
 int config_parse_unit_path_printf(
@@ -167,7 +174,8 @@ int config_parse_unit_path_printf(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
@@ -179,10 +187,9 @@ int config_parse_unit_path_printf(
 
         k = unit_full_printf(u, rvalue);
         if (!k)
-                log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                          filename, line, rvalue);
+                LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
-        return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
+        return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata, issues);
 }
 
 int config_parse_socket_listen(
@@ -193,7 +200,8 @@ int config_parse_socket_listen(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         SocketPort *p, *tail;
         Socket *s;
@@ -225,8 +233,7 @@ int config_parse_socket_listen(
                                 free(p);
                                 return log_oom();
                         } else
-                                log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                                          filename, line, rvalue);
+                                LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
                 }
 
                 path_kill_slashes(p->path);
@@ -238,12 +245,11 @@ int config_parse_socket_listen(
                 p->type = SOCKET_SOCKET;
                 k = unit_full_printf(UNIT(s), rvalue);
                 if (!k)
-                        log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                                  filename, line, rvalue);
+                        LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
                 if (r < 0) {
-                        log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
                 }
@@ -255,12 +261,11 @@ int config_parse_socket_listen(
                 p->type = SOCKET_SOCKET;
                 k = unit_full_printf(UNIT(s), rvalue);
                 if (!k)
-                        log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                                  filename, line, rvalue);
+                        LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
                 r = socket_address_parse(&p->address, k ? k : rvalue);
                 if (r < 0) {
-                        log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
                 }
@@ -275,7 +280,7 @@ int config_parse_socket_listen(
                 }
 
                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
-                        log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Address family not supported, ignoring: %s", rvalue);
                         free(p);
                         return 0;
                 }
@@ -300,7 +305,8 @@ int config_parse_socket_bind(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Socket *s;
         SocketAddressBindIPv6Only b;
@@ -318,7 +324,7 @@ int config_parse_socket_bind(
 
                 r = parse_boolean(rvalue);
                 if (r < 0) {
-                        log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
                         return 0;
                 }
 
@@ -337,7 +343,8 @@ int config_parse_exec_nice(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         int priority;
@@ -348,12 +355,12 @@ int config_parse_exec_nice(
         assert(data);
 
         if (safe_atoi(rvalue, &priority) < 0) {
-                log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse nice priority, ignoring: %s. ", rvalue);
                 return 0;
         }
 
         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
-                log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Nice priority out of range, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -371,7 +378,8 @@ int config_parse_exec_oom_score_adjust(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         int oa;
@@ -382,12 +390,12 @@ int config_parse_exec_oom_score_adjust(
         assert(data);
 
         if (safe_atoi(rvalue, &oa) < 0) {
-                log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
                 return 0;
         }
 
         if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
-                log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "[%s:%u] OOM score adjust value out of range, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -405,7 +413,8 @@ int config_parse_exec(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecCommand **e = data, *nce;
         char *path, **n;
@@ -458,8 +467,8 @@ int config_parse_exec(
                 }
 
                 if (*rvalue != '/') {
-                        log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
-                                  filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Executable path is not absolute, ignoring: %s",
+                                  rvalue);
                         return 0;
                 }
 
@@ -492,7 +501,7 @@ int config_parse_exec(
                                 }
 
                                 if (!utf8_is_valid(path)) {
-                                        log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
+                                        log_syntax(issues, filename, line, false, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
                                         r = 0;
                                         goto fail;
                                 }
@@ -507,7 +516,7 @@ int config_parse_exec(
                                 }
 
                                 if (!utf8_is_valid(c)) {
-                                        log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
+                                        log_syntax(issues, filename, line, false, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
                                         r = 0;
                                         goto fail;
                                 }
@@ -517,7 +526,7 @@ int config_parse_exec(
                 n[k] = NULL;
 
                 if (!n[0]) {
-                        log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Invalid command line, ignoring: %s", rvalue);
                         r = 0;
                         goto fail;
                 }
@@ -571,7 +580,8 @@ int config_parse_socket_bindtodevice(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Socket *s = data;
         char *n;
@@ -605,7 +615,8 @@ int config_parse_exec_io_class(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         int x;
@@ -617,7 +628,7 @@ int config_parse_exec_io_class(
 
         x = ioprio_class_from_string(rvalue);
         if (x < 0) {
-                log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -635,7 +646,8 @@ int config_parse_exec_io_priority(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         int i;
@@ -646,7 +658,7 @@ int config_parse_exec_io_priority(
         assert(data);
 
         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
-                log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse io priority, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -664,7 +676,8 @@ int config_parse_exec_cpu_sched_policy(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
 
         ExecContext *c = data;
@@ -677,7 +690,7 @@ int config_parse_exec_cpu_sched_policy(
 
         x = sched_policy_from_string(rvalue);
         if (x < 0) {
-                log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -697,7 +710,8 @@ int config_parse_exec_cpu_sched_prio(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         int i, min, max;
@@ -708,7 +722,7 @@ int config_parse_exec_cpu_sched_prio(
         assert(data);
 
         if (safe_atoi(rvalue, &i) < 0) {
-                log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -717,7 +731,7 @@ int config_parse_exec_cpu_sched_prio(
         max = sched_get_priority_max(c->cpu_sched_policy);
 
         if (i < min || i > max) {
-                log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "[CPU scheduling priority is out of range, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -735,7 +749,8 @@ int config_parse_exec_cpu_affinity(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         char *w;
@@ -773,7 +788,7 @@ int config_parse_exec_cpu_affinity(
                 }
 
                 if (r < 0 || cpu >= c->cpuset_ncpus) {
-                        log_error("[%s:%u] Failed to parse CPU affinity %s, ignoring: %s",
+                        log_syntax(issues, filename, line, false, "Failed to parse CPU affinity %s, ignoring: %s",
                                   filename, line, t, rvalue);
                         return 0;
                 }
@@ -792,7 +807,8 @@ int config_parse_exec_capabilities(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         cap_t cap;
@@ -807,7 +823,7 @@ int config_parse_exec_capabilities(
                 if (errno == ENOMEM)
                         return log_oom();
 
-                log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse capabilities, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -826,7 +842,8 @@ int config_parse_exec_secure_bits(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         char *w;
@@ -858,8 +875,8 @@ int config_parse_exec_secure_bits(
                 else if (first_word(w, "noroot-locked"))
                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
                 else {
-                        log_error("[%s:%u] Failed to parse secure bits, ignoring: %s",
-                                  filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse secure bits, ignoring: %s",
+                                   rvalue);
                         return 0;
                 }
         }
@@ -875,7 +892,8 @@ int config_parse_bounding_set(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         uint64_t *capability_bounding_set_drop = data;
         char *w;
@@ -910,8 +928,8 @@ int config_parse_bounding_set(
 
                 r = cap_from_name(t, &cap);
                 if (r < 0) {
-                        log_error("[%s:%u] Failed to parse capability in bounding set, ignoring: %s",
-                                  filename, line, t);
+                        log_syntax(issues, filename, line, false, "Failed to parse capability in bounding set, ignoring: %s",
+                                   t);
                         continue;
                 }
 
@@ -934,7 +952,8 @@ int config_parse_limit(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         struct rlimit **rl = data;
         unsigned long long u;
@@ -949,7 +968,7 @@ int config_parse_limit(
         if (streq(rvalue, "infinity"))
                 u = (unsigned long long) RLIM_INFINITY;
         else if (safe_atollu(rvalue, &u) < 0) {
-                log_error("[%s:%u] Failed to parse resource value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse resource value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -971,7 +990,8 @@ int config_parse_unit_cgroup(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         char *w;
@@ -995,8 +1015,7 @@ int config_parse_unit_cgroup(
 
                 k = unit_full_printf(u, t);
                 if (!k)
-                        log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                                  filename, line, t);
+                        LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
 
                 ku = cunescape(k ? k : t);
                 if (!ku)
@@ -1004,8 +1023,8 @@ int config_parse_unit_cgroup(
 
                 r = unit_add_cgroup_from_text(u, ku, true, NULL);
                 if (r < 0) {
-                        log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s",
-                                  filename, line, k, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse cgroup value %s, ignoring: %s",
+                                   k, rvalue);
                         return 0;
                 }
         }
@@ -1022,7 +1041,8 @@ int config_parse_sysv_priority(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int *priority = data;
         int i;
@@ -1033,7 +1053,7 @@ int config_parse_sysv_priority(
         assert(data);
 
         if (safe_atoi(rvalue, &i) < 0 || i < 0) {
-                log_error("[%s:%u] Failed to parse SysV start priority, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse SysV start priority, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1050,7 +1070,8 @@ int config_parse_fsck_passno(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int *passno = data;
         int i;
@@ -1061,7 +1082,7 @@ int config_parse_fsck_passno(
         assert(data);
 
         if (safe_atoi(rvalue, &i) || i < 0) {
-                log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse fsck pass number, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1079,7 +1100,8 @@ int config_parse_kill_signal(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int *sig = data;
         int r;
@@ -1091,7 +1113,7 @@ int config_parse_kill_signal(
 
         r = signal_from_string_try_harder(rvalue);
         if (r <= 0) {
-                log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse kill signal, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1107,7 +1129,8 @@ int config_parse_exec_mount_flags(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         char *w;
@@ -1134,8 +1157,8 @@ int config_parse_exec_mount_flags(
                 else if (streq(w, "private"))
                         flags |= MS_PRIVATE;
                 else {
-                        log_error("[%s:%u] Failed to parse mount flag %s, ignoring: %s",
-                                  filename, line, t, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse mount flag %s, ignoring: %s",
+                                  t, rvalue);
                         return 0;
                 }
         }
@@ -1152,7 +1175,8 @@ int config_parse_timer(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Timer *t = data;
         usec_t u = 0;
@@ -1174,20 +1198,20 @@ int config_parse_timer(
 
         b = timer_base_from_string(lvalue);
         if (b < 0) {
-                log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse timer base, ignoring: %s", lvalue);
                 return 0;
         }
 
         if (b == TIMER_CALENDAR) {
                 if (calendar_spec_from_string(rvalue, &c) < 0) {
-                        log_error("[%s:%u] Failed to parse calendar specification, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse calendar specification, ignoring: %s", rvalue);
                         return 0;
                 }
 
                 id = CLOCK_REALTIME;
         } else {
                 if (parse_usec(rvalue, &u) < 0) {
-                        log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Failed to parse timer value, ignoring: %s", rvalue);
                         return 0;
                 }
 
@@ -1216,7 +1240,8 @@ int config_parse_timer_unit(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Timer *t = data;
         int r;
@@ -1236,13 +1261,13 @@ int config_parse_timer_unit(
                 return log_oom();
 
         if (endswith(p, ".timer")) {
-                log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Unit cannot be of type timer, ignoring: %s", rvalue);
                 return 0;
         }
 
         r = manager_load_unit(UNIT(t)->manager, p, NULL, NULL, &u);
         if (r < 0) {
-                log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
+                log_syntax(issues, filename, line, false, "Failed to load unit %s, ignoring: %s", rvalue, bus_error(&error, r));
                 dbus_error_free(&error);
                 return 0;
         }
@@ -1260,7 +1285,8 @@ int config_parse_path_spec(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Path *p = data;
         PathSpec *s;
@@ -1280,7 +1306,7 @@ int config_parse_path_spec(
 
         b = path_type_from_string(lvalue);
         if (b < 0) {
-                log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse path type, ignoring: %s", lvalue);
                 return 0;
         }
 
@@ -1290,12 +1316,11 @@ int config_parse_path_spec(
                 if (!k)
                         return log_oom();
                 else
-                        log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
-                                  filename, line, rvalue);
+                        LOG_WARN_UNIT_SPEC(issues, filename, line, rvalue);
         }
 
         if (!path_is_absolute(k)) {
-                log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
+                log_syntax(issues, filename, line, false, "Path is not absolute, ignoring: %s", k);
                 free(k);
                 return 0;
         }
@@ -1323,7 +1348,8 @@ int config_parse_path_unit(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Path *t = data;
         int r;
@@ -1343,13 +1369,13 @@ int config_parse_path_unit(
                 return log_oom();
 
         if (endswith(p, ".path")) {
-                log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, p);
+                log_syntax(issues, filename, line, false, "Unit cannot be of type path, ignoring: %s", p);
                 return 0;
         }
 
         r = manager_load_unit(UNIT(t)->manager, p, NULL, &error, &u);
         if (r < 0) {
-                log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, p, bus_error(&error, r));
+                log_syntax(issues, filename, line, false, "Failed to load unit %s, ignoring: %s", p, bus_error(&error, r));
                 dbus_error_free(&error);
                 return 0;
         }
@@ -1367,7 +1393,8 @@ int config_parse_socket_service(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Socket *s = data;
         int r;
@@ -1387,13 +1414,13 @@ int config_parse_socket_service(
                 return log_oom();
 
         if (!endswith(p, ".service")) {
-                log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Unit must be of type service, ignoring: %s", rvalue);
                 return 0;
         }
 
         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
         if (r < 0) {
-                log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
+                log_syntax(issues, filename, line, false, "Failed to load unit %s, ignoring: %s", rvalue, bus_error(&error, r));
                 dbus_error_free(&error);
                 return 0;
         }
@@ -1411,7 +1438,8 @@ int config_parse_service_sockets(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Service *s = data;
         int r;
@@ -1435,15 +1463,15 @@ int config_parse_service_sockets(
                         return log_oom();
 
                 if (!endswith(k, ".socket")) {
-                        log_error("[%s:%u] Unit must be of type socket, ignoring: %s",
-                                  filename, line, k);
+                        log_syntax(issues, filename, line, false, "Unit must be of type socket, ignoring: %s",
+                                  k);
                         continue;
                 }
 
                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
                 if (r < 0)
-                        log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
-                                  filename, line, k, strerror(-r));
+                        log_syntax(issues, filename, line, false, "Failed to add dependency on %s, ignoring: %s",
+                                  k, strerror(-r));
 
                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
                 if (r < 0)
@@ -1461,7 +1489,8 @@ int config_parse_service_timeout(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Service *s = userdata;
         int r;
@@ -1471,7 +1500,7 @@ int config_parse_service_timeout(
         assert(rvalue);
         assert(s);
 
-        r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+        r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata, issues);
         if (r < 0)
                 return r;
 
@@ -1492,7 +1521,8 @@ int config_parse_unit_env_file(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char ***env = data;
         Unit *u = userdata;
@@ -1516,7 +1546,7 @@ int config_parse_unit_env_file(
                 return log_oom();
 
         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
-                log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
+                log_syntax(issues, filename, line, false, "Path '%s' is not absolute, ignoring.", s);
                 return 0;
         }
 
@@ -1535,7 +1565,8 @@ int config_parse_environ(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         char*** env = data, *w, *state;
@@ -1567,7 +1598,7 @@ int config_parse_environ(
                         return log_oom();
 
                 if (!env_assignment_is_valid(n)) {
-                        log_error("[%s:%u] Invalid environment assignment, ignoring: %s", filename, line, rvalue);
+                        log_syntax(issues, filename, line, false, "Invalid environment assignment, ignoring: %s", rvalue);
                         continue;
                 }
 
@@ -1590,7 +1621,8 @@ int config_parse_ip_tos(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int *ip_tos = data, x;
 
@@ -1601,7 +1633,7 @@ int config_parse_ip_tos(
 
         x = ip_tos_from_string(rvalue);
         if (x < 0) {
-                log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse IP TOS value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1617,7 +1649,8 @@ int config_parse_unit_condition_path(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ConditionType cond = ltype;
         Unit *u = data;
@@ -1650,7 +1683,7 @@ int config_parse_unit_condition_path(
                 return log_oom();
 
         if (!path_is_absolute(p)) {
-                log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
+                log_syntax(issues, filename, line, false, "Path in condition not absolute, ignoring: %s", p);
                 return 0;
         }
 
@@ -1670,7 +1703,8 @@ int config_parse_unit_condition_string(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ConditionType cond = ltype;
         Unit *u = data;
@@ -1718,7 +1752,8 @@ int config_parse_unit_condition_null(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = data;
         Condition *c;
@@ -1747,7 +1782,7 @@ int config_parse_unit_condition_null(
 
         b = parse_boolean(rvalue);
         if (b < 0) {
-                log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1773,7 +1808,8 @@ int config_parse_unit_cgroup_attr(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = data;
         size_t a, b;
@@ -1796,7 +1832,7 @@ int config_parse_unit_cgroup_attr(
         a = strcspn(rvalue, WHITESPACE);
         b = strspn(rvalue + a, WHITESPACE);
         if (a <= 0 || b <= 0) {
-                log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse cgroup attribute value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1806,13 +1842,13 @@ int config_parse_unit_cgroup_attr(
 
         r = cgroup_semantics_find(NULL, n, rvalue + a + b, &v, &s);
         if (r < 0) {
-                log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse cgroup attribute value, ignoring: %s", rvalue);
                 return 0;
         }
 
         r = unit_add_cgroup_attribute(u, s, NULL, n, v ? v : rvalue + a + b, NULL);
         if (r < 0) {
-                log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to add cgroup attribute value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1827,7 +1863,8 @@ int config_parse_unit_cgroup_attr_pretty(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = data;
         _cleanup_free_ char *v = NULL;
@@ -1841,16 +1878,16 @@ int config_parse_unit_cgroup_attr_pretty(
 
         r = cgroup_semantics_find(NULL, lvalue, rvalue, &v, &s);
         if (r < 0) {
-                log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to parse cgroup attribute value, ignoring: %s", rvalue);
                 return 0;
         } else if (r == 0) {
-                log_error("[%s:%u] Unknown or unsupported cgroup attribute %s, ignoring: %s", filename, line, lvalue, rvalue);
+                log_syntax(issues, filename, line, false, "Unknown or unsupported cgroup attribute %s, ignoring: %s", lvalue, rvalue);
                 return 0;
         }
 
         r = unit_add_cgroup_attribute(u, s, NULL, NULL, v, NULL);
         if (r < 0) {
-                log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
+                log_syntax(issues, filename, line, false, "Failed to add cgroup attribute value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1865,7 +1902,8 @@ int config_parse_unit_requires_mounts_for(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         int r;
@@ -1878,7 +1916,7 @@ int config_parse_unit_requires_mounts_for(
 
         empty_before = !u->requires_mounts_for;
 
-        r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+        r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata, issues);
 
         /* Make it easy to find units with requires_mounts set */
         if (empty_before && u->requires_mounts_for)
@@ -1895,7 +1933,8 @@ int config_parse_documentation(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         Unit *u = userdata;
         int r;
@@ -1913,7 +1952,7 @@ int config_parse_documentation(
                 return 0;
         }
 
-        r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+        r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata, issues);
         if (r < 0)
                 return r;
 
@@ -1922,7 +1961,7 @@ int config_parse_documentation(
                 if (is_valid_documentation_url(*a))
                         *(b++) = *a;
                 else {
-                        log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
+                        log_syntax(issues, filename, line, false, "Invalid URL, ignoring: %s", *a);
                         free(*a);
                 }
         }
@@ -1949,7 +1988,8 @@ int config_parse_syscall_filter(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ExecContext *c = data;
         Unit *u = userdata;
@@ -2005,8 +2045,8 @@ int config_parse_syscall_filter(
 
                 id = syscall_from_name(t);
                 if (id < 0)  {
-                        log_error("[%s:%u] Failed to parse syscall, ignoring: %s",
-                                  filename, line, t);
+                        log_syntax(issues, filename, line, false, "Failed to parse syscall, ignoring: %s",
+                                   t);
                         continue;
                 }
 
@@ -2233,7 +2273,8 @@ static int load_from_path(Unit *u, const char *path) {
                 u->load_state = UNIT_MASKED;
         else {
                 /* Now, parse the file contents */
-                r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
+                r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup,
+                                 (void*) load_fragment_gperf_lookup, false, u, &u->issues);
                 if (r < 0)
                         goto finish;
 
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index dfb2ef0..f2406d3 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -29,56 +29,56 @@ int unit_load_fragment(Unit *u);
 
 void unit_dump_config_items(FILE *f);
 
-int config_parse_warn_compat(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_deps(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_oom_score_adjust(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_timeout(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_restart(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bindtodevice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_output(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_input(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_class(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_policy(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_prio(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_affinity(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_capabilities(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_secure_bits(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bounding_set(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sysv_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fsck_passno(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_signal(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_mount_flags(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_spec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_service(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_sockets(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_env_file(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ip_tos(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_null(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_notify_access(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_start_limit_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup_attr(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup_attr_pretty(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_requires_mounts_for(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_environ(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_warn_compat(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_deps(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_oom_score_adjust(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_service_timeout(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_service_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_service_restart(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_socket_bindtodevice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_output(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_input(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_io_class(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_io_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_cpu_sched_policy(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_cpu_sched_prio(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_cpu_affinity(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_capabilities(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_secure_bits(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_bounding_set(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_cgroup(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_sysv_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_fsck_passno(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_kill_signal(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_exec_mount_flags(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_timer(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_timer_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_path_spec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_path_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_socket_service(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_service_sockets(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_env_file(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_ip_tos(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_condition_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_condition_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_condition_null(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_kill_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_notify_access(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_start_limit_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_cgroup_attr(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_cgroup_attr_pretty(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unit_requires_mounts_for(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_syscall_filter(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_environ(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
 
 /* gperf prototypes */
 const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
diff --git a/src/core/main.c b/src/core/main.c
index bd7fc46..0132c10 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -438,7 +438,8 @@ static int config_parse_level2(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         assert(filename);
         assert(lvalue);
@@ -456,7 +457,8 @@ static int config_parse_target(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         assert(filename);
         assert(lvalue);
@@ -474,7 +476,8 @@ static int config_parse_color(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         assert(filename);
         assert(lvalue);
@@ -492,7 +495,8 @@ static int config_parse_location(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         assert(filename);
         assert(lvalue);
@@ -510,7 +514,8 @@ static int config_parse_cpu_affinity2(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char *w;
         size_t l;
@@ -584,7 +589,8 @@ static int config_parse_join_controllers(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         unsigned n = 0;
         char *state, *w;
@@ -727,7 +733,7 @@ static int parse_config_file(void) {
                 return 0;
         }
 
-        r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
+        r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL, NULL);
         if (r < 0)
                 log_warning("Failed to parse configuration file: %s", strerror(-r));
 
diff --git a/src/core/unit.c b/src/core/unit.c
index 7111679..77a4c74 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -406,6 +406,7 @@ void unit_free(Unit *u) {
 
         free(u->description);
         strv_free(u->documentation);
+        strv_free(u->issues);
         free(u->fragment_path);
         free(u->source_path);
         free(u->instance);
@@ -687,6 +688,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
         STRV_FOREACH(j, u->documentation)
                 fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
 
+        STRV_FOREACH(j, u->issues)
+                fprintf(f, "%s\tIssue: %s\n", prefix, *j);
+
         if ((following = unit_following(u)))
                 fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
 
diff --git a/src/core/unit.h b/src/core/unit.h
index 3da6a50..dd0faab 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -136,6 +136,8 @@ struct Unit {
         char *description;
         char **documentation;
 
+        char ** issues;
+
         char *fragment_path; /* if loaded from a config file this is the primary path to it */
         char *source_path; /* if converted, the source file */
         usec_t fragment_mtime;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index a9d7aa1..4c46259 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -42,6 +42,7 @@
 #include "socket-util.h"
 #include "cgroup-util.h"
 #include "list.h"
+#include "strv.h"
 #include "virt.h"
 #include "missing.h"
 #include "conf-parser.h"
@@ -1323,7 +1324,7 @@ static int server_parse_config_file(Server *s) {
         }
 
         r = config_parse(fn, f, "Journal\0", config_item_perf_lookup,
-                         (void*) journald_gperf_lookup, false, s);
+                         (void*) journald_gperf_lookup, false, s, &s->issues);
         if (r < 0)
                 log_warning("Failed to parse configuration file: %s", strerror(-r));
 
@@ -1503,6 +1504,8 @@ int server_init(Server *s) {
         if (!s->udev)
                 return -ENOMEM;
 
+        s->issues = NULL;
+
         s->rate_limit = journal_rate_limit_new(s->rate_limit_interval,
                                                s->rate_limit_burst);
         if (!s->rate_limit)
@@ -1584,4 +1587,7 @@ void server_done(Server *s) {
 
         if (s->udev)
                 udev_unref(s->udev);
+
+        if (s->issues)
+                strv_free(s->issues);
 }
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 21edd6b..01b3035 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -123,6 +123,8 @@ typedef struct Server {
 
         int sync_timer_fd;
         bool sync_scheduled;
+
+        char ** issues;
 } Server;
 
 #define N_IOVEC_META_FIELDS 17
@@ -135,12 +137,12 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
 /* gperf lookup function */
 const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length);
 
-int config_parse_storage(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_storage(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
 
 const char *storage_to_string(Storage s);
 Storage storage_from_string(const char *s);
 
-int config_parse_split_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_split_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
 
 const char *split_mode_to_string(SplitMode s);
 SplitMode split_mode_from_string(const char *s);
diff --git a/src/login/logind-action.h b/src/login/logind-action.h
index 7ab4464..4f43cfa 100644
--- a/src/login/logind-action.h
+++ b/src/login/logind-action.h
@@ -49,6 +49,6 @@ int manager_handle_action(
 const char* handle_action_to_string(HandleAction h);
 HandleAction handle_action_from_string(const char *s);
 
-int config_parse_handle_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_handle_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
 
 #endif
diff --git a/src/login/logind.c b/src/login/logind.c
index f72aac5..78bab71 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1702,7 +1702,7 @@ static int manager_parse_config_file(Manager *m) {
                 return -errno;
         }
 
-        r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
+        r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m, NULL);
         if (r < 0)
                 log_warning("Failed to parse configuration file: %s", strerror(-r));
 
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 60a6b35..d7a0807 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -35,25 +35,33 @@
 #include "set.h"
 #include "exit-status.h"
 
-static int log_syntax(const char * file, unsigned line, bool error, const char *description, ...) {
-        _cleanup_free_ char *buf = NULL;
+int log_syntax(char *** issues, const char * file, unsigned line, bool iserror, const char *description, ...) {
+        _cleanup_free_ char *error = NULL, *message = NULL;
 
         va_list arg_descr, arg_copy;
 
         va_start(arg_descr, description);
         va_copy(arg_copy, arg_descr);
-        if (vasprintf(&buf, description, arg_copy) < 0) {
+        if (vasprintf(&error, description, arg_copy) < 0) {
                 va_end(arg_descr);
                 return log_oom();
         }
         va_end(arg_descr);
 
+        if (asprintf(&message, "%s: [%s:%d]: %s",
+                     iserror ? "Error" : "Warning",
+                     file, line, error) < 0)
+                return log_oom();
+
+        if (issues && (strv_extend(issues, message) < 0))
+                return log_oom();
+
         return log_struct(error ? LOG_ERR : LOG_WARNING,
-                          "MESSAGE=[%s:%d]: %s", file, line, buf,
+                          "MESSAGE=%s", message,
                           "MESSAGE_ID=%s\n", error ? CONF_PARSER_ERROR : CONF_PARSER_WARNING,
                           "FILE=%s\n", file,
                           "LINE=%u\n", line,
-                          "ERROR=%s\n", buf,
+                          "ERROR=%s\n", error,
                           NULL);
 }
 
@@ -64,7 +72,8 @@ int config_item_table_lookup(
                 ConfigParserCallback *func,
                 int *ltype,
                 void **data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ConfigTableItem *t;
 
@@ -98,7 +107,8 @@ int config_item_perf_lookup(
                 ConfigParserCallback *func,
                 int *ltype,
                 void **data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
         const ConfigPerfItem *p;
@@ -141,7 +151,8 @@ static int next_assignment(
                 const char *lvalue,
                 const char *rvalue,
                 bool relaxed,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         ConfigParserCallback func = NULL;
         int ltype = 0;
@@ -154,20 +165,20 @@ static int next_assignment(
         assert(lvalue);
         assert(rvalue);
 
-        r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
+        r = lookup(table, section, lvalue, &func, &ltype, &data, userdata, issues);
         if (r < 0)
                 return r;
 
         if (r > 0) {
                 if (func)
-                        return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+                        return func(filename, line, section, lvalue, ltype, rvalue, data, userdata, issues);
 
                 return 0;
         }
 
         /* Warn about unknown non-extension fields. */
         if (!relaxed && !startswith(lvalue, "X-"))
-                log_syntax(filename, line, false, "Unknown lvalue '%s' in section '%s'", lvalue, section);
+                log_syntax(issues, filename, line, false, "Unknown lvalue '%s' in section '%s'", lvalue, section);
 
         return 0;
 }
@@ -182,7 +193,8 @@ static int parse_line(
                 bool relaxed,
                 char **section,
                 char *l,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char *e;
 
@@ -207,7 +219,7 @@ static int parse_line(
                 if (!fn)
                         return -ENOMEM;
 
-                r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
+                r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata, issues);
                 free(fn);
 
                 return r;
@@ -221,7 +233,7 @@ static int parse_line(
                 assert(k > 0);
 
                 if (l[k-1] != ']') {
-                        log_syntax(filename, line, true, "Invalid section header");
+                        log_syntax(issues, filename, line, true, "Invalid section header");
                         return -EBADMSG;
                 }
 
@@ -232,7 +244,7 @@ static int parse_line(
                 if (sections && !nulstr_contains(sections, n)) {
 
                         if (! relaxed)
-                                log_syntax(filename, line, false, "Unknown section '%s'. Ignoring.", n);
+                                log_syntax(issues, filename, line, false, "Unknown section '%s'. Ignoring.", n);
 
                         free(n);
                         *section = NULL;
@@ -247,14 +259,14 @@ static int parse_line(
         if (sections && !*section) {
 
                 if (!relaxed)
-                        log_syntax(filename, line, false, "Assignment outside of section. Ignoring.");
+                        log_syntax(issues, filename, line, false, "Assignment outside of section. Ignoring.");
 
                 return 0;
         }
 
         e = strchr(l, '=');
         if (!e) {
-                log_syntax(filename, line, true, "Missing '='.");
+                log_syntax(issues, filename, line, true, "Missing '='.");
                 return -EBADMSG;
         }
 
@@ -270,7 +282,8 @@ static int parse_line(
                         strstrip(l),
                         strstrip(e),
                         relaxed,
-                        userdata);
+                        userdata,
+                        issues);
 }
 
 /* Go through the file and parse each line */
@@ -281,7 +294,8 @@ int config_parse(
                 ConfigItemLookup lookup,
                 void *table,
                 bool relaxed,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         unsigned line = 0;
         char *section = NULL;
@@ -362,7 +376,8 @@ int config_parse(
                                 relaxed,
                                 &section,
                                 p,
-                                userdata);
+                                userdata,
+                                issues);
                 free(c);
 
                 if (r < 0)
@@ -389,7 +404,8 @@ int config_parse_int(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int *i = data;
         int r;
@@ -401,7 +417,7 @@ int config_parse_int(
 
         r = safe_atoi(rvalue, i);
         if (r < 0) {
-                log_syntax(filename, line, true, "Failed to parse numeric value '%s'. Ingoring.", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse numeric value '%s'. Ingoring.", rvalue);
                 return 0;
         }
 
@@ -416,7 +432,8 @@ int config_parse_long(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         long *i = data;
         int r;
@@ -428,7 +445,7 @@ int config_parse_long(
 
         r = safe_atoli(rvalue, i);
         if (r < 0) {
-                log_syntax(filename, line, true, "Failed to parse numeric value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse numeric value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -443,7 +460,8 @@ int config_parse_uint64(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         uint64_t *u = data;
         int r;
@@ -455,7 +473,7 @@ int config_parse_uint64(
 
         r = safe_atou64(rvalue, u);
         if (r < 0) {
-                log_syntax(filename, line, true, "Failed to parse numeric value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse numeric value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -470,7 +488,8 @@ int config_parse_unsigned(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         unsigned *u = data;
         int r;
@@ -482,7 +501,7 @@ int config_parse_unsigned(
 
         r = safe_atou(rvalue, u);
         if (r < 0) {
-                log_syntax(filename, line, true, "Failed to parse numeric value: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse numeric value: %s", rvalue);
                 return r;
         }
 
@@ -497,7 +516,8 @@ int config_parse_double(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         double *d = data;
         int r;
@@ -509,7 +529,7 @@ int config_parse_double(
 
         r = safe_atod(rvalue, d);
         if (r < 0) {
-                log_syntax(filename, line, true, "Failed to parse numeric value: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse numeric value: %s", rvalue);
                 return r;
         }
 
@@ -524,7 +544,8 @@ int config_parse_bytes_size(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         size_t *sz = data;
         off_t o;
@@ -535,7 +556,7 @@ int config_parse_bytes_size(
         assert(data);
 
         if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
-                log_syntax(filename, line, true, "Failed to parse byte value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse byte value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -552,7 +573,8 @@ int config_parse_bytes_off(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         off_t *bytes = data;
 
@@ -564,7 +586,7 @@ int config_parse_bytes_off(
         assert_cc(sizeof(off_t) == sizeof(uint64_t));
 
         if (parse_bytes(rvalue, bytes) < 0) {
-                log_syntax(filename, line, true, "Failed to parse bytes value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse bytes value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -579,7 +601,8 @@ int config_parse_bool(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int k;
         bool *b = data;
@@ -590,7 +613,7 @@ int config_parse_bool(
         assert(data);
 
         if ((k = parse_boolean(rvalue)) < 0) {
-                log_syntax(filename, line, true, "Failed to parse boolean value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse boolean value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -606,7 +629,8 @@ int config_parse_tristate(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         int k;
         int *b = data;
@@ -620,7 +644,7 @@ int config_parse_tristate(
 
         k = parse_boolean(rvalue);
         if (k < 0) {
-                log_syntax(filename, line, true, "Failed to parse boolean value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse boolean value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -636,7 +660,8 @@ int config_parse_string(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char **s = data;
         char *n;
@@ -651,7 +676,7 @@ int config_parse_string(
                 return log_oom();
 
         if (!utf8_is_valid(n)) {
-                log_syntax(filename, line, true, "[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", rvalue);
+                log_syntax(issues, filename, line, true, "[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", rvalue);
                 free(n);
                 return 0;
         }
@@ -675,7 +700,8 @@ int config_parse_path(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char **s = data;
         char *n;
@@ -686,12 +712,12 @@ int config_parse_path(
         assert(data);
 
         if (!utf8_is_valid(rvalue)) {
-                log_syntax(filename, line, true, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
                 return 0;
         }
 
         if (!path_is_absolute(rvalue)) {
-                log_syntax(filename, line, true, "Not an absolute path, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Not an absolute path, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -715,7 +741,8 @@ int config_parse_strv(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char *** sv = data, *w, *state;
         size_t l;
@@ -750,7 +777,7 @@ int config_parse_strv(
                         return log_oom();
 
                 if (!utf8_is_valid(n)) {
-                        log_syntax(filename, line, true, "[%s:%u] String is not UTF-8 clean, ignoring: %s", rvalue);
+                        log_syntax(issues, filename, line, true, "[%s:%u] String is not UTF-8 clean, ignoring: %s", rvalue);
                         continue;
                 }
 
@@ -770,7 +797,8 @@ int config_parse_path_strv(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char*** sv = data, *w, *state;
         size_t l;
@@ -796,12 +824,12 @@ int config_parse_path_strv(
                         return log_oom();
 
                 if (!utf8_is_valid(n)) {
-                        log_syntax(filename, line, true, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+                        log_syntax(issues, filename, line, true, "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
                         continue;
                 }
 
                 if (!path_is_absolute(n)) {
-                        log_syntax(filename, line, true, "Not an absolute path, ignoring: %s", rvalue);
+                        log_syntax(issues, filename, line, true, "Not an absolute path, ignoring: %s", rvalue);
                         continue;
                 }
 
@@ -822,7 +850,8 @@ int config_parse_usec(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         usec_t *usec = data;
 
@@ -832,7 +861,7 @@ int config_parse_usec(
         assert(data);
 
         if (parse_usec(rvalue, usec) < 0) {
-                log_syntax(filename, line, true, "Failed to parse time value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse time value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -847,7 +876,8 @@ int config_parse_nsec(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         nsec_t *nsec = data;
 
@@ -857,7 +887,7 @@ int config_parse_nsec(
         assert(data);
 
         if (parse_nsec(rvalue, nsec) < 0) {
-                log_syntax(filename, line, true, "Failed to parse time value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse time value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -872,7 +902,8 @@ int config_parse_mode(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         mode_t *m = data;
         long l;
@@ -886,12 +917,12 @@ int config_parse_mode(
         errno = 0;
         l = strtol(rvalue, &x, 8);
         if (!x || x == rvalue || *x || errno) {
-                log_syntax(filename, line, true, "Failed to parse mode value, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse mode value, ignoring: %s", rvalue);
                 return 0;
         }
 
         if (l < 0000 || l > 07777) {
-                log_syntax(filename, line, true, "Mode value out of range, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Mode value out of range, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -907,7 +938,8 @@ int config_parse_facility(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
 
         int *o = data, x;
@@ -919,7 +951,7 @@ int config_parse_facility(
 
         x = log_facility_unshifted_from_string(rvalue);
         if (x < 0) {
-                log_syntax(filename, line, true, "Failed to parse log facility, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse log facility, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -936,7 +968,8 @@ int config_parse_level(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
 
         int *o = data, x;
@@ -948,7 +981,7 @@ int config_parse_level(
 
         x = log_level_from_string(rvalue);
         if (x < 0) {
-                log_syntax(filename, line, true, "Failed to parse log level, ignoring: %s", rvalue);
+                log_syntax(issues, filename, line, true, "Failed to parse log level, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -964,7 +997,8 @@ int config_parse_set_status(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char *w;
         size_t l;
@@ -1007,18 +1041,18 @@ int config_parse_set_status(
 
                                 r = set_put(status_set->signal, INT_TO_PTR(val));
                                 if (r < 0) {
-                                        log_syntax(filename, line, true, "Unable to store: %s", w);
+                                        log_syntax(issues, filename, line, true, "Unable to store: %s", w);
                                         return r;
                                 }
                         } else {
-                                log_syntax(filename, line, true, "Failed to parse value, ignoring: %s", w);
+                                log_syntax(issues, filename, line, true, "Failed to parse value, ignoring: %s", w);
                                 return 0;
                         }
                 } else {
                         free(temp);
 
                         if (val < 0 || val > 255)
-                                log_syntax(filename, line, false, "Value %d is outside range 0-255, ignoring", val);
+                                log_syntax(issues, filename, line, false, "Value %d is outside range 0-255, ignoring", val);
                         else {
                                 r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func);
                                 if (r < 0)
@@ -1026,7 +1060,7 @@ int config_parse_set_status(
 
                                 r = set_put(status_set->code, INT_TO_PTR(val));
                                 if (r < 0) {
-                                        log_syntax(filename, line, true, "[%s:%u] Unable to store: %s", w);
+                                        log_syntax(issues, filename, line, true, "[%s:%u] Unable to store: %s", w);
                                         return r;
                                 }
                         }
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 62c9a33..7a6bc4e 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -36,7 +36,8 @@ typedef int (*ConfigParserCallback)(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata);
+                void *userdata,
+                char *** issues);
 
 /* Wraps information for parsing a specific configuration variable, to
  * be stored in a simple array */
@@ -68,15 +69,16 @@ typedef int (*ConfigItemLookup)(
                 ConfigParserCallback *func,
                 int *ltype,
                 void **data,
-                void *userdata);
+                void *userdata,
+                char *** issues);
 
 /* Linear table search implementation of ConfigItemLookup, based on
  * ConfigTableItem arrays */
-int config_item_table_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
+int config_item_table_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata, char *** issues);
 
 /* gperf implementation of ConfigItemLookup, based on gperf
  * ConfigPerfItem tables */
-int config_item_perf_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
+int config_item_perf_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata, char *** issues);
 
 int config_parse(
                 const char *filename,
@@ -85,28 +87,31 @@ int config_parse(
                 ConfigItemLookup lookup,
                 void *table,
                 bool relaxed,
-                void *userdata);
+                void *userdata,
+                char *** issues);
 
 /* Generic parsers */
-int config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_long(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_double(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bytes_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bytes_off(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tristate(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_usec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_nsec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_facility(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_level(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_set_status(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_long(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_double(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_bytes_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_bytes_off(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_tristate(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_usec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_nsec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_facility(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_level(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+int config_parse_set_status(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata, char *** issues);
+
+int log_syntax(char *** issues, const char * file, unsigned line, bool iserror, const char *description, ...);
 
 #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg)                \
         int function(                                                   \
@@ -117,7 +122,8 @@ int config_parse_set_status(const char *filename, unsigned line, const char *sec
                         int ltype,                                      \
                         const char *rvalue,                             \
                         void *data,                                     \
-                        void *userdata) {                               \
+                        void *userdata,                                 \
+                        char *** issues) {                              \
                                                                         \
                 type *i = data, x;                                      \
                                                                         \
diff --git a/src/shared/install.c b/src/shared/install.c
index 2555a36..ebcd754 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -829,6 +829,7 @@ static void install_info_free(InstallInfo *i) {
         strv_free(i->aliases);
         strv_free(i->wanted_by);
         strv_free(i->required_by);
+        strv_free(i->issues);
         free(i);
 }
 
@@ -929,7 +930,8 @@ static int config_parse_also(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         char *w;
         size_t l;
@@ -964,7 +966,8 @@ static int config_parse_user(
                 int ltype,
                 const char *rvalue,
                 void *data,
-                void *userdata) {
+                void *userdata,
+                char *** issues) {
 
         InstallInfo *i = data;
         char* printed;
@@ -1016,7 +1019,7 @@ static int unit_file_load(
                 return -ENOMEM;
         }
 
-        r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
+        r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info, &info->issues);
         if (r < 0)
                 return r;
 
diff --git a/src/shared/install.h b/src/shared/install.h
index 755ddde..0ff46b0 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -71,6 +71,8 @@ typedef struct {
         char **aliases;
         char **wanted_by;
         char **required_by;
+
+        char ** issues;
 } InstallInfo;
 
 int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 0ad5112..9bbb977 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2228,6 +2228,8 @@ typedef struct UnitStatusInfo {
         const char *load_error;
         const char *result;
 
+        char **issues;
+
         usec_t inactive_exit_timestamp;
         usec_t inactive_exit_timestamp_monotonic;
         usec_t active_enter_timestamp;
@@ -2387,6 +2389,19 @@ static void print_status_info(UnitStatusInfo *i) {
                 }
         }
 
+        if (!strv_isempty(i->issues)) {
+                char **t;
+                bool first = true;
+
+                STRV_FOREACH(t, i->issues) {
+                        if (first) {
+                                printf("\t  Issues: %s\n", *t);
+                                first = false;
+                        } else
+                                printf("\t          %s\n", *t);
+                }
+        }
+
         if (!strv_isempty(i->listen)) {
                 char **t;
                 bool first = true;
@@ -2773,6 +2788,28 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         }
 
                 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
+                           streq(name, "Issues")) {
+
+                        DBusMessageIter sub;
+
+                        dbus_message_iter_recurse(iter, &sub);
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
+                                const char *s;
+                                char **l;
+
+                                dbus_message_iter_get_basic(&sub, &s);
+
+                                l = strv_append(i->issues, s);
+                                if (!l)
+                                        return -ENOMEM;
+
+                                strv_free(i->issues);
+                                i->issues = l;
+
+                                dbus_message_iter_next(&sub);
+                        }
+
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
                            startswith(name, "Listen")) {
                         DBusMessageIter sub;
 
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index c1a2d4a..570cf9c 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -87,13 +87,13 @@ static void test_config_parse_exec(void) {
         /* basic test */
         r = config_parse_exec("fake", 1, "section",
                               "LValue", 0, "/RValue r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         check_execcommand(c, "/RValue", "/RValue", "r1", false);
 
         r = config_parse_exec("fake", 2, "section",
                               "LValue", 0, "/RValue///slashes/// r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
        /* test slashes */
         assert_se(r >= 0);
         c1 = c->command_next;
@@ -103,7 +103,7 @@ static void test_config_parse_exec(void) {
         /* honour_argv0 */
         r = config_parse_exec("fake", 3, "section",
                               "LValue", 0, "@/RValue///slashes2/// argv0 r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue/slashes2", "argv0", "r1", false);
@@ -111,7 +111,7 @@ static void test_config_parse_exec(void) {
         /* ignore && honour_argv0 */
         r = config_parse_exec("fake", 4, "section",
                               "LValue", 0, "-@/RValue///slashes3/// argv0a r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -120,7 +120,7 @@ static void test_config_parse_exec(void) {
         /* ignore && honour_argv0 */
         r = config_parse_exec("fake", 4, "section",
                               "LValue", 0, "@-/RValue///slashes4/// argv0b r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -129,14 +129,14 @@ static void test_config_parse_exec(void) {
         /* ignore && ignore */
         r = config_parse_exec("fake", 4, "section",
                               "LValue", 0, "--/RValue argv0 r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         /* ignore && ignore */
         r = config_parse_exec("fake", 4, "section",
                               "LValue", 0, "- at -/RValue argv0 r1",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
@@ -145,7 +145,7 @@ static void test_config_parse_exec(void) {
                               "LValue", 0,
                               "-@/RValue argv0 r1 ; "
                               "/goo/goo boo",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -159,7 +159,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec("fake", 5, "section",
                               "LValue", 0,
                               "-@/RValue argv0 r1 ; ",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -171,7 +171,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec("fake", 5, "section",
                               "LValue", 0,
                               "/usr/bin/find \\;",
-                              &c, NULL);
+                              &c, NULL, NULL);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 99a626c..f006759 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -277,7 +277,7 @@ static int parse_password(const char *filename, char **wall) {
                 return -errno;
         }
 
-        r = config_parse(filename, f, NULL, config_item_table_lookup, (void*) items, true, NULL);
+        r = config_parse(filename, f, NULL, config_item_table_lookup, (void*) items, true, NULL, NULL);
         if (r < 0) {
                 log_error("Failed to parse password file %s: %s", filename, strerror(-r));
                 goto finish;
-- 
1.8.1.2



More information about the systemd-devel mailing list