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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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"); }