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