]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
edfea9fe ZJS |
2 | |
3 | #include <stdlib.h> | |
4 | ||
e82116e5 | 5 | #include "analyze.h" |
edfea9fe | 6 | #include "analyze-condition.h" |
f2562398 | 7 | #include "analyze-verify-util.h" |
edfea9fe ZJS |
8 | #include "condition.h" |
9 | #include "conf-parser.h" | |
10 | #include "load-fragment.h" | |
11 | #include "service.h" | |
12 | ||
edfea9fe | 13 | static int parse_condition(Unit *u, const char *line) { |
625a1640 LP |
14 | assert(u); |
15 | assert(line); | |
16 | ||
17 | for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) { | |
18 | ConfigParserCallback callback; | |
19 | Condition **target; | |
20 | const char *p, *name; | |
21 | ||
22 | name = condition_type_to_string(t); | |
23 | p = startswith(line, name); | |
24 | if (p) | |
25 | target = &u->conditions; | |
26 | else { | |
27 | name = assert_type_to_string(t); | |
28 | p = startswith(line, name); | |
29 | if (!p) | |
30 | continue; | |
31 | ||
32 | target = &u->asserts; | |
33 | } | |
08ef6886 | 34 | |
edfea9fe | 35 | p += strspn(p, WHITESPACE); |
08ef6886 | 36 | |
edfea9fe | 37 | if (*p != '=') |
08ef6886 LP |
38 | continue; |
39 | p++; | |
edfea9fe | 40 | |
08ef6886 | 41 | p += strspn(p, WHITESPACE); |
edfea9fe | 42 | |
476cfe62 | 43 | if (condition_takes_path(t)) |
625a1640 LP |
44 | callback = config_parse_unit_condition_path; |
45 | else | |
46 | callback = config_parse_unit_condition_string; | |
47 | ||
48 | return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u); | |
edfea9fe ZJS |
49 | } |
50 | ||
51 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); | |
52 | } | |
53 | ||
54 | _printf_(7, 8) | |
55 | static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) { | |
99534007 | 56 | Unit *u = ASSERT_PTR(userdata); |
edfea9fe ZJS |
57 | va_list ap; |
58 | int r; | |
59 | ||
edfea9fe ZJS |
60 | /* "upgrade" debug messages */ |
61 | level = MIN(LOG_INFO, level); | |
62 | ||
63 | va_start(ap, format); | |
64 | r = log_object_internalv(level, error, file, line, func, | |
65 | NULL, | |
66 | u->id, | |
67 | NULL, | |
68 | NULL, | |
69 | format, ap); | |
70 | va_end(ap); | |
71 | ||
72 | return r; | |
73 | } | |
74 | ||
4870133b | 75 | static int verify_conditions(char **lines, RuntimeScope scope, const char *unit, const char *root) { |
edfea9fe ZJS |
76 | _cleanup_(manager_freep) Manager *m = NULL; |
77 | Unit *u; | |
edfea9fe ZJS |
78 | int r, q = 1; |
79 | ||
8de7929d | 80 | if (unit) { |
ff7af46e | 81 | r = verify_set_unit_path(STRV_MAKE(unit)); |
8de7929d | 82 | if (r < 0) |
ff7af46e | 83 | return log_error_errno(r, "Failed to set unit load path: %m"); |
8de7929d DDM |
84 | } |
85 | ||
bed6bffc | 86 | r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL|MANAGER_TEST_DONT_OPEN_EXECUTOR, &m); |
edfea9fe ZJS |
87 | if (r < 0) |
88 | return log_error_errno(r, "Failed to initialize manager: %m"); | |
89 | ||
90 | log_debug("Starting manager..."); | |
8de7929d | 91 | r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, root); |
edfea9fe ZJS |
92 | if (r < 0) |
93 | return r; | |
94 | ||
8de7929d DDM |
95 | if (unit) { |
96 | _cleanup_free_ char *prepared = NULL; | |
edfea9fe | 97 | |
8de7929d DDM |
98 | r = verify_prepare_filename(unit, &prepared); |
99 | if (r < 0) | |
100 | return log_error_errno(r, "Failed to prepare filename %s: %m", unit); | |
101 | ||
102 | r = manager_load_startable_unit_or_warn(m, NULL, prepared, &u); | |
edfea9fe ZJS |
103 | if (r < 0) |
104 | return r; | |
8de7929d | 105 | } else { |
8de7929d DDM |
106 | r = unit_new_for_name(m, sizeof(Service), "test.service", &u); |
107 | if (r < 0) | |
108 | return log_error_errno(r, "Failed to create test.service: %m"); | |
109 | ||
110 | STRV_FOREACH(line, lines) { | |
111 | r = parse_condition(u, *line); | |
112 | if (r < 0) | |
113 | return r; | |
114 | } | |
edfea9fe ZJS |
115 | } |
116 | ||
f24590df RP |
117 | condition_test_logger_t logger = arg_quiet ? NULL : log_helper; |
118 | r = condition_test_list(u->asserts, environ, assert_type_to_string, logger, u); | |
edfea9fe | 119 | if (u->asserts) |
f24590df | 120 | log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE, "Asserts %s.", r > 0 ? "succeeded" : "failed"); |
edfea9fe | 121 | |
f24590df | 122 | q = condition_test_list(u->conditions, environ, condition_type_to_string, logger, u); |
edfea9fe | 123 | if (u->conditions) |
f24590df | 124 | log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE, "Conditions %s.", q > 0 ? "succeeded" : "failed"); |
edfea9fe ZJS |
125 | |
126 | return r > 0 && q > 0 ? 0 : -EIO; | |
127 | } | |
e82116e5 | 128 | |
ef38bedb | 129 | int verb_condition(int argc, char *argv[], void *userdata) { |
fddad5f4 ZJS |
130 | int r; |
131 | ||
4870133b | 132 | r = verify_conditions(strv_skip(argv, 1), arg_runtime_scope, arg_unit, arg_root); |
fddad5f4 ZJS |
133 | if (r < 0) |
134 | return r; | |
135 | ||
136 | return EXIT_SUCCESS; | |
e82116e5 | 137 | } |