chiark / gitweb /
polkit: don't start polkit agent when running as root
[elogind.git] / src / shared / conf-parser.c
index 2c855157a9a9c83e07a1427d6cd179b6a878f6d6..9c1a02241a95e358abb484fb9bab1ff4575ef585 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <string.h>
-#include <stdio.h>
 #include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
 
-#include "conf-parser.h"
+#include "alloc-util.h"
 #include "conf-files.h"
-#include "util.h"
+#include "conf-parser.h"
+#include "extract-word.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "log.h"
 #include "macro.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "signal-util.h"
+#include "string-util.h"
 #include "strv.h"
-#include "log.h"
+#include "syslog-util.h"
+#include "time-util.h"
 #include "utf8.h"
-#include "path-util.h"
-#include "sd-messages.h"
 
 int config_item_table_lookup(
                 const void *table,
@@ -146,8 +155,7 @@ static int next_assignment(const char *unit,
 
         /* Warn about unknown non-extension fields. */
         if (!relaxed && !startswith(lvalue, "X-"))
-                log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
-                           "Unknown lvalue '%s' in section '%s'", lvalue, section);
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section);
 
         return 0;
 }
@@ -195,8 +203,7 @@ static int parse_line(const char* unit,
                  * Support for them should be eventually removed. */
 
                 if (!allow_include) {
-                        log_syntax(unit, LOG_ERR, filename, line, EBADMSG,
-                                   ".include not allowed here. Ignoring.");
+                        log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
                         return 0;
                 }
 
@@ -215,8 +222,7 @@ static int parse_line(const char* unit,
                 assert(k > 0);
 
                 if (l[k-1] != ']') {
-                        log_syntax(unit, LOG_ERR, filename, line, EBADMSG,
-                                   "Invalid section header '%s'", l);
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l);
                         return -EBADMSG;
                 }
 
@@ -227,12 +233,10 @@ static int parse_line(const char* unit,
                 if (sections && !nulstr_contains(sections, n)) {
 
                         if (!relaxed && !startswith(n, "X-"))
-                                log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
-                                           "Unknown section '%s'. Ignoring.", n);
+                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);
 
                         free(n);
-                        free(*section);
-                        *section = NULL;
+                        *section = mfree(*section);
                         *section_line = 0;
                         *section_ignored = true;
                 } else {
@@ -248,16 +252,15 @@ static int parse_line(const char* unit,
         if (sections && !*section) {
 
                 if (!relaxed && !*section_ignored)
-                        log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
-                                   "Assignment outside of section. Ignoring.");
+                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");
 
                 return 0;
         }
 
         e = strchr(l, '=');
         if (!e) {
-                log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Missing '='.");
-                return -EBADMSG;
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='.");
+                return -EINVAL;
         }
 
         *e = 0;
@@ -291,7 +294,7 @@ int config_parse(const char *unit,
         _cleanup_free_ char *section = NULL, *continuation = NULL;
         _cleanup_fclose_ FILE *ours = NULL;
         unsigned line = 0, section_line = 0;
-        bool section_ignored = false;
+        bool section_ignored = false, allow_bom = true;
         int r;
 
         assert(filename);
@@ -311,11 +314,11 @@ int config_parse(const char *unit,
 
         fd_warn_permissions(filename, fileno(f));
 
-        while (!feof(f)) {
-                char l[LINE_MAX], *p, *c = NULL, *e;
+        for (;;) {
+                char buf[LINE_MAX], *l, *p, *c = NULL, *e;
                 bool escaped = false;
 
-                if (!fgets(l, sizeof(l), f)) {
+                if (!fgets(buf, sizeof buf, f)) {
                         if (feof(f))
                                 break;
 
@@ -323,6 +326,11 @@ int config_parse(const char *unit,
                         return -errno;
                 }
 
+                l = buf;
+                if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
+                        l += strlen(UTF8_BYTE_ORDER_MARK);
+                allow_bom = false;
+
                 truncate_nl(l);
 
                 if (continuation) {
@@ -333,8 +341,7 @@ int config_parse(const char *unit,
                                 return -ENOMEM;
                         }
 
-                        free(continuation);
-                        continuation = NULL;
+                        continuation = mfree(continuation);
                         p = c;
                 } else
                         p = l;
@@ -421,7 +428,8 @@ int config_parse_many(const char *conf_file,
 }
 
 #define DEFINE_PARSER(type, vartype, conv_func)                         \
-        int config_parse_##type(const char *unit,                       \
+        int config_parse_##type(                                        \
+                        const char *unit,                               \
                                 const char *filename,                   \
                                 unsigned line,                          \
                                 const char *section,                    \
@@ -442,20 +450,25 @@ int config_parse_many(const char *conf_file,
                                                                         \
                 r = conv_func(rvalue, i);                               \
                 if (r < 0)                                              \
-                        log_syntax(unit, LOG_ERR, filename, line, -r,   \
+                        log_syntax(unit, LOG_ERR, filename, line, r,    \
                                    "Failed to parse %s value, ignoring: %s", \
-                                   #vartype, rvalue);                   \
+                                   #type, rvalue);                      \
                                                                         \
                 return 0;                                               \
-        }
-
-DEFINE_PARSER(int, int, safe_atoi)
-DEFINE_PARSER(long, long, safe_atoli)
-DEFINE_PARSER(uint64, uint64_t, safe_atou64)
-DEFINE_PARSER(unsigned, unsigned, safe_atou)
-DEFINE_PARSER(double, double, safe_atod)
-DEFINE_PARSER(nsec, nsec_t, parse_nsec)
-DEFINE_PARSER(sec, usec_t, parse_sec)
+        }                                                               \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+DEFINE_PARSER(int, int, safe_atoi);
+DEFINE_PARSER(long, long, safe_atoli);
+DEFINE_PARSER(uint32, uint32_t, safe_atou32);
+DEFINE_PARSER(uint64, uint64_t, safe_atou64);
+DEFINE_PARSER(unsigned, unsigned, safe_atou);
+DEFINE_PARSER(double, double, safe_atod);
+#if 0 /// UNNEEDED by elogind
+DEFINE_PARSER(nsec, nsec_t, parse_nsec);
+#endif // 0
+DEFINE_PARSER(sec, usec_t, parse_sec);
+DEFINE_PARSER(mode, mode_t, parse_mode);
 
 int config_parse_iec_size(const char* unit,
                             const char *filename,
@@ -469,7 +482,7 @@ int config_parse_iec_size(const char* unit,
                             void *userdata) {
 
         size_t *sz = data;
-        off_t o;
+        uint64_t v;
         int r;
 
         assert(filename);
@@ -477,16 +490,17 @@ int config_parse_iec_size(const char* unit,
         assert(rvalue);
         assert(data);
 
-        r = parse_size(rvalue, 1024, &o);
-        if (r < 0 || (off_t) (size_t) o != o) {
-                log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
+        r = parse_size(rvalue, 1024, &v);
+        if (r < 0 || (uint64_t) (size_t) v != v) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
                 return 0;
         }
 
-        *sz = (size_t) o;
+        *sz = (size_t) v;
         return 0;
 }
 
+#if 0 /// UNNEEDED by elogind
 int config_parse_si_size(const char* unit,
                             const char *filename,
                             unsigned line,
@@ -499,7 +513,7 @@ int config_parse_si_size(const char* unit,
                             void *userdata) {
 
         size_t *sz = data;
-        off_t o;
+        uint64_t v;
         int r;
 
         assert(filename);
@@ -507,17 +521,17 @@ int config_parse_si_size(const char* unit,
         assert(rvalue);
         assert(data);
 
-        r = parse_size(rvalue, 1000, &o);
-        if (r < 0 || (off_t) (size_t) o != o) {
-                log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
+        r = parse_size(rvalue, 1000, &v);
+        if (r < 0 || (uint64_t) (size_t) v != v) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
                 return 0;
         }
 
-        *sz = (size_t) o;
+        *sz = (size_t) v;
         return 0;
 }
 
-int config_parse_iec_off(const char* unit,
+int config_parse_iec_uint64(const char* unit,
                            const char *filename,
                            unsigned line,
                            const char *section,
@@ -528,7 +542,7 @@ int config_parse_iec_off(const char* unit,
                            void *data,
                            void *userdata) {
 
-        off_t *bytes = data;
+        uint64_t *bytes = data;
         int r;
 
         assert(filename);
@@ -536,14 +550,13 @@ int config_parse_iec_off(const char* unit,
         assert(rvalue);
         assert(data);
 
-        assert_cc(sizeof(off_t) == sizeof(uint64_t));
-
         r = parse_size(rvalue, 1024, bytes);
         if (r < 0)
-                log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
 
         return 0;
 }
+#endif // 0
 
 int config_parse_bool(const char* unit,
                       const char *filename,
@@ -566,8 +579,7 @@ int config_parse_bool(const char* unit,
 
         k = parse_boolean(rvalue);
         if (k < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, -k,
-                           "Failed to parse boolean value, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -575,6 +587,41 @@ int config_parse_bool(const char* unit,
         return 0;
 }
 
+#if 0 /// UNNEEDED by elogind
+int config_parse_tristate(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        int k, *t = data;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        /* A tristate is pretty much a boolean, except that it can
+         * also take the special value -1, indicating "uninitialized",
+         * much like NULL is for a pointer type. */
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        *t = !!k;
+        return 0;
+}
+#endif // 0
+
 int config_parse_string(
                 const char *unit,
                 const char *filename,
@@ -595,7 +642,7 @@ int config_parse_string(
         assert(data);
 
         if (!utf8_is_valid(rvalue)) {
-                log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+                log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
                 return 0;
         }
 
@@ -633,12 +680,12 @@ int config_parse_path(
         assert(data);
 
         if (!utf8_is_valid(rvalue)) {
-                log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+                log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
                 return 0;
         }
 
         if (!path_is_absolute(rvalue)) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -666,9 +713,6 @@ int config_parse_strv(const char *unit,
                       void *userdata) {
 
         char ***sv = data;
-        const char *word, *state;
-        size_t l;
-        int r;
 
         assert(filename);
         assert(lvalue);
@@ -691,58 +735,66 @@ int config_parse_strv(const char *unit,
                 return 0;
         }
 
-        FOREACH_WORD_QUOTED(word, l, rvalue, state) {
-                char *n;
-
-                n = strndup(word, l);
-                if (!n)
+        for (;;) {
+                char *word = NULL;
+                int r;
+                r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
+                if (r == 0)
+                        break;
+                if (r == -ENOMEM)
                         return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+                        break;
+                }
 
-                if (!utf8_is_valid(n)) {
-                        log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
-                        free(n);
+                if (!utf8_is_valid(word)) {
+                        log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
+                        free(word);
                         continue;
                 }
-
-                r = strv_consume(sv, n);
+                r = strv_consume(sv, word);
                 if (r < 0)
                         return log_oom();
         }
-        if (!isempty(state))
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Trailing garbage, ignoring.");
 
         return 0;
 }
 
-int config_parse_mode(
+#if 0 /// UNNEEDED by elogind
+int config_parse_log_facility(
                 const char *unit,
                 const char *filename,
                 unsigned line,
                 const char *section,
-                      unsigned section_line,
+                unsigned section_line,
                 const char *lvalue,
                 int ltype,
                 const char *rvalue,
                 void *data,
                 void *userdata) {
 
-        mode_t *m = data;
+
+        int *o = data, x;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(data);
 
-        if (parse_mode(rvalue, m) < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse mode value, ignoring: %s", rvalue);
+        x = log_facility_unshifted_from_string(rvalue);
+        if (x < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
                 return 0;
         }
 
+        *o = (x << 3) | LOG_PRI(*o);
+
         return 0;
 }
+#endif // 0
 
-int config_parse_log_facility(
+int config_parse_log_level(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -762,18 +814,17 @@ int config_parse_log_facility(
         assert(rvalue);
         assert(data);
 
-        x = log_facility_unshifted_from_string(rvalue);
+        x = log_level_from_string(rvalue);
         if (x < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log facility, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
                 return 0;
         }
 
-        *o = (x << 3) | LOG_PRI(*o);
-
+        *o = (*o & LOG_FACMASK) | x;
         return 0;
 }
 
-int config_parse_log_level(
+int config_parse_signal(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -785,20 +836,50 @@ int config_parse_log_level(
                 void *data,
                 void *userdata) {
 
+        int *sig = data, r;
 
-        int *o = data, x;
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(sig);
+
+        r = signal_from_string_try_harder(rvalue);
+        if (r <= 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        *sig = r;
+        return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int config_parse_personality(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        unsigned long *personality = data, p;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
+        assert(personality);
 
-        x = log_level_from_string(rvalue);
-        if (x < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log level, ignoring: %s", rvalue);
+        p = personality_from_string(rvalue);
+        if (p == PERSONALITY_INVALID) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
                 return 0;
         }
 
-        *o = (*o & LOG_FACMASK) | x;
+        *personality = p;
         return 0;
 }
+#endif // 0