2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
#include <getopt.h>
|
2015-09-23 03:01:06 +02:00
|
|
|
#include <stdio.h>
|
2019-03-27 11:32:41 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2013-06-28 04:12:58 +02:00
|
|
|
|
|
|
|
#include "sd-bus.h"
|
2014-12-22 19:45:32 +01:00
|
|
|
#include "sd-event.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "bus-error.h"
|
2020-06-28 15:59:37 +02:00
|
|
|
#include "bus-locator.h"
|
2020-06-28 16:08:37 +02:00
|
|
|
#include "bus-map-properties.h"
|
2016-04-20 17:43:13 +02:00
|
|
|
#include "bus-unit-util.h"
|
2019-03-06 19:38:45 +01:00
|
|
|
#include "bus-wait-for-jobs.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "calendarspec.h"
|
2014-03-05 18:57:21 +01:00
|
|
|
#include "env-util.h"
|
2019-10-29 18:07:07 +01:00
|
|
|
#include "exit-status.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2016-11-07 16:14:59 +01:00
|
|
|
#include "format-util.h"
|
2018-11-22 19:30:03 +01:00
|
|
|
#include "main-func.h"
|
2015-11-16 22:09:36 +01:00
|
|
|
#include "parse-util.h"
|
2013-09-09 23:31:10 +02:00
|
|
|
#include "path-util.h"
|
2018-11-20 15:42:57 +01:00
|
|
|
#include "pretty-print.h"
|
2016-08-17 14:24:17 +02:00
|
|
|
#include "process-util.h"
|
2014-12-22 19:45:32 +01:00
|
|
|
#include "ptyfwd.h"
|
2015-05-29 20:14:11 +02:00
|
|
|
#include "signal-util.h"
|
2015-09-01 18:43:08 +02:00
|
|
|
#include "spawn-polkit-agent.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "strv.h"
|
2015-10-07 22:45:48 +02:00
|
|
|
#include "terminal-util.h"
|
2017-12-23 08:59:56 +01:00
|
|
|
#include "unit-def.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "unit-name.h"
|
2015-10-25 22:32:30 +01:00
|
|
|
#include "user-util.h"
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2015-09-01 18:43:08 +02:00
|
|
|
static bool arg_ask_password = true;
|
2013-07-01 00:03:57 +02:00
|
|
|
static bool arg_scope = false;
|
2013-07-26 16:09:25 +02:00
|
|
|
static bool arg_remain_after_exit = false;
|
2015-04-28 12:33:19 +02:00
|
|
|
static bool arg_no_block = false;
|
2016-08-17 14:24:17 +02:00
|
|
|
static bool arg_wait = false;
|
2013-07-01 00:03:57 +02:00
|
|
|
static const char *arg_unit = NULL;
|
2013-07-01 00:40:56 +02:00
|
|
|
static const char *arg_description = NULL;
|
2013-07-01 03:02:42 +02:00
|
|
|
static const char *arg_slice = NULL;
|
2020-04-08 14:57:52 +02:00
|
|
|
static bool arg_slice_inherit = false;
|
2013-07-30 02:28:22 +02:00
|
|
|
static bool arg_send_sighup = false;
|
2013-10-30 16:44:55 +01:00
|
|
|
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
2014-03-05 03:38:36 +01:00
|
|
|
static const char *arg_host = NULL;
|
2013-10-30 16:44:55 +01:00
|
|
|
static bool arg_user = false;
|
2014-02-05 02:02:00 +01:00
|
|
|
static const char *arg_service_type = NULL;
|
|
|
|
static const char *arg_exec_user = NULL;
|
|
|
|
static const char *arg_exec_group = NULL;
|
|
|
|
static int arg_nice = 0;
|
|
|
|
static bool arg_nice_set = false;
|
|
|
|
static char **arg_environment = NULL;
|
2014-03-05 03:36:22 +01:00
|
|
|
static char **arg_property = NULL;
|
2017-09-08 15:38:40 +02:00
|
|
|
static enum {
|
|
|
|
ARG_STDIO_NONE, /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */
|
|
|
|
ARG_STDIO_PTY, /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */
|
|
|
|
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;
|
2017-12-18 15:46:45 +01:00
|
|
|
static char **arg_path_property = NULL;
|
|
|
|
static char **arg_socket_property = NULL;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
static char **arg_timer_property = NULL;
|
2019-03-14 19:55:29 +01:00
|
|
|
static bool arg_with_timer = false;
|
2014-12-22 20:39:10 +01:00
|
|
|
static bool arg_quiet = false;
|
2017-11-13 17:17:53 +01:00
|
|
|
static bool arg_aggressive_gc = false;
|
2018-11-22 12:07:25 +01:00
|
|
|
static char *arg_working_directory = NULL;
|
2018-11-22 19:24:48 +01:00
|
|
|
static bool arg_shell = false;
|
|
|
|
static char **arg_cmdline = NULL;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2018-11-22 19:34:15 +01:00
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_path_property, strv_freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_socket_property, strv_freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_timer_property, strv_freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_working_directory, freep);
|
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep);
|
|
|
|
|
2018-08-09 10:32:31 +02:00
|
|
|
static int help(void) {
|
|
|
|
_cleanup_free_ char *link = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = terminal_urlify_man("systemd-run", "1", &link);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2019-11-15 18:38:44 +01:00
|
|
|
printf("%s [OPTIONS...] COMMAND [ARGUMENTS...]\n"
|
|
|
|
"\n%sRun the specified command in a transient scope or service.%s\n\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" -h --help Show this help\n"
|
|
|
|
" --version Show package version\n"
|
2015-09-01 18:43:08 +02:00
|
|
|
" --no-ask-password Do not prompt for password\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" --user Run as user unit\n"
|
|
|
|
" -H --host=[USER@]HOST Operate on remote host\n"
|
|
|
|
" -M --machine=CONTAINER Operate on local container\n"
|
|
|
|
" --scope Run this as scope rather than service\n"
|
2019-10-23 09:13:15 +02:00
|
|
|
" -u --unit=UNIT Run under the specified unit name\n"
|
2016-08-06 00:30:12 +02:00
|
|
|
" -p --property=NAME=VALUE Set service or scope unit property\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" --description=TEXT Description for unit\n"
|
|
|
|
" --slice=SLICE Run in the specified slice\n"
|
2020-04-08 14:57:52 +02:00
|
|
|
" --slice-inherit Inherit the slice\n"
|
2015-04-28 12:33:19 +02:00
|
|
|
" --no-block Do not wait until operation finished\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" -r --remain-after-exit Leave service around until explicitly stopped\n"
|
2016-08-17 14:24:17 +02:00
|
|
|
" --wait Wait until service stopped again\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" --send-sighup Send SIGHUP when terminating\n"
|
|
|
|
" --service-type=TYPE Service type\n"
|
|
|
|
" --uid=USER Run as system user\n"
|
|
|
|
" --gid=GROUP Run as system group\n"
|
|
|
|
" --nice=NICE Nice level\n"
|
2018-11-22 12:07:25 +01:00
|
|
|
" --working-directory=PATH Set working directory\n"
|
|
|
|
" -d --same-dir Inherit working directory from caller\n"
|
2016-04-20 14:38:01 +02:00
|
|
|
" -E --setenv=NAME=VALUE Set environment\n"
|
2017-09-08 15:38:40 +02:00
|
|
|
" -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n"
|
|
|
|
" STDERR\n"
|
|
|
|
" -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n"
|
2017-11-13 17:17:53 +01:00
|
|
|
" -q --quiet Suppress information messages during runtime\n"
|
2018-11-22 19:24:48 +01:00
|
|
|
" -G --collect Unload unit after it ran, even when failed\n"
|
|
|
|
" -S --shell Invoke a $SHELL interactively\n\n"
|
2017-12-18 15:46:45 +01:00
|
|
|
"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"
|
2016-08-06 00:30:12 +02:00
|
|
|
"Timer options:\n"
|
2015-01-28 03:22:57 +01:00
|
|
|
" --on-active=SECONDS Run after SECONDS delay\n"
|
|
|
|
" --on-boot=SECONDS Run SECONDS after machine was booted up\n"
|
|
|
|
" --on-startup=SECONDS Run SECONDS after systemd activation\n"
|
|
|
|
" --on-unit-active=SECONDS Run SECONDS after the last activation\n"
|
|
|
|
" --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n"
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
" --on-calendar=SPEC Realtime timer\n"
|
2019-03-14 21:36:47 +01:00
|
|
|
" --on-timezone-change Run when the timezone changes\n"
|
|
|
|
" --on-clock-change Run when the realtime clock jumps\n"
|
2016-08-06 00:30:12 +02:00
|
|
|
" --timer-property=NAME=VALUE Set timer unit property\n"
|
2018-08-09 10:32:31 +02:00
|
|
|
"\nSee the %s for details.\n"
|
|
|
|
, program_invocation_short_name
|
2019-11-15 18:38:44 +01:00
|
|
|
, ansi_highlight(), ansi_normal()
|
2018-08-09 10:32:31 +02:00
|
|
|
, link
|
|
|
|
);
|
|
|
|
|
|
|
|
return 0;
|
2013-07-01 00:03:57 +02:00
|
|
|
}
|
|
|
|
|
2017-12-11 13:21:10 +01:00
|
|
|
static int add_timer_property(const char *name, const char *val) {
|
2018-01-04 11:12:57 +01:00
|
|
|
char *p;
|
2017-12-11 13:21:10 +01:00
|
|
|
|
|
|
|
assert(name);
|
|
|
|
assert(val);
|
|
|
|
|
|
|
|
p = strjoin(name, "=", val);
|
|
|
|
if (!p)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
if (strv_consume(&arg_timer_property, p) < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
return 0;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
}
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
static int parse_argv(int argc, char *argv[]) {
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ARG_VERSION = 0x100,
|
|
|
|
ARG_USER,
|
2013-11-06 17:31:20 +01:00
|
|
|
ARG_SYSTEM,
|
2013-07-01 00:03:57 +02:00
|
|
|
ARG_SCOPE,
|
2013-07-01 03:02:42 +02:00
|
|
|
ARG_DESCRIPTION,
|
2013-07-30 02:28:22 +02:00
|
|
|
ARG_SLICE,
|
2020-04-08 14:57:52 +02:00
|
|
|
ARG_SLICE_INHERIT,
|
2013-07-30 02:28:22 +02:00
|
|
|
ARG_SEND_SIGHUP,
|
2016-04-18 02:46:00 +02:00
|
|
|
ARG_SERVICE_TYPE,
|
2014-02-05 02:02:00 +01:00
|
|
|
ARG_EXEC_USER,
|
|
|
|
ARG_EXEC_GROUP,
|
|
|
|
ARG_NICE,
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
ARG_ON_ACTIVE,
|
|
|
|
ARG_ON_BOOT,
|
|
|
|
ARG_ON_STARTUP,
|
|
|
|
ARG_ON_UNIT_ACTIVE,
|
|
|
|
ARG_ON_UNIT_INACTIVE,
|
|
|
|
ARG_ON_CALENDAR,
|
2019-03-14 21:36:47 +01:00
|
|
|
ARG_ON_TIMEZONE_CHANGE,
|
|
|
|
ARG_ON_CLOCK_CHANGE,
|
2015-04-28 12:33:19 +02:00
|
|
|
ARG_TIMER_PROPERTY,
|
2017-12-18 15:46:45 +01:00
|
|
|
ARG_PATH_PROPERTY,
|
|
|
|
ARG_SOCKET_PROPERTY,
|
2015-04-28 12:33:19 +02:00
|
|
|
ARG_NO_BLOCK,
|
2016-04-18 02:46:00 +02:00
|
|
|
ARG_NO_ASK_PASSWORD,
|
2016-08-17 14:24:17 +02:00
|
|
|
ARG_WAIT,
|
2018-11-22 12:07:25 +01:00
|
|
|
ARG_WORKING_DIRECTORY,
|
2018-11-22 19:24:48 +01:00
|
|
|
ARG_SHELL,
|
2013-07-01 00:03:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct option options[] = {
|
2018-11-22 12:07:25 +01:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "version", no_argument, NULL, ARG_VERSION },
|
|
|
|
{ "user", no_argument, NULL, ARG_USER },
|
|
|
|
{ "system", no_argument, NULL, ARG_SYSTEM },
|
|
|
|
{ "scope", no_argument, NULL, ARG_SCOPE },
|
2019-10-23 09:13:15 +02:00
|
|
|
{ "unit", required_argument, NULL, 'u' },
|
2018-11-22 12:07:25 +01:00
|
|
|
{ "description", required_argument, NULL, ARG_DESCRIPTION },
|
|
|
|
{ "slice", required_argument, NULL, ARG_SLICE },
|
2020-04-08 14:57:52 +02:00
|
|
|
{ "slice-inherit", no_argument, NULL, ARG_SLICE_INHERIT },
|
2018-11-22 12:07:25 +01:00
|
|
|
{ "remain-after-exit", no_argument, NULL, 'r' },
|
|
|
|
{ "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
|
|
|
|
{ "host", required_argument, NULL, 'H' },
|
|
|
|
{ "machine", required_argument, NULL, 'M' },
|
|
|
|
{ "service-type", required_argument, NULL, ARG_SERVICE_TYPE },
|
|
|
|
{ "wait", no_argument, NULL, ARG_WAIT },
|
|
|
|
{ "uid", required_argument, NULL, ARG_EXEC_USER },
|
|
|
|
{ "gid", required_argument, NULL, ARG_EXEC_GROUP },
|
|
|
|
{ "nice", required_argument, NULL, ARG_NICE },
|
|
|
|
{ "setenv", required_argument, NULL, 'E' },
|
|
|
|
{ "property", required_argument, NULL, 'p' },
|
|
|
|
{ "tty", no_argument, NULL, 't' }, /* deprecated alias */
|
|
|
|
{ "pty", no_argument, NULL, 't' },
|
|
|
|
{ "pipe", no_argument, NULL, 'P' },
|
|
|
|
{ "quiet", no_argument, NULL, 'q' },
|
|
|
|
{ "on-active", required_argument, NULL, ARG_ON_ACTIVE },
|
|
|
|
{ "on-boot", required_argument, NULL, ARG_ON_BOOT },
|
|
|
|
{ "on-startup", required_argument, NULL, ARG_ON_STARTUP },
|
|
|
|
{ "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE },
|
|
|
|
{ "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
|
|
|
|
{ "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
|
2019-03-14 21:36:47 +01:00
|
|
|
{ "on-timezone-change",no_argument, NULL, ARG_ON_TIMEZONE_CHANGE},
|
|
|
|
{ "on-clock-change", no_argument, NULL, ARG_ON_CLOCK_CHANGE },
|
2018-11-22 12:07:25 +01:00
|
|
|
{ "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' },
|
|
|
|
{ "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY },
|
|
|
|
{ "same-dir", no_argument, NULL, 'd' },
|
2018-11-22 19:24:48 +01:00
|
|
|
{ "shell", no_argument, NULL, 'S' },
|
2013-11-06 18:28:39 +01:00
|
|
|
{},
|
2013-07-01 00:03:57 +02:00
|
|
|
};
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
bool with_trigger = false;
|
2014-02-05 02:02:00 +01:00
|
|
|
int r, c;
|
2013-07-01 00:03:57 +02:00
|
|
|
|
|
|
|
assert(argc >= 0);
|
|
|
|
assert(argv);
|
|
|
|
|
2019-10-23 09:13:15 +02:00
|
|
|
while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0)
|
2013-07-01 00:03:57 +02:00
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
case 'h':
|
2018-08-09 10:32:31 +02:00
|
|
|
return help();
|
2013-07-01 00:03:57 +02:00
|
|
|
|
2016-08-06 00:30:12 +02:00
|
|
|
case ARG_VERSION:
|
|
|
|
return version();
|
|
|
|
|
2015-09-01 18:43:08 +02:00
|
|
|
case ARG_NO_ASK_PASSWORD:
|
|
|
|
arg_ask_password = false;
|
|
|
|
break;
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
case ARG_USER:
|
|
|
|
arg_user = true;
|
|
|
|
break;
|
|
|
|
|
2013-11-06 17:31:20 +01:00
|
|
|
case ARG_SYSTEM:
|
|
|
|
arg_user = false;
|
|
|
|
break;
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
case ARG_SCOPE:
|
|
|
|
arg_scope = true;
|
|
|
|
break;
|
|
|
|
|
2019-10-23 09:13:15 +02:00
|
|
|
case 'u':
|
2013-07-01 00:03:57 +02:00
|
|
|
arg_unit = optarg;
|
|
|
|
break;
|
|
|
|
|
2013-07-01 00:40:56 +02:00
|
|
|
case ARG_DESCRIPTION:
|
|
|
|
arg_description = optarg;
|
|
|
|
break;
|
|
|
|
|
2013-07-01 03:02:42 +02:00
|
|
|
case ARG_SLICE:
|
|
|
|
arg_slice = optarg;
|
|
|
|
break;
|
|
|
|
|
2020-04-08 14:57:52 +02:00
|
|
|
case ARG_SLICE_INHERIT:
|
|
|
|
arg_slice_inherit = true;
|
|
|
|
break;
|
|
|
|
|
2013-07-30 02:28:22 +02:00
|
|
|
case ARG_SEND_SIGHUP:
|
|
|
|
arg_send_sighup = true;
|
|
|
|
break;
|
|
|
|
|
2013-07-26 16:09:25 +02:00
|
|
|
case 'r':
|
|
|
|
arg_remain_after_exit = true;
|
|
|
|
break;
|
|
|
|
|
2013-10-30 16:44:55 +01:00
|
|
|
case 'H':
|
|
|
|
arg_transport = BUS_TRANSPORT_REMOTE;
|
|
|
|
arg_host = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'M':
|
2014-12-23 23:38:13 +01:00
|
|
|
arg_transport = BUS_TRANSPORT_MACHINE;
|
2013-10-30 16:44:55 +01:00
|
|
|
arg_host = optarg;
|
|
|
|
break;
|
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
case ARG_SERVICE_TYPE:
|
|
|
|
arg_service_type = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_EXEC_USER:
|
|
|
|
arg_exec_user = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_EXEC_GROUP:
|
|
|
|
arg_exec_group = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_NICE:
|
2016-08-05 11:17:08 +02:00
|
|
|
r = parse_nice(optarg, &arg_nice);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to parse nice value: %s", optarg);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
arg_nice_set = true;
|
|
|
|
break;
|
|
|
|
|
2016-04-20 14:38:01 +02:00
|
|
|
case 'E':
|
2014-02-05 02:02:00 +01:00
|
|
|
if (strv_extend(&arg_environment, optarg) < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2014-03-05 03:36:22 +01:00
|
|
|
case 'p':
|
|
|
|
if (strv_extend(&arg_property, optarg) < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2017-09-08 15:38:40 +02:00
|
|
|
case 't': /* --pty */
|
|
|
|
if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */
|
|
|
|
arg_stdio = ARG_STDIO_AUTO;
|
|
|
|
else
|
|
|
|
arg_stdio = ARG_STDIO_PTY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'P': /* --pipe */
|
|
|
|
if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */
|
|
|
|
arg_stdio = ARG_STDIO_AUTO;
|
|
|
|
else
|
|
|
|
arg_stdio = ARG_STDIO_DIRECT;
|
2014-12-22 19:45:32 +01:00
|
|
|
break;
|
|
|
|
|
2014-12-22 20:39:10 +01:00
|
|
|
case 'q':
|
|
|
|
arg_quiet = true;
|
|
|
|
break;
|
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
case ARG_ON_ACTIVE:
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnActiveSec", optarg);
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_ON_BOOT:
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnBootSec", optarg);
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_ON_STARTUP:
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnStartupSec", optarg);
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_ON_UNIT_ACTIVE:
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnUnitActiveSec", optarg);
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_ON_UNIT_INACTIVE:
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnUnitInactiveSec", optarg);
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
2019-04-12 20:57:51 +02:00
|
|
|
case ARG_ON_CALENDAR: {
|
|
|
|
_cleanup_(calendar_spec_freep) CalendarSpec *cs = NULL;
|
|
|
|
|
|
|
|
r = calendar_spec_from_string(optarg, &cs);
|
|
|
|
if (r < 0)
|
2019-04-25 13:22:55 +02:00
|
|
|
return log_error_errno(r, "Failed to parse calendar event specification: %m");
|
|
|
|
|
2019-07-16 12:22:37 +02:00
|
|
|
/* Let's make sure the given calendar event is not in the past */
|
2019-04-25 13:22:55 +02:00
|
|
|
r = calendar_spec_next_usec(cs, now(CLOCK_REALTIME), NULL);
|
|
|
|
if (r == -ENOENT)
|
2019-04-26 08:46:01 +02:00
|
|
|
/* The calendar event is in the past — let's warn about this, but install it
|
|
|
|
* anyway as is. The service manager will trigger the service right away.
|
|
|
|
* Moreover, the server side might have a different clock or timezone than we
|
|
|
|
* do, hence it should decide when or whether to run something. */
|
2019-04-25 13:22:55 +02:00
|
|
|
log_warning("Specified calendar expression is in the past, proceeding anyway.");
|
|
|
|
else if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to calculate next time calendar expression elapses: %m");
|
2019-04-12 20:57:51 +02:00
|
|
|
|
2017-12-11 13:21:10 +01:00
|
|
|
r = add_timer_property("OnCalendar", optarg);
|
|
|
|
if (r < 0)
|
2019-03-14 21:36:47 +01:00
|
|
|
return r;
|
|
|
|
|
|
|
|
arg_with_timer = true;
|
|
|
|
break;
|
2019-04-12 20:57:51 +02:00
|
|
|
}
|
2019-03-14 21:36:47 +01:00
|
|
|
|
|
|
|
case ARG_ON_TIMEZONE_CHANGE:
|
|
|
|
r = add_timer_property("OnTimezoneChange", "yes");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
arg_with_timer = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_ON_CLOCK_CHANGE:
|
|
|
|
r = add_timer_property("OnClockChange", "yes");
|
|
|
|
if (r < 0)
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return r;
|
2015-10-08 15:01:42 +02:00
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = true;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ARG_TIMER_PROPERTY:
|
|
|
|
|
|
|
|
if (strv_extend(&arg_timer_property, optarg) < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
arg_with_timer = arg_with_timer ||
|
2018-11-23 16:30:23 +01:00
|
|
|
STARTSWITH_SET(optarg,
|
|
|
|
"OnActiveSec=",
|
|
|
|
"OnBootSec=",
|
|
|
|
"OnStartupSec=",
|
|
|
|
"OnUnitActiveSec=",
|
|
|
|
"OnUnitInactiveSec=",
|
|
|
|
"OnCalendar=");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
break;
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
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;
|
|
|
|
|
2015-04-28 12:33:19 +02:00
|
|
|
case ARG_NO_BLOCK:
|
|
|
|
arg_no_block = true;
|
|
|
|
break;
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
case ARG_WAIT:
|
|
|
|
arg_wait = true;
|
|
|
|
break;
|
|
|
|
|
2018-11-22 12:07:25 +01:00
|
|
|
case ARG_WORKING_DIRECTORY:
|
|
|
|
r = parse_path_argument_and_warn(optarg, true, &arg_working_directory);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd': {
|
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
|
|
|
|
r = safe_getcwd(&p);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to get current working directory: %m");
|
|
|
|
|
|
|
|
if (empty_or_root(p))
|
|
|
|
arg_working_directory = mfree(arg_working_directory);
|
|
|
|
else
|
|
|
|
free_and_replace(arg_working_directory, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-13 17:17:53 +01:00
|
|
|
case 'G':
|
|
|
|
arg_aggressive_gc = true;
|
|
|
|
break;
|
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
case 'S':
|
|
|
|
arg_shell = true;
|
|
|
|
break;
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
case '?':
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
default:
|
2013-11-06 18:28:39 +01:00
|
|
|
assert_not_reached("Unhandled option");
|
2013-07-01 00:03:57 +02:00
|
|
|
}
|
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
with_trigger = !!arg_path_property || !!arg_socket_property || arg_with_timer;
|
2017-12-18 15:46:45 +01:00
|
|
|
|
|
|
|
/* currently, only single trigger (path, socket, timer) unit can be created simultaneously */
|
2019-03-14 19:55:29 +01:00
|
|
|
if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) arg_with_timer > 1)
|
2018-11-20 23:40:44 +01:00
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Only single trigger (path, socket, timer) unit can be created.");
|
2017-09-08 15:38:40 +02:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
if (arg_shell) {
|
|
|
|
/* If --shell is imply --pty --pipe --same-dir --service-type=exec --wait --collect, unless otherwise
|
|
|
|
* specified. */
|
|
|
|
|
|
|
|
if (!arg_scope) {
|
|
|
|
if (arg_stdio == ARG_STDIO_NONE)
|
|
|
|
arg_stdio = ARG_STDIO_AUTO;
|
|
|
|
|
|
|
|
if (!arg_working_directory) {
|
|
|
|
r = safe_getcwd(&arg_working_directory);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to get current working directory: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!arg_service_type) {
|
|
|
|
arg_service_type = strdup("exec");
|
|
|
|
if (!arg_service_type)
|
|
|
|
return log_oom();
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_wait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_aggressive_gc = true;
|
|
|
|
}
|
|
|
|
|
2020-10-09 15:06:34 +02:00
|
|
|
if (arg_stdio == ARG_STDIO_AUTO)
|
2017-09-08 15:38:40 +02:00
|
|
|
/* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
|
|
|
|
* to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
|
|
|
|
* pipeline, but we are neatly interactive with tty-level isolation otherwise. */
|
|
|
|
arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
|
|
|
|
ARG_STDIO_PTY :
|
|
|
|
ARG_STDIO_DIRECT;
|
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
if (argc > optind) {
|
|
|
|
char **l;
|
|
|
|
|
|
|
|
if (arg_shell)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "If --shell is used, no command line is expected.");
|
|
|
|
|
|
|
|
l = strv_copy(argv + optind);
|
|
|
|
if (!l)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
strv_free_and_replace(arg_cmdline, l);
|
|
|
|
|
|
|
|
} else if (arg_shell) {
|
|
|
|
_cleanup_free_ char *s = NULL;
|
|
|
|
char **l;
|
|
|
|
|
|
|
|
r = get_shell(&s);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to determine shell: %m");
|
|
|
|
|
|
|
|
l = strv_new(s);
|
|
|
|
if (!l)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
strv_free_and_replace(arg_cmdline, l);
|
|
|
|
|
|
|
|
} else if (!arg_unit || !with_trigger)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Command line to execute required.");
|
2013-07-01 00:03:57 +02:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Execution in user context is not supported on non-local systems.");
|
2013-10-30 16:44:55 +01:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Scope execution is not supported on non-local systems.");
|
2013-10-30 16:44:55 +01:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_scope && (arg_remain_after_exit || arg_service_type))
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--remain-after-exit and --service-type= are not supported in --scope mode.");
|
2014-02-05 02:02:00 +01:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope))
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--pty/--pipe is not compatible in timer or --scope mode.");
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--pty/--pipe is only supported when connecting to the local system or containers.");
|
2015-10-08 15:01:42 +02:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_stdio != ARG_STDIO_NONE && arg_no_block)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--pty/--pipe is not compatible with --no-block.");
|
2016-12-24 00:30:49 +01:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_scope && with_trigger)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Path, socket or timer options are not supported in --scope mode.");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2019-03-14 19:55:29 +01:00
|
|
|
if (arg_timer_property && !arg_with_timer)
|
2018-11-20 23:40:44 +01:00
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--timer-property= has no effect without any other timer options.");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
if (arg_wait) {
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_no_block)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--wait may not be combined with --no-block.");
|
2016-08-17 14:24:17 +02:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (with_trigger)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--wait may not be combined with path, socket or timer operations.");
|
2016-08-17 14:24:17 +02:00
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_scope)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"--wait may not be combined with --scope.");
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-12-23 08:59:56 +01:00
|
|
|
static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
|
2013-06-28 04:12:58 +02:00
|
|
|
int r;
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2017-11-13 17:17:53 +01:00
|
|
|
if (arg_aggressive_gc) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2017-11-13 17:17:53 +01:00
|
|
|
}
|
|
|
|
|
2017-12-23 08:59:56 +01:00
|
|
|
r = bus_append_unit_property_assignment_many(m, t, properties);
|
2016-08-05 18:32:42 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2014-03-05 03:36:22 +01:00
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int transient_cgroup_set_properties(sd_bus_message *m) {
|
2020-04-08 14:57:52 +02:00
|
|
|
_cleanup_free_ char *name = NULL;
|
|
|
|
_cleanup_free_ char *slice = NULL;
|
2014-12-22 19:45:32 +01:00
|
|
|
int r;
|
|
|
|
assert(m);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2020-04-08 14:57:52 +02:00
|
|
|
if (arg_slice_inherit) {
|
|
|
|
char *end;
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2020-04-08 14:57:52 +02:00
|
|
|
if (arg_user)
|
|
|
|
r = cg_pid_get_user_slice(0, &name);
|
|
|
|
else
|
|
|
|
r = cg_pid_get_slice(0, &name);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
2020-04-08 14:57:52 +02:00
|
|
|
return log_error_errno(r, "Failed to get PID slice: %m");
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2020-04-08 14:57:52 +02:00
|
|
|
end = endswith(name, ".slice");
|
|
|
|
if (!end)
|
|
|
|
return -ENXIO;
|
|
|
|
*end = 0;
|
2013-07-01 03:02:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 14:57:52 +02:00
|
|
|
if (!isempty(arg_slice)) {
|
|
|
|
if (name) {
|
|
|
|
char *j = strjoin(name, "-", arg_slice);
|
|
|
|
free_and_replace(name, j);
|
|
|
|
} else
|
|
|
|
name = strdup(arg_slice);
|
|
|
|
if (!name)
|
|
|
|
return log_oom();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
r = unit_name_mangle_with_suffix(name, "as slice",
|
|
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
|
|
".slice", &slice);
|
|
|
|
if (r < 0)
|
|
|
|
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 bus_log_create_error(r);
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int transient_kill_set_properties(sd_bus_message *m) {
|
2017-11-29 20:05:22 +01:00
|
|
|
int r;
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
assert(m);
|
|
|
|
|
2017-11-29 20:05:22 +01:00
|
|
|
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;
|
2013-07-01 00:03:57 +02:00
|
|
|
}
|
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
static int transient_service_set_properties(sd_bus_message *m, const char *pty_path) {
|
2017-09-08 15:38:40 +02:00
|
|
|
bool send_term = false;
|
2013-07-01 00:03:57 +02:00
|
|
|
int r;
|
|
|
|
|
2013-11-08 19:49:49 +01:00
|
|
|
assert(m);
|
|
|
|
|
2017-12-23 08:59:56 +01:00
|
|
|
r = transient_unit_set_properties(m, UNIT_SERVICE, arg_property);
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = transient_kill_set_properties(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = transient_cgroup_set_properties(m);
|
2013-11-21 20:05:49 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2017-09-08 15:38:40 +02:00
|
|
|
if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
|
2016-08-17 14:24:17 +02:00
|
|
|
r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
|
|
|
|
2014-03-05 03:36:22 +01:00
|
|
|
if (arg_remain_after_exit) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-03-05 03:36:22 +01:00
|
|
|
}
|
2013-07-26 16:09:25 +02:00
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
if (arg_service_type) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_exec_user) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_exec_group) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_nice_set) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
}
|
|
|
|
|
2018-11-22 12:07:25 +01:00
|
|
|
if (arg_working_directory) {
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "WorkingDirectory", "s", arg_working_directory);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
}
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
if (pty_path) {
|
|
|
|
r = sd_bus_message_append(m,
|
|
|
|
"(sv)(sv)(sv)(sv)",
|
|
|
|
"StandardInput", "s", "tty",
|
|
|
|
"StandardOutput", "s", "tty",
|
|
|
|
"StandardError", "s", "tty",
|
|
|
|
"TTYPath", "s", pty_path);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2017-09-08 15:38:40 +02:00
|
|
|
send_term = true;
|
|
|
|
|
|
|
|
} else if (arg_stdio == ARG_STDIO_DIRECT) {
|
|
|
|
r = sd_bus_message_append(m,
|
|
|
|
"(sv)(sv)(sv)",
|
|
|
|
"StandardInputFileDescriptor", "h", STDIN_FILENO,
|
|
|
|
"StandardOutputFileDescriptor", "h", STDOUT_FILENO,
|
|
|
|
"StandardErrorFileDescriptor", "h", STDERR_FILENO);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2017-09-08 15:38:40 +02:00
|
|
|
|
|
|
|
send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (send_term) {
|
|
|
|
const char *e;
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
e = getenv("TERM");
|
|
|
|
if (e) {
|
|
|
|
char *n;
|
|
|
|
|
2015-02-03 02:05:59 +01:00
|
|
|
n = strjoina("TERM=", e);
|
2014-12-22 19:45:32 +01:00
|
|
|
r = sd_bus_message_append(m,
|
|
|
|
"(sv)",
|
|
|
|
"Environment", "as", 1, n);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-12-22 19:45:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
if (!strv_isempty(arg_environment)) {
|
|
|
|
r = sd_bus_message_open_container(m, 'r', "sv");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_append(m, "s", "Environment");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_open_container(m, 'v', "as");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_append_strv(m, arg_environment);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-02-05 02:02:00 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Exec container */
|
2018-11-22 19:24:48 +01:00
|
|
|
if (!strv_isempty(arg_cmdline)) {
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_open_container(m, 'r', "sv");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_append(m, "s", "ExecStart");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_open_container(m, 'v', "a(sasb)");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_open_container(m, 'a', "(sasb)");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_open_container(m, 'r', "sasb");
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
r = sd_bus_message_append(m, "s", arg_cmdline[0]);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
r = sd_bus_message_append_strv(m, arg_cmdline);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_append(m, "b", false);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
static int transient_scope_set_properties(sd_bus_message *m) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
|
2017-12-23 08:59:56 +01:00
|
|
|
r = transient_unit_set_properties(m, UNIT_SCOPE, arg_property);
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = transient_kill_set_properties(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2016-04-22 17:31:40 +02:00
|
|
|
r = transient_cgroup_set_properties(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2017-07-20 16:19:18 +02:00
|
|
|
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached());
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
static int transient_timer_set_properties(sd_bus_message *m) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
|
2017-12-23 08:59:56 +01:00
|
|
|
r = transient_unit_set_properties(m, UNIT_TIMER, arg_timer_property);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-11-17 20:38:12 +01:00
|
|
|
/* Automatically clean up our transient timers */
|
|
|
|
r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
|
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return bus_log_create_error(r);
|
2015-11-17 20:38:12 +01:00
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
static int make_unit_name(sd_bus *bus, UnitType t, char **ret) {
|
|
|
|
const char *unique, *id;
|
|
|
|
char *p;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(t >= 0);
|
|
|
|
assert(t < _UNIT_TYPE_MAX);
|
|
|
|
|
|
|
|
r = sd_bus_get_unique_name(bus, &unique);
|
|
|
|
if (r < 0) {
|
|
|
|
sd_id128_t rnd;
|
|
|
|
|
|
|
|
/* We couldn't get the unique name, which is a pretty
|
|
|
|
* common case if we are connected to systemd
|
|
|
|
* directly. In that case, just pick a random uuid as
|
|
|
|
* name */
|
|
|
|
|
|
|
|
r = sd_id128_randomize(&rnd);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to generate random run unit name: %m");
|
|
|
|
|
|
|
|
if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We managed to get the unique name, then let's use that to
|
|
|
|
* name our transient units. */
|
|
|
|
|
|
|
|
id = startswith(unique, ":1.");
|
2018-11-20 23:40:44 +01:00
|
|
|
if (!id)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Unique name %s has unexpected format.",
|
|
|
|
unique);
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
|
2016-10-23 17:43:27 +02:00
|
|
|
p = strjoin("run-u", id, ".", unit_type_to_string(t));
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
if (!p)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
*ret = p;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
typedef struct RunContext {
|
|
|
|
sd_bus *bus;
|
|
|
|
sd_event *event;
|
|
|
|
PTYForward *forward;
|
|
|
|
sd_bus_slot *match;
|
|
|
|
|
2020-05-26 16:22:36 +02:00
|
|
|
/* Current state of the unit */
|
2016-08-17 14:24:17 +02:00
|
|
|
char *active_state;
|
2020-05-26 16:22:36 +02:00
|
|
|
bool has_job;
|
|
|
|
|
|
|
|
/* The exit data of the unit */
|
2016-08-17 14:24:17 +02:00
|
|
|
uint64_t inactive_exit_usec;
|
|
|
|
uint64_t inactive_enter_usec;
|
|
|
|
char *result;
|
|
|
|
uint64_t cpu_usage_nsec;
|
2017-09-26 16:33:03 +02:00
|
|
|
uint64_t ip_ingress_bytes;
|
|
|
|
uint64_t ip_egress_bytes;
|
2019-03-22 12:18:19 +01:00
|
|
|
uint64_t io_read_bytes;
|
|
|
|
uint64_t io_write_bytes;
|
2016-08-17 14:24:17 +02:00
|
|
|
uint32_t exit_code;
|
|
|
|
uint32_t exit_status;
|
|
|
|
} RunContext;
|
|
|
|
|
|
|
|
static void run_context_free(RunContext *c) {
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
c->forward = pty_forward_free(c->forward);
|
|
|
|
c->match = sd_bus_slot_unref(c->match);
|
|
|
|
c->bus = sd_bus_unref(c->bus);
|
|
|
|
c->event = sd_event_unref(c->event);
|
|
|
|
|
|
|
|
free(c->active_state);
|
|
|
|
free(c->result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void run_context_check_done(RunContext *c) {
|
2016-12-24 00:35:58 +01:00
|
|
|
bool done;
|
2016-08-17 14:24:17 +02:00
|
|
|
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
if (c->match)
|
2020-05-26 16:22:36 +02:00
|
|
|
done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
|
2016-12-24 00:35:58 +01:00
|
|
|
else
|
|
|
|
done = true;
|
2016-08-17 14:24:17 +02:00
|
|
|
|
2016-12-24 00:35:58 +01:00
|
|
|
if (c->forward && done) /* If the service is gone, it's time to drain the output */
|
|
|
|
done = pty_forward_drain(c->forward);
|
2016-08-17 14:24:17 +02:00
|
|
|
|
|
|
|
if (done)
|
|
|
|
sd_event_exit(c->event, EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-05-26 16:22:36 +02:00
|
|
|
static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
|
|
|
|
bool *b = userdata;
|
|
|
|
const char *job;
|
|
|
|
uint32_t id;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "(uo)", &id, &job);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*b = id != 0 || !streq(job, "/");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-12-23 22:56:39 +01:00
|
|
|
static int run_context_update(RunContext *c, const char *path) {
|
2016-08-17 14:24:17 +02:00
|
|
|
|
|
|
|
static const struct bus_properties_map map[] = {
|
2020-05-26 16:22:36 +02:00
|
|
|
{ "ActiveState", "s", NULL, offsetof(RunContext, active_state) },
|
|
|
|
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) },
|
|
|
|
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) },
|
|
|
|
{ "Result", "s", NULL, offsetof(RunContext, result) },
|
|
|
|
{ "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) },
|
|
|
|
{ "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) },
|
|
|
|
{ "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
|
|
|
|
{ "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
|
|
|
|
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
|
|
|
|
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
|
|
|
|
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
|
|
|
|
{ "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
|
2016-08-17 14:24:17 +02:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2017-02-08 17:59:58 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2016-08-17 14:24:17 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
r = bus_map_all_properties(c->bus,
|
|
|
|
"org.freedesktop.systemd1",
|
2016-12-23 22:56:39 +01:00
|
|
|
path,
|
2016-08-17 14:24:17 +02:00
|
|
|
map,
|
2018-03-28 13:37:27 +02:00
|
|
|
BUS_MAP_STRDUP,
|
2017-02-08 17:59:58 +01:00
|
|
|
&error,
|
2018-03-19 15:46:29 +01:00
|
|
|
NULL,
|
2016-08-17 14:24:17 +02:00
|
|
|
c);
|
|
|
|
if (r < 0) {
|
|
|
|
sd_event_exit(c->event, EXIT_FAILURE);
|
2017-02-08 17:59:58 +01:00
|
|
|
return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r));
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
run_context_check_done(c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-12-23 22:56:39 +01:00
|
|
|
static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
|
|
|
RunContext *c = userdata;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
return run_context_update(c, sd_bus_message_get_path(m));
|
|
|
|
}
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
|
|
|
|
RunContext *c = userdata;
|
|
|
|
|
|
|
|
assert(f);
|
|
|
|
|
|
|
|
if (rcode < 0) {
|
|
|
|
sd_event_exit(c->event, EXIT_FAILURE);
|
|
|
|
return log_error_errno(rcode, "Error on PTY forwarding logic: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
run_context_check_done(c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
static int start_transient_service(
|
|
|
|
sd_bus *bus,
|
2016-08-17 14:24:17 +02:00
|
|
|
int *retval) {
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_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;
|
2015-04-28 12:33:19 +02:00
|
|
|
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
2014-12-23 01:58:49 +01:00
|
|
|
_cleanup_free_ char *service = NULL, *pty_path = NULL;
|
2014-12-22 19:45:32 +01:00
|
|
|
_cleanup_close_ int master = -1;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
2016-08-17 14:24:17 +02:00
|
|
|
assert(retval);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2017-09-08 15:38:40 +02:00
|
|
|
if (arg_stdio == ARG_STDIO_PTY) {
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2014-12-23 01:58:49 +01:00
|
|
|
if (arg_transport == BUS_TRANSPORT_LOCAL) {
|
2018-05-31 12:04:37 +02:00
|
|
|
master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
|
2014-12-23 01:58:49 +01:00
|
|
|
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");
|
|
|
|
|
2015-09-01 19:39:14 +02:00
|
|
|
if (unlockpt(master) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to unlock tty: %m");
|
|
|
|
|
2014-12-23 23:38:13 +01:00
|
|
|
} else if (arg_transport == BUS_TRANSPORT_MACHINE) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
|
2016-05-22 00:30:33 +02:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL;
|
2014-12-23 01:58:49 +01:00
|
|
|
const char *s;
|
|
|
|
|
2015-10-08 15:01:42 +02:00
|
|
|
r = sd_bus_default_system(&system_bus);
|
2014-12-23 01:58:49 +01:00
|
|
|
if (r < 0)
|
2015-10-08 15:01:42 +02:00
|
|
|
return log_error_errno(r, "Failed to connect to system bus: %m");
|
2014-12-23 01:58:49 +01:00
|
|
|
|
|
|
|
r = sd_bus_call_method(system_bus,
|
|
|
|
"org.freedesktop.machine1",
|
|
|
|
"/org/freedesktop/machine1",
|
|
|
|
"org.freedesktop.machine1.Manager",
|
|
|
|
"OpenMachinePTY",
|
|
|
|
&error,
|
2016-05-22 00:30:33 +02:00
|
|
|
&pty_reply,
|
2014-12-23 01:58:49 +01:00
|
|
|
"s", arg_host);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
2020-09-14 18:16:54 +02:00
|
|
|
return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, r));
|
2014-12-23 01:58:49 +01:00
|
|
|
|
2016-05-22 00:30:33 +02:00
|
|
|
r = sd_bus_message_read(pty_reply, "hs", &master, &s);
|
2014-12-23 01:58:49 +01:00
|
|
|
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");
|
2014-12-22 19:45:32 +01:00
|
|
|
}
|
|
|
|
|
2020-04-22 20:08:34 +02:00
|
|
|
/* Optionally, wait for the start job to complete. If we are supposed to read the service's stdin
|
|
|
|
* lets skip this however, because we should start that already when the start job is running, and
|
|
|
|
* there's little point in waiting for the start job to complete in that case anyway, as we'll wait
|
|
|
|
* for EOF anyway, which is going to be much later. */
|
|
|
|
if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) {
|
2015-04-28 12:33:19 +02:00
|
|
|
r = bus_wait_for_jobs_new(bus, &w);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not watch jobs: %m");
|
|
|
|
}
|
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (arg_unit) {
|
2019-10-24 14:09:11 +02:00
|
|
|
r = unit_name_mangle_with_suffix(arg_unit, "as unit",
|
|
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
|
|
".service", &service);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to mangle unit name: %m");
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
} else {
|
|
|
|
r = make_unit_name(bus, UNIT_SERVICE, &service);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2020-05-03 08:41:14 +02:00
|
|
|
r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
|
2013-07-01 00:40:56 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-07-01 00:40:56 +02:00
|
|
|
|
2015-09-01 18:43:08 +02:00
|
|
|
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Name and mode */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_append(m, "ss", service, "fail");
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Properties */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
r = transient_service_set_properties(m, pty_path);
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_close_container(m);
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Auxiliary units */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_append(m, "a(sa(sv))", 0);
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-09-01 18:43:08 +02:00
|
|
|
|
2015-04-28 12:33:19 +02:00
|
|
|
r = sd_bus_call(bus, m, 0, &error, &reply);
|
2015-10-08 15:01:42 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2015-04-28 12:33:19 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
if (!arg_quiet)
|
|
|
|
log_info("Running as unit: %s", service);
|
|
|
|
|
2017-09-08 15:38:40 +02:00
|
|
|
if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
|
2017-09-26 16:33:03 +02:00
|
|
|
_cleanup_(run_context_free) RunContext c = {
|
|
|
|
.cpu_usage_nsec = NSEC_INFINITY,
|
|
|
|
.ip_ingress_bytes = UINT64_MAX,
|
|
|
|
.ip_egress_bytes = UINT64_MAX,
|
2019-03-22 12:18:19 +01:00
|
|
|
.io_read_bytes = UINT64_MAX,
|
|
|
|
.io_write_bytes = UINT64_MAX,
|
2017-09-26 16:33:03 +02:00
|
|
|
.inactive_exit_usec = USEC_INFINITY,
|
|
|
|
.inactive_enter_usec = USEC_INFINITY,
|
|
|
|
};
|
2016-12-24 00:35:58 +01:00
|
|
|
_cleanup_free_ char *path = NULL;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
c.bus = sd_bus_ref(bus);
|
|
|
|
|
|
|
|
r = sd_event_default(&c.event);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (r < 0)
|
2014-12-22 19:45:32 +01:00
|
|
|
return log_error_errno(r, "Failed to get event loop: %m");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
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.");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
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);
|
2017-12-05 18:31:32 +01:00
|
|
|
|
|
|
|
/* Make sure to process any TTY events before we process bus events */
|
|
|
|
(void) pty_forward_set_priority(c.forward, SD_EVENT_PRIORITY_IMPORTANT);
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-12-24 00:35:58 +01:00
|
|
|
path = unit_dbus_path_from_name(service);
|
|
|
|
if (!path)
|
|
|
|
return log_oom();
|
2016-08-17 14:24:17 +02:00
|
|
|
|
2017-12-19 12:29:04 +01:00
|
|
|
r = sd_bus_match_signal_async(
|
|
|
|
bus,
|
|
|
|
&c.match,
|
|
|
|
"org.freedesktop.systemd1",
|
|
|
|
path,
|
|
|
|
"org.freedesktop.DBus.Properties",
|
|
|
|
"PropertiesChanged",
|
|
|
|
on_properties_changed, NULL, &c);
|
2016-12-24 00:35:58 +01:00
|
|
|
if (r < 0)
|
2017-12-19 12:29:04 +01:00
|
|
|
return log_error_errno(r, "Failed to request properties changed signal match: %m");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2017-12-05 18:31:32 +01:00
|
|
|
r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL);
|
2016-12-24 00:35:58 +01:00
|
|
|
if (r < 0)
|
2017-12-19 12:29:04 +01:00
|
|
|
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
2016-12-23 22:56:39 +01:00
|
|
|
|
2016-12-24 00:35:58 +01:00
|
|
|
r = run_context_update(&c, path);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2016-08-17 14:24:17 +02:00
|
|
|
|
|
|
|
r = sd_event_loop(c.event);
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (r < 0)
|
2014-12-22 19:45:32 +01:00
|
|
|
return log_error_errno(r, "Failed to run event loop: %m");
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
if (c.forward) {
|
|
|
|
char last_char = 0;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
r = pty_forward_get_last_char(c.forward, &last_char);
|
|
|
|
if (r >= 0 && !arg_quiet && last_char != '\n')
|
|
|
|
fputc('\n', stdout);
|
|
|
|
}
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
2016-12-24 00:35:58 +01:00
|
|
|
if (arg_wait && !arg_quiet) {
|
2016-12-24 00:34:34 +01:00
|
|
|
|
2019-10-29 17:30:36 +01:00
|
|
|
/* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its
|
2016-12-24 00:34:34 +01:00
|
|
|
* original settings (i.e. proper line breaks), so that we can show the summary in a pretty
|
|
|
|
* way. */
|
|
|
|
c.forward = pty_forward_free(c.forward);
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
if (!isempty(c.result))
|
|
|
|
log_info("Finished with result: %s", strna(c.result));
|
2013-07-01 00:40:56 +02:00
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
if (c.exit_code == CLD_EXITED)
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("Main processes terminated with: code=%s/status=%i",
|
|
|
|
sigchld_code_to_string(c.exit_code), c.exit_status);
|
2016-08-17 14:24:17 +02:00
|
|
|
else if (c.exit_code > 0)
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("Main processes terminated with: code=%s/status=%s",
|
|
|
|
sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
|
2016-08-17 14:24:17 +02:00
|
|
|
|
2019-07-04 19:10:11 +02:00
|
|
|
if (timestamp_is_set(c.inactive_enter_usec) &&
|
|
|
|
timestamp_is_set(c.inactive_exit_usec) &&
|
2016-08-17 14:24:17 +02:00
|
|
|
c.inactive_enter_usec > c.inactive_exit_usec) {
|
|
|
|
char ts[FORMAT_TIMESPAN_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("Service runtime: %s",
|
|
|
|
format_timespan(ts, sizeof ts, c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
|
|
|
|
2017-09-26 16:33:03 +02:00
|
|
|
if (c.cpu_usage_nsec != NSEC_INFINITY) {
|
2016-08-17 14:24:17 +02:00
|
|
|
char ts[FORMAT_TIMESPAN_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("CPU time consumed: %s",
|
2020-10-09 14:59:44 +02:00
|
|
|
format_timespan(ts, sizeof ts, DIV_ROUND_UP(c.cpu_usage_nsec, NSEC_PER_USEC), USEC_PER_MSEC));
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
2017-09-26 16:33:03 +02:00
|
|
|
|
|
|
|
if (c.ip_ingress_bytes != UINT64_MAX) {
|
|
|
|
char bytes[FORMAT_BYTES_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("IP traffic received: %s", format_bytes(bytes, sizeof bytes, c.ip_ingress_bytes));
|
2017-09-26 16:33:03 +02:00
|
|
|
}
|
|
|
|
if (c.ip_egress_bytes != UINT64_MAX) {
|
|
|
|
char bytes[FORMAT_BYTES_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("IP traffic sent: %s", format_bytes(bytes, sizeof bytes, c.ip_egress_bytes));
|
2017-09-26 16:33:03 +02:00
|
|
|
}
|
2019-03-22 12:18:19 +01:00
|
|
|
if (c.io_read_bytes != UINT64_MAX) {
|
|
|
|
char bytes[FORMAT_BYTES_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("IO bytes read: %s", format_bytes(bytes, sizeof bytes, c.io_read_bytes));
|
2019-03-22 12:18:19 +01:00
|
|
|
}
|
|
|
|
if (c.io_write_bytes != UINT64_MAX) {
|
|
|
|
char bytes[FORMAT_BYTES_MAX];
|
2019-10-29 17:30:36 +01:00
|
|
|
log_info("IO bytes written: %s", format_bytes(bytes, sizeof bytes, c.io_write_bytes));
|
2019-03-22 12:18:19 +01:00
|
|
|
}
|
2016-08-17 14:24:17 +02:00
|
|
|
}
|
|
|
|
|
2019-10-29 18:07:07 +01:00
|
|
|
/* Try to propagate the service's return value. But if the service defines
|
|
|
|
* e.g. SuccessExitStatus, honour this, and return 0 to mean "success". */
|
|
|
|
if (streq_ptr(c.result, "success"))
|
|
|
|
*retval = 0;
|
|
|
|
else if (streq_ptr(c.result, "exit-code") && c.exit_status > 0)
|
2016-08-17 14:24:17 +02:00
|
|
|
*retval = c.exit_status;
|
2019-10-29 18:07:07 +01:00
|
|
|
else if (streq_ptr(c.result, "signal"))
|
|
|
|
*retval = EXIT_EXCEPTION;
|
2016-08-17 14:24:17 +02:00
|
|
|
else
|
|
|
|
*retval = EXIT_FAILURE;
|
|
|
|
}
|
2014-03-05 19:02:53 +01:00
|
|
|
|
|
|
|
return 0;
|
2013-07-01 00:03:57 +02:00
|
|
|
}
|
|
|
|
|
2018-11-22 20:40:00 +01:00
|
|
|
static int acquire_invocation_id(sd_bus *bus, sd_id128_t *ret) {
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
const void *p;
|
|
|
|
size_t l;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(ret);
|
2013-07-01 00:03:57 +02:00
|
|
|
|
2018-11-22 20:40:00 +01:00
|
|
|
r = sd_bus_get_property(bus,
|
|
|
|
"org.freedesktop.systemd1",
|
|
|
|
"/org/freedesktop/systemd1/unit/self",
|
|
|
|
"org.freedesktop.systemd1.Unit",
|
|
|
|
"InvocationID",
|
|
|
|
&error,
|
|
|
|
&reply,
|
|
|
|
"ay");
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to request invocation ID for scope: %s", bus_error_message(&error, r));
|
|
|
|
|
|
|
|
r = sd_bus_message_read_array(reply, 'y', &p, &l);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
|
|
|
if (l != sizeof(sd_id128_t))
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid UUID size, %zu != %zu.", l, sizeof(sd_id128_t));
|
|
|
|
|
|
|
|
memcpy(ret, p, l);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int start_transient_scope(sd_bus *bus) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_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;
|
2015-04-28 12:21:31 +02:00
|
|
|
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
2014-12-22 19:45:32 +01:00
|
|
|
_cleanup_strv_free_ char **env = NULL, **user_env = NULL;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
_cleanup_free_ char *scope = NULL;
|
2015-04-28 12:21:31 +02:00
|
|
|
const char *object = NULL;
|
2018-11-22 20:40:00 +01:00
|
|
|
sd_id128_t invocation_id;
|
2013-07-01 00:03:57 +02:00
|
|
|
int r;
|
|
|
|
|
2013-11-08 19:49:49 +01:00
|
|
|
assert(bus);
|
2018-11-22 19:24:48 +01:00
|
|
|
assert(!strv_isempty(arg_cmdline));
|
2013-11-08 19:49:49 +01:00
|
|
|
|
2015-04-28 12:21:31 +02:00
|
|
|
r = bus_wait_for_jobs_new(bus, &w);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2014-07-25 15:38:31 +02:00
|
|
|
if (arg_unit) {
|
2019-10-24 14:09:11 +02:00
|
|
|
r = unit_name_mangle_with_suffix(arg_unit, "as unit",
|
|
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
|
|
".scope", &scope);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to mangle scope name: %m");
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
} else {
|
|
|
|
r = make_unit_name(bus, UNIT_SCOPE, &scope);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
2013-07-01 00:03:57 +02:00
|
|
|
|
2020-05-03 08:41:14 +02:00
|
|
|
r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2015-09-01 18:43:08 +02:00
|
|
|
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Name and Mode */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_append(m, "ss", scope, "fail");
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Properties */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
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)
|
2017-11-29 20:05:22 +01:00
|
|
|
return r;
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_close_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2014-12-23 01:58:49 +01:00
|
|
|
/* Auxiliary units */
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
r = sd_bus_message_append(m, "a(sa(sv))", 0);
|
2013-07-01 00:03:57 +02:00
|
|
|
if (r < 0)
|
2014-03-05 19:02:53 +01:00
|
|
|
return bus_log_create_error(r);
|
2013-07-01 00:03:57 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-09-01 18:43:08 +02:00
|
|
|
|
2015-04-28 12:21:31 +02:00
|
|
|
r = sd_bus_call(bus, m, 0, &error, &reply);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
2020-09-14 18:16:54 +02:00
|
|
|
return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, r));
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2018-11-22 20:40:00 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
r = acquire_invocation_id(bus, &invocation_id);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = strv_extendf(&user_env, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(invocation_id));
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2014-03-05 18:57:21 +01:00
|
|
|
if (arg_nice_set) {
|
2014-11-28 19:57:32 +01:00
|
|
|
if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to set nice level: %m");
|
2014-03-05 18:57:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_exec_group) {
|
|
|
|
gid_t gid;
|
|
|
|
|
2018-08-02 18:36:47 +02:00
|
|
|
r = get_group_creds(&arg_exec_group, &gid, 0);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
|
2014-03-05 18:57:21 +01:00
|
|
|
|
2014-11-28 19:57:32 +01:00
|
|
|
if (setresgid(gid, gid, gid) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
|
2014-03-05 18:57:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_exec_user) {
|
|
|
|
const char *home, *shell;
|
|
|
|
uid_t uid;
|
|
|
|
gid_t gid;
|
|
|
|
|
2018-08-20 16:06:41 +02:00
|
|
|
r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
|
2014-03-05 18:57:21 +01:00
|
|
|
|
2016-08-25 10:24:10 +02:00
|
|
|
if (home) {
|
|
|
|
r = strv_extendf(&user_env, "HOME=%s", home);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
}
|
2014-03-05 18:57:21 +01:00
|
|
|
|
2016-08-25 10:24:10 +02:00
|
|
|
if (shell) {
|
|
|
|
r = strv_extendf(&user_env, "SHELL=%s", shell);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
}
|
2014-03-05 18:57:21 +01:00
|
|
|
|
|
|
|
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) {
|
2014-11-28 19:57:32 +01:00
|
|
|
if (setresgid(gid, gid, gid) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
|
2014-03-05 18:57:21 +01:00
|
|
|
}
|
|
|
|
|
2014-11-28 19:57:32 +01:00
|
|
|
if (setresuid(uid, uid, uid) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
|
2014-03-05 18:57:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
env = strv_env_merge(3, environ, user_env, arg_environment);
|
|
|
|
if (!env)
|
|
|
|
return log_oom();
|
|
|
|
|
2014-12-22 20:39:10 +01:00
|
|
|
if (!arg_quiet)
|
2016-04-04 11:28:14 +02:00
|
|
|
log_info("Running scope as unit: %s", scope);
|
2014-03-05 19:02:53 +01:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
execvpe(arg_cmdline[0], arg_cmdline, env);
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
return log_error_errno(errno, "Failed to execute: %m");
|
|
|
|
}
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
static int start_transient_trigger(
|
2014-12-22 19:45:32 +01:00
|
|
|
sd_bus *bus,
|
2017-12-18 15:46:45 +01:00
|
|
|
const char *suffix) {
|
2014-12-22 19:45:32 +01:00
|
|
|
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_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;
|
2015-04-28 12:21:31 +02:00
|
|
|
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
2017-12-18 15:46:45 +01:00
|
|
|
_cleanup_free_ char *trigger = NULL, *service = NULL;
|
2015-04-28 12:21:31 +02:00
|
|
|
const char *object = NULL;
|
2014-12-22 19:45:32 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
|
2015-04-28 12:21:31 +02:00
|
|
|
r = bus_wait_for_jobs_new(bus, &w);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
if (arg_unit) {
|
2015-04-30 20:21:00 +02:00
|
|
|
switch (unit_name_to_type(arg_unit)) {
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
case UNIT_SERVICE:
|
|
|
|
service = strdup(arg_unit);
|
|
|
|
if (!service)
|
|
|
|
return log_oom();
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
r = unit_name_change_suffix(service, suffix, &trigger);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to change unit suffix: %m");
|
2014-12-22 19:45:32 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UNIT_TIMER:
|
2017-12-18 15:46:45 +01:00
|
|
|
trigger = strdup(arg_unit);
|
|
|
|
if (!trigger)
|
2014-12-22 19:45:32 +01:00
|
|
|
return log_oom();
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
r = unit_name_change_suffix(trigger, ".service", &service);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to change unit suffix: %m");
|
2014-12-22 19:45:32 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-10-24 14:09:11 +02:00
|
|
|
r = unit_name_mangle_with_suffix(arg_unit, "as unit",
|
|
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
|
|
".service", &service);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to mangle unit name: %m");
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2019-10-24 14:09:11 +02:00
|
|
|
r = unit_name_mangle_with_suffix(arg_unit, "as trigger",
|
|
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
|
|
suffix, &trigger);
|
2015-04-30 20:21:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to mangle unit name: %m");
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
} else {
|
|
|
|
r = make_unit_name(bus, UNIT_SERVICE, &service);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
r = unit_name_change_suffix(service, suffix, &trigger);
|
run: when automatically generating names for transient units, use unique bus ID, fallback to random
Previously we used the process ID to generate transient unit names.
However, that is problematic as PIDs get reused easily, and applying
them to remote systems makes little sense.
Fortunately, each bus peer gets a unique, non-reusable ID assigned when
attaching to a bus, hence let's use that, if we can. In some cases we
cannot however, because we connect directly to PID's private socket, and
thus are not a proper bus peer with a unique ID. In that case generate a
random UUID to name the unit after.
2015-11-17 14:11:12 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to change unit suffix: %m");
|
|
|
|
}
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2020-05-03 08:41:14 +02:00
|
|
|
r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2015-09-01 18:43:08 +02:00
|
|
|
r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_create_error(r);
|
|
|
|
|
2014-12-22 19:45:32 +01:00
|
|
|
/* Name and Mode */
|
2017-12-18 15:46:45 +01:00
|
|
|
r = sd_bus_message_append(m, "ss", trigger, "fail");
|
2014-12-22 19:45:32 +01:00
|
|
|
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);
|
|
|
|
|
2017-12-18 15:46:45 +01:00
|
|
|
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");
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return r;
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
if (!strv_isempty(arg_cmdline)) {
|
2014-12-22 19:45:32 +01:00
|
|
|
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);
|
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
r = transient_service_set_properties(m, NULL);
|
2014-12-22 19:45:32 +01:00
|
|
|
if (r < 0)
|
2017-11-29 20:05:22 +01:00
|
|
|
return r;
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-09-01 18:43:08 +02:00
|
|
|
|
2015-04-28 12:21:31 +02:00
|
|
|
r = sd_bus_call(bus, m, 0, &error, &reply);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
2020-09-14 18:16:54 +02:00
|
|
|
return log_error_errno(r, "Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, r));
|
2014-12-22 19:45:32 +01:00
|
|
|
|
2015-04-28 12:21:31 +02:00
|
|
|
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;
|
|
|
|
|
2016-08-24 12:12:18 +02:00
|
|
|
if (!arg_quiet) {
|
2017-12-18 15:46:45 +01:00
|
|
|
log_info("Running %s as unit: %s", suffix + 1, trigger);
|
2018-11-22 19:24:48 +01:00
|
|
|
if (!strv_isempty(arg_cmdline))
|
2016-08-24 12:12:18 +02:00
|
|
|
log_info("Will run service as unit: %s", service);
|
|
|
|
}
|
2014-12-22 19:45:32 +01:00
|
|
|
|
|
|
|
return 0;
|
2013-06-28 04:12:58 +02:00
|
|
|
}
|
|
|
|
|
2018-11-22 19:30:03 +01:00
|
|
|
static int run(int argc, char* argv[]) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
2018-11-22 19:24:48 +01:00
|
|
|
_cleanup_free_ char *description = NULL;
|
2016-08-17 14:24:17 +02:00
|
|
|
int r, retval = EXIT_SUCCESS;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2019-04-26 12:28:25 +02:00
|
|
|
log_show_color(true);
|
2013-06-28 04:12:58 +02:00
|
|
|
log_parse_environment();
|
|
|
|
log_open();
|
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
r = parse_argv(argc, argv);
|
|
|
|
if (r <= 0)
|
2018-11-22 19:34:15 +01:00
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2020-09-17 15:44:59 +02:00
|
|
|
if (!strv_isempty(arg_cmdline) &&
|
|
|
|
arg_transport == BUS_TRANSPORT_LOCAL &&
|
|
|
|
!strv_find_startswith(arg_property, "RootDirectory=") &&
|
|
|
|
!strv_find_startswith(arg_property, "RootImage=")) {
|
|
|
|
/* Patch in an absolute path to fail early for user convenience, but only when we can do it
|
|
|
|
* (i.e. we will be running from the same file system). This also uses the user's $PATH,
|
|
|
|
* while we use a fixed search path in the manager. */
|
2015-10-22 18:24:59 +02:00
|
|
|
|
2020-09-17 15:44:59 +02:00
|
|
|
_cleanup_free_ char *command = NULL;
|
2020-09-17 13:44:12 +02:00
|
|
|
r = find_executable(arg_cmdline[0], &command);
|
2018-11-22 19:34:15 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to find executable %s: %m", arg_cmdline[0]);
|
2015-10-22 18:24:59 +02:00
|
|
|
|
2018-11-22 19:24:48 +01:00
|
|
|
free_and_replace(arg_cmdline[0], command);
|
2013-09-08 13:51:39 +02:00
|
|
|
}
|
|
|
|
|
2013-07-01 00:40:56 +02:00
|
|
|
if (!arg_description) {
|
2018-11-22 19:24:48 +01:00
|
|
|
description = strv_join(arg_cmdline, " ");
|
2018-11-22 19:34:15 +01:00
|
|
|
if (!description)
|
|
|
|
return log_oom();
|
2013-07-01 00:40:56 +02:00
|
|
|
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
if (arg_unit && isempty(description)) {
|
2015-07-29 20:25:57 +02:00
|
|
|
r = free_and_strdup(&description, arg_unit);
|
|
|
|
if (r < 0)
|
2018-11-22 19:34:15 +01:00
|
|
|
return log_oom();
|
run: introduce timer support option
Support timer options --on-active=, --on-boot=, --on-startup=,
--on-unit-active=, --on-unit-inactive=, --on-calendar=. Each options
corresponding with OnActiveSec=, OnBootSec=, OnStartupSec=,
OnUnitActiveSec=, OnUnitInactiveSec=, OnCalendar= of timer
respectively. And OnCalendar= and WakeSystem= supported by
--timer-property= option like --property= of systemd-run.
And if --unit= option and timer options are specified the command can
be omitted. In this case, systemd-run assumes the target service is
already loaded. And just try to generate transient timer unit only.
2014-12-09 08:07:16 +01:00
|
|
|
}
|
|
|
|
|
2013-07-01 00:40:56 +02:00
|
|
|
arg_description = description;
|
|
|
|
}
|
|
|
|
|
2016-08-17 14:24:17 +02:00
|
|
|
/* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct
|
|
|
|
* connection */
|
2017-09-08 15:38:40 +02:00
|
|
|
if (arg_wait || arg_stdio != ARG_STDIO_NONE)
|
2016-08-17 14:24:17 +02:00
|
|
|
r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus);
|
|
|
|
else
|
|
|
|
r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
|
2018-11-22 19:34:15 +01:00
|
|
|
if (r < 0)
|
2020-07-20 13:20:52 +02:00
|
|
|
return bus_log_connect_error(r);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-07-01 00:03:57 +02:00
|
|
|
if (arg_scope)
|
2018-11-22 19:24:48 +01:00
|
|
|
r = start_transient_scope(bus);
|
2017-12-18 15:46:45 +01:00
|
|
|
else if (arg_path_property)
|
2018-11-22 19:24:48 +01:00
|
|
|
r = start_transient_trigger(bus, ".path");
|
2017-12-18 15:46:45 +01:00
|
|
|
else if (arg_socket_property)
|
2018-11-22 19:24:48 +01:00
|
|
|
r = start_transient_trigger(bus, ".socket");
|
2019-03-14 19:55:29 +01:00
|
|
|
else if (arg_with_timer)
|
2018-11-22 19:24:48 +01:00
|
|
|
r = start_transient_trigger(bus, ".timer");
|
2013-07-01 00:03:57 +02:00
|
|
|
else
|
2018-11-22 19:24:48 +01:00
|
|
|
r = start_transient_service(bus, &retval);
|
2018-11-22 19:34:15 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2018-11-22 19:34:15 +01:00
|
|
|
return retval;
|
2013-06-28 04:12:58 +02:00
|
|
|
}
|
2018-11-22 19:30:03 +01:00
|
|
|
|
|
|
|
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
|