Exemple #1
0
static int
connect_bus(void)
{
    int r;
    sd_bus *bus = NULL;
    struct source_ctx *s;

    r = sd_bus_default_system(&bus);
    SOL_INT_CHECK(r, < 0, r);

    s = sol_mainloop_source_get_data(_ctx.mainloop_source);

    r = sd_bus_attach_event(bus, s->event,
        SD_EVENT_PRIORITY_NORMAL);
    SOL_INT_CHECK_GOTO(r, < 0, fail);

    r = sd_bus_add_match(bus, NULL,
        "type='signal',"
        "sender='org.freedesktop.DBus.Local',"
        "interface='org.freedesktop.DBus.Local',"
        "member='Disconnected'",
        _match_disconnected, &_ctx);
    SOL_INT_CHECK_GOTO(r, < 0, fail);

    _ctx.bus = bus;

    return 0;

fail:
    sd_bus_unref(bus);
    return r;
}
Exemple #2
0
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
    _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
    int r;

    assert(c);
    assert(event);
    assert(_bus);

    r = sd_bus_default_system(&bus);
    if (r < 0)
        return log_error_errno(r, "Failed to get system bus connection: %m");

    r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
    if (r < 0)
        return log_error_errno(r, "Failed to register object: %m");

    r = sd_bus_request_name(bus, "org.freedesktop.hostname1", 0);
    if (r < 0)
        return log_error_errno(r, "Failed to register name: %m");

    r = sd_bus_attach_event(bus, event, 0);
    if (r < 0)
        return log_error_errno(r, "Failed to attach bus to event loop: %m");

    *_bus = bus;
    bus = NULL;

    return 0;
}
Exemple #3
0
int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
        int r;

        assert(transport >= 0);
        assert(transport < _BUS_TRANSPORT_MAX);
        assert(bus);

        assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
        assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);

        switch (transport) {

        case BUS_TRANSPORT_LOCAL:
                if (user)
                        r = sd_bus_default_user(bus);
                else
                        r = sd_bus_default_system(bus);

                break;

        case BUS_TRANSPORT_REMOTE:
                r = sd_bus_open_system_remote(bus, host);
                break;

        case BUS_TRANSPORT_CONTAINER:
                r = sd_bus_open_system_container(bus, host);
                break;

        default:
                assert_not_reached("Hmm, unknown transport type.");
        }

        return r;
}
int manager_new(Manager **ret) {
        _cleanup_manager_free_ Manager *m = NULL;
        int r;

        m = new0(Manager, 1);
        if (!m)
                return -ENOMEM;

        r = sd_event_default(&m->event);
        if (r < 0)
                return r;

        sd_event_set_watchdog(m->event, true);

        r = sd_rtnl_open(&m->rtnl, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
        if (r < 0)
                return r;

        r = sd_bus_default_system(&m->bus);
        if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
                return r;

        r = setup_signals(m);
        if (r < 0)
                return r;

        m->udev = udev_new();
        if (!m->udev)
                return -ENOMEM;

        /* udev does not initialize devices inside containers,
         * so we rely on them being already initialized before
         * entering the container */
        if (detect_container(NULL) > 0) {
                m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "kernel");
                if (!m->udev_monitor)
                        return -ENOMEM;
        } else {
                m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
                if (!m->udev_monitor)
                        return -ENOMEM;
        }

        m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
        if (!m->links)
                return -ENOMEM;

        m->netdevs = hashmap_new(string_hash_func, string_compare_func);
        if (!m->netdevs)
                return -ENOMEM;

        LIST_HEAD_INIT(m->networks);

        *ret = m;
        m = NULL;

        return 0;
}
Exemple #5
0
int manager_new(Manager **ret) {
        _cleanup_manager_free_ Manager *m = NULL;
        int r;

        m = new0(Manager, 1);
        if (!m)
                return -ENOMEM;

        r = sd_event_default(&m->event);
        if (r < 0)
                return r;

        sd_event_set_watchdog(m->event, true);

        r = sd_rtnl_open(RTMGRP_LINK | RTMGRP_IPV4_IFADDR, &m->rtnl);
        if (r < 0)
                return r;

        r = sd_bus_default_system(&m->bus);
        if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
                return r;

        m->udev = udev_new();
        if (!m->udev)
                return -ENOMEM;

        m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
        if (!m->udev_monitor)
                return -ENOMEM;

        m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
        if (!m->links)
                return -ENOMEM;

        m->bridges = hashmap_new(string_hash_func, string_compare_func);
        if (!m->bridges)
                return -ENOMEM;

        LIST_HEAD_INIT(m->networks);

        *ret = m;
        m = NULL;

        return 0;
}
Exemple #6
0
static int manager_connect_bus(Manager *m) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        int r;

        assert(m);
        assert(!m->bus);

        r = sd_bus_default_system(&m->bus);
        if (r < 0)
                return log_error_errno(r, "Failed to connect to system bus: %m");

        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add manager object vtable: %m");

        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add machine object vtable: %m");

        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add machine enumerator: %m");

        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add image object vtable: %m");

        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add image enumerator: %m");

        r = sd_bus_add_match(m->bus,
                             NULL,
                             "type='signal',"
                             "sender='org.freedesktop.systemd1',"
                             "interface='org.freedesktop.systemd1.Manager',"
                             "member='JobRemoved',"
                             "path='/org/freedesktop/systemd1'",
                             match_job_removed,
                             m);
        if (r < 0)
                return log_error_errno(r, "Failed to add match for JobRemoved: %m");

        r = sd_bus_add_match(m->bus,
                             NULL,
                             "type='signal',"
                             "sender='org.freedesktop.systemd1',"
                             "interface='org.freedesktop.systemd1.Manager',"
                             "member='UnitRemoved',"
                             "path='/org/freedesktop/systemd1'",
                             match_unit_removed,
                             m);
        if (r < 0)
                return log_error_errno(r, "Failed to add match for UnitRemoved: %m");

        r = sd_bus_add_match(m->bus,
                             NULL,
                             "type='signal',"
                             "sender='org.freedesktop.systemd1',"
                             "interface='org.freedesktop.DBus.Properties',"
                             "member='PropertiesChanged',"
                             "arg0='org.freedesktop.systemd1.Unit'",
                             match_properties_changed,
                             m);
        if (r < 0)
                return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");

        r = sd_bus_add_match(m->bus,
                             NULL,
                             "type='signal',"
                             "sender='org.freedesktop.systemd1',"
                             "interface='org.freedesktop.systemd1.Manager',"
                             "member='Reloading',"
                             "path='/org/freedesktop/systemd1'",
                             match_reloading,
                             m);
        if (r < 0)
                return log_error_errno(r, "Failed to add match for Reloading: %m");

        r = sd_bus_call_method(
                        m->bus,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "Subscribe",
                        &error,
                        NULL, NULL);
        if (r < 0) {
                log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", 0);
        if (r < 0)
                return log_error_errno(r, "Failed to register name: %m");

        r = sd_bus_attach_event(m->bus, m->event, 0);
        if (r < 0)
                return log_error_errno(r, "Failed to attach bus to event loop: %m");

        return 0;
}
Exemple #7
0
int main(int argc, char *argv[]) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
        int r;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r < 0)
                return EXIT_FAILURE;
        if (r == 0)
                return EXIT_SUCCESS;

        r = sd_bus_default_system(&bus);
        if (r < 0) {
                log_error("Failed to connect to bus: %s", strerror(-r));
                return EXIT_FAILURE;
        }

        if (arg_action == ACTION_LIST) {

                r = print_inhibitors(bus, &error);
                if (r < 0) {
                        log_error("Failed to list inhibitors: %s", bus_error_message(&error, -r));
                        return EXIT_FAILURE;
                }

        } else {
                _cleanup_close_ int fd = -1;
                _cleanup_free_ char *w = NULL;
                pid_t pid;

                if (!arg_who)
                        arg_who = w = strv_join(argv + optind, " ");

                fd = inhibit(bus, &error);
                if (fd < 0) {
                        log_error("Failed to inhibit: %s", bus_error_message(&error, -r));
                        return EXIT_FAILURE;
                }

                pid = fork();
                if (pid < 0) {
                        log_error("Failed to fork: %m");
                        return EXIT_FAILURE;
                }

                if (pid == 0) {
                        /* Child */

                        close_all_fds(NULL, 0);

                        execvp(argv[optind], argv + optind);
                        log_error("Failed to execute %s: %m", argv[optind]);
                        _exit(EXIT_FAILURE);
                }

                r = wait_for_terminate_and_warn(argv[optind], pid);
                return r < 0 ? EXIT_FAILURE : r;
        }

        return 0;
}
Exemple #8
0
int main(int argc, char *argv[]) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
        int r, boolean;
        const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
        uint8_t u, v;
        void *buffer = NULL;
        size_t sz;
        char *h;
        const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
        char *s;
        _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
        _cleanup_fclose_ FILE *ms = NULL;
        size_t first_size = 0, second_size = 0, third_size = 0;
        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
        double dbl;
        uint64_t u64;

        r = sd_bus_default_system(&bus);
        if (r < 0)
                return EXIT_TEST_SKIP;

        r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", "a string");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "s", NULL);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "()");
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
        assert_se(r >= 0);

        r = sd_bus_message_open_container(m, 'a', "s");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "foobar");
        assert_se(r >= 0);

        r = sd_bus_message_append_basic(m, 's', "waldo");
        assert_se(r >= 0);

        r = sd_bus_message_close_container(m);
        assert_se(r >= 0);

        r = sd_bus_message_append_string_space(m, 5, &s);
        assert_se(r >= 0);
        strcpy(s, "hallo");

        r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
        assert_se(r >= 0);

        r = sd_bus_message_append_array(m, 'u', NULL, 0);
        assert_se(r >= 0);

        r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/");
        assert_se(r >= 0);

        r = bus_message_seal(m, 4711, 0);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        ms = open_memstream(&first, &first_size);
        bus_message_dump(m, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));

        r = bus_message_get_blob(m, &buffer, &sz);
        assert_se(r >= 0);

        h = hexmem(buffer, sz);
        assert_se(h);

        log_info("message size = %zu, contents =\n%s", sz, h);
        free(h);

