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