Ejemplo n.º 1
0
static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *what, *who, *why, *mode;
        unsigned int uid, pid;
        unsigned n = 0;
        int r;

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListInhibitors",
                        error,
                        &reply,
                        "");
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
                _cleanup_free_ char *comm = NULL, *u = NULL;

                get_process_comm(pid, &comm);
                u = uid_to_name(uid);

                printf("     Who: %s (UID "UID_FMT"/%s, PID "PID_FMT"/%s)\n"
                       "    What: %s\n"
                       "     Why: %s\n"
                       "    Mode: %s\n\n",
                       who, uid, strna(u), pid, strna(comm),
                       what,
                       why,
                       mode);

                n++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return bus_log_parse_error(r);

        printf("%u inhibitors listed.\n", n);
        return 0;
}
Ejemplo n.º 2
0
static int list_timezones(int argc, char **argv, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        sd_bus *bus = userdata;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        int r;
        char** zones;

        r = sd_bus_call_method(bus,
                               "org.freedesktop.timedate1",
                               "/org/freedesktop/timedate1",
                               "org.freedesktop.timedate1",
                               "ListTimezones",
                               &error,
                               &reply,
                               NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to request list of time zones: %s",
                                       bus_error_message(&error, r));

        r = sd_bus_message_read_strv(reply, &zones);
        if (r < 0)
                return bus_log_parse_error(r);

        (void) pager_open(arg_pager_flags);
        strv_print(zones);

        return 0;
}
static int show_one_name(sd_bus *bus, const char* attr) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *s;
        int r;

        r = sd_bus_get_property(
                        bus,
                        "org.freedesktop.hostname1",
                        "/org/freedesktop/hostname1",
                        "org.freedesktop.hostname1",
                        attr,
                        &error, &reply, "s");
        if (r < 0) {
                log_error("Could not get property: %s", bus_error_message(&error, -r));
                return r;
        }

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

        printf("%s\n", s);

        return 0;
}
Ejemplo n.º 4
0
static int list_sessions(int argc, char *argv[], void *userdata) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *id, *user, *seat, *object;
        sd_bus *bus = userdata;
        unsigned k = 0;
        uint32_t uid;
        int r;

        assert(bus);
        assert(argv);

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListSessions",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list sessions: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(susso)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");

        while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
                printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u sessions listed.\n", k);

        return 0;
}
Ejemplo n.º 5
0
static int print_changes(sd_bus_message *m) {
        int r;

        if (arg_quiet)
                return 0;

        r = sd_bus_message_enter_container(m, 'a', "(sss)");
        if (r < 0)
                return bus_log_parse_error(r);

        for (;;) {
                const char *type, *path, *source;

                r = sd_bus_message_read(m, "(sss)", &type, &path, &source);
                if (r < 0)
                        return bus_log_parse_error(r);
                if (r == 0)
                        break;

                if (streq(type, "symlink"))
                        log_info("Created symlink %s %s %s.", path, special_glyph(SPECIAL_GLYPH_ARROW), source);
                else if (streq(type, "copy")) {
                        if (isempty(source))
                                log_info("Copied %s.", path);
                        else
                                log_info("Copied %s %s %s.", source, special_glyph(SPECIAL_GLYPH_ARROW), path);
                } else if (streq(type, "unlink"))
                        log_info("Removed %s.", path);
                else if (streq(type, "write"))
                        log_info("Written %s.", path);
                else if (streq(type, "mkdir"))
                        log_info("Created directory %s.", path);
                else
                        log_error("Unexpected change: %s/%s/%s", type, path, source);
        }

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

        return 0;
}
Ejemplo n.º 6
0
static int list_users(sd_bus *bus, char **args, unsigned n) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *user, *object;
        unsigned k = 0;
        uint32_t uid;
        int r;

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListUsers",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list users: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(uso)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%10s %-16s\n", "UID", "USER");

        while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
                printf("%10u %-16s\n", (unsigned) uid, user);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u users listed.\n", k);

        return 0;
}
Ejemplo n.º 7
0
static int list_seats(sd_bus *bus, char **args, unsigned n) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        const char *seat, *object;
        unsigned k = 0;
        int r;

        pager_open_if_enabled();

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.login1",
                        "/org/freedesktop/login1",
                        "org.freedesktop.login1.Manager",
                        "ListSeats",
                        &error, &reply,
                        "");
        if (r < 0) {
                log_error("Failed to list seats: %s", bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(so)");
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("%-16s\n", "SEAT");

        while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
                printf("%-16s\n", seat);
                k++;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        if (arg_legend)
                printf("\n%u seats listed.\n", k);

        return 0;
}
Ejemplo n.º 8
0
int terminate_machine(sd_bus *bus, pid_t pid) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        const char *path;
        int r;

        assert(bus);

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.machine1",
                        "/org/freedesktop/machine1",
                        "org.freedesktop.machine1.Manager",
                        "GetMachineByPID",
                        &error,
                        &reply,
                        "u",
                        (uint32_t) pid);
        if (r < 0) {
                /* Note that the machine might already have been
                 * cleaned up automatically, hence don't consider it a
                 * failure if we cannot get the machine object. */
                log_debug("Failed to get machine: %s", bus_error_message(&error, r));
                return 0;
        }

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

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.machine1",
                        path,
                        "org.freedesktop.machine1.Machine",
                        "Terminate",
                        &error,
                        NULL,
                        NULL);
        if (r < 0) {
                log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
                return 0;
        }

        return 0;
}
Ejemplo n.º 9
0
static int show_timesync(int argc, char **argv, void *userdata) {
        sd_bus *bus = userdata;
        int r;

        assert(bus);

        r = bus_print_all_properties(bus,
                                     "org.freedesktop.timesync1",
                                     "/org/freedesktop/timesync1",
                                     print_timesync_property,
                                     arg_property,
                                     arg_value,
                                     arg_all,
                                     NULL);
        if (r < 0)
                return bus_log_parse_error(r);

        return 0;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
int main(int argc, char *argv[]) {
        int r = 0, retval = EXIT_FAILURE;
        int output_flags;
        _cleanup_free_ char *root = NULL;
        _cleanup_bus_close_unref_ sd_bus *bus = NULL;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r < 0)
                goto finish;
        else if (r == 0) {
                retval = EXIT_SUCCESS;
                goto finish;
        }

        if (!arg_no_pager) {
                r = pager_open(false);
                if (r > 0) {
                        if (arg_full == -1)
                                arg_full = true;
                }
        }

        output_flags =
                arg_all * OUTPUT_SHOW_ALL |
                (arg_full > 0) * OUTPUT_FULL_WIDTH;

        r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
        if (r < 0) {
                log_error_errno(r, "Failed to create bus connection: %m");
                goto finish;
        }

        if (optind < argc) {
                int i;

                for (i = optind; i < argc; i++) {
                        int q;

                        fprintf(stdout, "%s:\n", argv[i]);
                        fflush(stdout);

                        if (arg_machine)
                                root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
                        else
                                root = strdup(argv[i]);
                        if (!root)
                                return log_oom();

                        q = show_cgroup_by_path(root, NULL, 0,
                                                arg_kernel_threads, output_flags);
                        if (q < 0)
                                r = q;
                }

        } else {
                _cleanup_free_ char *p;

                p = get_current_dir_name();
                if (!p) {
                        log_error_errno(errno, "Cannot determine current working directory: %m");
                        goto finish;
                }

                if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
                        printf("Working Directory %s:\n", p);
                        r = show_cgroup_by_path(p, NULL, 0,
                                                arg_kernel_threads, output_flags);
                } else {
                        if (arg_machine) {
                                char *m;
                                const char *cgroup;
                                _cleanup_free_ char *scope = NULL;
                                _cleanup_free_ char *path = NULL;
                                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;

                                m = strjoina("/run/systemd/machines/", arg_machine);
                                r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
                                if (r < 0) {
                                        log_error_errno(r, "Failed to get machine path: %m");
                                        goto finish;
                                }

                                path = unit_dbus_path_from_name(scope);
                                if (!path) {
                                        log_oom();
                                        goto finish;
                                }

                                r = sd_bus_get_property(
                                                bus,
                                                "org.freedesktop.systemd1",
                                                path,
                                                "org.freedesktop.systemd1.Scope",
                                                "ControlGroup",
                                                &error,
                                                &reply,
                                                "s");

                                if (r < 0) {
                                        log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
                                        goto finish;
                                }

                                r = sd_bus_message_read(reply, "s", &cgroup);
                                if (r < 0) {
                                        bus_log_parse_error(r);
                                        goto finish;
                                }

                                root = strdup(cgroup);
                                if (!root) {
                                        log_oom();
                                        goto finish;
                                }

                        } else
                                r = cg_get_root_path(&root);
                        if (r < 0) {
                                log_error_errno(r, "Failed to get %s path: %m",
                                                arg_machine ? "machine" : "root");
                                goto finish;
                        }

                        r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0,
                                        arg_kernel_threads, output_flags);
                }
        }

        if (r < 0) {
                log_error_errno(r, "Failed to list cgroup tree %s: %m", root);
                retval = EXIT_FAILURE;
        } else
                retval = EXIT_SUCCESS;

