]> git.ipfire.org Git - thirdparty/systemd.git/blob - load-fragment.c
first attempt in implementinging execution logic
[thirdparty/systemd.git] / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 #include <assert.h>
4 #include <errno.h>
5 #include <string.h>
6
7 #include "name.h"
8 #include "strv.h"
9 #include "conf-parser.h"
10 #include "load-fragment.h"
11 #include "log.h"
12
13 static int config_parse_deps(
14 const char *filename,
15 unsigned line,
16 const char *section,
17 const char *lvalue,
18 const char *rvalue,
19 void *data,
20 void *userdata) {
21
22 Set **set = data;
23 Name *name = userdata;
24 char *w;
25 size_t l;
26 char *state;
27
28 assert(filename);
29 assert(lvalue);
30 assert(rvalue);
31 assert(data);
32
33 FOREACH_WORD(w, &l, rvalue, state) {
34 char *t;
35 int r;
36 Name *other;
37
38 if (!(t = strndup(w, l)))
39 return -ENOMEM;
40
41 r = manager_load_name(name->meta.manager, t, &other);
42 free(t);
43
44 if (r < 0)
45 return r;
46
47 if (!*set)
48 if (!(*set = set_new(trivial_hash_func, trivial_compare_func)))
49 return -ENOMEM;
50
51 if ((r = set_put(*set, other)) < 0)
52 return r;
53 }
54
55 return 0;
56 }
57
58 static int config_parse_names(
59 const char *filename,
60 unsigned line,
61 const char *section,
62 const char *lvalue,
63 const char *rvalue,
64 void *data,
65 void *userdata) {
66
67 Set **set = data;
68 Name *name = userdata;
69 char *w;
70 size_t l;
71 char *state;
72
73 assert(filename);
74 assert(lvalue);
75 assert(rvalue);
76 assert(data);
77
78 FOREACH_WORD(w, &l, rvalue, state) {
79 char *t;
80 int r;
81 Name *other;
82
83 if (!(t = strndup(w, l)))
84 return -ENOMEM;
85
86 other = manager_get_name(name->meta.manager, t);
87
88 if (other) {
89
90 if (other != name) {
91
92 if (other->meta.load_state != NAME_STUB) {
93 free(t);
94 return -EEXIST;
95 }
96
97 if ((r = name_merge(name, other)) < 0) {
98 free(t);
99 return r;
100 }
101 }
102
103 } else {
104
105 if (!*set)
106 if (!(*set = set_new(trivial_hash_func, trivial_compare_func))) {
107 free(t);
108 return -ENOMEM;
109 }
110
111 if ((r = set_put(*set, t)) < 0) {
112 free(t);
113 return r;
114 }
115
116 t = NULL;
117 }
118
119 free(t);
120 }
121
122 return 0;
123 }
124
125 static int config_parse_listen(
126 const char *filename,
127 unsigned line,
128 const char *section,
129 const char *lvalue,
130 const char *rvalue,
131 void *data,
132 void *userdata) {
133
134 int r;
135
136 assert(filename);
137 assert(lvalue);
138 assert(rvalue);
139 assert(data);
140
141 if ((r = address_parse(data, rvalue)) < 0) {
142 log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
143 return r;
144 }
145
146 return 0;
147 }
148
149 static int config_parse_type(
150 const char *filename,
151 unsigned line,
152 const char *section,
153 const char *lvalue,
154 const char *rvalue,
155 void *data,
156 void *userdata) {
157
158 int *type = data;
159
160 assert(filename);
161 assert(lvalue);
162 assert(rvalue);
163 assert(data);
164
165 if (streq(rvalue, "stream"))
166 *type = SOCK_STREAM;
167 else if (streq(rvalue, "dgram"))
168 *type = SOCK_DGRAM;
169 else {
170 log_error("[%s:%u] Failed to parse socket type value: %s", filename, line, rvalue);
171 return -EINVAL;
172 }
173
174 return 0;
175 }
176
177 int name_load_fragment(Name *n) {
178
179 static const char* const section_table[_NAME_TYPE_MAX] = {
180 [NAME_SERVICE] = "Service",
181 [NAME_TIMER] = "Timer",
182 [NAME_SOCKET] = "Socket",
183 [NAME_MILESTONE] = "Milestone",
184 [NAME_DEVICE] = "Device",
185 [NAME_MOUNT] = "Mount",
186 [NAME_AUTOMOUNT] = "Automount",
187 [NAME_SNAPSHOT] = "Snapshot"
188 };
189
190 const ConfigItem items[] = {
191 { "Names", config_parse_names, &n->meta.names, "Meta" },
192 { "Description", config_parse_string, &n->meta.description, "Meta" },
193 { "Requires", config_parse_deps, n->meta.dependencies+NAME_REQUIRES, "Meta" },
194 { "SoftRequires", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUIRES, "Meta" },
195 { "Wants", config_parse_deps, n->meta.dependencies+NAME_WANTS, "Meta" },
196 { "Requisite", config_parse_deps, n->meta.dependencies+NAME_REQUISITE, "Meta" },
197 { "SoftRequisite", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUISITE, "Meta" },
198 { "Conflicts", config_parse_deps, n->meta.dependencies+NAME_CONFLICTS, "Meta" },
199 { "Before", config_parse_deps, n->meta.dependencies+NAME_BEFORE, "Meta" },
200 { "After", config_parse_deps, n->meta.dependencies+NAME_AFTER, "Meta" },
201 { "Listen", config_parse_listen, &n->socket.address, "Socket" },
202 { "Type", config_parse_type, &n->socket.address.type, "Socket" },
203 { NULL, NULL, NULL, NULL }
204 };
205
206 const
207
208 char *t;
209 int r;
210 void *state;
211 const char *sections[3];
212
213 assert(n);
214 assert(n->meta.load_state == NAME_STUB);
215
216 sections[0] = "Meta";
217 sections[1] = section_table[n->meta.type];
218 sections[2] = NULL;
219
220 SET_FOREACH(t, n->meta.names, state)
221 if ((r = config_parse(t, sections, items, n)) < 0)
222 goto fail;
223
224 r = 0;
225
226 fail:
227 return r;
228 }