diff options
Diffstat (limited to 'src/run')
-rw-r--r-- | src/run/run.c | 262 |
1 files changed, 118 insertions, 144 deletions
diff --git a/src/run/run.c b/src/run/run.c index f9ca5683a2..5d7441ac93 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -67,26 +68,10 @@ static enum { ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */ ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */ } arg_stdio = ARG_STDIO_NONE; -static usec_t arg_on_active = 0; -static usec_t arg_on_boot = 0; -static usec_t arg_on_startup = 0; -static usec_t arg_on_unit_active = 0; -static usec_t arg_on_unit_inactive = 0; -static const char *arg_on_calendar = NULL; static char **arg_timer_property = NULL; +static bool with_timer = false; static bool arg_quiet = false; - -static void polkit_agent_open_if_enabled(void) { - - /* Open the polkit agent as a child process if necessary */ - if (!arg_ask_password) - return; - - if (arg_transport != BUS_TRANSPORT_LOCAL) - return; - - polkit_agent_open(); -} +static bool arg_aggressive_gc = false; static void help(void) { printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n" @@ -114,7 +99,8 @@ static void help(void) { " -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n" " STDERR\n" " -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n" - " -q --quiet Suppress information messages during runtime\n\n" + " -q --quiet Suppress information messages during runtime\n" + " -G --collect Unload unit after it ran, even when failed\n\n" "Timer options:\n" " --on-active=SECONDS Run after SECONDS delay\n" " --on-boot=SECONDS Run SECONDS after machine was booted up\n" @@ -126,8 +112,22 @@ static void help(void) { , program_invocation_short_name); } -static bool with_timer(void) { - return arg_on_active || arg_on_boot || arg_on_startup || arg_on_unit_active || arg_on_unit_inactive || arg_on_calendar; +static int add_timer_property(const char *name, const char *val) { + _cleanup_free_ char *p = NULL; + + assert(name); + assert(val); + + p = strjoin(name, "=", val); + if (!p) + return log_oom(); + + if (strv_consume(&arg_timer_property, p) < 0) + return log_oom(); + + p = NULL; + + return 0; } static int parse_argv(int argc, char *argv[]) { @@ -190,6 +190,7 @@ static int parse_argv(int argc, char *argv[]) { { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "collect", no_argument, NULL, 'G' }, {}, }; @@ -198,7 +199,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPq", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqG", options, NULL)) >= 0) switch (c) { @@ -306,74 +307,65 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_ON_ACTIVE: - - r = parse_sec(optarg, &arg_on_active); - if (r < 0) { - log_error("Failed to parse timer value: %s", optarg); + r = add_timer_property("OnActiveSec", optarg); + if (r < 0) return r; - } + with_timer = true; break; case ARG_ON_BOOT: - - r = parse_sec(optarg, &arg_on_boot); - if (r < 0) { - log_error("Failed to parse timer value: %s", optarg); + r = add_timer_property("OnBootSec", optarg); + if (r < 0) return r; - } + with_timer = true; break; case ARG_ON_STARTUP: - - r = parse_sec(optarg, &arg_on_startup); - if (r < 0) { - log_error("Failed to parse timer value: %s", optarg); + r = add_timer_property("OnStartupSec", optarg); + if (r < 0) return r; - } + with_timer = true; break; case ARG_ON_UNIT_ACTIVE: - - r = parse_sec(optarg, &arg_on_unit_active); - if (r < 0) { - log_error("Failed to parse timer value: %s", optarg); + r = add_timer_property("OnUnitActiveSec", optarg); + if (r < 0) return r; - } + with_timer = true; break; case ARG_ON_UNIT_INACTIVE: - - r = parse_sec(optarg, &arg_on_unit_inactive); - if (r < 0) { - log_error("Failed to parse timer value: %s", optarg); + r = add_timer_property("OnUnitInactiveSec", optarg); + if (r < 0) return r; - } + with_timer = true; break; - case ARG_ON_CALENDAR: { - CalendarSpec *spec = NULL; - - r = calendar_spec_from_string(optarg, &spec); - if (r < 0) { - log_error("Invalid calendar spec: %s", optarg); + case ARG_ON_CALENDAR: + r = add_timer_property("OnCalendar", optarg); + if (r < 0) return r; - } - calendar_spec_free(spec); - arg_on_calendar = optarg; + with_timer = true; break; - } case ARG_TIMER_PROPERTY: if (strv_extend(&arg_timer_property, optarg) < 0) return log_oom(); + with_timer = with_timer || + !!startswith(optarg, "OnActiveSec=") || + !!startswith(optarg, "OnBootSec=") || + !!startswith(optarg, "OnStartupSec=") || + !!startswith(optarg, "OnUnitActiveSec=") || + !!startswith(optarg, "OnUnitInactiveSec=") || + !!startswith(optarg, "OnCalendar="); break; case ARG_NO_BLOCK: @@ -384,6 +376,10 @@ static int parse_argv(int argc, char *argv[]) { arg_wait = true; break; + case 'G': + arg_aggressive_gc = true; + break; + case '?': return -EINVAL; @@ -401,7 +397,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_STDIO_DIRECT; } - if ((optind >= argc) && (!arg_unit || !with_timer())) { + if ((optind >= argc) && (!arg_unit || !with_timer)) { log_error("Command line to execute required."); return -EINVAL; } @@ -421,7 +417,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (arg_stdio != ARG_STDIO_NONE && (with_timer() || arg_scope)) { + if (arg_stdio != ARG_STDIO_NONE && (with_timer || arg_scope)) { log_error("--pty/--pipe is not compatible in timer or --scope mode."); return -EINVAL; } @@ -436,12 +432,12 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (arg_scope && with_timer()) { + if (arg_scope && with_timer) { log_error("Timer options are not supported in --scope mode."); return -EINVAL; } - if (arg_timer_property && !with_timer()) { + if (arg_timer_property && !with_timer) { log_error("--timer-property= has no effect without any other timer options."); return -EINVAL; } @@ -452,7 +448,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (with_timer()) { + if (with_timer) { log_error("--wait may not be combined with timer operations."); return -EINVAL; } @@ -471,7 +467,13 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) { r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); if (r < 0) - return r; + return bus_log_create_error(r); + + if (arg_aggressive_gc) { + r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed"); + if (r < 0) + return bus_log_create_error(r); + } r = bus_append_unit_property_assignment_many(m, properties); if (r < 0) @@ -485,27 +487,32 @@ static int transient_cgroup_set_properties(sd_bus_message *m) { assert(m); if (!isempty(arg_slice)) { - _cleanup_free_ char *slice; + _cleanup_free_ char *slice = NULL; r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice); if (r < 0) - return r; + return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice); r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) - return r; + return bus_log_create_error(r); } return 0; } static int transient_kill_set_properties(sd_bus_message *m) { + int r; + assert(m); - if (arg_send_sighup) - return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup); - else - return 0; + if (arg_send_sighup) { + r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; } static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) { @@ -529,37 +536,37 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons if (arg_wait || arg_stdio != ARG_STDIO_NONE) { r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1); if (r < 0) - return r; + return bus_log_create_error(r); } if (arg_remain_after_exit) { r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); if (r < 0) - return r; + return bus_log_create_error(r); } if (arg_service_type) { r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type); if (r < 0) - return r; + return bus_log_create_error(r); } if (arg_exec_user) { r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user); if (r < 0) - return r; + return bus_log_create_error(r); } if (arg_exec_group) { r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group); if (r < 0) - return r; + return bus_log_create_error(r); } if (arg_nice_set) { r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice); if (r < 0) - return r; + return bus_log_create_error(r); } if (pty_path) { @@ -570,7 +577,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons "StandardError", "s", "tty", "TTYPath", "s", pty_path); if (r < 0) - return r; + return bus_log_create_error(r); send_term = true; @@ -581,7 +588,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons "StandardOutputFileDescriptor", "h", STDOUT_FILENO, "StandardErrorFileDescriptor", "h", STDERR_FILENO); if (r < 0) - return r; + return bus_log_create_error(r); send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO); } @@ -598,85 +605,85 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons "(sv)", "Environment", "as", 1, n); if (r < 0) - return r; + return bus_log_create_error(r); } } if (!strv_isempty(arg_environment)) { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append(m, "s", "Environment"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append_strv(m, arg_environment); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); } /* Exec container */ { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append(m, "s", "ExecStart"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'v', "a(sasb)"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sasb)"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'r', "sasb"); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append(m, "s", argv[0]); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append_strv(m, argv); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_append(m, "b", false); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) - return r; + return bus_log_create_error(r); } return 0; @@ -701,7 +708,7 @@ static int transient_scope_set_properties(sd_bus_message *m) { r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached()); if (r < 0) - return r; + return bus_log_create_error(r); return 0; } @@ -718,43 +725,7 @@ static int transient_timer_set_properties(sd_bus_message *m) { /* Automatically clean up our transient timers */ r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false); if (r < 0) - return r; - - if (arg_on_active) { - r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active); - if (r < 0) - return r; - } - - if (arg_on_boot) { - r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot); - if (r < 0) - return r; - } - - if (arg_on_startup) { - r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup); - if (r < 0) - return r; - } - - if (arg_on_unit_active) { - r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active); - if (r < 0) - return r; - } - - if (arg_on_unit_inactive) { - r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive); - if (r < 0) - return r; - } - - if (arg_on_calendar) { - r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar); - if (r < 0) - return r; - } + return bus_log_create_error(r); return 0; } @@ -1016,7 +987,7 @@ static int start_transient_service( r = transient_service_set_properties(m, argv, pty_path); if (r < 0) - return bus_log_create_error(r); + return r; r = sd_bus_message_close_container(m); if (r < 0) @@ -1027,7 +998,7 @@ static int start_transient_service( if (r < 0) return bus_log_create_error(r); - polkit_agent_open_if_enabled(); + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) @@ -1078,6 +1049,9 @@ static int start_transient_service( return log_error_errno(r, "Failed to create PTY forwarder: %m"); pty_forward_set_handler(c.forward, pty_forward_handler, &c); + + /* Make sure to process any TTY events before we process bus events */ + (void) pty_forward_set_priority(c.forward, SD_EVENT_PRIORITY_IMPORTANT); } path = unit_dbus_path_from_name(service); @@ -1093,7 +1067,7 @@ static int start_transient_service( if (r < 0) return log_error_errno(r, "Failed to add properties changed signal."); - r = sd_bus_attach_event(bus, c.event, 0); + r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop."); @@ -1215,7 +1189,7 @@ static int start_transient_scope( r = transient_scope_set_properties(m); if (r < 0) - return bus_log_create_error(r); + return r; r = sd_bus_message_close_container(m); if (r < 0) @@ -1226,7 +1200,7 @@ static int start_transient_scope( if (r < 0) return bus_log_create_error(r); - polkit_agent_open_if_enabled(); + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { @@ -1396,7 +1370,7 @@ static int start_transient_timer( r = transient_timer_set_properties(m); if (r < 0) - return bus_log_create_error(r); + return r; r = sd_bus_message_close_container(m); if (r < 0) @@ -1421,7 +1395,7 @@ static int start_transient_timer( r = transient_service_set_properties(m, argv, NULL); if (r < 0) - return bus_log_create_error(r); + return r; r = sd_bus_message_close_container(m); if (r < 0) @@ -1436,7 +1410,7 @@ static int start_transient_timer( if (r < 0) return bus_log_create_error(r); - polkit_agent_open_if_enabled(); + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { @@ -1514,7 +1488,7 @@ int main(int argc, char* argv[]) { if (arg_scope) r = start_transient_scope(bus, argv + optind); - else if (with_timer()) + else if (with_timer) r = start_transient_timer(bus, argv + optind); else r = start_transient_service(bus, argv + optind, &retval); |