finish:
        pager_close();

        return retval;
}
Ejemplo n.º 12
0
int allocate_scope(
                sd_bus *bus,
                const char *machine_name,
                pid_t pid,
                const char *slice,
                CustomMount *mounts,
                unsigned n_mounts,
                int kill_signal,
                char **properties) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
        _cleanup_free_ char *scope = NULL;
        const char *description, *object;
        int r;

        assert(bus);

        r = bus_wait_for_jobs_new(bus, &w);
        if (r < 0)
                return log_error_errno(r, "Could not watch job: %m");

        r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
        if (r < 0)
                return log_error_errno(r, "Failed to mangle scope name: %m");

        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_append(m, "ss", scope, "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);

        description = strjoina("Container ", machine_name);

        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
                                  "PIDs", "au", 1, pid,
                                  "Description", "s", description,
                                  "Delegate", "b", 1,
                                  "Slice", "s", isempty(slice) ? "machine.slice" : slice);
        if (r < 0)
                return bus_log_create_error(r);

        r = append_controller_property(bus, m);
        if (r < 0)
                return r;

        r = append_machine_properties(
                        m,
                        mounts,
                        n_mounts,
                        kill_signal,
                        properties);
        if (r < 0)
                return r;

        r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
        if (r < 0)
                return r;

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

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

        r = sd_bus_call(bus, m, 0, &error, &reply);
        if (r < 0) {
                log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
                return r;
        }

        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, false);
        if (r < 0)
                return r;

        return 0;
}
Ejemplo n.º 13
0
static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        int r, c = 0;
        struct unit_times *unit_times = NULL;
        size_t size = 0;
        UnitInfo u;

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "ListUnits",
                        &error, &reply,
                        NULL);
        if (r < 0) {
                log_error("Failed to list units: %s", bus_error_message(&error, -r));
                goto fail;
        }

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
        if (r < 0) {
                bus_log_parse_error(r);
                goto fail;
        }

        while ((r = bus_parse_unit_info(reply, &u)) > 0) {
                struct unit_times *t;

                if (!GREEDY_REALLOC(unit_times, size, c+1)) {
                        r = log_oom();
                        goto fail;
                }

                t = unit_times+c;
                t->name = NULL;

                assert_cc(sizeof(usec_t) == sizeof(uint64_t));

                if (bus_get_uint64_property(bus, u.unit_path,
                                            "org.freedesktop.systemd1.Unit",
                                            "InactiveExitTimestampMonotonic",
                                            &t->activating) < 0 ||
                    bus_get_uint64_property(bus, u.unit_path,
                                            "org.freedesktop.systemd1.Unit",
                                            "ActiveEnterTimestampMonotonic",
                                            &t->activated) < 0 ||
                    bus_get_uint64_property(bus, u.unit_path,
                                            "org.freedesktop.systemd1.Unit",
                                            "ActiveExitTimestampMonotonic",
                                            &t->deactivating) < 0 ||
                    bus_get_uint64_property(bus, u.unit_path,
                                            "org.freedesktop.systemd1.Unit",
                                            "InactiveEnterTimestampMonotonic",
                                            &t->deactivated) < 0) {
                        r = -EIO;
                        goto fail;
                }

                if (t->activated >= t->activating)
                        t->time = t->activated - t->activating;
                else if (t->deactivated >= t->activating)
                        t->time = t->deactivated - t->activating;
                else
                        t->time = 0;

                if (t->activating == 0)
                        continue;

                t->name = strdup(u.id);
                if (t->name == NULL) {
                        r = log_oom();
                        goto fail;
                }
                c++;
        }
        if (r < 0) {
                bus_log_parse_error(r);
                goto fail;
        }

        *out = unit_times;
        return c;

