chiark / gitweb /
util: replace close_nointr_nofail() by a more useful safe_close()
[elogind.git] / src / core / busname.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "special.h"
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
25 #include "bus-util.h"
26 #include "service.h"
27 #include "dbus-busname.h"
28 #include "busname.h"
29
30 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
31         [BUSNAME_DEAD] = UNIT_INACTIVE,
32         [BUSNAME_LISTENING] = UNIT_ACTIVE,
33         [BUSNAME_RUNNING] = UNIT_ACTIVE,
34         [BUSNAME_FAILED] = UNIT_FAILED
35 };
36
37 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
38
39 static void busname_init(Unit *u) {
40         BusName *n = BUSNAME(u);
41
42         assert(u);
43         assert(u->load_state == UNIT_STUB);
44
45         n->starter_fd = -1;
46 }
47
48 static void busname_done(Unit *u) {
49         BusName *n = BUSNAME(u);
50
51         assert(u);
52
53         free(n->name);
54         n->name = NULL;
55
56         unit_ref_unset(&n->service);
57
58         n->event_source = sd_event_source_unref(n->event_source);
59         n->starter_fd = safe_close(n->starter_fd);
60 }
61
62 static int busname_add_default_default_dependencies(BusName *n) {
63         int r;
64
65         assert(n);
66
67         r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
68         if (r < 0)
69                 return r;
70
71         if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
72                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
73                 if (r < 0)
74                         return r;
75         }
76
77         return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
78 }
79
80 static int busname_add_extras(BusName *n) {
81         Unit *u = UNIT(n);
82         int r;
83
84         assert(n);
85
86         if (!n->name) {
87                 n->name = unit_name_to_prefix(u->id);
88                 if (!n->name)
89                         return -ENOMEM;
90         }
91
92         if (!u->description) {
93                 r = unit_set_description(u, n->name);
94                 if (r < 0)
95                         return r;
96         }
97
98         if (!UNIT_DEREF(n->service)) {
99                 Unit *x;
100
101                 r = unit_load_related_unit(u, ".service", &x);
102                 if (r < 0)
103                         return r;
104
105                 unit_ref_set(&n->service, x);
106         }
107
108         r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
109         if (r < 0)
110                 return r;
111
112         if (u->default_dependencies) {
113                 r = busname_add_default_default_dependencies(n);
114                 if (r < 0)
115                         return r;
116         }
117
118         return 0;
119 }
120
121 static int busname_verify(BusName *n) {
122         char *e;
123
124         assert(n);
125
126         if (UNIT(n)->load_state != UNIT_LOADED)
127                 return 0;
128
129         if (!service_name_is_valid(n->name)) {
130                 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
131                 return -EINVAL;
132         }
133
134         e = strappenda(n->name, ".busname");
135         if (!unit_has_name(UNIT(n), e)) {
136                 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
137                 return -EINVAL;
138         }
139
140         return 0;
141 }
142
143 static int busname_load(Unit *u) {
144         BusName *n = BUSNAME(u);
145         int r;
146
147         assert(u);
148         assert(u->load_state == UNIT_STUB);
149
150         r = unit_load_fragment_and_dropin(u);
151         if (r < 0)
152                 return r;
153
154         if (u->load_state == UNIT_LOADED) {
155                 /* This is a new unit? Then let's add in some extras */
156                 r = busname_add_extras(n);
157                 if (r < 0)
158                         return r;
159         }
160
161         return busname_verify(n);
162 }
163
164 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
165         BusName *n = BUSNAME(u);
166
167         assert(n);
168         assert(f);
169
170         fprintf(f,
171                 "%sBus Name State: %s\n"
172                 "%sResult: %s\n"
173                 "%sName: %s\n",
174                 prefix, busname_state_to_string(n->state),
175                 prefix, busname_result_to_string(n->result),
176                 prefix, n->name);
177 }
178
179 static void busname_unwatch_fd(BusName *n) {
180         int r;
181
182         assert(n);
183
184         if (n->event_source) {
185                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
186                 if (r < 0)
187                         log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
188         }
189 }
190
191 static void busname_close_fd(BusName *n) {
192         assert(n);
193
194         busname_unwatch_fd(n);
195
196         if (n->starter_fd <= 0)
197                 return;
198
199         n->starter_fd = safe_close(n->starter_fd);
200 }
201
202 static int busname_watch_fd(BusName *n) {
203         int r;
204
205         assert(n);
206
207         if (n->starter_fd < 0)
208                 return 0;
209
210         if (n->event_source)
211                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
212         else
213                 r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
214         if (r < 0) {
215                 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
216                 busname_unwatch_fd(n);
217                 return r;
218         }
219
220         return 0;
221 }
222
223 static int busname_open_fd(BusName *n) {
224         assert(n);
225
226         if (n->starter_fd >= 0)
227                 return 0;
228
229         n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
230                                                   n->name, n->policy);
231         if (n->starter_fd < 0) {
232                 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
233                 return n->starter_fd;
234         }
235
236         return 0;
237 }
238
239 static void busname_set_state(BusName *n, BusNameState state) {
240         BusNameState old_state;
241         assert(n);
242
243         old_state = n->state;
244         n->state = state;
245
246         if (state != BUSNAME_LISTENING)
247                 busname_unwatch_fd(n);
248
249         if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
250                 busname_close_fd(n);
251
252         if (state != old_state)
253                 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
254                                UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
255
256         unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
257 }
258
259 static int busname_coldplug(Unit *u) {
260         BusName *n = BUSNAME(u);
261         int r;
262
263         assert(n);
264         assert(n->state == BUSNAME_DEAD);
265
266         if (n->deserialized_state == n->state)
267                 return 0;
268
269         if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
270                 r = busname_open_fd(n);
271                 if (r < 0)
272                         return r;
273         }
274
275         if (n->deserialized_state == BUSNAME_LISTENING) {
276                 r = busname_watch_fd(n);
277                 if (r < 0)
278                         return r;
279         }
280
281         busname_set_state(n, n->deserialized_state);
282         return 0;
283 }
284
285 static void busname_enter_dead(BusName *n, BusNameResult f) {
286         assert(n);
287
288         if (f != BUSNAME_SUCCESS)
289                 n->result = f;
290
291         busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
292 }
293
294 static void busname_enter_listening(BusName *n) {
295         int r;
296
297         assert(n);
298
299         r = busname_open_fd(n);
300         if (r < 0) {
301                 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
302                 goto fail;
303         }
304
305         r = busname_watch_fd(n);
306         if (r < 0) {
307                 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
308                 goto fail;
309         }
310
311         busname_set_state(n, BUSNAME_LISTENING);
312         return;
313
314 fail:
315         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
316 }
317
318 static void busname_enter_running(BusName *n) {
319         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
320         bool pending = false;
321         Unit *other;
322         Iterator i;
323         int r;
324
325         assert(n);
326
327         /* We don't take conenctions anymore if we are supposed to
328          * shut down anyway */
329
330         if (unit_stop_pending(UNIT(n))) {
331                 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
332
333                 /* Flush all queued activation reqeuest by closing and reopening the connection */
334                 bus_kernel_drop_one(n->starter_fd);
335
336                 busname_enter_listening(n);
337                 return;
338         }
339
340         /* If there's already a start pending don't bother to do
341          * anything */
342         SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
343                 if (unit_active_or_pending(other)) {
344                         pending = true;
345                         break;
346                 }
347
348         if (!pending) {
349                 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
350                 if (r < 0)
351                         goto fail;
352         }
353
354         busname_set_state(n, BUSNAME_RUNNING);
355         return;
356
357 fail:
358         log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
359         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
360 }
361
362 static int busname_start(Unit *u) {
363         BusName *n = BUSNAME(u);
364
365         assert(n);
366
367         if (UNIT_ISSET(n->service)) {
368                 Service *service;
369
370                 service = SERVICE(UNIT_DEREF(n->service));
371
372                 if (UNIT(service)->load_state != UNIT_LOADED) {
373                         log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
374                         return -ENOENT;
375                 }
376         }
377
378         assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
379
380         n->result = BUSNAME_SUCCESS;
381         busname_enter_listening(n);
382
383         return 0;
384 }
385
386 static int busname_stop(Unit *u) {
387         BusName *n = BUSNAME(u);
388
389         assert(n);
390         assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
391
392         busname_enter_dead(n, BUSNAME_SUCCESS);
393         return 0;
394 }
395
396 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
397         BusName *n = BUSNAME(u);
398
399         assert(n);
400         assert(f);
401         assert(fds);
402
403         unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
404         unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
405
406         if (n->starter_fd >= 0) {
407                 int copy;
408
409                 copy = fdset_put_dup(fds, n->starter_fd);
410                 if (copy < 0)
411                         return copy;
412
413                 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
414         }
415
416         return 0;
417 }
418
419 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
420         BusName *n = BUSNAME(u);
421
422         assert(n);
423         assert(key);
424         assert(value);
425
426         if (streq(key, "state")) {
427                 BusNameState state;
428
429                 state = busname_state_from_string(value);
430                 if (state < 0)
431                         log_debug_unit(u->id, "Failed to parse state value %s", value);
432                 else
433                         n->deserialized_state = state;
434
435         } else if (streq(key, "result")) {
436                 BusNameResult f;
437
438                 f = busname_result_from_string(value);
439                 if (f < 0)
440                         log_debug_unit(u->id, "Failed to parse result value %s", value);
441                 else if (f != BUSNAME_SUCCESS)
442                         n->result = f;
443
444         } else if (streq(key, "starter-fd")) {
445                 int fd;
446
447                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
448                         log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
449                 else {
450                         safe_close(n->starter_fd);
451                         n->starter_fd = fdset_remove(fds, fd);
452                 }
453         } else
454                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
455
456         return 0;
457 }
458
459 _pure_ static UnitActiveState busname_active_state(Unit *u) {
460         assert(u);
461
462         return state_translation_table[BUSNAME(u)->state];
463 }
464
465 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
466         assert(u);
467
468         return busname_state_to_string(BUSNAME(u)->state);
469 }
470
471 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
472         BusName *n = userdata;
473
474         assert(n);
475         assert(fd >= 0);
476
477         if (n->state != BUSNAME_LISTENING)
478                 return 0;
479
480         log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
481
482         if (revents != EPOLLIN) {
483                 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
484                                UNIT(n)->id, revents);
485                 goto fail;
486         }
487
488         busname_enter_running(n);
489         return 0;
490 fail:
491
492         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
493         return 0;
494 }
495
496 static void busname_reset_failed(Unit *u) {
497         BusName *n = BUSNAME(u);
498
499         assert(n);
500
501         if (n->state == BUSNAME_FAILED)
502                 busname_set_state(n, BUSNAME_DEAD);
503
504         n->result = BUSNAME_SUCCESS;
505 }
506
507 static void busname_trigger_notify(Unit *u, Unit *other) {
508         BusName *n = BUSNAME(u);
509         Service *s;
510
511         assert(n);
512         assert(other);
513
514         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
515                 return;
516
517         if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
518                 return;
519
520         s = SERVICE(other);
521
522         if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
523                 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
524         else if (IN_SET(s->state,
525                         SERVICE_DEAD, SERVICE_FAILED,
526                         SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
527                         SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
528                         SERVICE_AUTO_RESTART))
529                 busname_enter_listening(n);
530 }
531
532 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
533         [BUSNAME_DEAD] = "dead",
534         [BUSNAME_LISTENING] = "listening",
535         [BUSNAME_RUNNING] = "running",
536         [BUSNAME_FAILED] = "failed"
537 };
538
539 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
540
541 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
542         [BUSNAME_SUCCESS] = "success",
543         [BUSNAME_FAILURE_RESOURCES] = "resources",
544         [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
545 };
546
547 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
548
549 static const char* const busname_policy_access_table[_BUSNAME_POLICY_ACCESS_MAX] = {
550         [BUSNAME_POLICY_ACCESS_SEE] = "see",
551         [BUSNAME_POLICY_ACCESS_TALK] = "talk",
552         [BUSNAME_POLICY_ACCESS_OWN] = "own",
553 };
554
555 DEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
556
557 const UnitVTable busname_vtable = {
558         .object_size = sizeof(BusName),
559
560         .sections =
561                 "Unit\0"
562                 "BusName\0"
563                 "Install\0",
564         .private_section = "BusName",
565
566         .init = busname_init,
567         .done = busname_done,
568         .load = busname_load,
569
570         .coldplug = busname_coldplug,
571
572         .dump = busname_dump,
573
574         .start = busname_start,
575         .stop = busname_stop,
576
577         .serialize = busname_serialize,
578         .deserialize_item = busname_deserialize_item,
579
580         .active_state = busname_active_state,
581         .sub_state_to_string = busname_sub_state_to_string,
582
583         .trigger_notify = busname_trigger_notify,
584
585         .reset_failed = busname_reset_failed,
586
587         .bus_interface = "org.freedesktop.systemd1.BusName",
588         .bus_vtable = bus_busname_vtable,
589
590         .status_message_formats = {
591                 .finished_start_job = {
592                         [JOB_DONE]       = "Listening on %s.",
593                         [JOB_FAILED]     = "Failed to listen on %s.",
594                         [JOB_DEPENDENCY] = "Dependency failed for %s.",
595                         [JOB_TIMEOUT]    = "Timed out starting %s.",
596                 },
597                 .finished_stop_job = {
598                         [JOB_DONE]       = "Closed %s.",
599                         [JOB_FAILED]     = "Failed stopping %s.",
600                         [JOB_TIMEOUT]    = "Timed out stopping %s.",
601                 },
602         },
603 };