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