fail:
        free_unit_times(unit_times, (unsigned) c);
        return r;
}
Ejemplo n.º 14
0
static int start_transient_timer(
    sd_bus *bus,
    char **argv) {

    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_free_ char *timer = NULL, *service = NULL;
    const char *object = NULL;
    int r;

    assert(bus);
    assert(argv);

    r = bus_wait_for_jobs_new(bus, &w);
    if (r < 0)
        return log_oom();

    if (arg_unit) {
        switch (unit_name_to_type(arg_unit)) {

        case UNIT_SERVICE:
            service = strdup(arg_unit);
            if (!service)
                return log_oom();

            r = unit_name_change_suffix(service, ".timer", &timer);
            if (r < 0)
                return log_error_errno(r, "Failed to change unit suffix: %m");
            break;

        case UNIT_TIMER:
            timer = strdup(arg_unit);
            if (!timer)
                return log_oom();

            r = unit_name_change_suffix(timer, ".service", &service);
            if (r < 0)
                return log_error_errno(r, "Failed to change unit suffix: %m");
            break;

        default:
            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");

            r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
            if (r < 0)
                return log_error_errno(r, "Failed to mangle unit name: %m");

            break;
        }
    } else {
        r = make_unit_name(bus, UNIT_SERVICE, &service);
        if (r < 0)
            return r;

        r = unit_name_change_suffix(service, ".timer", &timer);
        if (r < 0)
            return log_error_errno(r, "Failed to change unit suffix: %m");
    }

    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", timer, "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_timer_set_properties(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_message_open_container(m, 'a', "(sa(sv))");
    if (r < 0)
        return bus_log_create_error(r);

    if (!strv_isempty(argv)) {
        r = sd_bus_message_open_container(m, 'r', "sa(sv)");
        if (r < 0)
            return bus_log_create_error(r);

        r = sd_bus_message_append(m, "s", service);
        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);

        r = transient_service_set_properties(m, argv, NULL);
        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_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);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0) {
        log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
        return r;
    }

    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 timer as unit: %s", timer);
        if (argv[0])
            log_info("Will run service as unit: %s", service);
    }

    return 0;
}
Ejemplo n.º 15
0
static int inspect_image(int argc, char *argv[], void *userdata) {
        _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_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        _cleanup_strv_free_ char **matches = NULL;
        _cleanup_free_ char *image = NULL;
        bool nl = false, header = false;
        const void *data;
        const char *path;
        size_t sz;
        int r;

        r = determine_image(argv[1], false, &image);
        if (r < 0)
                return r;

        r = determine_matches(argv[1], argv + 2, true, &matches);
        if (r < 0)
                return r;

        r = acquire_bus(&bus);
        if (r < 0)
                return r;

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

        r = sd_bus_message_append(m, "s", image);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append_strv(m, matches);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_call(bus, m, 0, &error, &reply);
        if (r < 0)
                return log_error_errno(r, "Failed to inspect image metadata: %s", bus_error_message(&error, r));

        r = sd_bus_message_read(reply, "s", &path);
        if (r < 0)
                return bus_log_parse_error(r);

        r = sd_bus_message_read_array(reply, 'y', &data, &sz);
        if (r < 0)
                return bus_log_parse_error(r);

        (void) pager_open(arg_pager_flags);

        if (arg_cat) {
                printf("%s-- OS Release: --%s\n", ansi_highlight(), ansi_normal());
                fwrite(data, sz, 1, stdout);
                fflush(stdout);
                nl = true;
        } else {
                _cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL;
                _cleanup_fclose_ FILE *f;

                f = fmemopen_unlocked((void*) data, sz, "re");
                if (!f)
                        return log_error_errno(errno, "Failed to open /etc/os-release buffer: %m");

                r = parse_env_file(f, "/etc/os-release",
                                   "PORTABLE_PRETTY_NAME", &pretty_portable,
                                   "PRETTY_NAME", &pretty_os);
                if (r < 0)
                        return log_error_errno(r, "Failed to parse /etc/os-release: %m");

                printf("Image:\n\t%s\n"
                       "Portable Service:\n\t%s\n"
                       "Operating System:\n\t%s\n",
                       path,
                       strna(pretty_portable),
                       strna(pretty_os));
        }

        r = sd_bus_message_enter_container(reply, 'a', "{say}");
        if (r < 0)
                return bus_log_parse_error(r);

        for (;;) {
                const char *name;

                r = sd_bus_message_enter_container(reply, 'e', "say");
                if (r < 0)
                        return bus_log_parse_error(r);
                if (r == 0)
                        break;

                r = sd_bus_message_read(reply, "s", &name);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_read_array(reply, 'y', &data, &sz);
                if (r < 0)
                        return bus_log_parse_error(r);

                if (arg_cat) {
                        if (nl)
                                fputc('\n', stdout);

                        printf("%s-- Unit file: %s --%s\n", ansi_highlight(), name, ansi_normal());
                        fwrite(data, sz, 1, stdout);
                        fflush(stdout);
                        nl = true;
                } else {
                        if (!header) {
                                fputs("Unit files:\n", stdout);
                                header = true;
                        }

                        fputc('\t', stdout);
                        fputs(name, stdout);
                        fputc('\n', stdout);
                }

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        return bus_log_parse_error(r);
        }

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return bus_log_parse_error(r);

        return 0;
}
Ejemplo n.º 16
0
static int resolve_host(sd_bus *bus, const char *name) {

        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *canonical = NULL;
        unsigned c = 0;
        int r, ifindex;
        uint64_t flags;

        assert(name);

        log_debug("Resolving %s (family %s, ifindex %i).", name, af_to_name(arg_family) ?: "*", arg_ifindex);

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
                return r;
        }

        r = sd_bus_message_read(reply, "i", &ifindex);
        if (r < 0)
                return bus_log_parse_error(r);

        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
                const void *a;
                int family;
                size_t sz;
                _cleanup_free_ char *pretty = NULL;
                char ifname[IF_NAMESIZE] = "";

                r = sd_bus_message_read(reply, "i", &family);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        return bus_log_parse_error(r);

                if (!IN_SET(family, AF_INET, AF_INET6)) {
                        log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
                        continue;
                }

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        log_error("%s: systemd-resolved returned address of invalid size %zu for family %s",
                                  name, sz, af_to_name(family) ?: "unknown");
                        continue;
                }