#ifdef HAVE_GLIB
        {
                GDBusMessage *g;
                char *p;

#if !defined(GLIB_VERSION_2_36)
                g_type_init();
#endif

                g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
                p = g_dbus_message_print(g, 0);
                log_info("%s", p);
                g_free(p);
                g_object_unref(g);
        }
#endif

#ifdef HAVE_DBUS
        {
                DBusMessage *w;
                DBusError error;

                dbus_error_init(&error);

                w = dbus_message_demarshal(buffer, sz, &error);
                if (!w)
                        log_error("%s", error.message);
                else
                        dbus_message_unref(w);

                dbus_error_free(&error);
        }
#endif

        m = sd_bus_message_unref(m);

        r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m);
        assert_se(r >= 0);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        fclose(ms);
        ms = open_memstream(&second, &second_size);
        bus_message_dump(m, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));
        assert_se(first_size == second_size);
        assert_se(memcmp(first, second, first_size) == 0);

        assert_se(sd_bus_message_rewind(m, true) >= 0);

        r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature);
        assert_se(r > 0);
        assert_se(streq(x, "a string"));
        assert_se(streq(x2, ""));
        assert_se(streq(y, "string #1"));
        assert_se(streq(z, "string #2"));
        assert_se(streq(a_signature, "sba(tt)ss"));

        r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "foo"));
        assert_se(streq(z, "bar"));
        assert_se(streq(a, "waldo"));
        assert_se(streq(b, "piep"));
        assert_se(streq(c, "pap"));
        assert_se(streq(d, "after"));

        r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
        assert_se(r > 0);
        assert_se(u == 3);
        assert_se(streq(x, "foo"));
        assert_se(v == 5);
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
        assert_se(r > 0);
        assert_se(v == 8);
        assert_se(u64 == 777);
        assert_se(u == 7);

        r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
        assert_se(r > 0);
        assert_se(v == 9);
        assert_se(u == 77);
        assert_se(u64 == 7777);

        r = sd_bus_message_read(m, "y", &v);
        assert_se(r > 0);
        assert_se(v == 10);

        r = sd_bus_message_read(m, "()");
        assert_se(r > 0);

        r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
        assert_se(r > 0);
        assert_se(boolean);
        assert_se(streq(x, "aaa"));
        assert_se(streq(y, "1"));
        assert_se(streq(a, "bbb"));
        assert_se(streq(b, "2"));
        assert_se(streq(c, "ccc"));
        assert_se(streq(d, "3"));

        assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);

        r = sd_bus_message_read(m, "as", 2, &x, &y);
        assert_se(r > 0);
        assert_se(streq(x, "foobar"));
        assert_se(streq(y, "waldo"));

        r = sd_bus_message_read_basic(m, 's', &s);
        assert_se(r > 0);
        assert_se(streq(s, "hallo"));

        r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
        assert_se(r > 0);
        assert_se(sz == sizeof(integer_array));
        assert_se(memcmp(integer_array, return_array, sz) == 0);

        r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz);
        assert_se(r > 0);
        assert_se(sz == 0);

        r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y);
        assert_se(r > 0);
        assert_se(streq(x, "foo"));
        assert_se(u64 == 815ULL);
        assert_se(fabs(dbl - 47.0) < 0.1);
        assert_se(streq(y, "/"));

        r = sd_bus_message_peek_type(m, NULL, NULL);
        assert_se(r == 0);

        r = sd_bus_message_new_method_call(bus, &copy, "foobar.waldo", "/", "foobar.waldo", "Piep");
        assert_se(r >= 0);

        r = sd_bus_message_rewind(m, true);
        assert_se(r >= 0);

        r = sd_bus_message_copy(copy, m, true);
        assert_se(r >= 0);

        r = bus_message_seal(copy, 4712, 0);
        assert_se(r >= 0);

        fclose(ms);
        ms = open_memstream(&third, &third_size);
        bus_message_dump(copy, ms, 0);
        fflush(ms);
        assert_se(!ferror(ms));

        printf("<%.*s>\n", (int) first_size, first);
        printf("<%.*s>\n", (int) third_size, third);

        assert_se(first_size == third_size);
        assert_se(memcmp(first, third, third_size) == 0);

        r = sd_bus_message_rewind(m, true);
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);

        r = sd_bus_message_skip(m, "ssasg");
        assert_se(r > 0);

        assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);

        r = sd_bus_message_skip(m, "sass");
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);

        r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
        assert_se(r >= 0);

        assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);

        r = sd_bus_message_read(m, "b", &boolean);
        assert_se(r > 0);
        assert_se(boolean);

        r = sd_bus_message_enter_container(m, 0, NULL);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &x, &y);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &a, &b);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &c, &d);
        assert_se(r > 0);

        r = sd_bus_message_read(m, "(ss)", &x, &y);
        assert_se(r == 0);

        r = sd_bus_message_exit_container(m);
        assert_se(r >= 0);

        assert_se(streq(x, "aaa"));
        assert_se(streq(y, "1"));
        assert_se(streq(a, "bbb"));
        assert_se(streq(b, "2"));
        assert_se(streq(c, "ccc"));
        assert_se(streq(d, "3"));

        test_bus_label_escape();
        test_bus_path_encode();
        test_bus_path_encode_unique();
        test_bus_path_encode_many();

        return 0;
}
Exemple #9
0
int register_machine(
                const char *machine_name,
                pid_t pid,
                const char *directory,
                sd_id128_t uuid,
                int local_ifindex,
                const char *slice,
                CustomMount *mounts,
                unsigned n_mounts,
                int kill_signal,
                char **properties,
                bool keep_unit) {

        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
        int r;

        r = sd_bus_default_system(&bus);
        if (r < 0)
                return log_error_errno(r, "Failed to open system bus: %m");

        if (keep_unit) {
                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "RegisterMachineWithNetwork",
                                &error,
                                NULL,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                "nspawn",
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
        } else {
                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
                char **i;
                unsigned j;

                r = sd_bus_message_new_method_call(
                                bus,
                                &m,
                                "org.freedesktop.machine1",
                                "/org/freedesktop/machine1",
                                "org.freedesktop.machine1.Manager",
                                "CreateMachineWithNetwork");
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_append(
                                m,
                                "sayssusai",
                                machine_name,
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
                                "nspawn",
                                "container",
                                (uint32_t) pid,
                                strempty(directory),
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_open_container(m, 'a', "(sv)");
                if (r < 0)
                        return bus_log_create_error(r);

                if (!isempty(slice)) {
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
                if (r < 0)
                        return bus_log_create_error(r);

                /* If you make changes here, also make sure to update
                 * [email protected], to keep the device
                 * policies in sync regardless if we are run with or
                 * without the --keep-unit switch. */
                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
                                          /* Allow the container to
                                           * access and create the API
                                           * device nodes, so that
                                           * PrivateDevices= in the
                                           * container can work
                                           * fine */
                                          "/dev/null", "rwm",
                                          "/dev/zero", "rwm",
                                          "/dev/full", "rwm",
                                          "/dev/random", "rwm",
                                          "/dev/urandom", "rwm",
                                          "/dev/tty", "rwm",
                                          "/dev/net/tun", "rwm",
                                          /* Allow the container
                                           * access to ptys. However,
                                           * do not permit the
                                           * container to ever create
                                           * these device nodes. */
                                          "/dev/pts/ptmx", "rw",
                                          "char-pts", "rw");
                if (r < 0)
                        return bus_log_create_error(r);

                for (j = 0; j < n_mounts; j++) {
                        CustomMount *cm = mounts + j;

                        if (cm->type != CUSTOM_MOUNT_BIND)
                                continue;

                        r = is_device_node(cm->source);
                        if (r < 0)
                                return log_error_errno(r, "Failed to stat %s: %m", cm->source);

                        if (r) {
                                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
                                        cm->source, cm->read_only ? "r" : "rw");
                                if (r < 0)
                                        return log_error_errno(r, "Failed to append message arguments: %m");
                        }
                }

                if (kill_signal != 0) {
                        r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                STRV_FOREACH(i, properties) {
                        r = sd_bus_message_open_container(m, 'r', "sv");
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = bus_append_unit_property_assignment(m, *i);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_close_container(m);
                        if (r < 0)
                                return bus_log_create_error(r);
                }

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_call(bus, m, 0, &error, NULL);
        }
Exemple #10
0
static int manager_connect_bus(Manager *m) {
        int r;

        assert(m);
        assert(!m->bus);

        r = sd_bus_default_system(&m->bus);
        if (r < 0)
                return log_error_errno(r, "Failed to connect to system bus: %m");

        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add manager object vtable: %m");

        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add machine object vtable: %m");

        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add machine enumerator: %m");

        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add image object vtable: %m");

        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add image enumerator: %m");

        r = sd_bus_match_signal_async(
                        m->bus,
                        NULL,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "JobRemoved",
                        match_job_removed, NULL, m);
        if (r < 0)
                return log_error_errno(r, "Failed to add match for JobRemoved: %m");

        r = sd_bus_match_signal_async(
                        m->bus,
                        NULL,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "UnitRemoved",
                        match_unit_removed, NULL, m);
        if (r < 0)
                return log_error_errno(r, "Failed to request match for UnitRemoved: %m");

        r = sd_bus_match_signal_async(
                        m->bus,
                        NULL,
                        "org.freedesktop.systemd1",
                        NULL,
                        "org.freedesktop.DBus.Properties",
                        "PropertiesChanged",
                        match_properties_changed, NULL, m);
        if (r < 0)
                return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");

        r = sd_bus_match_signal_async(
                        m->bus,
                        NULL,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "Reloading",
                        match_reloading, NULL, m);
        if (r < 0)
                return log_error_errno(r, "Failed to request match for Reloading: %m");

        r = sd_bus_call_method_async(
                        m->bus,
                        NULL,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "Subscribe",
                        NULL, NULL,
                        NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to enable subscription: %m");

        r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to request name: %m");

        r = sd_bus_attach_event(m->bus, m->event, 0);
        if (r < 0)
                return log_error_errno(r, "Failed to attach bus to event loop: %m");

        return 0;
}
Exemple #11
0
int main(int argc, char *argv[])
{
	static const char *matchfmt =
		"type='signal',"
		"interface='org.freedesktop.DBus.Properties',"
		"member='PropertiesChanged',"
		"arg0='org.openbmc.control.Power',"
		"path='%s',"
		"sender='%s'";
	static const char *usage =
		"Usage: %s OBJECTPATH on|off\n";
	static const size_t LEN = 256;

	sd_bus *conn = NULL;
	sd_event *loop = NULL;
	sd_bus_slot *slot = NULL;
	sd_bus_error error = SD_BUS_ERROR_NULL;
	char *service = NULL;
	int r, dest = -1, state;
	char match[LEN];

	if(argc < 3) {
		fprintf(stderr, usage, argv[0]);
		exit(EXIT_FAILURE);
	}

	if(!strcmp(argv[2], "on"))
		dest = 1;
	if(!strcmp(argv[2], "off"))
		dest = 0;

	if(dest != 0 && dest != 1) {
		fprintf(stderr, usage, argv[0]);
		exit(EXIT_FAILURE);
	}

	r = sd_bus_default_system(&conn);
	if(r < 0) {
		fprintf(stderr, "Error connecting to system bus: %s\n",
				strerror(-r));
		goto finish;
	}

	r = mapper_get_service(conn, argv[1], &service);
	if (r < 0) {
		fprintf(stderr, "Error obtaining host service: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_event_default(&loop);
	if (r < 0) {
		fprintf(stderr, "Error obtaining event loop: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
	if (r < 0) {
		fprintf(stderr, "Failed to attach system "
				"bus to event loop: %s\n",
				strerror(-r));
		goto finish;
	}

	if(strlen(matchfmt) + strnlen(argv[1], LEN) > LEN) {
		r = -E2BIG;
		fprintf(stderr, "Error adding match rule: %s\n",
				strerror(-r));
		goto finish;
	}

	sprintf(match, matchfmt, argv[1], service);

	r = sd_bus_add_match(conn,
			&slot,
			match,
			callback,
			loop);
	if(r < 0) {
		fprintf(stderr, "Error adding match rule: %s\n",
				strerror(-r));
		goto finish;
	}

	r = sd_bus_get_property_trivial(conn,
			service,
			argv[1],
			"org.openbmc.control.Power",
			"pgood",
			&error,
			'i',
			&state);
	if(r < 0) {
		fprintf(stderr, "Error getting property: %s\n",
				strerror(-r));
		goto finish;
	}

	if(dest == state)
		goto finish;

	r = sd_event_loop(loop);
	if(r < 0) {
		fprintf(stderr, "Error starting event loop: %s\n",
				strerror(-r));
		goto finish;
	}

finish:
	exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
Exemple #12
0
static int manager_new(struct manager **out)
{
	struct manager *m;
	static const int sigs[] = {
		SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0
	};
	unsigned int i;
	sigset_t mask;
	int r;

	m = calloc(1, sizeof(*m));
	if (!m)
		return log_ENOMEM();

	shl_htable_init_uint(&m->links);

	r = sd_event_default(&m->event);
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	r = sd_event_set_watchdog(m->event, true);
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	r = sd_bus_default_system(&m->bus);
	if (r < 0) {
		log_error("cannot connect to system bus: %d", r);
		goto error;
	}

	r = sd_bus_attach_event(m->bus, m->event, 0);
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	for (i = 0; sigs[i]; ++i) {
		sigemptyset(&mask);
		sigaddset(&mask, sigs[i]);
		sigprocmask(SIG_BLOCK, &mask, NULL);

		r = sd_event_add_signal(m->event,
					&m->sigs[i],
					sigs[i],
					manager_signal_fn,
					m);
		if (r < 0) {
			log_vERR(r);
			goto error;
		}

		/* low-priority to allow others to handle it first */
		sd_event_source_set_priority(m->sigs[i], 100);
	}

	m->udev = udev_new();
	if (!m->udev) {
		r = log_ENOMEM();
		goto error;
	}

	m->udev_mon = udev_monitor_new_from_netlink(m->udev, "udev");
	if (!m->udev_mon) {
		r = log_ENOMEM();
		goto error;
	}

	r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_mon,
							    "net",
							    "wlan");
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	r = udev_monitor_enable_receiving(m->udev_mon);
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	r = sd_event_add_io(m->event,
			    &m->udev_mon_source,
			    udev_monitor_get_fd(m->udev_mon),
			    EPOLLHUP | EPOLLERR | EPOLLIN,
			    manager_udev_fn,
			    m);
	if (r < 0) {
		log_vERR(r);
		goto error;
	}

	r = manager_dbus_connect(m);
	if (r < 0)
		goto error;

	if (out)
		*out = m;

	return 0;

error:
	manager_free(m);
	return r;
}
Exemple #13
0
static int start_transient_service(
    sd_bus *bus,
    char **argv,
    int *retval) {

    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_free_ char *service = NULL, *pty_path = NULL;
    _cleanup_close_ int master = -1;
    int r;

    assert(bus);
    assert(argv);
    assert(retval);

    if (arg_pty) {

        if (arg_transport == BUS_TRANSPORT_LOCAL) {
            master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
            if (master < 0)
                return log_error_errno(errno, "Failed to acquire pseudo tty: %m");

            r = ptsname_malloc(master, &pty_path);
            if (r < 0)
                return log_error_errno(r, "Failed to determine tty name: %m");

            if (unlockpt(master) < 0)
                return log_error_errno(errno, "Failed to unlock tty: %m");

        } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
            _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
            _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL;
            const char *s;

            r = sd_bus_default_system(&system_bus);
            if (r < 0)
                return log_error_errno(r, "Failed to connect to system bus: %m");

            r = sd_bus_call_method(system_bus,
                                   "org.freedesktop.machine1",
                                   "/org/freedesktop/machine1",
                                   "org.freedesktop.machine1.Manager",
                                   "OpenMachinePTY",
                                   &error,
                                   &pty_reply,
                                   "s", arg_host);
            if (r < 0) {
                log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
                return r;
            }

            r = sd_bus_message_read(pty_reply, "hs", &master, &s);
            if (r < 0)
                return bus_log_parse_error(r);

            master = fcntl(master, F_DUPFD_CLOEXEC, 3);
            if (master < 0)
                return log_error_errno(errno, "Failed to duplicate master fd: %m");

            pty_path = strdup(s);
            if (!pty_path)
                return log_oom();
        } else
            assert_not_reached("Can't allocate tty via ssh");
    }

    if (!arg_no_block) {
        r = bus_wait_for_jobs_new(bus, &w);
        if (r < 0)
            return log_error_errno(r, "Could not watch jobs: %m");
    }

    if (arg_unit) {
        r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
        if (r < 0)
            return log_error_errno(r, "Failed to mangle unit name: %m");
    } else {
        r = make_unit_name(bus, UNIT_SERVICE, &service);
        if (r < 0)
            return r;
    }

    r = sd_bus_message_new_method_call(
            bus,
            &m,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "StartTransientUnit");
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
    if (r < 0)
        return bus_log_create_error(r);

    /* Name and mode */
    r = sd_bus_message_append(m, "ss", service, "fail");
    if (r < 0)
        return bus_log_create_error(r);

    /* Properties */
    r = sd_bus_message_open_container(m, 'a', "(sv)");
    if (r < 0)
        return bus_log_create_error(r);

    r = transient_service_set_properties(m, argv, pty_path);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    /* Auxiliary units */
    r = sd_bus_message_append(m, "a(sa(sv))", 0);
    if (r < 0)
        return bus_log_create_error(r);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0)
        return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));

    if (w) {
        const char *object;

        r = sd_bus_message_read(reply, "o", &object);
        if (r < 0)
            return bus_log_parse_error(r);

        r = bus_wait_for_jobs_one(w, object, arg_quiet);
        if (r < 0)
            return r;
    }

    if (!arg_quiet)
        log_info("Running as unit: %s", service);

    if (arg_wait || master >= 0) {
        _cleanup_(run_context_free) RunContext c = {};

        c.bus = sd_bus_ref(bus);

        r = sd_event_default(&c.event);
        if (r < 0)
            return log_error_errno(r, "Failed to get event loop: %m");

        if (master >= 0) {
            assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
            (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
            (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);

            if (!arg_quiet)
                log_info("Press ^] three times within 1s to disconnect TTY.");

            r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward);
            if (r < 0)
                return log_error_errno(r, "Failed to create PTY forwarder: %m");

            pty_forward_set_handler(c.forward, pty_forward_handler, &c);
        }

        if (arg_wait) {
            _cleanup_free_ char *path = NULL;
            const char *mt;

            path = unit_dbus_path_from_name(service);
            if (!path)
                return log_oom();

            mt = strjoina("type='signal',"
                          "sender='org.freedesktop.systemd1',"
                          "path='", path, "',"
                          "interface='org.freedesktop.DBus.Properties',"
                          "member='PropertiesChanged'");
            r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c);
            if (r < 0)
                return log_error_errno(r, "Failed to add properties changed signal.");

            r = sd_bus_attach_event(bus, c.event, 0);
            if (r < 0)
                return log_error_errno(r, "Failed to attach bus to event loop.");
        }

        r = sd_event_loop(c.event);
        if (r < 0)
            return log_error_errno(r, "Failed to run event loop: %m");

        if (c.forward) {
            char last_char = 0;

            r = pty_forward_get_last_char(c.forward, &last_char);
            if (r >= 0 && !arg_quiet && last_char != '\n')
                fputc('\n', stdout);
        }

        if (!arg_quiet) {
            if (!isempty(c.result))
                log_info("Finished with result: %s", strna(c.result));

            if (c.exit_code == CLD_EXITED)
                log_info("Main processes terminated with: code=%s/status=%i", sigchld_code_to_string(c.exit_code), c.exit_status);
            else if (c.exit_code > 0)
                log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));

            if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY &&
                    c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY &&
                    c.inactive_enter_usec > c.inactive_exit_usec) {
                char ts[FORMAT_TIMESPAN_MAX];
                log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
            }

            if (c.cpu_usage_nsec > 0 && c.cpu_usage_nsec != NSEC_INFINITY) {
                char ts[FORMAT_TIMESPAN_MAX];
                log_info("CPU time consumed: %s", format_timespan(ts, sizeof(ts), (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC));
            }
        }

        /* Try to propagate the service's return value */
        if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED)
            *retval = c.exit_status;
        else
            *retval = EXIT_FAILURE;
    }

    return 0;
}