From d59ef3e24362aa7a9e209ed07db5feca1a2cdb8e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 18 Dec 2017 23:46:45 +0900 Subject: [PATCH] run: add support to create transient path and socket unit --- src/run/run.c | 86 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/src/run/run.c b/src/run/run.c index 510b6ab..b018d15 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -69,6 +69,8 @@ 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 char **arg_path_property = NULL; +static char **arg_socket_property = NULL; static char **arg_timer_property = NULL; static bool with_timer = false; static bool arg_quiet = false; @@ -102,6 +104,10 @@ static void help(void) { " -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n" " -q --quiet Suppress information messages during runtime\n" " -G --collect Unload unit after it ran, even when failed\n\n" + "Path options:\n" + " --path-property=NAME=VALUE Set path unit property\n\n" + "Socket options:\n" + " --socket-property=NAME=VALUE Set socket unit property\n\n" "Timer options:\n" " --on-active=SECONDS Run after SECONDS delay\n" " --on-boot=SECONDS Run SECONDS after machine was booted up\n" @@ -153,6 +159,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_ON_UNIT_INACTIVE, ARG_ON_CALENDAR, ARG_TIMER_PROPERTY, + ARG_PATH_PROPERTY, + ARG_SOCKET_PROPERTY, ARG_NO_BLOCK, ARG_NO_ASK_PASSWORD, ARG_WAIT, @@ -189,12 +197,15 @@ static int parse_argv(int argc, char *argv[]) { { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE }, { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, + { "path-property", required_argument, NULL, ARG_PATH_PROPERTY }, + { "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "collect", no_argument, NULL, 'G' }, {}, }; + bool with_trigger = false; int r, c; assert(argc >= 0); @@ -369,6 +380,20 @@ static int parse_argv(int argc, char *argv[]) { !!startswith(optarg, "OnCalendar="); break; + case ARG_PATH_PROPERTY: + + if (strv_extend(&arg_path_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_SOCKET_PROPERTY: + + if (strv_extend(&arg_socket_property, optarg) < 0) + return log_oom(); + + break; + case ARG_NO_BLOCK: arg_no_block = true; break; @@ -388,6 +413,13 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + with_trigger = !!arg_path_property || !!arg_socket_property || with_timer; + + /* currently, only single trigger (path, socket, timer) unit can be created simultaneously */ + if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) with_timer > 1) { + log_error("Only single trigger (path, socket, timer) unit can be created."); + return -EINVAL; + } if (arg_stdio == ARG_STDIO_AUTO) { /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully @@ -398,7 +430,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_trigger)) { log_error("Command line to execute required."); return -EINVAL; } @@ -418,7 +450,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_trigger || arg_scope)) { log_error("--pty/--pipe is not compatible in timer or --scope mode."); return -EINVAL; } @@ -433,8 +465,8 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (arg_scope && with_timer) { - log_error("Timer options are not supported in --scope mode."); + if (arg_scope && with_trigger) { + log_error("Path, socket or timer options are not supported in --scope mode."); return -EINVAL; } @@ -449,8 +481,8 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (with_timer) { - log_error("--wait may not be combined with timer operations."); + if (with_trigger) { + log_error("--wait may not be combined with path, socket or timer operations."); return -EINVAL; } @@ -1283,14 +1315,15 @@ static int start_transient_scope( return log_error_errno(errno, "Failed to execute: %m"); } -static int start_transient_timer( +static int start_transient_trigger( sd_bus *bus, - char **argv) { + char **argv, + const char *suffix) { _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; + _cleanup_free_ char *trigger = NULL, *service = NULL; const char *object = NULL; int r; @@ -1309,17 +1342,17 @@ static int start_transient_timer( if (!service) return log_oom(); - r = unit_name_change_suffix(service, ".timer", &timer); + r = unit_name_change_suffix(service, suffix, &trigger); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; case UNIT_TIMER: - timer = strdup(arg_unit); - if (!timer) + trigger = strdup(arg_unit); + if (!trigger) return log_oom(); - r = unit_name_change_suffix(timer, ".service", &service); + r = unit_name_change_suffix(trigger, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; @@ -1329,7 +1362,7 @@ static int start_transient_timer( 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); + r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, suffix, &trigger); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -1340,7 +1373,7 @@ static int start_transient_timer( if (r < 0) return r; - r = unit_name_change_suffix(service, ".timer", &timer); + r = unit_name_change_suffix(service, suffix, &trigger); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); } @@ -1360,7 +1393,7 @@ static int start_transient_timer( return bus_log_create_error(r); /* Name and Mode */ - r = sd_bus_message_append(m, "ss", timer, "fail"); + r = sd_bus_message_append(m, "ss", trigger, "fail"); if (r < 0) return bus_log_create_error(r); @@ -1369,7 +1402,14 @@ static int start_transient_timer( if (r < 0) return bus_log_create_error(r); - r = transient_timer_set_properties(m); + if (streq(suffix, ".path")) + r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property); + else if (streq(suffix, ".socket")) + r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property); + else if (streq(suffix, ".timer")) + r = transient_timer_set_properties(m); + else + assert_not_reached("Invalid suffix"); if (r < 0) return r; @@ -1415,7 +1455,7 @@ static int start_transient_timer( 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)); + log_error("Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, -r)); return r; } @@ -1428,7 +1468,7 @@ static int start_transient_timer( return r; if (!arg_quiet) { - log_info("Running timer as unit: %s", timer); + log_info("Running %s as unit: %s", suffix + 1, trigger); if (argv[0]) log_info("Will run service as unit: %s", service); } @@ -1489,14 +1529,20 @@ int main(int argc, char* argv[]) { if (arg_scope) r = start_transient_scope(bus, argv + optind); + else if (arg_path_property) + r = start_transient_trigger(bus, argv + optind, ".path"); + else if (arg_socket_property) + r = start_transient_trigger(bus, argv + optind, ".socket"); else if (with_timer) - r = start_transient_timer(bus, argv + optind); + r = start_transient_trigger(bus, argv + optind, ".timer"); else r = start_transient_service(bus, argv + optind, &retval); finish: strv_free(arg_environment); strv_free(arg_property); + strv_free(arg_path_property); + strv_free(arg_socket_property); strv_free(arg_timer_property); return r < 0 ? EXIT_FAILURE : retval; -- 2.7.4