Ejemplo n.º 17
0
static int list_images(int argc, char *argv[], void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        _cleanup_(table_unrefp) Table *table = NULL;
        int r;

        r = acquire_bus(&bus);
        if (r < 0)
                return r;

        r = sd_bus_call_method(
                        bus,
                        "org.freedesktop.portable1",
                        "/org/freedesktop/portable1",
                        "org.freedesktop.portable1.Manager",
                        "ListImages",
                        &error,
                        &reply,
                        NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to list images: %s", bus_error_message(&error, r));

        table = table_new("name", "type", "ro", "crtime", "mtime", "usage", "state");
        if (!table)
                return log_oom();

        r = sd_bus_message_enter_container(reply, 'a', "(ssbtttso)");
        if (r < 0)
                return bus_log_parse_error(r);

        for (;;) {
                const char *name, *type, *state;
                uint64_t crtime, mtime, usage;
                TableCell *cell;
                bool ro_bool;
                int ro_int;

                r = sd_bus_message_read(reply, "(ssbtttso)", &name, &type, &ro_int, &crtime, &mtime, &usage, &state, NULL);
                if (r < 0)
                        return bus_log_parse_error(r);
                if (r == 0)
                        break;

                r = table_add_many(table,
                                   TABLE_STRING, name,
                                   TABLE_STRING, type);
                if (r < 0)
                        return log_error_errno(r, "Failed to add row to table: %m");

                ro_bool = ro_int;
                r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool);
                if (r < 0)
                        return log_error_errno(r, "Failed to add row to table: %m");

                if (ro_bool) {
                        r = table_set_color(table, cell, ansi_highlight_red());
                        if (r < 0)
                                return log_error_errno(r, "Failed to set table cell color: %m");
                }

                r = table_add_many(table,
                                   TABLE_TIMESTAMP, crtime,
                                   TABLE_TIMESTAMP, mtime,
                                   TABLE_SIZE, usage);
                if (r < 0)
                        return log_error_errno(r, "Failed to add row to table: %m");

                r = table_add_cell(table, &cell, TABLE_STRING, state);
                if (r < 0)
                        return log_error_errno(r, "Failed to add row to table: %m");

                if (!streq(state, "detached")) {
                        r = table_set_color(table, cell, ansi_highlight_green());
                        if (r < 0)
                                return log_error_errno(r, "Failed to set table cell color: %m");
                }
        }

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return bus_log_parse_error(r);

        if (table_get_rows(table) > 1) {
                r = table_set_sort(table, (size_t) 0, (size_t) -1);
                if (r < 0)
                        return log_error_errno(r, "Failed to sort table: %m");

                table_set_header(table, arg_legend);

                r = table_print(table, NULL);
                if (r < 0)
                        return log_error_errno(r, "Failed to show table: %m");
        }

        if (arg_legend) {
                if (table_get_rows(table) > 1)
                        printf("\n%zu images listed.\n", table_get_rows(table) - 1);
                else
                        printf("No images.\n");
        }

        return 0;
}
Ejemplo n.º 18
0
static int resolve_host(sd_bus *bus, const char *name) {

        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *canonical = NULL;
        char ifname[IF_NAMESIZE] = "";
        unsigned c = 0;
        int r;
        uint64_t flags;
        usec_t ts;

        assert(name);

        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);

        log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
        if (r < 0)
                return bus_log_create_error(r);

        ts = now(CLOCK_MONOTONIC);

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
                return r;
        }

        ts = now(CLOCK_MONOTONIC) - ts;

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                const void *a;
                size_t sz;
                _cleanup_free_ char *pretty = NULL;
                int ifindex, family;

                assert_cc(sizeof(int) == sizeof(int32_t));

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        return bus_log_parse_error(r);

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        return bus_log_parse_error(r);

                if (!IN_SET(family, AF_INET, AF_INET6)) {
                        log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
                        continue;
                }

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
                        continue;
                }
