]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/run/run.c
Add SPDX license identifiers to source files under the LGPL
[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-name.h"
44 #include "user-util.h"
45
46 static bool arg_ask_password = true;
47 static bool arg_scope = false;
48 static bool arg_remain_after_exit = false;
49 static bool arg_no_block = false;
50 static bool arg_wait = false;
51 static const char *arg_unit = NULL;
52 static const char *arg_description = NULL;
53 static const char *arg_slice = NULL;
54 static bool arg_send_sighup = false;
55 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
56 static const char *arg_host = NULL;
57 static bool arg_user = false;
58 static const char *arg_service_type = NULL;
59 static const char *arg_exec_user = NULL;
60 static const char *arg_exec_group = NULL;
61 static int arg_nice = 0;
62 static bool arg_nice_set = false;
63 static char **arg_environment = NULL;
64 static char **arg_property = NULL;
65 static enum {
66 ARG_STDIO_NONE, /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */
67 ARG_STDIO_PTY, /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */
68 ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
69 ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
70 } arg_stdio = ARG_STDIO_NONE;
71 static usec_t arg_on_active = 0;
72 static usec_t arg_on_boot = 0;
73 static usec_t arg_on_startup = 0;
74 static usec_t arg_on_unit_active = 0;
75 static usec_t arg_on_unit_inactive = 0;
76 static const char *arg_on_calendar = NULL;
77 static char **arg_timer_property = NULL;
78 static bool arg_quiet = false;
79 static bool arg_aggressive_gc = false;
80
81 static void help(void) {
82 printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
83 "Run the specified command in a transient scope or service.\n\n"
84 " -h --help Show this help\n"
85 " --version Show package version\n"
86 " --no-ask-password Do not prompt for password\n"
87 " --user Run as user unit\n"
88 " -H --host=[USER@]HOST Operate on remote host\n"
89 " -M --machine=CONTAINER Operate on local container\n"
90 " --scope Run this as scope rather than service\n"
91 " --unit=UNIT Run under the specified unit name\n"
92 " -p --property=NAME=VALUE Set service or scope unit property\n"
93 " --description=TEXT Description for unit\n"
94 " --slice=SLICE Run in the specified slice\n"
95 " --no-block Do not wait until operation finished\n"
96 " -r --remain-after-exit Leave service around until explicitly stopped\n"
97 " --wait Wait until service stopped again\n"
98 " --send-sighup Send SIGHUP when terminating\n"
99 " --service-type=TYPE Service type\n"
100 " --uid=USER Run as system user\n"
101 " --gid=GROUP Run as system group\n"
102 " --nice=NICE Nice level\n"
103 " -E --setenv=NAME=VALUE Set environment\n"
104 " -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n"
105 " STDERR\n"
106 " -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n"
107 " -q --quiet Suppress information messages during runtime\n"
108 " -G --collect Unload unit after it ran, even when failed\n\n"
109 "Timer options:\n"
110 " --on-active=SECONDS Run after SECONDS delay\n"
111 " --on-boot=SECONDS Run SECONDS after machine was booted up\n"
112 " --on-startup=SECONDS Run SECONDS after systemd activation\n"
113 " --on-unit-active=SECONDS Run SECONDS after the last activation\n"
114 " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n"
115 " --on-calendar=SPEC Realtime timer\n"
116 " --timer-property=NAME=VALUE Set timer unit property\n"
117 , program_invocation_short_name);
118 }
119
120 static bool with_timer(void) {
121 return arg_on_active || arg_on_boot || arg_on_startup || arg_on_unit_active || arg_on_unit_inactive || arg_on_calendar;
122 }
123
124 static int parse_argv(int argc, char *argv[]) {
125
126 enum {
127 ARG_VERSION = 0x100,
128 ARG_USER,
129 ARG_SYSTEM,
130 ARG_SCOPE,
131 ARG_UNIT,
132 ARG_DESCRIPTION,
133 ARG_SLICE,
134 ARG_SEND_SIGHUP,
135 ARG_SERVICE_TYPE,
136 ARG_EXEC_USER,
137 ARG_EXEC_GROUP,
138 ARG_NICE,
139 ARG_ON_ACTIVE,
140 ARG_ON_BOOT,
141 ARG_ON_STARTUP,
142 ARG_ON_UNIT_ACTIVE,
143 ARG_ON_UNIT_INACTIVE,
144 ARG_ON_CALENDAR,
145 ARG_TIMER_PROPERTY,
146 ARG_NO_BLOCK,
147 ARG_NO_ASK_PASSWORD,
148 ARG_WAIT,
149 };
150
151 static const struct option options[] = {
152 { "help", no_argument, NULL, 'h' },
153 { "version", no_argument, NULL, ARG_VERSION },
154 { "user", no_argument, NULL, ARG_USER },
155 { "system", no_argument, NULL, ARG_SYSTEM },
156 { "scope", no_argument, NULL, ARG_SCOPE },
157 { "unit", required_argument, NULL, ARG_UNIT },
158 { "description", required_argument, NULL, ARG_DESCRIPTION },
159 { "slice", required_argument, NULL, ARG_SLICE },
160 { "remain-after-exit", no_argument, NULL, 'r' },
161 { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
162 { "host", required_argument, NULL, 'H' },
163 { "machine", required_argument, NULL, 'M' },
164 { "service-type", required_argument, NULL, ARG_SERVICE_TYPE },
165 { "wait", no_argument, NULL, ARG_WAIT },
166 { "uid", required_argument, NULL, ARG_EXEC_USER },
167 { "gid", required_argument, NULL, ARG_EXEC_GROUP },
168 { "nice", required_argument, NULL, ARG_NICE },
169 { "setenv", required_argument, NULL, 'E' },
170 { "property", required_argument, NULL, 'p' },
171 { "tty", no_argument, NULL, 't' }, /* deprecated alias */
172 { "pty", no_argument, NULL, 't' },
173 { "pipe", no_argument, NULL, 'P' },
174 { "quiet", no_argument, NULL, 'q' },
175 { "on-active", required_argument, NULL, ARG_ON_ACTIVE },
176 { "on-boot", required_argument, NULL, ARG_ON_BOOT },
177 { "on-startup", required_argument, NULL, ARG_ON_STARTUP },
178 { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE },
179 { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
180 { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
181 { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
182 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
183 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
184 { "collect", no_argument, NULL, 'G' },
185 {},
186 };
187
188 int r, c;
189
190 assert(argc >= 0);
191 assert(argv);
192
193 while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqG", options, NULL)) >= 0)
194
195 switch (c) {
196
197 case 'h':
198 help();
199 return 0;
200
201 case ARG_VERSION:
202 return version();
203
204 case ARG_NO_ASK_PASSWORD:
205 arg_ask_password = false;
206 break;
207
208 case ARG_USER:
209 arg_user = true;
210 break;
211
212 case ARG_SYSTEM:
213 arg_user = false;
214 break;
215
216 case ARG_SCOPE:
217 arg_scope = true;
218 break;
219
220 case ARG_UNIT:
221 arg_unit = optarg;
222 break;
223
224 case ARG_DESCRIPTION:
225 arg_description = optarg;
226 break;
227
228 case ARG_SLICE:
229 arg_slice = optarg;
230 break;
231
232 case ARG_SEND_SIGHUP:
233 arg_send_sighup = true;
234 break;
235
236 case 'r':
237 arg_remain_after_exit = true;
238 break;
239
240 case 'H':
241 arg_transport = BUS_TRANSPORT_REMOTE;
242 arg_host = optarg;
243 break;
244
245 case 'M':
246 arg_transport = BUS_TRANSPORT_MACHINE;
247 arg_host = optarg;
248 break;
249
250 case ARG_SERVICE_TYPE:
251 arg_service_type = optarg;
252 break;
253
254 case ARG_EXEC_USER:
255 arg_exec_user = optarg;
256 break;
257
258 case ARG_EXEC_GROUP:
259 arg_exec_group = optarg;
260 break;
261
262 case ARG_NICE:
263 r = parse_nice(optarg, &arg_nice);
264 if (r < 0)
265 return log_error_errno(r, "Failed to parse nice value: %s", optarg);
266
267 arg_nice_set = true;
268 break;
269
270 case 'E':
271 if (strv_extend(&arg_environment, optarg) < 0)
272 return log_oom();
273
274 break;
275
276 case 'p':
277 if (strv_extend(&arg_property, optarg) < 0)
278 return log_oom();
279
280 break;
281
282 case 't': /* --pty */
283 if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */
284 arg_stdio = ARG_STDIO_AUTO;
285 else
286 arg_stdio = ARG_STDIO_PTY;
287 break;
288
289 case 'P': /* --pipe */
290 if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */
291 arg_stdio = ARG_STDIO_AUTO;
292 else
293 arg_stdio = ARG_STDIO_DIRECT;
294 break;
295
296 case 'q':
297 arg_quiet = true;
298 break;
299
300 case ARG_ON_ACTIVE:
301
302 r = parse_sec(optarg, &arg_on_active);
303 if (r < 0) {
304 log_error("Failed to parse timer value: %s", optarg);
305 return r;
306 }
307
308 break;
309
310 case ARG_ON_BOOT:
311
312 r = parse_sec(optarg, &arg_on_boot);
313 if (r < 0) {
314 log_error("Failed to parse timer value: %s", optarg);
315 return r;
316 }
317
318 break;
319
320 case ARG_ON_STARTUP:
321
322 r = parse_sec(optarg, &arg_on_startup);
323 if (r < 0) {
324 log_error("Failed to parse timer value: %s", optarg);
325 return r;
326 }
327
328 break;
329
330 case ARG_ON_UNIT_ACTIVE:
331
332 r = parse_sec(optarg, &arg_on_unit_active);
333 if (r < 0) {
334 log_error("Failed to parse timer value: %s", optarg);
335 return r;
336 }
337
338 break;
339
340 case ARG_ON_UNIT_INACTIVE:
341
342 r = parse_sec(optarg, &arg_on_unit_inactive);
343 if (r < 0) {
344 log_error("Failed to parse timer value: %s", optarg);
345 return r;
346 }
347
348 break;
349
350 case ARG_ON_CALENDAR: {
351 CalendarSpec *spec = NULL;
352
353 r = calendar_spec_from_string(optarg, &spec);
354 if (r < 0) {
355 log_error("Invalid calendar spec: %s", optarg);
356 return r;
357 }
358
359 calendar_spec_free(spec);
360 arg_on_calendar = optarg;
361 break;
362 }
363
364 case ARG_TIMER_PROPERTY:
365
366 if (strv_extend(&arg_timer_property, optarg) < 0)
367 return log_oom();
368
369 break;
370
371 case ARG_NO_BLOCK:
372 arg_no_block = true;
373 break;
374
375 case ARG_WAIT:
376 arg_wait = true;
377 break;
378
379 case 'G':
380 arg_aggressive_gc = true;
381 break;
382
383 case '?':
384 return -EINVAL;
385
386 default:
387 assert_not_reached("Unhandled option");
388 }
389
390
391 if (arg_stdio == ARG_STDIO_AUTO) {
392 /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
393 * to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
394 * pipeline, but we are neatly interactive with tty-level isolation otherwise. */
395 arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
396 ARG_STDIO_PTY :
397 ARG_STDIO_DIRECT;
398 }
399
400 if ((optind >= argc) && (!arg_unit || !with_timer())) {
401 log_error("Command line to execute required.");
402 return -EINVAL;
403 }
404
405 if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
406 log_error("Execution in user context is not supported on non-local systems.");
407 return -EINVAL;
408 }
409
410 if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
411 log_error("Scope execution is not supported on non-local systems.");
412 return -EINVAL;
413 }
414
415 if (arg_scope && (arg_remain_after_exit || arg_service_type)) {
416 log_error("--remain-after-exit and --service-type= are not supported in --scope mode.");
417 return -EINVAL;
418 }
419
420 if (arg_stdio != ARG_STDIO_NONE && (with_timer() || arg_scope)) {
421 log_error("--pty/--pipe is not compatible in timer or --scope mode.");
422 return -EINVAL;
423 }
424
425 if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE) {
426 log_error("--pty/--pipe is only supported when connecting to the local system or containers.");
427 return -EINVAL;
428 }
429
430 if (arg_stdio != ARG_STDIO_NONE && arg_no_block) {
431 log_error("--pty/--pipe is not compatible with --no-block.");
432 return -EINVAL;
433 }
434
435 if (arg_scope && with_timer()) {
436 log_error("Timer options are not supported in --scope mode.");
437 return -EINVAL;
438 }
439
440 if (arg_timer_property && !with_timer()) {
441 log_error("--timer-property= has no effect without any other timer options.");
442 return -EINVAL;
443 }
444
445 if (arg_wait) {
446 if (arg_no_block) {
447 log_error("--wait may not be combined with --no-block.");
448 return -EINVAL;
449 }
450
451 if (with_timer()) {
452 log_error("--wait may not be combined with timer operations.");
453 return -EINVAL;
454 }
455
456 if (arg_scope) {
457 log_error("--wait may not be combined with --scope.");
458 return -EINVAL;
459 }
460 }
461
462 return 1;
463 }
464
465 static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
466 int r;
467
468 r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
469 if (r < 0)
470 return r;
471
472 if (arg_aggressive_gc) {
473 r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
474 if (r < 0)
475 return r;
476 }
477
478 r = bus_append_unit_property_assignment_many(m, properties);
479 if (r < 0)
480 return r;
481
482 return 0;
483 }
484
485 static int transient_cgroup_set_properties(sd_bus_message *m) {
486 int r;
487 assert(m);
488
489 if (!isempty(arg_slice)) {
490 _cleanup_free_ char *slice;
491
492 r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice);
493 if (r < 0)
494 return r;
495
496 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
497 if (r < 0)
498 return r;
499 }
500
501 return 0;
502 }
503
504 static int transient_kill_set_properties(sd_bus_message *m) {
505 assert(m);
506
507 if (arg_send_sighup)
508 return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
509 else
510 return 0;
511 }
512
513 static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
514 bool send_term = false;
515 int r;
516
517 assert(m);
518
519 r = transient_unit_set_properties(m, arg_property);
520 if (r < 0)
521 return r;
522
523 r = transient_kill_set_properties(m);
524 if (r < 0)
525 return r;
526
527 r = transient_cgroup_set_properties(m);
528 if (r < 0)
529 return r;
530
531 if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
532 r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
533 if (r < 0)
534 return r;
535 }
536
537 if (arg_remain_after_exit) {
538 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
539 if (r < 0)
540 return r;
541 }
542
543 if (arg_service_type) {
544 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
545 if (r < 0)
546 return r;
547 }
548
549 if (arg_exec_user) {
550 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
551 if (r < 0)
552 return r;
553 }
554
555 if (arg_exec_group) {
556 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
557 if (r < 0)
558 return r;
559 }
560
561 if (arg_nice_set) {
562 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
563 if (r < 0)
564 return r;
565 }
566
567 if (pty_path) {
568 r = sd_bus_message_append(m,
569 "(sv)(sv)(sv)(sv)",
570 "StandardInput", "s", "tty",
571 "StandardOutput", "s", "tty",
572 "StandardError", "s", "tty",
573 "TTYPath", "s", pty_path);
574 if (r < 0)
575 return r;
576
577 send_term = true;
578
579 } else if (arg_stdio == ARG_STDIO_DIRECT) {
580 r = sd_bus_message_append(m,
581 "(sv)(sv)(sv)",
582 "StandardInputFileDescriptor", "h", STDIN_FILENO,
583 "StandardOutputFileDescriptor", "h", STDOUT_FILENO,
584 "StandardErrorFileDescriptor", "h", STDERR_FILENO);
585 if (r < 0)
586 return r;
587
588 send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
589 }
590
591 if (send_term) {
592 const char *e;
593
594 e = getenv("TERM");
595 if (e) {
596 char *n;
597
598 n = strjoina("TERM=", e);
599 r = sd_bus_message_append(m,
600 "(sv)",
601 "Environment", "as", 1, n);
602 if (r < 0)
603 return r;
604 }
605 }
606
607 if (!strv_isempty(arg_environment)) {
608 r = sd_bus_message_open_container(m, 'r', "sv");
609 if (r < 0)
610 return r;
611
612 r = sd_bus_message_append(m, "s", "Environment");
613 if (r < 0)
614 return r;
615
616 r = sd_bus_message_open_container(m, 'v', "as");
617 if (r < 0)
618 return r;
619
620 r = sd_bus_message_append_strv(m, arg_environment);
621 if (r < 0)
622 return r;
623
624 r = sd_bus_message_close_container(m);
625 if (r < 0)
626 return r;
627
628 r = sd_bus_message_close_container(m);
629 if (r < 0)
630 return r;
631 }
632
633 /* Exec container */
634 {
635 r = sd_bus_message_open_container(m, 'r', "sv");
636 if (r < 0)
637 return r;
638
639 r = sd_bus_message_append(m, "s", "ExecStart");
640 if (r < 0)
641 return r;
642
643 r = sd_bus_message_open_container(m, 'v', "a(sasb)");
644 if (r < 0)
645 return r;
646
647 r = sd_bus_message_open_container(m, 'a', "(sasb)");
648 if (r < 0)
649 return r;
650
651 r = sd_bus_message_open_container(m, 'r', "sasb");
652 if (r < 0)
653 return r;
654
655 r = sd_bus_message_append(m, "s", argv[0]);
656 if (r < 0)
657 return r;
658
659 r = sd_bus_message_append_strv(m, argv);
660 if (r < 0)
661 return r;
662
663 r = sd_bus_message_append(m, "b", false);
664 if (r < 0)
665 return r;
666
667 r = sd_bus_message_close_container(m);
668 if (r < 0)
669 return r;
670
671 r = sd_bus_message_close_container(m);
672 if (r < 0)
673 return r;
674
675 r = sd_bus_message_close_container(m);
676 if (r < 0)
677 return r;
678
679 r = sd_bus_message_close_container(m);
680 if (r < 0)
681 return r;
682 }
683
684 return 0;
685 }
686
687 static int transient_scope_set_properties(sd_bus_message *m) {
688 int r;
689
690 assert(m);
691
692 r = transient_unit_set_properties(m, arg_property);
693 if (r < 0)
694 return r;
695
696 r = transient_kill_set_properties(m);
697 if (r < 0)
698 return r;
699
700 r = transient_cgroup_set_properties(m);
701 if (r < 0)
702 return r;
703
704 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached());
705 if (r < 0)
706 return r;
707
708 return 0;
709 }
710
711 static int transient_timer_set_properties(sd_bus_message *m) {
712 int r;
713
714 assert(m);
715
716 r = transient_unit_set_properties(m, arg_timer_property);
717 if (r < 0)
718 return r;
719
720 /* Automatically clean up our transient timers */
721 r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
722 if (r < 0)
723 return r;
724
725 if (arg_on_active) {
726 r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
727 if (r < 0)
728 return r;
729 }
730
731 if (arg_on_boot) {
732 r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
733 if (r < 0)
734 return r;
735 }
736
737 if (arg_on_startup) {
738 r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
739 if (r < 0)
740 return r;
741 }
742
743 if (arg_on_unit_active) {
744 r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
745 if (r < 0)
746 return r;
747 }
748
749 if (arg_on_unit_inactive) {
750 r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
751 if (r < 0)
752 return r;
753 }
754
755 if (arg_on_calendar) {
756 r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
757 if (r < 0)
758 return r;
759 }
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 bus_log_create_error(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 const char *mt;
1063
1064 c.bus = sd_bus_ref(bus);
1065
1066 r = sd_event_default(&c.event);
1067 if (r < 0)
1068 return log_error_errno(r, "Failed to get event loop: %m");
1069
1070 if (master >= 0) {
1071 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
1072 (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
1073 (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);
1074
1075 if (!arg_quiet)
1076 log_info("Press ^] three times within 1s to disconnect TTY.");
1077
1078 r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward);
1079 if (r < 0)
1080 return log_error_errno(r, "Failed to create PTY forwarder: %m");
1081
1082 pty_forward_set_handler(c.forward, pty_forward_handler, &c);
1083 }
1084
1085 path = unit_dbus_path_from_name(service);
1086 if (!path)
1087 return log_oom();
1088
1089 mt = strjoina("type='signal',"
1090 "sender='org.freedesktop.systemd1',"
1091 "path='", path, "',"
1092 "interface='org.freedesktop.DBus.Properties',"
1093 "member='PropertiesChanged'");
1094 r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c);
1095 if (r < 0)
1096 return log_error_errno(r, "Failed to add properties changed signal.");
1097
1098 r = sd_bus_attach_event(bus, c.event, 0);
1099 if (r < 0)
1100 return log_error_errno(r, "Failed to attach bus to event loop.");
1101
1102 r = run_context_update(&c, path);
1103 if (r < 0)
1104 return r;
1105
1106 r = sd_event_loop(c.event);
1107 if (r < 0)
1108 return log_error_errno(r, "Failed to run event loop: %m");
1109
1110 if (c.forward) {
1111 char last_char = 0;
1112
1113 r = pty_forward_get_last_char(c.forward, &last_char);
1114 if (r >= 0 && !arg_quiet && last_char != '\n')
1115 fputc('\n', stdout);
1116 }
1117
1118 if (arg_wait && !arg_quiet) {
1119
1120 /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, in its
1121 * original settings (i.e. proper line breaks), so that we can show the summary in a pretty
1122 * way. */
1123 c.forward = pty_forward_free(c.forward);
1124
1125 if (!isempty(c.result))
1126 log_info("Finished with result: %s", strna(c.result));
1127
1128 if (c.exit_code == CLD_EXITED)
1129 log_info("Main processes terminated with: code=%s/status=%i", sigchld_code_to_string(c.exit_code), c.exit_status);
1130 else if (c.exit_code > 0)
1131 log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
1132
1133 if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY &&
1134 c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY &&
1135 c.inactive_enter_usec > c.inactive_exit_usec) {
1136 char ts[FORMAT_TIMESPAN_MAX];
1137 log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
1138 }
1139
1140 if (c.cpu_usage_nsec != NSEC_INFINITY) {
1141 char ts[FORMAT_TIMESPAN_MAX];
1142 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));
1143 }
1144
1145 if (c.ip_ingress_bytes != UINT64_MAX) {
1146 char bytes[FORMAT_BYTES_MAX];
1147 log_info("IP traffic received: %s", format_bytes(bytes, sizeof(bytes), c.ip_ingress_bytes));
1148 }
1149 if (c.ip_egress_bytes != UINT64_MAX) {
1150 char bytes[FORMAT_BYTES_MAX];
1151 log_info("IP traffic sent: %s", format_bytes(bytes, sizeof(bytes), c.ip_egress_bytes));
1152 }
1153 }
1154
1155 /* Try to propagate the service's return value */
1156 if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED)
1157 *retval = c.exit_status;
1158 else
1159 *retval = EXIT_FAILURE;
1160 }
1161
1162 return 0;
1163 }
1164
1165 static int start_transient_scope(
1166 sd_bus *bus,
1167 char **argv) {
1168
1169 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1170 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1171 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1172 _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
1173 _cleanup_free_ char *scope = NULL;
1174 const char *object = NULL;
1175 int r;
1176
1177 assert(bus);
1178 assert(argv);
1179
1180 r = bus_wait_for_jobs_new(bus, &w);
1181 if (r < 0)
1182 return log_oom();
1183
1184 if (arg_unit) {
1185 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
1186 if (r < 0)
1187 return log_error_errno(r, "Failed to mangle scope name: %m");
1188 } else {
1189 r = make_unit_name(bus, UNIT_SCOPE, &scope);
1190 if (r < 0)
1191 return r;
1192 }
1193
1194 r = sd_bus_message_new_method_call(
1195 bus,
1196 &m,
1197 "org.freedesktop.systemd1",
1198 "/org/freedesktop/systemd1",
1199 "org.freedesktop.systemd1.Manager",
1200 "StartTransientUnit");
1201 if (r < 0)
1202 return bus_log_create_error(r);
1203
1204 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1205 if (r < 0)
1206 return bus_log_create_error(r);
1207
1208 /* Name and Mode */
1209 r = sd_bus_message_append(m, "ss", scope, "fail");
1210 if (r < 0)
1211 return bus_log_create_error(r);
1212
1213 /* Properties */
1214 r = sd_bus_message_open_container(m, 'a', "(sv)");
1215 if (r < 0)
1216 return bus_log_create_error(r);
1217
1218 r = transient_scope_set_properties(m);
1219 if (r < 0)
1220 return bus_log_create_error(r);
1221
1222 r = sd_bus_message_close_container(m);
1223 if (r < 0)
1224 return bus_log_create_error(r);
1225
1226 /* Auxiliary units */
1227 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1228 if (r < 0)
1229 return bus_log_create_error(r);
1230
1231 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1232
1233 r = sd_bus_call(bus, m, 0, &error, &reply);
1234 if (r < 0) {
1235 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
1236 return r;
1237 }
1238
1239 if (arg_nice_set) {
1240 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
1241 return log_error_errno(errno, "Failed to set nice level: %m");
1242 }
1243
1244 if (arg_exec_group) {
1245 gid_t gid;
1246
1247 r = get_group_creds(&arg_exec_group, &gid);
1248 if (r < 0)
1249 return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
1250
1251 if (setresgid(gid, gid, gid) < 0)
1252 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1253 }
1254
1255 if (arg_exec_user) {
1256 const char *home, *shell;
1257 uid_t uid;
1258 gid_t gid;
1259
1260 r = get_user_creds_clean(&arg_exec_user, &uid, &gid, &home, &shell);
1261 if (r < 0)
1262 return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
1263
1264 if (home) {
1265 r = strv_extendf(&user_env, "HOME=%s", home);
1266 if (r < 0)
1267 return log_oom();
1268 }
1269
1270 if (shell) {
1271 r = strv_extendf(&user_env, "SHELL=%s", shell);
1272 if (r < 0)
1273 return log_oom();
1274 }
1275
1276 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
1277 if (r < 0)
1278 return log_oom();
1279
1280 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
1281 if (r < 0)
1282 return log_oom();
1283
1284 if (!arg_exec_group) {
1285 if (setresgid(gid, gid, gid) < 0)
1286 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1287 }
1288
1289 if (setresuid(uid, uid, uid) < 0)
1290 return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
1291 }
1292
1293 env = strv_env_merge(3, environ, user_env, arg_environment);
1294 if (!env)
1295 return log_oom();
1296
1297 r = sd_bus_message_read(reply, "o", &object);
1298 if (r < 0)
1299 return bus_log_parse_error(r);
1300
1301 r = bus_wait_for_jobs_one(w, object, arg_quiet);
1302 if (r < 0)
1303 return r;
1304
1305 if (!arg_quiet)
1306 log_info("Running scope as unit: %s", scope);
1307
1308 execvpe(argv[0], argv, env);
1309
1310 return log_error_errno(errno, "Failed to execute: %m");
1311 }
1312
1313 static int start_transient_timer(
1314 sd_bus *bus,
1315 char **argv) {
1316
1317 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1318 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1319 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1320 _cleanup_free_ char *timer = NULL, *service = NULL;
1321 const char *object = NULL;
1322 int r;
1323
1324 assert(bus);
1325 assert(argv);
1326
1327 r = bus_wait_for_jobs_new(bus, &w);
1328 if (r < 0)
1329 return log_oom();
1330
1331 if (arg_unit) {
1332 switch (unit_name_to_type(arg_unit)) {
1333
1334 case UNIT_SERVICE:
1335 service = strdup(arg_unit);
1336 if (!service)
1337 return log_oom();
1338
1339 r = unit_name_change_suffix(service, ".timer", &timer);
1340 if (r < 0)
1341 return log_error_errno(r, "Failed to change unit suffix: %m");
1342 break;
1343
1344 case UNIT_TIMER:
1345 timer = strdup(arg_unit);
1346 if (!timer)
1347 return log_oom();
1348
1349 r = unit_name_change_suffix(timer, ".service", &service);
1350 if (r < 0)
1351 return log_error_errno(r, "Failed to change unit suffix: %m");
1352 break;
1353
1354 default:
1355 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
1356 if (r < 0)
1357 return log_error_errno(r, "Failed to mangle unit name: %m");
1358
1359 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
1360 if (r < 0)
1361 return log_error_errno(r, "Failed to mangle unit name: %m");
1362
1363 break;
1364 }
1365 } else {
1366 r = make_unit_name(bus, UNIT_SERVICE, &service);
1367 if (r < 0)
1368 return r;
1369
1370 r = unit_name_change_suffix(service, ".timer", &timer);
1371 if (r < 0)
1372 return log_error_errno(r, "Failed to change unit suffix: %m");
1373 }
1374
1375 r = sd_bus_message_new_method_call(
1376 bus,
1377 &m,
1378 "org.freedesktop.systemd1",
1379 "/org/freedesktop/systemd1",
1380 "org.freedesktop.systemd1.Manager",
1381 "StartTransientUnit");
1382 if (r < 0)
1383 return bus_log_create_error(r);
1384
1385 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1386 if (r < 0)
1387 return bus_log_create_error(r);
1388
1389 /* Name and Mode */
1390 r = sd_bus_message_append(m, "ss", timer, "fail");
1391 if (r < 0)
1392 return bus_log_create_error(r);
1393
1394 /* Properties */
1395 r = sd_bus_message_open_container(m, 'a', "(sv)");
1396 if (r < 0)
1397 return bus_log_create_error(r);
1398
1399 r = transient_timer_set_properties(m);
1400 if (r < 0)
1401 return bus_log_create_error(r);
1402
1403 r = sd_bus_message_close_container(m);
1404 if (r < 0)
1405 return bus_log_create_error(r);
1406
1407 r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1408 if (r < 0)
1409 return bus_log_create_error(r);
1410
1411 if (!strv_isempty(argv)) {
1412 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1413 if (r < 0)
1414 return bus_log_create_error(r);
1415
1416 r = sd_bus_message_append(m, "s", service);
1417 if (r < 0)
1418 return bus_log_create_error(r);
1419
1420 r = sd_bus_message_open_container(m, 'a', "(sv)");
1421 if (r < 0)
1422 return bus_log_create_error(r);
1423
1424 r = transient_service_set_properties(m, argv, NULL);
1425 if (r < 0)
1426 return bus_log_create_error(r);
1427
1428 r = sd_bus_message_close_container(m);
1429 if (r < 0)
1430 return bus_log_create_error(r);
1431
1432 r = sd_bus_message_close_container(m);
1433 if (r < 0)
1434 return bus_log_create_error(r);
1435 }
1436
1437 r = sd_bus_message_close_container(m);
1438 if (r < 0)
1439 return bus_log_create_error(r);
1440
1441 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1442
1443 r = sd_bus_call(bus, m, 0, &error, &reply);
1444 if (r < 0) {
1445 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
1446 return r;
1447 }
1448
1449 r = sd_bus_message_read(reply, "o", &object);
1450 if (r < 0)
1451 return bus_log_parse_error(r);
1452
1453 r = bus_wait_for_jobs_one(w, object, arg_quiet);
1454 if (r < 0)
1455 return r;
1456
1457 if (!arg_quiet) {
1458 log_info("Running timer as unit: %s", timer);
1459 if (argv[0])
1460 log_info("Will run service as unit: %s", service);
1461 }
1462
1463 return 0;
1464 }
1465
1466 int main(int argc, char* argv[]) {
1467 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1468 _cleanup_free_ char *description = NULL, *command = NULL;
1469 int r, retval = EXIT_SUCCESS;
1470
1471 log_parse_environment();
1472 log_open();
1473
1474 r = parse_argv(argc, argv);
1475 if (r <= 0)
1476 goto finish;
1477
1478 if (argc > optind && arg_transport == BUS_TRANSPORT_LOCAL) {
1479 /* Patch in an absolute path */
1480
1481 r = find_binary(argv[optind], &command);
1482 if (r < 0) {
1483 log_error_errno(r, "Failed to find executable %s: %m", argv[optind]);
1484 goto finish;
1485 }
1486
1487 argv[optind] = command;
1488 }
1489
1490 if (!arg_description) {
1491 description = strv_join(argv + optind, " ");
1492 if (!description) {
1493 r = log_oom();
1494 goto finish;
1495 }
1496
1497 if (arg_unit && isempty(description)) {
1498 r = free_and_strdup(&description, arg_unit);
1499 if (r < 0)
1500 goto finish;
1501 }
1502
1503 arg_description = description;
1504 }
1505
1506 /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct
1507 * connection */
1508 if (arg_wait || arg_stdio != ARG_STDIO_NONE)
1509 r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus);
1510 else
1511 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1512 if (r < 0) {
1513 log_error_errno(r, "Failed to create bus connection: %m");
1514 goto finish;
1515 }
1516
1517 if (arg_scope)
1518 r = start_transient_scope(bus, argv + optind);
1519 else if (with_timer())
1520 r = start_transient_timer(bus, argv + optind);
1521 else
1522 r = start_transient_service(bus, argv + optind, &retval);
1523
1524 finish:
1525 strv_free(arg_environment);
1526 strv_free(arg_property);
1527 strv_free(arg_timer_property);
1528
1529 return r < 0 ? EXIT_FAILURE : retval;
1530 }