assert(b);
assert(!b->track_queue);
+ assert(!b->tracks);
b->state = BUS_CLOSED;
return 0;
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
char *p, **a;
return free_and_strdup(&bus->description, description);
}
-#endif // 0
_public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
return 0;
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) {
assert_return(bus, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->allow_interactive_authorization;
}
-#endif // 0
static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
const char *s;
b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
}
+ b->is_local = true;
+
return 0;
}
freeaddrinfo(result);
+ b->is_local = false;
+
return 0;
}
b->exec_path = path;
b->exec_argv = argv;
+
+ b->is_local = false;
+
return 0;
fail:
b->kernel = path;
path = NULL;
+ b->is_local = true;
+
return 0;
}
b->sockaddr.un.sun_family = AF_UNIX;
strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
- b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen("/var/run/dbus/system_bus_socket");
+ b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
+ b->is_local = false;
return 0;
}
if (r < 0)
return r;
+ b->is_local = false;
+
return 0;
}
return sd_bus_open_user(ret);
else
#endif // 0
- return sd_bus_open_system(ret);
+ return sd_bus_open_system(ret);
}
r = sd_bus_new(&b);
/* We don't know whether the bus is trusted or not, so better
* be safe, and authenticate everything */
b->trusted = false;
+ b->is_local = false;
b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
b->trusted = false;
b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
+ b->is_local = true;
r = sd_bus_start(b);
if (r < 0)
/* We don't do any per-method access control on the user
* bus. */
b->trusted = true;
+ b->is_local = true;
r = sd_bus_start(b);
if (r < 0)
return -ENOMEM;
}
- b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c, NULL);
+ b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c);
if (!b->address)
return -ENOMEM;
bus->bus_client = true;
bus->trusted = false;
bus->is_system = true;
+ bus->is_local = false;
r = sd_bus_start(bus);
if (r < 0)
if (!e)
return -ENOMEM;
- b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
+ b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e);
if (!b->address)
return -ENOMEM;
bus->bus_client = true;
bus->trusted = false;
bus->is_system = true;
+ bus->is_local = false;
r = sd_bus_start(bus);
if (r < 0)
return NULL;
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_is_open(sd_bus *bus) {
assert_return(bus, -EINVAL);
return BUS_IS_OPEN(bus->state);
}
-#endif // 0
_public_ int sd_bus_can_send(sd_bus *bus, char type) {
int r;
return bus_type_is_valid(type);
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
int r;
*id = bus->server_id;
return 0;
}
-#endif // 0
static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
assert(b);
return bus_send_internal(bus, m, cookie, false);
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
int r;
return sd_bus_send(bus, m, cookie);
}
-#endif // 0
static usec_t calc_elapse(uint64_t usec) {
if (usec == (uint64_t) -1)
} else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
r = sd_bus_error_copy(error, &incoming->error);
- sd_bus_message_unref(incoming);
- return r;
+ sd_bus_message_unref(incoming);
+ return r;
} else {
r = -EIO;
goto fail;
return sd_bus_error_set_errno(error, r);
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_get_fd(sd_bus *bus) {
assert_return(bus, -EINVAL);
return bus->input_fd;
}
-#endif // 0
_public_ int sd_bus_get_events(sd_bus *bus) {
int flags = 0;
return r;
}
-static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+static int bus_exit_now(sd_bus *bus) {
+ assert(bus);
+
+ /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
+ * sd_event_exit(), otherwise invokes libc exit(). */
+
+ if (bus->exited) /* did we already exit? */
+ return 0;
+ if (!bus->exit_triggered) /* was the exit condition triggered? */
+ return 0;
+ if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
+ return 0;
+
+ bus->exited = true; /* never exit more than once */
+
+ log_debug("Bus connection disconnected, exiting.");
+
+ if (bus->event)
+ return sd_event_exit(bus->event, EXIT_FAILURE);
+ else
+ exit(EXIT_FAILURE);
+
+ assert_not_reached("exit() didn't exit?");
+}
+
+static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct reply_callback *c;
+ sd_bus_slot *slot;
int r;
assert(bus);
- assert(bus->state == BUS_CLOSING);
+ assert(c);
- c = ordered_hashmap_first(bus->reply_callbacks);
- if (c) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->cookie,
+ &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+ &m);
+ if (r < 0)
+ return r;
- /* First, fail all outstanding method calls */
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
- &m);
- if (r < 0)
- return r;
+ r = bus_seal_synthetic_message(bus, m);
+ if (r < 0)
+ return r;
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
+ if (c->timeout != 0) {
+ prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
+ ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
+ slot = container_of(c, sd_bus_slot, reply_callback);
- slot = container_of(c, sd_bus_slot, reply_callback);
+ bus->iteration_counter++;
- bus->iteration_counter++;
+ bus->current_message = m;
+ bus->current_slot = sd_bus_slot_ref(slot);
+ bus->current_handler = c->callback;
+ bus->current_userdata = slot->userdata;
+ r = c->callback(m, slot->userdata, &error_buffer);
+ bus->current_userdata = NULL;
+ bus->current_handler = NULL;
+ bus->current_slot = NULL;
+ bus->current_message = NULL;
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
+ if (slot->floating) {
+ bus_slot_disconnect(slot);
+ sd_bus_slot_unref(slot);
+ }
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
+ sd_bus_slot_unref(slot);
- sd_bus_slot_unref(slot);
+ return bus_maybe_reply_error(m, r, &error_buffer);
+}
+
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct reply_callback *c;
+ int r;
+
+ assert(bus);
+ assert(bus->state == BUS_CLOSING);
- return bus_maybe_reply_error(m, r, &error_buffer);
+ /* First, fail all outstanding method calls */
+ c = ordered_hashmap_first(bus->reply_callbacks);
+ if (c)
+ return process_closing_reply_callback(bus, c);
+
+ /* Then, fake-drop all remaining bus tracking references */
+ if (bus->tracks) {
+ bus_track_close(bus->tracks);
+ return 1;
}
/* Then, synthesize a Disconnected message */
if (r != 0)
goto finish;
+ /* Nothing else to do, exit now, if the condition holds */
+ bus->exit_triggered = true;
+ (void) bus_exit_now(bus);
+
if (ret) {
*ret = m;
m = NULL;
return bus_process_internal(bus, false, 0, ret);
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_message **ret) {
return bus_process_internal(bus, true, priority, ret);
}
-#endif // 0
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
struct pollfd p[2] = {};
}
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_add_filter(
sd_bus *bus,
sd_bus_slot **slot,
return 0;
}
-#endif // 0
_public_ int sd_bus_add_match(
sd_bus *bus,
return bus->current_message;
}
-#if 0 /// UNNEEDED by elogind
_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) {
assert_return(bus, NULL);
return bus->current_slot;
}
-#endif // 0
_public_ sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus) {
assert_return(bus, NULL);
return sd_bus_default_user(ret);
else
#endif // 0
- return sd_bus_default_system(ret);
+ return sd_bus_default_system(ret);
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
assert_return(b, -EINVAL);
assert_return(tid, -EINVAL);
if (!e)
return -ENOMEM;
- ret = strjoin(prefix, "/", e, NULL);
+ ret = strjoin(prefix, "/", e);
if (!ret)
return -ENOMEM;
*description = bus->description;
return 0;
}
-#endif // 0
int bus_get_root_path(sd_bus *bus) {
int r;
return r;
}
-#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
int r;
_public_ void sd_bus_default_flush_close(void) {
flush_close(default_starter_bus);
+#if 0 /// There is no user bus with elogind
flush_close(default_user_bus);
+#endif // 0
flush_close(default_system_bus);
}
-#endif // 0
+
+_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+
+ /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
+ * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
+ * from the client side. */
+ bus->exit_on_disconnect = b;
+
+ /* If the exit condition was triggered already, exit immediately. */
+ return bus_exit_now(bus);
+}
+
+_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+
+ return bus->exit_on_disconnect;
+}