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