bus-util.c revision 21586b77de9bad401f245dd55b75cedb0c2e9b7c
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2013 Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenint bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen r = sd_bus_add_match(bus, match, quit_callback, e);
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersenint bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen bool exiting = false;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r == 0 && !exiting) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = bus_async_unregister_and_quit(e, bus, name);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering "org.freedesktop.PolicyKit1",
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering "org.freedesktop.PolicyKit1.Authority",
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering "CheckAuthorization",
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering "(sa{sv})sa{ss}us",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen /* Treat no PK available as access denied */
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (q->serial > 0 && b)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = sd_bus_reply_method_errno(q->request, r, NULL);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = q->callback(bus, q->request, q->userdata, &error_buffer);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = bus_maybe_reply_error(q->request, r, &error_buffer);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* This is the second invocation of this function, and
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * there's already a response from polkit, let's
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * process it */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (sd_bus_message_is_method_error(q->reply, NULL)) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Copy error from polkit reply */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Treat no PK available as access denied */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.PolicyKit1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.PolicyKit1.Authority",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "CheckAuthorization",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "(sa{sv})sa{ss}us",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenvoid bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen l = sizeof(struct ucred);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (l != sizeof(struct ucred))
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* If we are root, then let's talk directly to the system
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen * instance, instead of going via the bus */
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen const char *e;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen /* If we are supposed to talk to the instance, try via
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen * XDG_RUNTIME_DIR first, then fallback to normal bus
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersenint bus_print_property(const char *name, sd_bus_message *property, bool all) {
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering r = sd_bus_message_peek_type(property, &type, &contents);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering const char *s;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_bus_message_read_basic(property, type, &s);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen r = sd_bus_message_read_basic(property, type, &b);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = sd_bus_message_read_basic(property, type, &u);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen /* Yes, heuristics! But we can change this check
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen * should it turn out to not be sufficient */
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen t = format_timestamp(timestamp, sizeof(timestamp), u);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen printf("%s=%llu\n", name, (unsigned long long) u);
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &u);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (strstr(name, "UMask") || strstr(name, "Mode"))
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen r = sd_bus_message_read_basic(property, type, &i);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_bus_message_read_basic(property, type, &d);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen const char *str;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (all || n > 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen unsigned int i;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen for (i = 0; i < n; i++)
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (all || n > 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsigned int i;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen for (i = 0; i < n; i++)
be077570f779664ed87b50f60608df9fbe258821Tom Gundersenint bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "org.freedesktop.DBus.Properties",
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = sd_bus_message_peek_type(reply, NULL, &contents);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r == 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* skip what we didn't read */
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersenint bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen const void *v;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen else if (n == 16)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen const char *s;
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering r = sd_bus_message_read_basic(m, type, &u);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen "org.freedesktop.DBus.Properties",
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = sd_bus_message_peek_type(m, NULL, &contents);
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
2a1288ff89322a2f49c79f6d1832c8164c14a05cLennart Poetteringint bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen assert_not_reached("Hmm, unknown transport type.");
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersenint bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert_not_reached("Hmm, unknown transport type.");
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen return sd_bus_message_append(reply, "b", *tristate > 0);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering int b = *(bool*) userdata;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering return sd_bus_message_append_basic(reply, 'b', &b);
const char *property,
void *userdata,
const char *path,
const char *interface,
const char *property,
void *userdata,
const char *path,
const char *interface,
const char *property,
void *userdata,
int bus_log_parse_error(int r) {
int bus_log_create_error(int r) {
assert(u);
return sd_bus_message_read(
&u->id,
&u->description,
&u->load_state,
&u->active_state,
&u->sub_state,
&u->following,
&u->unit_path,
&u->job_id,
&u->job_type,
&u->job_path);
assert(m);
log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",