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);
60 if (n->starter_fd >= 0) {
61 close_nointr_nofail(n->starter_fd);
66 static int busname_add_default_default_dependencies(BusName *n) {
71 r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
75 if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
76 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
81 return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
84 static int busname_add_extras(BusName *n) {
91 n->name = unit_name_to_prefix(u->id);
96 if (!u->description) {
97 r = unit_set_description(u, n->name);
102 if (!UNIT_DEREF(n->service)) {
105 r = unit_load_related_unit(u, ".service", &x);
109 unit_ref_set(&n->service, x);
112 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
116 if (u->default_dependencies) {
117 r = busname_add_default_default_dependencies(n);
127 static int busname_verify(BusName *n) {
132 if (UNIT(n)->load_state != UNIT_LOADED)
135 if (!service_name_is_valid(n->name)) {
136 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
140 e = strappenda(n->name, ".busname");
141 if (!unit_has_name(UNIT(n), e)) {
142 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
149 static int busname_load(Unit *u) {
150 BusName *n = BUSNAME(u);
154 assert(u->load_state == UNIT_STUB);
156 r = unit_load_fragment_and_dropin(u);
160 if (u->load_state == UNIT_LOADED) {
161 /* This is a new unit? Then let's add in some extras */
162 r = busname_add_extras(n);
167 return busname_verify(n);
170 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
171 BusName *n = BUSNAME(u);
177 "%sBus Name State: %s\n"
180 prefix, busname_state_to_string(n->state),
181 prefix, busname_result_to_string(n->result),
185 static void busname_unwatch_fd(BusName *n) {
190 if (n->event_source) {
191 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
193 log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
197 static void busname_close_fd(BusName *n) {
200 busname_unwatch_fd(n);
202 if (n->starter_fd <= 0)
205 close_nointr_nofail(n->starter_fd);
209 static int busname_watch_fd(BusName *n) {
214 if (n->starter_fd < 0)
218 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
220 r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
222 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
223 busname_unwatch_fd(n);
230 static int busname_open_fd(BusName *n) {
233 if (n->starter_fd >= 0)
236 n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
238 if (n->starter_fd < 0) {
239 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
240 return n->starter_fd;
246 static void busname_set_state(BusName *n, BusNameState state) {
247 BusNameState old_state;
250 old_state = n->state;
253 if (state != BUSNAME_LISTENING)
254 busname_unwatch_fd(n);
256 if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
259 if (state != old_state)
260 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
261 UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
263 unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
266 static int busname_coldplug(Unit *u) {
267 BusName *n = BUSNAME(u);
271 assert(n->state == BUSNAME_DEAD);
273 if (n->deserialized_state == n->state)
276 if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
277 r = busname_open_fd(n);
282 if (n->deserialized_state == BUSNAME_LISTENING) {
283 r = busname_watch_fd(n);
288 busname_set_state(n, n->deserialized_state);
292 static void busname_enter_dead(BusName *n, BusNameResult f) {
295 if (f != BUSNAME_SUCCESS)
298 busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
301 static void busname_enter_listening(BusName *n) {
306 r = busname_open_fd(n);
308 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
312 r = busname_watch_fd(n);
314 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
318 busname_set_state(n, BUSNAME_LISTENING);
322 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
325 static void busname_enter_running(BusName *n) {
326 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
327 bool pending = false;
334 /* We don't take conenctions anymore if we are supposed to
335 * shut down anyway */
337 if (unit_stop_pending(UNIT(n))) {
338 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
340 /* Flush all queued activation reqeuest by closing and reopening the connection */
341 bus_kernel_drop_one(n->starter_fd);
343 busname_enter_listening(n);
347 /* If there's already a start pending don't bother to do
349 SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
350 if (unit_active_or_pending(other)) {
356 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
361 busname_set_state(n, BUSNAME_RUNNING);
365 log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
366 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
369 static int busname_start(Unit *u) {
370 BusName *n = BUSNAME(u);
374 if (UNIT_ISSET(n->service)) {
377 service = SERVICE(UNIT_DEREF(n->service));
379 if (UNIT(service)->load_state != UNIT_LOADED) {
380 log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
385 assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
387 n->result = BUSNAME_SUCCESS;
388 busname_enter_listening(n);
393 static int busname_stop(Unit *u) {
394 BusName *n = BUSNAME(u);
397 assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
399 busname_enter_dead(n, BUSNAME_SUCCESS);
403 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
404 BusName *n = BUSNAME(u);
410 unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
411 unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
413 if (n->starter_fd >= 0) {
416 copy = fdset_put_dup(fds, n->starter_fd);
420 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
426 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
427 BusName *n = BUSNAME(u);
433 if (streq(key, "state")) {
436 state = busname_state_from_string(value);
438 log_debug_unit(u->id, "Failed to parse state value %s", value);
440 n->deserialized_state = state;
442 } else if (streq(key, "result")) {
445 f = busname_result_from_string(value);
447 log_debug_unit(u->id, "Failed to parse result value %s", value);
448 else if (f != BUSNAME_SUCCESS)
451 } else if (streq(key, "starter-fd")) {
454 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
455 log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
457 if (n->starter_fd >= 0)
458 close_nointr_nofail(n->starter_fd);
459 n->starter_fd = fdset_remove(fds, fd);
462 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
467 _pure_ static UnitActiveState busname_active_state(Unit *u) {
470 return state_translation_table[BUSNAME(u)->state];
473 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
476 return busname_state_to_string(BUSNAME(u)->state);
479 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
480 BusName *n = userdata;
485 if (n->state != BUSNAME_LISTENING)
488 log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
490 if (revents != EPOLLIN) {
491 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
492 UNIT(n)->id, revents);
496 busname_enter_running(n);
500 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
504 static void busname_reset_failed(Unit *u) {
505 BusName *n = BUSNAME(u);
509 if (n->state == BUSNAME_FAILED)
510 busname_set_state(n, BUSNAME_DEAD);
512 n->result = BUSNAME_SUCCESS;
515 static void busname_trigger_notify(Unit *u, Unit *other) {
516 BusName *n = BUSNAME(u);
522 if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
525 if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
530 if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
531 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
532 else if (IN_SET(s->state,
533 SERVICE_DEAD, SERVICE_FAILED,
534 SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
535 SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
536 SERVICE_AUTO_RESTART))
537 busname_enter_listening(n);
540 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
541 [BUSNAME_DEAD] = "dead",
542 [BUSNAME_LISTENING] = "listening",
543 [BUSNAME_RUNNING] = "running",
544 [BUSNAME_FAILED] = "failed"
547 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
549 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
550 [BUSNAME_SUCCESS] = "success",
551 [BUSNAME_FAILURE_RESOURCES] = "resources",
552 [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
555 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
557 static const char* const busname_policy_access_table[_BUSNAME_POLICY_ACCESS_MAX] = {
558 [BUSNAME_POLICY_ACCESS_SEE] = "see",
559 [BUSNAME_POLICY_ACCESS_TALK] = "talk",
560 [BUSNAME_POLICY_ACCESS_OWN] = "own",
563 DEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
565 const UnitVTable busname_vtable = {
566 .object_size = sizeof(BusName),
572 .private_section = "BusName",
574 .init = busname_init,
575 .done = busname_done,
576 .load = busname_load,
578 .coldplug = busname_coldplug,
580 .dump = busname_dump,
582 .start = busname_start,
583 .stop = busname_stop,
585 .serialize = busname_serialize,
586 .deserialize_item = busname_deserialize_item,
588 .active_state = busname_active_state,
589 .sub_state_to_string = busname_sub_state_to_string,
591 .trigger_notify = busname_trigger_notify,
593 .reset_failed = busname_reset_failed,
595 .bus_interface = "org.freedesktop.systemd1.BusName",
596 .bus_vtable = bus_busname_vtable,
598 .status_message_formats = {
599 .finished_start_job = {
600 [JOB_DONE] = "Listening on %s.",
601 [JOB_FAILED] = "Failed to listen on %s.",
602 [JOB_DEPENDENCY] = "Dependency failed for %s.",
603 [JOB_TIMEOUT] = "Timed out starting %s.",
605 .finished_stop_job = {
606 [JOB_DONE] = "Closed %s.",
607 [JOB_FAILED] = "Failed stopping %s.",
608 [JOB_TIMEOUT] = "Timed out stopping %s.",