1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
27 #include "dbus-busname.h"
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
37 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
39 static void busname_init(Unit *u) {
40 BusName *n = BUSNAME(u);
43 assert(u->load_state == UNIT_STUB);
48 static void busname_done(Unit *u) {
49 BusName *n = BUSNAME(u);
56 unit_ref_unset(&n->service);
58 n->event_source = sd_event_source_unref(n->event_source);
59 n->starter_fd = safe_close(n->starter_fd);
62 static int busname_add_default_default_dependencies(BusName *n) {
67 r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
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);
77 return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
80 static int busname_add_extras(BusName *n) {
87 n->name = unit_name_to_prefix(u->id);
92 if (!u->description) {
93 r = unit_set_description(u, n->name);
98 if (!UNIT_DEREF(n->service)) {
101 r = unit_load_related_unit(u, ".service", &x);
105 unit_ref_set(&n->service, x);
108 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
112 if (u->default_dependencies) {
113 r = busname_add_default_default_dependencies(n);
121 static int busname_verify(BusName *n) {
126 if (UNIT(n)->load_state != UNIT_LOADED)
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);
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);
143 static int busname_load(Unit *u) {
144 BusName *n = BUSNAME(u);
148 assert(u->load_state == UNIT_STUB);
150 r = unit_load_fragment_and_dropin(u);
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);
161 return busname_verify(n);
164 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
165 BusName *n = BUSNAME(u);
171 "%sBus Name State: %s\n"
174 prefix, busname_state_to_string(n->state),
175 prefix, busname_result_to_string(n->result),
179 static void busname_unwatch_fd(BusName *n) {
184 if (n->event_source) {
185 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
187 log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
191 static void busname_close_fd(BusName *n) {
194 busname_unwatch_fd(n);
196 if (n->starter_fd <= 0)
199 n->starter_fd = safe_close(n->starter_fd);
202 static int busname_watch_fd(BusName *n) {
207 if (n->starter_fd < 0)
211 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
213 r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
215 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
216 busname_unwatch_fd(n);
223 static int busname_open_fd(BusName *n) {
226 if (n->starter_fd >= 0)
229 n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
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;
239 static void busname_set_state(BusName *n, BusNameState state) {
240 BusNameState old_state;
243 old_state = n->state;
246 if (state != BUSNAME_LISTENING)
247 busname_unwatch_fd(n);
249 if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
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));
256 unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
259 static int busname_coldplug(Unit *u) {
260 BusName *n = BUSNAME(u);
264 assert(n->state == BUSNAME_DEAD);
266 if (n->deserialized_state == n->state)
269 if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
270 r = busname_open_fd(n);
275 if (n->deserialized_state == BUSNAME_LISTENING) {
276 r = busname_watch_fd(n);
281 busname_set_state(n, n->deserialized_state);
285 static void busname_enter_dead(BusName *n, BusNameResult f) {
288 if (f != BUSNAME_SUCCESS)
291 busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
294 static void busname_enter_listening(BusName *n) {
299 r = busname_open_fd(n);
301 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
305 r = busname_watch_fd(n);
307 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
311 busname_set_state(n, BUSNAME_LISTENING);
315 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
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;
327 /* We don't take conenctions anymore if we are supposed to
328 * shut down anyway */
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);
333 /* Flush all queued activation reqeuest by closing and reopening the connection */
334 bus_kernel_drop_one(n->starter_fd);
336 busname_enter_listening(n);
340 /* If there's already a start pending don't bother to do
342 SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
343 if (unit_active_or_pending(other)) {
349 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
354 busname_set_state(n, BUSNAME_RUNNING);
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);
362 static int busname_start(Unit *u) {
363 BusName *n = BUSNAME(u);
367 if (UNIT_ISSET(n->service)) {
370 service = SERVICE(UNIT_DEREF(n->service));
372 if (UNIT(service)->load_state != UNIT_LOADED) {
373 log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
378 assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
380 n->result = BUSNAME_SUCCESS;
381 busname_enter_listening(n);
386 static int busname_stop(Unit *u) {
387 BusName *n = BUSNAME(u);
390 assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
392 busname_enter_dead(n, BUSNAME_SUCCESS);
396 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
397 BusName *n = BUSNAME(u);
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));
406 if (n->starter_fd >= 0) {
409 copy = fdset_put_dup(fds, n->starter_fd);
413 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
419 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
420 BusName *n = BUSNAME(u);
426 if (streq(key, "state")) {
429 state = busname_state_from_string(value);
431 log_debug_unit(u->id, "Failed to parse state value %s", value);
433 n->deserialized_state = state;
435 } else if (streq(key, "result")) {
438 f = busname_result_from_string(value);
440 log_debug_unit(u->id, "Failed to parse result value %s", value);
441 else if (f != BUSNAME_SUCCESS)
444 } else if (streq(key, "starter-fd")) {
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);
450 safe_close(n->starter_fd);
451 n->starter_fd = fdset_remove(fds, fd);
454 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
459 _pure_ static UnitActiveState busname_active_state(Unit *u) {
462 return state_translation_table[BUSNAME(u)->state];
465 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
468 return busname_state_to_string(BUSNAME(u)->state);
471 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
472 BusName *n = userdata;
477 if (n->state != BUSNAME_LISTENING)
480 log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
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);
488 busname_enter_running(n);
492 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
496 static void busname_reset_failed(Unit *u) {
497 BusName *n = BUSNAME(u);
501 if (n->state == BUSNAME_FAILED)
502 busname_set_state(n, BUSNAME_DEAD);
504 n->result = BUSNAME_SUCCESS;
507 static void busname_trigger_notify(Unit *u, Unit *other) {
508 BusName *n = BUSNAME(u);
514 if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
517 if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
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);
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"
539 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
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",
547 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
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",
555 DEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
557 const UnitVTable busname_vtable = {
558 .object_size = sizeof(BusName),
564 .private_section = "BusName",
566 .init = busname_init,
567 .done = busname_done,
568 .load = busname_load,
570 .coldplug = busname_coldplug,
572 .dump = busname_dump,
574 .start = busname_start,
575 .stop = busname_stop,
577 .serialize = busname_serialize,
578 .deserialize_item = busname_deserialize_item,
580 .active_state = busname_active_state,
581 .sub_state_to_string = busname_sub_state_to_string,
583 .trigger_notify = busname_trigger_notify,
585 .reset_failed = busname_reset_failed,
587 .bus_interface = "org.freedesktop.systemd1.BusName",
588 .bus_vtable = bus_busname_vtable,
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.",
597 .finished_stop_job = {
598 [JOB_DONE] = "Closed %s.",
599 [JOB_FAILED] = "Failed stopping %s.",
600 [JOB_TIMEOUT] = "Timed out stopping %s.",