#include <netinet/ether.h>
#include "conf-parser.h"
+#include "conf-files.h"
#include "util.h"
#include "macro.h"
#include "strv.h"
#include "exit-status.h"
#include "sd-messages.h"
-int log_syntax_internal(const char *unit, int level,
- const char *file, unsigned line, const char *func,
- const char *config_file, unsigned config_line,
- int error, const char *format, ...) {
+int log_syntax_internal(
+ const char *unit,
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *config_file,
+ unsigned config_line,
+ int error,
+ const char *format, ...) {
_cleanup_free_ char *msg = NULL;
int r;
if (unit)
r = log_struct_internal(level,
+ error,
file, line, func,
getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
- MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
+ LOG_MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
"CONFIG_FILE=%s", config_file,
"CONFIG_LINE=%u", config_line,
- "ERRNO=%d", error > 0 ? error : EINVAL,
- "MESSAGE=[%s:%u] %s", config_file, config_line, msg,
+ LOG_MESSAGE("[%s:%u] %s", config_file, config_line, msg),
NULL);
else
r = log_struct_internal(level,
+ error,
file, line, func,
- MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
+ LOG_MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
"CONFIG_FILE=%s", config_file,
"CONFIG_LINE=%u", config_line,
- "ERRNO=%d", error > 0 ? error : EINVAL,
- "MESSAGE=[%s:%u] %s", config_file, config_line, msg,
+ LOG_MESSAGE("[%s:%u] %s", config_file, config_line, msg),
NULL);
return r;
}
int config_item_table_lookup(
- void *table,
+ const void *table,
const char *section,
const char *lvalue,
ConfigParserCallback *func,
void **data,
void *userdata) {
- ConfigTableItem *t;
+ const ConfigTableItem *t;
assert(table);
assert(lvalue);
}
int config_item_perf_lookup(
- void *table,
+ const void *table,
const char *section,
const char *lvalue,
ConfigParserCallback *func,
const char *filename,
unsigned line,
ConfigItemLookup lookup,
- void *table,
+ const void *table,
const char *section,
unsigned section_line,
const char *lvalue,
unsigned line,
const char *sections,
ConfigItemLookup lookup,
- void *table,
+ const void *table,
bool relaxed,
bool allow_include,
char **section,
unsigned *section_line,
+ bool *section_ignored,
char *l,
void *userdata) {
if (!fn)
return -ENOMEM;
- return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, userdata);
+ return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata);
}
if (*l == '[') {
if (sections && !nulstr_contains(sections, n)) {
- if (!relaxed)
+ if (!relaxed && !startswith(n, "X-"))
log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Unknown section '%s'. Ignoring.", n);
free(*section);
*section = NULL;
*section_line = 0;
+ *section_ignored = true;
} else {
free(*section);
*section = n;
*section_line = line;
+ *section_ignored = false;
}
return 0;
if (sections && !*section) {
- if (!relaxed)
+ if (!relaxed && !*section_ignored)
log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Assignment outside of section. Ignoring.");
FILE *f,
const char *sections,
ConfigItemLookup lookup,
- void *table,
+ const void *table,
bool relaxed,
bool allow_include,
+ bool warn,
void *userdata) {
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
unsigned line = 0, section_line = 0;
+ bool section_ignored = false;
int r;
assert(filename);
if (!f) {
f = ours = fopen(filename, "re");
if (!f) {
- log_error("Failed to open configuration file '%s': %m", filename);
- return -errno;
+ /* Only log on request, except for ENOENT,
+ * since we return 0 to the caller. */
+ if (warn || errno == ENOENT)
+ log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
+ "Failed to open configuration file '%s': %m", filename);
+ return errno == ENOENT ? 0 : -errno;
}
}
if (feof(f))
break;
- log_error("Failed to read configuration file '%s': %m", filename);
+ log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
return -errno;
}
if (continuation) {
c = strappend(continuation, l);
- if (!c)
+ if (!c) {
+ if (warn)
+ log_oom();
return -ENOMEM;
+ }
free(continuation);
continuation = NULL;
continuation = c;
else {
continuation = strdup(l);
- if (!continuation)
+ if (!continuation) {
+ if (warn)
+ log_oom();
return -ENOMEM;
+ }
}
continue;
allow_include,
§ion,
§ion_line,
+ §ion_ignored,
p,
userdata);
free(c);
+ if (r < 0) {
+ if (warn)
+ log_warning_errno(r, "Failed to parse file '%s': %m",
+ filename);
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+/* Parse each config file in the specified directories. */
+int config_parse_many(const char *conf_file,
+ const char *conf_file_dirs,
+ const char *sections,
+ ConfigItemLookup lookup,
+ const void *table,
+ bool relaxed,
+ void *userdata) {
+ _cleanup_strv_free_ char **files = NULL;
+ char **fn;
+ int r;
+
+ r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+ if (r < 0)
+ return r;
+
+ if (conf_file) {
+ r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata);
+ if (r < 0)
+ return r;
+ }
+
+ STRV_FOREACH(fn, files) {
+ r = config_parse(NULL, *fn, NULL, sections, lookup, table, relaxed, false, true, userdata);
if (r < 0)
return r;
}
return 0;
}
-int config_parse_string(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 config_parse_string(
+ 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) {
- char **s = data;
- char *n;
+ char **s = data, *n;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- n = strdup(rvalue);
- if (!n)
- return log_oom();
-
- if (!utf8_is_valid(n)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "String is not UTF-8 clean, ignoring assignment: %s", rvalue);
- free(n);
+ if (!utf8_is_valid(rvalue)) {
+ log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
return 0;
}
- free(*s);
- if (*n)
- *s = n;
+ if (isempty(rvalue))
+ n = NULL;
else {
- free(n);
- *s = NULL;
+ n = strdup(rvalue);
+ if (!n)
+ return log_oom();
}
+ free(*s);
+ *s = n;
+
return 0;
}
-int config_parse_path(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 config_parse_path(
+ 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) {
- char **s = data;
- char *n;
- int offset;
+ char **s = data, *n;
assert(filename);
assert(lvalue);
assert(data);
if (!utf8_is_valid(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+ log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
return 0;
}
- offset = rvalue[0] == '-' && (streq(lvalue, "InaccessibleDirectories") ||
- streq(lvalue, "ReadOnlyDirectories"));
- if (!path_is_absolute(rvalue + offset)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Not an absolute path, ignoring: %s", rvalue);
+ if (!path_is_absolute(rvalue)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
return 0;
}
void *data,
void *userdata) {
- char *** sv = data, *w, *state;
+ char ***sv = data;
+ const char *word, *state;
size_t l;
int r;
return 0;
}
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- _cleanup_free_ char *n;
+ FOREACH_WORD_QUOTED(word, l, rvalue, state) {
+ char *n;
- n = cunescape_length(w, l);
+ n = strndup(word, l);
if (!n)
return log_oom();
if (!utf8_is_valid(n)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "String is not UTF-8 clean, ignoring: %s", rvalue);
+ log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+ free(n);
continue;
}
- r = strv_extend(sv, n);
+ r = strv_consume(sv, n);
if (r < 0)
return log_oom();
}
+ if (!isempty(state))
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Trailing garbage, ignoring.");
return 0;
}
x = log_facility_unshifted_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, EINVAL, "Failed to parse log facility, ignoring: %s", rvalue);
return 0;
}
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);
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log level, ignoring: %s", rvalue);
return 0;
}