Ejemplo n.º 19
0
static int start_transient_scope(
    sd_bus *bus,
    char **argv) {

    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
    _cleanup_free_ char *scope = NULL;
    const char *object = NULL;
    int r;

    assert(bus);
    assert(argv);

    r = bus_wait_for_jobs_new(bus, &w);
    if (r < 0)
        return log_oom();

    if (arg_unit) {
        r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
        if (r < 0)
            return log_error_errno(r, "Failed to mangle scope name: %m");
    } else {
        r = make_unit_name(bus, UNIT_SCOPE, &scope);
        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", scope, "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_scope_set_properties(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);

    /* 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) {
        log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
        return r;
    }

    if (arg_nice_set) {
        if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
            return log_error_errno(errno, "Failed to set nice level: %m");
    }

    if (arg_exec_group) {
        gid_t gid;

        r = get_group_creds(&arg_exec_group, &gid);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);

        if (setresgid(gid, gid, gid) < 0)
            return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
    }

    if (arg_exec_user) {
        const char *home, *shell;
        uid_t uid;
        gid_t gid;

        r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);

        r = strv_extendf(&user_env, "HOME=%s", home);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "SHELL=%s", shell);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        if (!arg_exec_group) {
            if (setresgid(gid, gid, gid) < 0)
                return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
        }

        if (setresuid(uid, uid, uid) < 0)
            return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
    }

    env = strv_env_merge(3, environ, user_env, arg_environment);
    if (!env)
        return log_oom();

    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 scope as unit: %s", scope);

    execvpe(argv[0], argv, env);

    return log_error_errno(errno, "Failed to execute: %m");
}