]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/run/run.c
41570bf12ebbea796bf373d8127ab37f267ac712
[thirdparty/systemd.git] / src / run / run.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8
9 #include "sd-bus.h"
10 #include "sd-event.h"
11
12 #include "alloc-util.h"
13 #include "build.h"
14 #include "bus-error.h"
15 #include "bus-locator.h"
16 #include "bus-map-properties.h"
17 #include "bus-unit-util.h"
18 #include "bus-wait-for-jobs.h"
19 #include "calendarspec.h"
20 #include "env-util.h"
21 #include "exit-status.h"
22 #include "fd-util.h"
23 #include "format-util.h"
24 #include "main-func.h"
25 #include "parse-argument.h"
26 #include "parse-util.h"
27 #include "path-util.h"
28 #include "pretty-print.h"
29 #include "process-util.h"
30 #include "ptyfwd.h"
31 #include "signal-util.h"
32 #include "spawn-polkit-agent.h"
33 #include "strv.h"
34 #include "terminal-util.h"
35 #include "unit-def.h"
36 #include "unit-name.h"
37 #include "user-util.h"
38
39 static bool arg_ask_password = true;
40 static bool arg_scope = false;
41 static bool arg_remain_after_exit = false;
42 static bool arg_no_block = false;
43 static bool arg_wait = false;
44 static const char *arg_unit = NULL;
45 static const char *arg_description = NULL;
46 static const char *arg_slice = NULL;
47 static bool arg_slice_inherit = false;
48 static bool arg_expand_environment = true;
49 static bool arg_send_sighup = false;
50 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
51 static const char *arg_host = NULL;
52 static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
53 static const char *arg_service_type = NULL;
54 static const char *arg_exec_user = NULL;
55 static const char *arg_exec_group = NULL;
56 static int arg_nice = 0;
57 static bool arg_nice_set = false;
58 static char **arg_environment = NULL;
59 static char **arg_property = NULL;
60 static enum {
61 ARG_STDIO_NONE, /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */
62 ARG_STDIO_PTY, /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */
63 ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
64 ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
65 } arg_stdio = ARG_STDIO_NONE;
66 static char **arg_path_property = NULL;
67 static char **arg_socket_property = NULL;
68 static char **arg_timer_property = NULL;
69 static bool arg_with_timer = false;
70 static bool arg_quiet = false;
71 static bool arg_aggressive_gc = false;
72 static char *arg_working_directory = NULL;
73 static bool arg_shell = false;
74 static char **arg_cmdline = NULL;
75
76 STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
77 STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
78 STATIC_DESTRUCTOR_REGISTER(arg_path_property, strv_freep);
79 STATIC_DESTRUCTOR_REGISTER(arg_socket_property, strv_freep);
80 STATIC_DESTRUCTOR_REGISTER(arg_timer_property, strv_freep);
81 STATIC_DESTRUCTOR_REGISTER(arg_working_directory, freep);
82 STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep);
83
84 static int help(void) {
85 _cleanup_free_ char *link = NULL;
86 int r;
87
88 r = terminal_urlify_man("systemd-run", "1", &link);
89 if (r < 0)
90 return log_oom();
91
92 printf("%s [OPTIONS...] COMMAND [ARGUMENTS...]\n"
93 "\n%sRun the specified command in a transient scope or service.%s\n\n"
94 " -h --help Show this help\n"
95 " --version Show package version\n"
96 " --no-ask-password Do not prompt for password\n"
97 " --user Run as user unit\n"
98 " -H --host=[USER@]HOST Operate on remote host\n"
99 " -M --machine=CONTAINER Operate on local container\n"
100 " --scope Run this as scope rather than service\n"
101 " -u --unit=UNIT Run under the specified unit name\n"
102 " -p --property=NAME=VALUE Set service or scope unit property\n"
103 " --description=TEXT Description for unit\n"
104 " --slice=SLICE Run in the specified slice\n"
105 " --slice-inherit Inherit the slice\n"
106 " --expand-environment=BOOL Control expansion of environment variables\n"
107 " --no-block Do not wait until operation finished\n"
108 " -r --remain-after-exit Leave service around until explicitly stopped\n"
109 " --wait Wait until service stopped again\n"
110 " --send-sighup Send SIGHUP when terminating\n"
111 " --service-type=TYPE Service type\n"
112 " --uid=USER Run as system user\n"
113 " --gid=GROUP Run as system group\n"
114 " --nice=NICE Nice level\n"
115 " --working-directory=PATH Set working directory\n"
116 " -d --same-dir Inherit working directory from caller\n"
117 " -E --setenv=NAME[=VALUE] Set environment variable\n"
118 " -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n"
119 " STDERR\n"
120 " -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n"
121 " -q --quiet Suppress information messages during runtime\n"
122 " -G --collect Unload unit after it ran, even when failed\n"
123 " -S --shell Invoke a $SHELL interactively\n\n"
124 "Path options:\n"
125 " --path-property=NAME=VALUE Set path unit property\n\n"
126 "Socket options:\n"
127 " --socket-property=NAME=VALUE Set socket unit property\n\n"
128 "Timer options:\n"
129 " --on-active=SECONDS Run after SECONDS delay\n"
130 " --on-boot=SECONDS Run SECONDS after machine was booted up\n"
131 " --on-startup=SECONDS Run SECONDS after systemd activation\n"
132 " --on-unit-active=SECONDS Run SECONDS after the last activation\n"
133 " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n"
134 " --on-calendar=SPEC Realtime timer\n"
135 " --on-timezone-change Run when the timezone changes\n"
136 " --on-clock-change Run when the realtime clock jumps\n"
137 " --timer-property=NAME=VALUE Set timer unit property\n"
138 "\nSee the %s for details.\n",
139 program_invocation_short_name,
140 ansi_highlight(),
141 ansi_normal(),
142 link);
143
144 return 0;
145 }
146
147 static int add_timer_property(const char *name, const char *val) {
148 char *p;
149
150 assert(name);
151 assert(val);
152
153 p = strjoin(name, "=", val);
154 if (!p)
155 return log_oom();
156
157 if (strv_consume(&arg_timer_property, p) < 0)
158 return log_oom();
159
160 return 0;
161 }
162
163 static int parse_argv(int argc, char *argv[]) {
164
165 enum {
166 ARG_VERSION = 0x100,
167 ARG_USER,
168 ARG_SYSTEM,
169 ARG_SCOPE,
170 ARG_DESCRIPTION,
171 ARG_SLICE,
172 ARG_SLICE_INHERIT,
173 ARG_EXPAND_ENVIRONMENT,
174 ARG_SEND_SIGHUP,
175 ARG_SERVICE_TYPE,
176 ARG_EXEC_USER,
177 ARG_EXEC_GROUP,
178 ARG_NICE,
179 ARG_ON_ACTIVE,
180 ARG_ON_BOOT,
181 ARG_ON_STARTUP,
182 ARG_ON_UNIT_ACTIVE,
183 ARG_ON_UNIT_INACTIVE,
184 ARG_ON_CALENDAR,
185 ARG_ON_TIMEZONE_CHANGE,
186 ARG_ON_CLOCK_CHANGE,
187 ARG_TIMER_PROPERTY,
188 ARG_PATH_PROPERTY,
189 ARG_SOCKET_PROPERTY,
190 ARG_NO_BLOCK,
191 ARG_NO_ASK_PASSWORD,
192 ARG_WAIT,
193 ARG_WORKING_DIRECTORY,
194 ARG_SHELL,
195 };
196
197 static const struct option options[] = {
198 { "help", no_argument, NULL, 'h' },
199 { "version", no_argument, NULL, ARG_VERSION },
200 { "user", no_argument, NULL, ARG_USER },
201 { "system", no_argument, NULL, ARG_SYSTEM },
202 { "scope", no_argument, NULL, ARG_SCOPE },
203 { "unit", required_argument, NULL, 'u' },
204 { "description", required_argument, NULL, ARG_DESCRIPTION },
205 { "slice", required_argument, NULL, ARG_SLICE },
206 { "slice-inherit", no_argument, NULL, ARG_SLICE_INHERIT },
207 { "remain-after-exit", no_argument, NULL, 'r' },
208 { "expand-environment", required_argument, NULL, ARG_EXPAND_ENVIRONMENT },
209 { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
210 { "host", required_argument, NULL, 'H' },
211 { "machine", required_argument, NULL, 'M' },
212 { "service-type", required_argument, NULL, ARG_SERVICE_TYPE },
213 { "wait", no_argument, NULL, ARG_WAIT },
214 { "uid", required_argument, NULL, ARG_EXEC_USER },
215 { "gid", required_argument, NULL, ARG_EXEC_GROUP },
216 { "nice", required_argument, NULL, ARG_NICE },
217 { "setenv", required_argument, NULL, 'E' },
218 { "property", required_argument, NULL, 'p' },
219 { "tty", no_argument, NULL, 't' }, /* deprecated alias */
220 { "pty", no_argument, NULL, 't' },
221 { "pipe", no_argument, NULL, 'P' },
222 { "quiet", no_argument, NULL, 'q' },
223 { "on-active", required_argument, NULL, ARG_ON_ACTIVE },
224 { "on-boot", required_argument, NULL, ARG_ON_BOOT },
225 { "on-startup", required_argument, NULL, ARG_ON_STARTUP },
226 { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE },
227 { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
228 { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
229 { "on-timezone-change", no_argument, NULL, ARG_ON_TIMEZONE_CHANGE },
230 { "on-clock-change", no_argument, NULL, ARG_ON_CLOCK_CHANGE },
231 { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
232 { "path-property", required_argument, NULL, ARG_PATH_PROPERTY },
233 { "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY },
234 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
235 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
236 { "collect", no_argument, NULL, 'G' },
237 { "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY },
238 { "same-dir", no_argument, NULL, 'd' },
239 { "shell", no_argument, NULL, 'S' },
240 {},
241 };
242
243 bool with_trigger = false;
244 int r, c;
245
246 assert(argc >= 0);
247 assert(argv);
248
249 /* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long()
250 * that checks for GNU extensions in optstring ('-' or '+' at the beginning). */
251 optind = 0;
252 while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0)
253
254 switch (c) {
255
256 case 'h':
257 return help();
258
259 case ARG_VERSION:
260 return version();
261
262 case ARG_NO_ASK_PASSWORD:
263 arg_ask_password = false;
264 break;
265
266 case ARG_USER:
267 arg_runtime_scope = RUNTIME_SCOPE_USER;
268 break;
269
270 case ARG_SYSTEM:
271 arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
272 break;
273
274 case ARG_SCOPE:
275 arg_scope = true;
276 break;
277
278 case 'u':
279 arg_unit = optarg;
280 break;
281
282 case ARG_DESCRIPTION:
283 arg_description = optarg;
284 break;
285
286 case ARG_SLICE:
287 arg_slice = optarg;
288 break;
289
290 case ARG_SLICE_INHERIT:
291 arg_slice_inherit = true;
292 break;
293
294 case ARG_EXPAND_ENVIRONMENT:
295 r = parse_boolean_argument("--expand-environment=", optarg, &arg_expand_environment);
296 if (r < 0)
297 return r;
298 break;
299
300 case ARG_SEND_SIGHUP:
301 arg_send_sighup = true;
302 break;
303
304 case 'r':
305 arg_remain_after_exit = true;
306 break;
307
308 case 'H':
309 arg_transport = BUS_TRANSPORT_REMOTE;
310 arg_host = optarg;
311 break;
312
313 case 'M':
314 arg_transport = BUS_TRANSPORT_MACHINE;
315 arg_host = optarg;
316 break;
317
318 case ARG_SERVICE_TYPE:
319 arg_service_type = optarg;
320 break;
321
322 case ARG_EXEC_USER:
323 arg_exec_user = optarg;
324 break;
325
326 case ARG_EXEC_GROUP:
327 arg_exec_group = optarg;
328 break;
329
330 case ARG_NICE:
331 r = parse_nice(optarg, &arg_nice);
332 if (r < 0)
333 return log_error_errno(r, "Failed to parse nice value: %s", optarg);
334
335 arg_nice_set = true;
336 break;
337
338 case 'E':
339 r = strv_env_replace_strdup_passthrough(&arg_environment, optarg);
340 if (r < 0)
341 return log_error_errno(r, "Cannot assign environment variable %s: %m", optarg);
342
343 break;
344
345 case 'p':
346 if (strv_extend(&arg_property, optarg) < 0)
347 return log_oom();
348
349 break;
350
351 case 't': /* --pty */
352 if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */
353 arg_stdio = ARG_STDIO_AUTO;
354 else
355 arg_stdio = ARG_STDIO_PTY;
356 break;
357
358 case 'P': /* --pipe */
359 if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */
360 arg_stdio = ARG_STDIO_AUTO;
361 else
362 arg_stdio = ARG_STDIO_DIRECT;
363 break;
364
365 case 'q':
366 arg_quiet = true;
367 break;
368
369 case ARG_ON_ACTIVE:
370 r = add_timer_property("OnActiveSec", optarg);
371 if (r < 0)
372 return r;
373
374 arg_with_timer = true;
375 break;
376
377 case ARG_ON_BOOT:
378 r = add_timer_property("OnBootSec", optarg);
379 if (r < 0)
380 return r;
381
382 arg_with_timer = true;
383 break;
384
385 case ARG_ON_STARTUP:
386 r = add_timer_property("OnStartupSec", optarg);
387 if (r < 0)
388 return r;
389
390 arg_with_timer = true;
391 break;
392
393 case ARG_ON_UNIT_ACTIVE:
394 r = add_timer_property("OnUnitActiveSec", optarg);
395 if (r < 0)
396 return r;
397
398 arg_with_timer = true;
399 break;
400
401 case ARG_ON_UNIT_INACTIVE:
402 r = add_timer_property("OnUnitInactiveSec", optarg);
403 if (r < 0)
404 return r;
405
406 arg_with_timer = true;
407 break;
408
409 case ARG_ON_CALENDAR: {
410 _cleanup_(calendar_spec_freep) CalendarSpec *cs = NULL;
411
412 r = calendar_spec_from_string(optarg, &cs);
413 if (r < 0)
414 return log_error_errno(r, "Failed to parse calendar event specification: %m");
415
416 /* Let's make sure the given calendar event is not in the past */
417 r = calendar_spec_next_usec(cs, now(CLOCK_REALTIME), NULL);
418 if (r == -ENOENT)
419 /* The calendar event is in the past — let's warn about this, but install it
420 * anyway as is. The service manager will trigger the service right away.
421 * Moreover, the server side might have a different clock or timezone than we
422 * do, hence it should decide when or whether to run something. */
423 log_warning("Specified calendar expression is in the past, proceeding anyway.");
424 else if (r < 0)
425 return log_error_errno(r, "Failed to calculate next time calendar expression elapses: %m");
426
427 r = add_timer_property("OnCalendar", optarg);
428 if (r < 0)
429 return r;
430
431 arg_with_timer = true;
432 break;
433 }
434
435 case ARG_ON_TIMEZONE_CHANGE:
436 r = add_timer_property("OnTimezoneChange", "yes");
437 if (r < 0)
438 return r;
439
440 arg_with_timer = true;
441 break;
442
443 case ARG_ON_CLOCK_CHANGE:
444 r = add_timer_property("OnClockChange", "yes");
445 if (r < 0)
446 return r;
447
448 arg_with_timer = true;
449 break;
450
451 case ARG_TIMER_PROPERTY:
452
453 if (strv_extend(&arg_timer_property, optarg) < 0)
454 return log_oom();
455
456 arg_with_timer = arg_with_timer ||
457 STARTSWITH_SET(optarg,
458 "OnActiveSec=",
459 "OnBootSec=",
460 "OnStartupSec=",
461 "OnUnitActiveSec=",
462 "OnUnitInactiveSec=",
463 "OnCalendar=");
464 break;
465
466 case ARG_PATH_PROPERTY:
467
468 if (strv_extend(&arg_path_property, optarg) < 0)
469 return log_oom();
470
471 break;
472
473 case ARG_SOCKET_PROPERTY:
474
475 if (strv_extend(&arg_socket_property, optarg) < 0)
476 return log_oom();
477
478 break;
479
480 case ARG_NO_BLOCK:
481 arg_no_block = true;
482 break;
483
484 case ARG_WAIT:
485 arg_wait = true;
486 break;
487
488 case ARG_WORKING_DIRECTORY:
489 r = parse_path_argument(optarg, true, &arg_working_directory);
490 if (r < 0)
491 return r;
492
493 break;
494
495 case 'd': {
496 _cleanup_free_ char *p = NULL;
497
498 r = safe_getcwd(&p);
499 if (r < 0)
500 return log_error_errno(r, "Failed to get current working directory: %m");
501
502 if (empty_or_root(p))
503 arg_working_directory = mfree(arg_working_directory);
504 else
505 free_and_replace(arg_working_directory, p);
506 break;
507 }
508
509 case 'G':
510 arg_aggressive_gc = true;
511 break;
512
513 case 'S':
514 arg_shell = true;
515 break;
516
517 case '?':
518 return -EINVAL;
519
520 default:
521 assert_not_reached();
522 }
523
524 /* If we are talking to the per-user instance PolicyKit isn't going to help */
525 if (arg_runtime_scope == RUNTIME_SCOPE_USER)
526 arg_ask_password = false;
527
528 with_trigger = !!arg_path_property || !!arg_socket_property || arg_with_timer;
529
530 /* currently, only single trigger (path, socket, timer) unit can be created simultaneously */
531 if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) arg_with_timer > 1)
532 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
533 "Only single trigger (path, socket, timer) unit can be created.");
534
535 if (arg_shell) {
536 /* If --shell is imply --pty --pipe --same-dir --service-type=exec --wait --collect, unless otherwise
537 * specified. */
538
539 if (!arg_scope) {
540 if (arg_stdio == ARG_STDIO_NONE)
541 arg_stdio = ARG_STDIO_AUTO;
542
543 if (!arg_working_directory) {
544 r = safe_getcwd(&arg_working_directory);
545 if (r < 0)
546 return log_error_errno(r, "Failed to get current working directory: %m");
547 }
548
549 if (!arg_service_type) {
550 arg_service_type = strdup("exec");
551 if (!arg_service_type)
552 return log_oom();
553 }
554
555 arg_wait = true;
556 }
557
558 arg_aggressive_gc = true;
559 }
560
561 if (arg_stdio == ARG_STDIO_AUTO)
562 /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
563 * to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
564 * pipeline, but we are neatly interactive with tty-level isolation otherwise. */
565 arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
566 ARG_STDIO_PTY :
567 ARG_STDIO_DIRECT;
568
569 if (argc > optind) {
570 char **l;
571
572 if (arg_shell)
573 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "If --shell is used, no command line is expected.");
574
575 l = strv_copy(argv + optind);
576 if (!l)
577 return log_oom();
578
579 strv_free_and_replace(arg_cmdline, l);
580
581 } else if (arg_shell) {
582 _cleanup_free_ char *s = NULL;
583 char **l;
584
585 r = get_shell(&s);
586 if (r < 0)
587 return log_error_errno(r, "Failed to determine shell: %m");
588
589 l = strv_new(s);
590 if (!l)
591 return log_oom();
592
593 strv_free_and_replace(arg_cmdline, l);
594
595 } else if (!arg_unit || !with_trigger)
596 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Command line to execute required.");
597
598 if (arg_runtime_scope == RUNTIME_SCOPE_USER && arg_transport == BUS_TRANSPORT_REMOTE)
599 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
600 "Execution in user context is not supported on remote systems.");
601
602 if (arg_scope && arg_transport == BUS_TRANSPORT_REMOTE)
603 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
604 "Scope execution is not supported on remote systems.");
605
606 if (arg_scope && (arg_remain_after_exit || arg_service_type))
607 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
608 "--remain-after-exit and --service-type= are not supported in --scope mode.");
609
610 if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope))
611 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
612 "--pty/--pipe is not compatible in timer or --scope mode.");
613
614 if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE)
615 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
616 "--pty/--pipe is only supported when connecting to the local system or containers.");
617
618 if (arg_stdio != ARG_STDIO_NONE && arg_no_block)
619 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
620 "--pty/--pipe is not compatible with --no-block.");
621
622 if (arg_scope && with_trigger)
623 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
624 "Path, socket or timer options are not supported in --scope mode.");
625
626 if (arg_timer_property && !arg_with_timer)
627 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
628 "--timer-property= has no effect without any other timer options.");
629
630 if (arg_wait) {
631 if (arg_no_block)
632 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
633 "--wait may not be combined with --no-block.");
634
635 if (with_trigger)
636 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
637 "--wait may not be combined with path, socket or timer operations.");
638
639 if (arg_scope)
640 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
641 "--wait may not be combined with --scope.");
642 }
643
644 return 1;
645 }
646
647 static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
648 int r;
649
650 r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
651 if (r < 0)
652 return bus_log_create_error(r);
653
654 if (arg_aggressive_gc) {
655 r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
656 if (r < 0)
657 return bus_log_create_error(r);
658 }
659
660 return bus_append_unit_property_assignment_many(m, t, properties);
661 }
662
663 static int transient_cgroup_set_properties(sd_bus_message *m) {
664 _cleanup_free_ char *name = NULL;
665 _cleanup_free_ char *slice = NULL;
666 int r;
667 assert(m);
668
669 if (arg_slice_inherit) {
670 char *end;
671
672 switch (arg_runtime_scope) {
673
674 case RUNTIME_SCOPE_USER:
675 r = cg_pid_get_user_slice(0, &name);
676 break;
677
678 case RUNTIME_SCOPE_SYSTEM:
679 r = cg_pid_get_slice(0, &name);
680 break;
681
682 default:
683 assert_not_reached();
684 }
685
686 if (r < 0)
687 return log_error_errno(r, "Failed to get PID slice: %m");
688
689 end = endswith(name, ".slice");
690 if (!end)
691 return -ENXIO;
692 *end = 0;
693 }
694
695 if (!isempty(arg_slice) && !strextend_with_separator(&name, "-", arg_slice))
696 return log_oom();
697
698 if (!name)
699 return 0;
700
701 r = unit_name_mangle_with_suffix(name, "as slice",
702 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
703 ".slice", &slice);
704 if (r < 0)
705 return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
706
707 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
708 if (r < 0)
709 return bus_log_create_error(r);
710
711 return 0;
712 }
713
714 static int transient_kill_set_properties(sd_bus_message *m) {
715 int r;
716
717 assert(m);
718
719 if (arg_send_sighup) {
720 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
721 if (r < 0)
722 return bus_log_create_error(r);
723 }
724
725 return 0;
726 }
727
728 static int transient_service_set_properties(sd_bus_message *m, const char *pty_path) {
729 bool send_term = false;
730 int r;
731
732 /* We disable environment expansion on the server side via ExecStartEx=:.
733 * ExecStartEx was added relatively recently (v243), and some bugs were fixed only later.
734 * So use that feature only if required. It will fail with older systemds. */
735 bool use_ex_prop = !arg_expand_environment;
736
737 assert(m);
738
739 r = transient_unit_set_properties(m, UNIT_SERVICE, arg_property);
740 if (r < 0)
741 return r;
742
743 r = transient_kill_set_properties(m);
744 if (r < 0)
745 return r;
746
747 r = transient_cgroup_set_properties(m);
748 if (r < 0)
749 return r;
750
751 if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
752 r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
753 if (r < 0)
754 return bus_log_create_error(r);
755 }
756
757 if (arg_remain_after_exit) {
758 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
759 if (r < 0)
760 return bus_log_create_error(r);
761 }
762
763 if (arg_service_type) {
764 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
765 if (r < 0)
766 return bus_log_create_error(r);
767 }
768
769 if (arg_exec_user) {
770 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
771 if (r < 0)
772 return bus_log_create_error(r);
773 }
774
775 if (arg_exec_group) {
776 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
777 if (r < 0)
778 return bus_log_create_error(r);
779 }
780
781 if (arg_nice_set) {
782 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
783 if (r < 0)
784 return bus_log_create_error(r);
785 }
786
787 if (arg_working_directory) {
788 r = sd_bus_message_append(m, "(sv)", "WorkingDirectory", "s", arg_working_directory);
789 if (r < 0)
790 return bus_log_create_error(r);
791 }
792
793 if (pty_path) {
794 r = sd_bus_message_append(m,
795 "(sv)(sv)(sv)(sv)",
796 "StandardInput", "s", "tty",
797 "StandardOutput", "s", "tty",
798 "StandardError", "s", "tty",
799 "TTYPath", "s", pty_path);
800 if (r < 0)
801 return bus_log_create_error(r);
802
803 send_term = true;
804
805 } else if (arg_stdio == ARG_STDIO_DIRECT) {
806 r = sd_bus_message_append(m,
807 "(sv)(sv)(sv)",
808 "StandardInputFileDescriptor", "h", STDIN_FILENO,
809 "StandardOutputFileDescriptor", "h", STDOUT_FILENO,
810 "StandardErrorFileDescriptor", "h", STDERR_FILENO);
811 if (r < 0)
812 return bus_log_create_error(r);
813
814 send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
815 }
816
817 if (send_term) {
818 const char *e;
819
820 e = getenv("TERM");
821 if (e) {
822 _cleanup_free_ char *n = NULL;
823
824 n = strjoin("TERM=", e);
825 if (!n)
826 return log_oom();
827
828 r = sd_bus_message_append(m,
829 "(sv)",
830 "Environment", "as", 1, n);
831 if (r < 0)
832 return bus_log_create_error(r);
833 }
834 }
835
836 if (!strv_isempty(arg_environment)) {
837 r = sd_bus_message_open_container(m, 'r', "sv");
838 if (r < 0)
839 return bus_log_create_error(r);
840
841 r = sd_bus_message_append(m, "s", "Environment");
842 if (r < 0)
843 return bus_log_create_error(r);
844
845 r = sd_bus_message_open_container(m, 'v', "as");
846 if (r < 0)
847 return bus_log_create_error(r);
848
849 r = sd_bus_message_append_strv(m, arg_environment);
850 if (r < 0)
851 return bus_log_create_error(r);
852
853 r = sd_bus_message_close_container(m);
854 if (r < 0)
855 return bus_log_create_error(r);
856
857 r = sd_bus_message_close_container(m);
858 if (r < 0)
859 return bus_log_create_error(r);
860 }
861
862 /* Exec container */
863 if (!strv_isempty(arg_cmdline)) {
864 r = sd_bus_message_open_container(m, 'r', "sv");
865 if (r < 0)
866 return bus_log_create_error(r);
867
868 r = sd_bus_message_append(m, "s",
869 use_ex_prop ? "ExecStartEx" : "ExecStart");
870 if (r < 0)
871 return bus_log_create_error(r);
872
873 r = sd_bus_message_open_container(m, 'v',
874 use_ex_prop ? "a(sasas)" : "a(sasb)");
875 if (r < 0)
876 return bus_log_create_error(r);
877
878 r = sd_bus_message_open_container(m, 'a',
879 use_ex_prop ? "(sasas)" : "(sasb)");
880 if (r < 0)
881 return bus_log_create_error(r);
882
883 r = sd_bus_message_open_container(m, 'r',
884 use_ex_prop ? "sasas" : "sasb");
885 if (r < 0)
886 return bus_log_create_error(r);
887
888 r = sd_bus_message_append(m, "s", arg_cmdline[0]);
889 if (r < 0)
890 return bus_log_create_error(r);
891
892 r = sd_bus_message_append_strv(m, arg_cmdline);
893 if (r < 0)
894 return bus_log_create_error(r);
895
896 if (use_ex_prop)
897 r = sd_bus_message_append_strv(
898 m,
899 STRV_MAKE(arg_expand_environment ? NULL : "no-env-expand"));
900 else
901 r = sd_bus_message_append(m, "b", false);
902 if (r < 0)
903 return bus_log_create_error(r);
904
905 r = sd_bus_message_close_container(m);
906 if (r < 0)
907 return bus_log_create_error(r);
908
909 r = sd_bus_message_close_container(m);
910 if (r < 0)
911 return bus_log_create_error(r);
912
913 r = sd_bus_message_close_container(m);
914 if (r < 0)
915 return bus_log_create_error(r);
916
917 r = sd_bus_message_close_container(m);
918 if (r < 0)
919 return bus_log_create_error(r);
920 }
921
922 return 0;
923 }
924
925 static int transient_scope_set_properties(sd_bus_message *m) {
926 int r;
927
928 assert(m);
929
930 r = transient_unit_set_properties(m, UNIT_SCOPE, arg_property);
931 if (r < 0)
932 return r;
933
934 r = transient_kill_set_properties(m);
935 if (r < 0)
936 return r;
937
938 r = transient_cgroup_set_properties(m);
939 if (r < 0)
940 return r;
941
942 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached());
943 if (r < 0)
944 return bus_log_create_error(r);
945
946 return 0;
947 }
948
949 static int transient_timer_set_properties(sd_bus_message *m) {
950 int r;
951
952 assert(m);
953
954 r = transient_unit_set_properties(m, UNIT_TIMER, arg_timer_property);
955 if (r < 0)
956 return r;
957
958 /* Automatically clean up our transient timers */
959 r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
960 if (r < 0)
961 return bus_log_create_error(r);
962
963 return 0;
964 }
965
966 static int make_unit_name(sd_bus *bus, UnitType t, char **ret) {
967 const char *unique, *id;
968 char *p;
969 int r;
970
971 assert(bus);
972 assert(t >= 0);
973 assert(t < _UNIT_TYPE_MAX);
974
975 r = sd_bus_get_unique_name(bus, &unique);
976 if (r < 0) {
977 sd_id128_t rnd;
978
979 /* We couldn't get the unique name, which is a pretty
980 * common case if we are connected to systemd
981 * directly. In that case, just pick a random uuid as
982 * name */
983
984 r = sd_id128_randomize(&rnd);
985 if (r < 0)
986 return log_error_errno(r, "Failed to generate random run unit name: %m");
987
988 if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0)
989 return log_oom();
990
991 return 0;
992 }
993
994 /* We managed to get the unique name, then let's use that to name our transient units. */
995
996 id = startswith(unique, ":1."); /* let' strip the usual prefix */
997 if (!id)
998 id = startswith(unique, ":"); /* the spec only requires things to start with a colon, hence
999 * let's add a generic fallback for that. */
1000 if (!id)
1001 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1002 "Unique name %s has unexpected format.",
1003 unique);
1004
1005 p = strjoin("run-u", id, ".", unit_type_to_string(t));
1006 if (!p)
1007 return log_oom();
1008
1009 *ret = p;
1010 return 0;
1011 }
1012
1013 typedef struct RunContext {
1014 sd_bus *bus;
1015 sd_event *event;
1016 PTYForward *forward;
1017 sd_bus_slot *match;
1018
1019 /* Current state of the unit */
1020 char *active_state;
1021 bool has_job;
1022
1023 /* The exit data of the unit */
1024 uint64_t inactive_exit_usec;
1025 uint64_t inactive_enter_usec;
1026 char *result;
1027 uint64_t cpu_usage_nsec;
1028 uint64_t ip_ingress_bytes;
1029 uint64_t ip_egress_bytes;
1030 uint64_t io_read_bytes;
1031 uint64_t io_write_bytes;
1032 uint32_t exit_code;
1033 uint32_t exit_status;
1034 } RunContext;
1035
1036 static void run_context_free(RunContext *c) {
1037 assert(c);
1038
1039 c->forward = pty_forward_free(c->forward);
1040 c->match = sd_bus_slot_unref(c->match);
1041 c->bus = sd_bus_unref(c->bus);
1042 c->event = sd_event_unref(c->event);
1043
1044 free(c->active_state);
1045 free(c->result);
1046 }
1047
1048 static void run_context_check_done(RunContext *c) {
1049 bool done;
1050
1051 assert(c);
1052
1053 if (c->match)
1054 done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
1055 else
1056 done = true;
1057
1058 if (c->forward && done) /* If the service is gone, it's time to drain the output */
1059 done = pty_forward_drain(c->forward);
1060
1061 if (done)
1062 sd_event_exit(c->event, EXIT_SUCCESS);
1063 }
1064
1065 static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1066 bool *b = userdata;
1067 const char *job;
1068 uint32_t id;
1069 int r;
1070
1071 r = sd_bus_message_read(m, "(uo)", &id, &job);
1072 if (r < 0)
1073 return r;
1074
1075 *b = id != 0 || !streq(job, "/");
1076 return 0;
1077 }
1078
1079 static int run_context_update(RunContext *c, const char *path) {
1080
1081 static const struct bus_properties_map map[] = {
1082 { "ActiveState", "s", NULL, offsetof(RunContext, active_state) },
1083 { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) },
1084 { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) },
1085 { "Result", "s", NULL, offsetof(RunContext, result) },
1086 { "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) },
1087 { "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) },
1088 { "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
1089 { "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
1090 { "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
1091 { "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
1092 { "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
1093 { "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
1094 {}
1095 };
1096
1097 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1098 int r;
1099
1100 r = bus_map_all_properties(c->bus,
1101 "org.freedesktop.systemd1",
1102 path,
1103 map,
1104 BUS_MAP_STRDUP,
1105 &error,
1106 NULL,
1107 c);
1108 if (r < 0) {
1109 sd_event_exit(c->event, EXIT_FAILURE);
1110 return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r));
1111 }
1112
1113 run_context_check_done(c);
1114 return 0;
1115 }
1116
1117 static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1118 RunContext *c = ASSERT_PTR(userdata);
1119
1120 assert(m);
1121
1122 return run_context_update(c, sd_bus_message_get_path(m));
1123 }
1124
1125 static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
1126 RunContext *c = userdata;
1127
1128 assert(f);
1129
1130 if (rcode < 0) {
1131 sd_event_exit(c->event, EXIT_FAILURE);
1132 return log_error_errno(rcode, "Error on PTY forwarding logic: %m");
1133 }
1134
1135 run_context_check_done(c);
1136 return 0;
1137 }
1138
1139 static int make_transient_service_unit(
1140 sd_bus *bus,
1141 sd_bus_message **message,
1142 const char *service,
1143 const char *pty_path) {
1144
1145 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1146 int r;
1147
1148 assert(bus);
1149 assert(message);
1150 assert(service);
1151
1152 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1153 if (r < 0)
1154 return bus_log_create_error(r);
1155
1156 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1157 if (r < 0)
1158 return bus_log_create_error(r);
1159
1160 /* Name and mode */
1161 r = sd_bus_message_append(m, "ss", service, "fail");
1162 if (r < 0)
1163 return bus_log_create_error(r);
1164
1165 /* Properties */
1166 r = sd_bus_message_open_container(m, 'a', "(sv)");
1167 if (r < 0)
1168 return bus_log_create_error(r);
1169
1170 r = transient_service_set_properties(m, pty_path);
1171 if (r < 0)
1172 return r;
1173
1174 r = sd_bus_message_close_container(m);
1175 if (r < 0)
1176 return bus_log_create_error(r);
1177
1178 /* Auxiliary units */
1179 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1180 if (r < 0)
1181 return bus_log_create_error(r);
1182
1183 *message = TAKE_PTR(m);
1184 return 0;
1185 }
1186
1187 static int bus_call_with_hint(
1188 sd_bus *bus,
1189 sd_bus_message *message,
1190 const char *name,
1191 sd_bus_message **reply) {
1192
1193 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1194 int r;
1195
1196 r = sd_bus_call(bus, message, 0, &error, reply);
1197 if (r < 0) {
1198 log_error_errno(r, "Failed to start transient %s unit: %s", name, bus_error_message(&error, r));
1199
1200 if (!arg_expand_environment &&
1201 sd_bus_error_has_names(&error,
1202 SD_BUS_ERROR_UNKNOWN_PROPERTY,
1203 SD_BUS_ERROR_PROPERTY_READ_ONLY))
1204 log_notice_errno(r, "Hint: --expand-environment=no is not supported by old systemd");
1205 }
1206
1207 return r;
1208 }
1209
1210 static int start_transient_service(sd_bus *bus) {
1211 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1212 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1213 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1214 _cleanup_free_ char *service = NULL, *pty_path = NULL;
1215 _cleanup_close_ int master = -EBADF;
1216 int r;
1217
1218 assert(bus);
1219
1220 if (arg_stdio == ARG_STDIO_PTY) {
1221
1222 if (arg_transport == BUS_TRANSPORT_LOCAL) {
1223 master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1224 if (master < 0)
1225 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
1226
1227 r = ptsname_malloc(master, &pty_path);
1228 if (r < 0)
1229 return log_error_errno(r, "Failed to determine tty name: %m");
1230
1231 if (unlockpt(master) < 0)
1232 return log_error_errno(errno, "Failed to unlock tty: %m");
1233
1234 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
1235 _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
1236 _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL;
1237 const char *s;
1238
1239 r = sd_bus_default_system(&system_bus);
1240 if (r < 0)
1241 return log_error_errno(r, "Failed to connect to system bus: %m");
1242
1243 r = sd_bus_call_method(system_bus,
1244 "org.freedesktop.machine1",
1245 "/org/freedesktop/machine1",
1246 "org.freedesktop.machine1.Manager",
1247 "OpenMachinePTY",
1248 &error,
1249 &pty_reply,
1250 "s", arg_host);
1251 if (r < 0)
1252 return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, r));
1253
1254 r = sd_bus_message_read(pty_reply, "hs", &master, &s);
1255 if (r < 0)
1256 return bus_log_parse_error(r);
1257
1258 master = fcntl(master, F_DUPFD_CLOEXEC, 3);
1259 if (master < 0)
1260 return log_error_errno(errno, "Failed to duplicate master fd: %m");
1261
1262 pty_path = strdup(s);
1263 if (!pty_path)
1264 return log_oom();
1265 } else
1266 assert_not_reached();
1267 }
1268
1269 /* Optionally, wait for the start job to complete. If we are supposed to read the service's stdin
1270 * lets skip this however, because we should start that already when the start job is running, and
1271 * there's little point in waiting for the start job to complete in that case anyway, as we'll wait
1272 * for EOF anyway, which is going to be much later. */
1273 if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) {
1274 r = bus_wait_for_jobs_new(bus, &w);
1275 if (r < 0)
1276 return log_error_errno(r, "Could not watch jobs: %m");
1277 }
1278
1279 if (arg_unit) {
1280 r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1281 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1282 ".service", &service);
1283 if (r < 0)
1284 return log_error_errno(r, "Failed to mangle unit name: %m");
1285 } else {
1286 r = make_unit_name(bus, UNIT_SERVICE, &service);
1287 if (r < 0)
1288 return r;
1289 }
1290
1291 r = make_transient_service_unit(bus, &m, service, pty_path);
1292 if (r < 0)
1293 return r;
1294
1295 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1296
1297 r = bus_call_with_hint(bus, m, "service", &reply);
1298 if (r < 0)
1299 return r;
1300
1301 if (w) {
1302 const char *object;
1303
1304 r = sd_bus_message_read(reply, "o", &object);
1305 if (r < 0)
1306 return bus_log_parse_error(r);
1307
1308 r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_runtime_scope == RUNTIME_SCOPE_USER ? STRV_MAKE_CONST("--user") : NULL);
1309 if (r < 0)
1310 return r;
1311 }
1312
1313 if (!arg_quiet)
1314 log_info("Running as unit: %s", service);
1315
1316 if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
1317 _cleanup_(run_context_free) RunContext c = {
1318 .cpu_usage_nsec = NSEC_INFINITY,
1319 .ip_ingress_bytes = UINT64_MAX,
1320 .ip_egress_bytes = UINT64_MAX,
1321 .io_read_bytes = UINT64_MAX,
1322 .io_write_bytes = UINT64_MAX,
1323 .inactive_exit_usec = USEC_INFINITY,
1324 .inactive_enter_usec = USEC_INFINITY,
1325 };
1326 _cleanup_free_ char *path = NULL;
1327
1328 c.bus = sd_bus_ref(bus);
1329
1330 r = sd_event_default(&c.event);
1331 if (r < 0)
1332 return log_error_errno(r, "Failed to get event loop: %m");
1333
1334 if (master >= 0) {
1335 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
1336 (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
1337 (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);
1338
1339 if (!arg_quiet)
1340 log_info("Press ^] three times within 1s to disconnect TTY.");
1341
1342 r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward);
1343 if (r < 0)
1344 return log_error_errno(r, "Failed to create PTY forwarder: %m");
1345
1346 pty_forward_set_handler(c.forward, pty_forward_handler, &c);
1347
1348 /* Make sure to process any TTY events before we process bus events */
1349 (void) pty_forward_set_priority(c.forward, SD_EVENT_PRIORITY_IMPORTANT);
1350 }
1351
1352 path = unit_dbus_path_from_name(service);
1353 if (!path)
1354 return log_oom();
1355
1356 r = sd_bus_match_signal_async(
1357 bus,
1358 &c.match,
1359 "org.freedesktop.systemd1",
1360 path,
1361 "org.freedesktop.DBus.Properties",
1362 "PropertiesChanged",
1363 on_properties_changed, NULL, &c);
1364 if (r < 0)
1365 return log_error_errno(r, "Failed to request properties changed signal match: %m");
1366
1367 r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL);
1368 if (r < 0)
1369 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1370
1371 r = run_context_update(&c, path);
1372 if (r < 0)
1373 return r;
1374
1375 r = sd_event_loop(c.event);
1376 if (r < 0)
1377 return log_error_errno(r, "Failed to run event loop: %m");
1378
1379 if (c.forward) {
1380 char last_char = 0;
1381
1382 r = pty_forward_get_last_char(c.forward, &last_char);
1383 if (r >= 0 && !arg_quiet && last_char != '\n')
1384 fputc('\n', stdout);
1385 }
1386
1387 if (arg_wait && !arg_quiet) {
1388
1389 /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its
1390 * original settings (i.e. proper line breaks), so that we can show the summary in a pretty
1391 * way. */
1392 c.forward = pty_forward_free(c.forward);
1393
1394 if (!isempty(c.result))
1395 log_info("Finished with result: %s", strna(c.result));
1396
1397 if (c.exit_code == CLD_EXITED)
1398 log_info("Main processes terminated with: code=%s/status=%u",
1399 sigchld_code_to_string(c.exit_code), c.exit_status);
1400 else if (c.exit_code > 0)
1401 log_info("Main processes terminated with: code=%s/status=%s",
1402 sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
1403
1404 if (timestamp_is_set(c.inactive_enter_usec) &&
1405 timestamp_is_set(c.inactive_exit_usec) &&
1406 c.inactive_enter_usec > c.inactive_exit_usec)
1407 log_info("Service runtime: %s",
1408 FORMAT_TIMESPAN(c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
1409
1410 if (c.cpu_usage_nsec != NSEC_INFINITY)
1411 log_info("CPU time consumed: %s",
1412 FORMAT_TIMESPAN(DIV_ROUND_UP(c.cpu_usage_nsec, NSEC_PER_USEC), USEC_PER_MSEC));
1413
1414 if (c.ip_ingress_bytes != UINT64_MAX)
1415 log_info("IP traffic received: %s", FORMAT_BYTES(c.ip_ingress_bytes));
1416
1417 if (c.ip_egress_bytes != UINT64_MAX)
1418 log_info("IP traffic sent: %s", FORMAT_BYTES(c.ip_egress_bytes));
1419
1420 if (c.io_read_bytes != UINT64_MAX)
1421 log_info("IO bytes read: %s", FORMAT_BYTES(c.io_read_bytes));
1422
1423 if (c.io_write_bytes != UINT64_MAX)
1424 log_info("IO bytes written: %s", FORMAT_BYTES(c.io_write_bytes));
1425 }
1426
1427 /* Try to propagate the service's return value. But if the service defines
1428 * e.g. SuccessExitStatus, honour this, and return 0 to mean "success". */
1429 if (streq_ptr(c.result, "success"))
1430 return EXIT_SUCCESS;
1431 if (streq_ptr(c.result, "exit-code") && c.exit_status > 0)
1432 return c.exit_status;
1433 if (streq_ptr(c.result, "signal"))
1434 return EXIT_EXCEPTION;
1435 return EXIT_FAILURE;
1436 }
1437
1438 return EXIT_SUCCESS;
1439 }
1440
1441 static int acquire_invocation_id(sd_bus *bus, sd_id128_t *ret) {
1442 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1443 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1444 const void *p;
1445 size_t l;
1446 int r;
1447
1448 assert(bus);
1449 assert(ret);
1450
1451 r = sd_bus_get_property(bus,
1452 "org.freedesktop.systemd1",
1453 "/org/freedesktop/systemd1/unit/self",
1454 "org.freedesktop.systemd1.Unit",
1455 "InvocationID",
1456 &error,
1457 &reply,
1458 "ay");
1459 if (r < 0)
1460 return log_error_errno(r, "Failed to request invocation ID for scope: %s", bus_error_message(&error, r));
1461
1462 r = sd_bus_message_read_array(reply, 'y', &p, &l);
1463 if (r < 0)
1464 return bus_log_parse_error(r);
1465
1466 if (l != sizeof(sd_id128_t))
1467 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid UUID size, %zu != %zu.", l, sizeof(sd_id128_t));
1468
1469 memcpy(ret, p, l);
1470 return 0;
1471 }
1472
1473 static int start_transient_scope(sd_bus *bus) {
1474 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1475 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1476 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1477 _cleanup_strv_free_ char **env = NULL, **user_env = NULL, **expanded_cmdline = NULL;
1478 _cleanup_free_ char *scope = NULL;
1479 const char *object = NULL;
1480 sd_id128_t invocation_id;
1481 int r;
1482
1483 assert(bus);
1484 assert(!strv_isempty(arg_cmdline));
1485
1486 r = bus_wait_for_jobs_new(bus, &w);
1487 if (r < 0)
1488 return log_oom();
1489
1490 if (arg_unit) {
1491 r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1492 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1493 ".scope", &scope);
1494 if (r < 0)
1495 return log_error_errno(r, "Failed to mangle scope name: %m");
1496 } else {
1497 r = make_unit_name(bus, UNIT_SCOPE, &scope);
1498 if (r < 0)
1499 return r;
1500 }
1501
1502 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1503 if (r < 0)
1504 return bus_log_create_error(r);
1505
1506 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1507 if (r < 0)
1508 return bus_log_create_error(r);
1509
1510 /* Name and Mode */
1511 r = sd_bus_message_append(m, "ss", scope, "fail");
1512 if (r < 0)
1513 return bus_log_create_error(r);
1514
1515 /* Properties */
1516 r = sd_bus_message_open_container(m, 'a', "(sv)");
1517 if (r < 0)
1518 return bus_log_create_error(r);
1519
1520 r = transient_scope_set_properties(m);
1521 if (r < 0)
1522 return r;
1523
1524 r = sd_bus_message_close_container(m);
1525 if (r < 0)
1526 return bus_log_create_error(r);
1527
1528 /* Auxiliary units */
1529 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1530 if (r < 0)
1531 return bus_log_create_error(r);
1532
1533 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1534
1535 r = sd_bus_call(bus, m, 0, &error, &reply);
1536 if (r < 0)
1537 return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, r));
1538
1539 r = sd_bus_message_read(reply, "o", &object);
1540 if (r < 0)
1541 return bus_log_parse_error(r);
1542
1543 r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_runtime_scope == RUNTIME_SCOPE_USER ? STRV_MAKE_CONST("--user") : NULL);
1544 if (r < 0)
1545 return r;
1546
1547 r = acquire_invocation_id(bus, &invocation_id);
1548 if (r < 0)
1549 return r;
1550
1551 r = strv_extendf(&user_env, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(invocation_id));
1552 if (r < 0)
1553 return log_oom();
1554
1555 if (arg_nice_set) {
1556 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
1557 return log_error_errno(errno, "Failed to set nice level: %m");
1558 }
1559
1560 if (arg_exec_group) {
1561 gid_t gid;
1562
1563 r = get_group_creds(&arg_exec_group, &gid, 0);
1564 if (r < 0)
1565 return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
1566
1567 if (setresgid(gid, gid, gid) < 0)
1568 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1569 }
1570
1571 if (arg_exec_user) {
1572 const char *home, *shell;
1573 uid_t uid;
1574 gid_t gid;
1575
1576 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS);
1577 if (r < 0)
1578 return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
1579
1580 if (home) {
1581 r = strv_extendf(&user_env, "HOME=%s", home);
1582 if (r < 0)
1583 return log_oom();
1584 }
1585
1586 if (shell) {
1587 r = strv_extendf(&user_env, "SHELL=%s", shell);
1588 if (r < 0)
1589 return log_oom();
1590 }
1591
1592 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
1593 if (r < 0)
1594 return log_oom();
1595
1596 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
1597 if (r < 0)
1598 return log_oom();
1599
1600 if (!arg_exec_group) {
1601 if (setresgid(gid, gid, gid) < 0)
1602 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1603 }
1604
1605 if (setresuid(uid, uid, uid) < 0)
1606 return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
1607 }
1608
1609 if (arg_working_directory && chdir(arg_working_directory) < 0)
1610 return log_error_errno(errno, "Failed to change directory to '%s': %m", arg_working_directory);
1611
1612 env = strv_env_merge(environ, user_env, arg_environment);
1613 if (!env)
1614 return log_oom();
1615
1616 if (!arg_quiet)
1617 log_info("Running scope as unit: %s", scope);
1618
1619 if (arg_expand_environment) {
1620 expanded_cmdline = replace_env_argv(arg_cmdline, env);
1621 if (!expanded_cmdline)
1622 return log_oom();
1623 arg_cmdline = expanded_cmdline;
1624 }
1625
1626 execvpe(arg_cmdline[0], arg_cmdline, env);
1627
1628 return log_error_errno(errno, "Failed to execute: %m");
1629 }
1630
1631 static int make_transient_trigger_unit(
1632 sd_bus *bus,
1633 sd_bus_message **message,
1634 const char *suffix,
1635 const char *trigger,
1636 const char *service) {
1637
1638 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1639 int r;
1640
1641 assert(bus);
1642 assert(message);
1643 assert(suffix);
1644 assert(trigger);
1645 assert(service);
1646
1647 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1648 if (r < 0)
1649 return bus_log_create_error(r);
1650
1651 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1652 if (r < 0)
1653 return bus_log_create_error(r);
1654
1655 /* Name and Mode */
1656 r = sd_bus_message_append(m, "ss", trigger, "fail");
1657 if (r < 0)
1658 return bus_log_create_error(r);
1659
1660 /* Properties */
1661 r = sd_bus_message_open_container(m, 'a', "(sv)");
1662 if (r < 0)
1663 return bus_log_create_error(r);
1664
1665 if (streq(suffix, ".path"))
1666 r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property);
1667 else if (streq(suffix, ".socket"))
1668 r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property);
1669 else if (streq(suffix, ".timer"))
1670 r = transient_timer_set_properties(m);
1671 else
1672 assert_not_reached();
1673 if (r < 0)
1674 return r;
1675
1676 r = sd_bus_message_close_container(m);
1677 if (r < 0)
1678 return bus_log_create_error(r);
1679
1680 r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1681 if (r < 0)
1682 return bus_log_create_error(r);
1683
1684 if (!strv_isempty(arg_cmdline)) {
1685 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1686 if (r < 0)
1687 return bus_log_create_error(r);
1688
1689 r = sd_bus_message_append(m, "s", service);
1690 if (r < 0)
1691 return bus_log_create_error(r);
1692
1693 r = sd_bus_message_open_container(m, 'a', "(sv)");
1694 if (r < 0)
1695 return bus_log_create_error(r);
1696
1697 r = transient_service_set_properties(m, NULL);
1698 if (r < 0)
1699 return r;
1700
1701 r = sd_bus_message_close_container(m);
1702 if (r < 0)
1703 return bus_log_create_error(r);
1704
1705 r = sd_bus_message_close_container(m);
1706 if (r < 0)
1707 return bus_log_create_error(r);
1708 }
1709
1710 r = sd_bus_message_close_container(m);
1711 if (r < 0)
1712 return bus_log_create_error(r);
1713
1714 *message = TAKE_PTR(m);
1715 return 0;
1716 }
1717
1718 static int start_transient_trigger(sd_bus *bus, const char *suffix) {
1719 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1720 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1721 _cleanup_free_ char *trigger = NULL, *service = NULL;
1722 const char *object = NULL;
1723 int r;
1724
1725 assert(bus);
1726 assert(suffix);
1727
1728 r = bus_wait_for_jobs_new(bus, &w);
1729 if (r < 0)
1730 return log_oom();
1731
1732 if (arg_unit) {
1733 switch (unit_name_to_type(arg_unit)) {
1734
1735 case UNIT_SERVICE:
1736 service = strdup(arg_unit);
1737 if (!service)
1738 return log_oom();
1739
1740 r = unit_name_change_suffix(service, suffix, &trigger);
1741 if (r < 0)
1742 return log_error_errno(r, "Failed to change unit suffix: %m");
1743 break;
1744
1745 case UNIT_TIMER:
1746 trigger = strdup(arg_unit);
1747 if (!trigger)
1748 return log_oom();
1749
1750 r = unit_name_change_suffix(trigger, ".service", &service);
1751 if (r < 0)
1752 return log_error_errno(r, "Failed to change unit suffix: %m");
1753 break;
1754
1755 default:
1756 r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1757 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1758 ".service", &service);
1759 if (r < 0)
1760 return log_error_errno(r, "Failed to mangle unit name: %m");
1761
1762 r = unit_name_mangle_with_suffix(arg_unit, "as trigger",
1763 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1764 suffix, &trigger);
1765 if (r < 0)
1766 return log_error_errno(r, "Failed to mangle unit name: %m");
1767
1768 break;
1769 }
1770 } else {
1771 r = make_unit_name(bus, UNIT_SERVICE, &service);
1772 if (r < 0)
1773 return r;
1774
1775 r = unit_name_change_suffix(service, suffix, &trigger);
1776 if (r < 0)
1777 return log_error_errno(r, "Failed to change unit suffix: %m");
1778 }
1779
1780 r = make_transient_trigger_unit(bus, &m, suffix, trigger, service);
1781 if (r < 0)
1782 return r;
1783
1784 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1785
1786 r = bus_call_with_hint(bus, m, suffix + 1, &reply);
1787 if (r < 0)
1788 return r;
1789
1790 r = sd_bus_message_read(reply, "o", &object);
1791 if (r < 0)
1792 return bus_log_parse_error(r);
1793
1794 r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_runtime_scope == RUNTIME_SCOPE_USER ? STRV_MAKE_CONST("--user") : NULL);
1795 if (r < 0)
1796 return r;
1797
1798 if (!arg_quiet) {
1799 log_info("Running %s as unit: %s", suffix + 1, trigger);
1800 if (!strv_isempty(arg_cmdline))
1801 log_info("Will run service as unit: %s", service);
1802 }
1803
1804 return EXIT_SUCCESS;
1805 }
1806
1807 static bool shall_make_executable_absolute(void) {
1808 if (strv_isempty(arg_cmdline))
1809 return false;
1810 if (arg_transport != BUS_TRANSPORT_LOCAL)
1811 return false;
1812
1813 FOREACH_STRING(f, "RootDirectory=", "RootImage=", "ExecSearchPath=", "MountImages=", "ExtensionImages=")
1814 if (strv_find_startswith(arg_property, f))
1815 return false;
1816
1817 return true;
1818 }
1819
1820 static int run(int argc, char* argv[]) {
1821 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1822 _cleanup_free_ char *description = NULL;
1823 int r;
1824
1825 log_show_color(true);
1826 log_parse_environment();
1827 log_open();
1828
1829 r = parse_argv(argc, argv);
1830 if (r <= 0)
1831 return r;
1832
1833 if (shall_make_executable_absolute()) {
1834 /* Patch in an absolute path to fail early for user convenience, but only when we can do it
1835 * (i.e. we will be running from the same file system). This also uses the user's $PATH,
1836 * while we use a fixed search path in the manager. */
1837
1838 _cleanup_free_ char *command = NULL;
1839 r = find_executable(arg_cmdline[0], &command);
1840 if (r < 0)
1841 return log_error_errno(r, "Failed to find executable %s: %m", arg_cmdline[0]);
1842
1843 free_and_replace(arg_cmdline[0], command);
1844 }
1845
1846 if (!arg_description) {
1847 description = strv_join(arg_cmdline, " ");
1848 if (!description)
1849 return log_oom();
1850
1851 if (arg_unit && isempty(description)) {
1852 r = free_and_strdup(&description, arg_unit);
1853 if (r < 0)
1854 return log_oom();
1855 }
1856
1857 arg_description = description;
1858 }
1859
1860 /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct
1861 * connection */
1862 if (arg_wait || arg_stdio != ARG_STDIO_NONE || (arg_runtime_scope == RUNTIME_SCOPE_USER && arg_transport != BUS_TRANSPORT_LOCAL))
1863 r = bus_connect_transport(arg_transport, arg_host, arg_runtime_scope, &bus);
1864 else
1865 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_runtime_scope, &bus);
1866 if (r < 0)
1867 return bus_log_connect_error(r, arg_transport);
1868
1869 if (arg_scope)
1870 return start_transient_scope(bus);
1871 if (arg_path_property)
1872 return start_transient_trigger(bus, ".path");
1873 if (arg_socket_property)
1874 return start_transient_trigger(bus, ".socket");
1875 if (arg_with_timer)
1876 return start_transient_trigger(bus, ".timer");
1877 return start_transient_service(bus);
1878 }
1879
1880 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);