chiark / gitweb /
first attempt in implementinging execution logic
[elogind.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 }