]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/run/run.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / run / run.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <getopt.h>
23 #include <stdio.h>
24
25 #include "sd-bus.h"
26 #include "sd-event.h"
27
28 #include "alloc-util.h"
29 #include "bus-error.h"
30 #include "bus-util.h"
31 #include "calendarspec.h"
32 #include "env-util.h"
33 #include "event-util.h"
34 #include "fd-util.h"
35 #include "formats-util.h"
36 #include "path-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 #include "parse-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 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 bool arg_pty = false;
65 static usec_t arg_on_active = 0;
66 static usec_t arg_on_boot = 0;
67 static usec_t arg_on_startup = 0;
68 static usec_t arg_on_unit_active = 0;
69 static usec_t arg_on_unit_inactive = 0;
70 static const char *arg_on_calendar = NULL;
71 static char **arg_timer_property = NULL;
72 static bool arg_quiet = false;
73
74 static void polkit_agent_open_if_enabled(void) {
75
76 /* Open the polkit agent as a child process if necessary */
77 if (!arg_ask_password)
78 return;
79
80 if (arg_transport != BUS_TRANSPORT_LOCAL)
81 return;
82
83 polkit_agent_open();
84 }
85
86 static void help(void) {
87 printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
88 "Run the specified command in a transient scope or service or timer\n"
89 "unit. If timer option is specified and unit is exist which is\n"
90 "specified with --unit option then command can be omitted.\n\n"
91 " -h --help Show this help\n"
92 " --version Show package version\n"
93 " --no-ask-password Do not prompt for password\n"
94 " --user Run as user unit\n"
95 " -H --host=[USER@]HOST Operate on remote host\n"
96 " -M --machine=CONTAINER Operate on local container\n"
97 " --scope Run this as scope rather than service\n"
98 " --unit=UNIT Run under the specified unit name\n"
99 " -p --property=NAME=VALUE Set unit property\n"
100 " --description=TEXT Description for unit\n"
101 " --slice=SLICE Run in the specified slice\n"
102 " --no-block Do not wait until operation finished\n"
103 " -r --remain-after-exit Leave service around until explicitly stopped\n"
104 " --send-sighup Send SIGHUP when terminating\n"
105 " --service-type=TYPE Service type\n"
106 " --uid=USER Run as system user\n"
107 " --gid=GROUP Run as system group\n"
108 " --nice=NICE Nice level\n"
109 " --setenv=NAME=VALUE Set environment\n"
110 " -t --pty Run service on pseudo tty\n"
111 " -q --quiet Suppress information messages during runtime\n\n"
112 "Timer options:\n\n"
113 " --on-active=SECONDS Run after SECONDS delay\n"
114 " --on-boot=SECONDS Run SECONDS after machine was booted up\n"
115 " --on-startup=SECONDS Run SECONDS after systemd activation\n"
116 " --on-unit-active=SECONDS Run SECONDS after the last activation\n"
117 " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n"
118 " --on-calendar=SPEC Realtime timer\n"
119 " --timer-property=NAME=VALUE Set timer unit property\n",
120 program_invocation_short_name);
121 }
122
123 static bool with_timer(void) {
124 return arg_on_active || arg_on_boot || arg_on_startup || arg_on_unit_active || arg_on_unit_inactive || arg_on_calendar;
125 }
126
127 static int parse_argv(int argc, char *argv[]) {
128
129 enum {
130 ARG_VERSION = 0x100,
131 ARG_NO_ASK_PASSWORD,
132 ARG_USER,
133 ARG_SYSTEM,
134 ARG_SCOPE,
135 ARG_UNIT,
136 ARG_DESCRIPTION,
137 ARG_SLICE,
138 ARG_SEND_SIGHUP,
139 ARG_EXEC_USER,
140 ARG_EXEC_GROUP,
141 ARG_SERVICE_TYPE,
142 ARG_NICE,
143 ARG_SETENV,
144 ARG_TTY,
145 ARG_ON_ACTIVE,
146 ARG_ON_BOOT,
147 ARG_ON_STARTUP,
148 ARG_ON_UNIT_ACTIVE,
149 ARG_ON_UNIT_INACTIVE,
150 ARG_ON_CALENDAR,
151 ARG_TIMER_PROPERTY,
152 ARG_NO_BLOCK,
153 };
154
155 static const struct option options[] = {
156 { "help", no_argument, NULL, 'h' },
157 { "version", no_argument, NULL, ARG_VERSION },
158 { "user", no_argument, NULL, ARG_USER },
159 { "system", no_argument, NULL, ARG_SYSTEM },
160 { "scope", no_argument, NULL, ARG_SCOPE },
161 { "unit", required_argument, NULL, ARG_UNIT },
162 { "description", required_argument, NULL, ARG_DESCRIPTION },
163 { "slice", required_argument, NULL, ARG_SLICE },
164 { "remain-after-exit", no_argument, NULL, 'r' },
165 { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
166 { "host", required_argument, NULL, 'H' },
167 { "machine", required_argument, NULL, 'M' },
168 { "service-type", required_argument, NULL, ARG_SERVICE_TYPE },
169 { "uid", required_argument, NULL, ARG_EXEC_USER },
170 { "gid", required_argument, NULL, ARG_EXEC_GROUP },
171 { "nice", required_argument, NULL, ARG_NICE },
172 { "setenv", required_argument, NULL, ARG_SETENV },
173 { "property", required_argument, NULL, 'p' },
174 { "tty", no_argument, NULL, 't' },
175 { "quiet", no_argument, NULL, 'q' },
176 { "on-active", required_argument, NULL, ARG_ON_ACTIVE },
177 { "on-boot", required_argument, NULL, ARG_ON_BOOT },
178 { "on-startup", required_argument, NULL, ARG_ON_STARTUP },
179 { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE },
180 { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
181 { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
182 { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
183 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
184 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
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:p:tq", options, NULL)) >= 0)
194
195 switch (c) {
196
197 case 'h':
198 help();
199 return 0;
200
201 case ARG_NO_ASK_PASSWORD:
202 arg_ask_password = false;
203 break;
204
205 case ARG_VERSION:
206 return version();
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 = safe_atoi(optarg, &arg_nice);
264 if (r < 0 || arg_nice < PRIO_MIN || arg_nice >= PRIO_MAX) {
265 log_error("Failed to parse nice value");
266 return -EINVAL;
267 }
268
269 arg_nice_set = true;
270 break;
271
272 case ARG_SETENV:
273 if (strv_extend(&arg_environment, optarg) < 0)
274 return log_oom();
275
276 break;
277
278 case 'p':
279 if (strv_extend(&arg_property, optarg) < 0)
280 return log_oom();
281
282 break;
283
284 case 't':
285 arg_pty = true;
286 break;
287
288 case 'q':
289 arg_quiet = true;
290 break;
291
292 case ARG_ON_ACTIVE:
293
294 r = parse_sec(optarg, &arg_on_active);
295 if (r < 0) {
296 log_error("Failed to parse timer value: %s", optarg);
297 return r;
298 }
299
300 break;
301
302 case ARG_ON_BOOT:
303
304 r = parse_sec(optarg, &arg_on_boot);
305 if (r < 0) {
306 log_error("Failed to parse timer value: %s", optarg);
307 return r;
308 }
309
310 break;
311
312 case ARG_ON_STARTUP:
313
314 r = parse_sec(optarg, &arg_on_startup);
315 if (r < 0) {
316 log_error("Failed to parse timer value: %s", optarg);
317 return r;
318 }
319
320 break;
321
322 case ARG_ON_UNIT_ACTIVE:
323
324 r = parse_sec(optarg, &arg_on_unit_active);
325 if (r < 0) {
326 log_error("Failed to parse timer value: %s", optarg);
327 return r;
328 }
329
330 break;
331
332 case ARG_ON_UNIT_INACTIVE:
333
334 r = parse_sec(optarg, &arg_on_unit_inactive);
335 if (r < 0) {
336 log_error("Failed to parse timer value: %s", optarg);
337 return r;
338 }
339
340 break;
341
342 case ARG_ON_CALENDAR: {
343 CalendarSpec *spec = NULL;
344
345 r = calendar_spec_from_string(optarg, &spec);
346 if (r < 0) {
347 log_error("Invalid calendar spec: %s", optarg);
348 return r;
349 }
350
351 calendar_spec_free(spec);
352 arg_on_calendar = optarg;
353 break;
354 }
355
356 case ARG_TIMER_PROPERTY:
357
358 if (strv_extend(&arg_timer_property, optarg) < 0)
359 return log_oom();
360
361 break;
362
363 case ARG_NO_BLOCK:
364 arg_no_block = true;
365 break;
366
367 case '?':
368 return -EINVAL;
369
370 default:
371 assert_not_reached("Unhandled option");
372 }
373
374 if ((optind >= argc) && (!arg_unit || !with_timer())) {
375 log_error("Command line to execute required.");
376 return -EINVAL;
377 }
378
379 if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
380 log_error("Execution in user context is not supported on non-local systems.");
381 return -EINVAL;
382 }
383
384 if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
385 log_error("Scope execution is not supported on non-local systems.");
386 return -EINVAL;
387 }
388
389 if (arg_scope && (arg_remain_after_exit || arg_service_type)) {
390 log_error("--remain-after-exit and --service-type= are not supported in --scope mode.");
391 return -EINVAL;
392 }
393
394 if (arg_pty && (with_timer() || arg_scope)) {
395 log_error("--pty is not compatible in timer or --scope mode.");
396 return -EINVAL;
397 }
398
399 if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) {
400 log_error("--pty is only supported when connecting to the local system or containers.");
401 return -EINVAL;
402 }
403
404 if (arg_scope && with_timer()) {
405 log_error("Timer options are not supported in --scope mode.");
406 return -EINVAL;
407 }
408
409 if (arg_timer_property && !with_timer()) {
410 log_error("--timer-property= has no effect without any other timer options.");
411 return -EINVAL;
412 }
413
414 return 1;
415 }
416
417 static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
418 char **i;
419 int r;
420
421 r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
422 if (r < 0)
423 return r;
424
425 STRV_FOREACH(i, properties) {
426 r = sd_bus_message_open_container(m, 'r', "sv");
427 if (r < 0)
428 return r;
429
430 r = bus_append_unit_property_assignment(m, *i);
431 if (r < 0)
432 return r;
433
434 r = sd_bus_message_close_container(m);
435 if (r < 0)
436 return r;
437 }
438
439 return 0;
440 }
441
442 static int transient_cgroup_set_properties(sd_bus_message *m) {
443 int r;
444 assert(m);
445
446 if (!isempty(arg_slice)) {
447 _cleanup_free_ char *slice;
448
449 r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice);
450 if (r < 0)
451 return r;
452
453 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
454 if (r < 0)
455 return r;
456 }
457
458 return 0;
459 }
460
461 static int transient_kill_set_properties(sd_bus_message *m) {
462 assert(m);
463
464 if (arg_send_sighup)
465 return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
466 else
467 return 0;
468 }
469
470 static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
471 int r;
472
473 assert(m);
474
475 r = transient_unit_set_properties(m, arg_property);
476 if (r < 0)
477 return r;
478
479 r = transient_kill_set_properties(m);
480 if (r < 0)
481 return r;
482
483 r = transient_cgroup_set_properties(m);
484 if (r < 0)
485 return r;
486
487 if (arg_remain_after_exit) {
488 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
489 if (r < 0)
490 return r;
491 }
492
493 if (arg_service_type) {
494 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
495 if (r < 0)
496 return r;
497 }
498
499 if (arg_exec_user) {
500 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
501 if (r < 0)
502 return r;
503 }
504
505 if (arg_exec_group) {
506 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
507 if (r < 0)
508 return r;
509 }
510
511 if (arg_nice_set) {
512 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
513 if (r < 0)
514 return r;
515 }
516
517 if (pty_path) {
518 const char *e;
519
520 r = sd_bus_message_append(m,
521 "(sv)(sv)(sv)(sv)",
522 "StandardInput", "s", "tty",
523 "StandardOutput", "s", "tty",
524 "StandardError", "s", "tty",
525 "TTYPath", "s", pty_path);
526 if (r < 0)
527 return r;
528
529 e = getenv("TERM");
530 if (e) {
531 char *n;
532
533 n = strjoina("TERM=", e);
534 r = sd_bus_message_append(m,
535 "(sv)",
536 "Environment", "as", 1, n);
537 if (r < 0)
538 return r;
539 }
540 }
541
542 if (!strv_isempty(arg_environment)) {
543 r = sd_bus_message_open_container(m, 'r', "sv");
544 if (r < 0)
545 return r;
546
547 r = sd_bus_message_append(m, "s", "Environment");
548 if (r < 0)
549 return r;
550
551 r = sd_bus_message_open_container(m, 'v', "as");
552 if (r < 0)
553 return r;
554
555 r = sd_bus_message_append_strv(m, arg_environment);
556 if (r < 0)
557 return r;
558
559 r = sd_bus_message_close_container(m);
560 if (r < 0)
561 return r;
562
563 r = sd_bus_message_close_container(m);
564 if (r < 0)
565 return r;
566 }
567
568 /* Exec container */
569 {
570 r = sd_bus_message_open_container(m, 'r', "sv");
571 if (r < 0)
572 return r;
573
574 r = sd_bus_message_append(m, "s", "ExecStart");
575 if (r < 0)
576 return r;
577
578 r = sd_bus_message_open_container(m, 'v', "a(sasb)");
579 if (r < 0)
580 return r;
581
582 r = sd_bus_message_open_container(m, 'a', "(sasb)");
583 if (r < 0)
584 return r;
585
586 r = sd_bus_message_open_container(m, 'r', "sasb");
587 if (r < 0)
588 return r;
589
590 r = sd_bus_message_append(m, "s", argv[0]);
591 if (r < 0)
592 return r;
593
594 r = sd_bus_message_append_strv(m, argv);
595 if (r < 0)
596 return r;
597
598 r = sd_bus_message_append(m, "b", false);
599 if (r < 0)
600 return r;
601
602 r = sd_bus_message_close_container(m);
603 if (r < 0)
604 return r;
605
606 r = sd_bus_message_close_container(m);
607 if (r < 0)
608 return r;
609
610 r = sd_bus_message_close_container(m);
611 if (r < 0)
612 return r;
613
614 r = sd_bus_message_close_container(m);
615 if (r < 0)
616 return r;
617 }
618
619 return 0;
620 }
621
622 static int transient_scope_set_properties(sd_bus_message *m) {
623 int r;
624
625 assert(m);
626
627 r = transient_unit_set_properties(m, arg_property);
628 if (r < 0)
629 return r;
630
631 r = transient_kill_set_properties(m);
632 if (r < 0)
633 return r;
634
635 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
636 if (r < 0)
637 return r;
638
639 return 0;
640 }
641
642 static int transient_timer_set_properties(sd_bus_message *m) {
643 int r;
644
645 assert(m);
646
647 r = transient_unit_set_properties(m, arg_timer_property);
648 if (r < 0)
649 return r;
650
651 if (arg_on_active) {
652 r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
653 if (r < 0)
654 return r;
655 }
656
657 if (arg_on_boot) {
658 r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
659 if (r < 0)
660 return r;
661 }
662
663 if (arg_on_startup) {
664 r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
665 if (r < 0)
666 return r;
667 }
668
669 if (arg_on_unit_active) {
670 r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
671 if (r < 0)
672 return r;
673 }
674
675 if (arg_on_unit_inactive) {
676 r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
677 if (r < 0)
678 return r;
679 }
680
681 if (arg_on_calendar) {
682 r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
683 if (r < 0)
684 return r;
685 }
686
687 return 0;
688 }
689
690 static int start_transient_service(
691 sd_bus *bus,
692 char **argv) {
693
694 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
695 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
696 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
697 _cleanup_free_ char *service = NULL, *pty_path = NULL;
698 _cleanup_close_ int master = -1;
699 int r;
700
701 assert(bus);
702 assert(argv);
703
704 if (arg_pty) {
705
706 if (arg_transport == BUS_TRANSPORT_LOCAL) {
707 master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
708 if (master < 0)
709 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
710
711 r = ptsname_malloc(master, &pty_path);
712 if (r < 0)
713 return log_error_errno(r, "Failed to determine tty name: %m");
714
715 if (unlockpt(master) < 0)
716 return log_error_errno(errno, "Failed to unlock tty: %m");
717
718 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
719 _cleanup_bus_unref_ sd_bus *system_bus = NULL;
720 const char *s;
721
722 r = sd_bus_default_system(&system_bus);
723 if (r < 0)
724 return log_error_errno(r, "Failed to connect to system bus: %m");
725
726 r = sd_bus_call_method(system_bus,
727 "org.freedesktop.machine1",
728 "/org/freedesktop/machine1",
729 "org.freedesktop.machine1.Manager",
730 "OpenMachinePTY",
731 &error,
732 &reply,
733 "s", arg_host);
734 if (r < 0) {
735 log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
736 return r;
737 }
738
739 r = sd_bus_message_read(reply, "hs", &master, &s);
740 if (r < 0)
741 return bus_log_parse_error(r);
742
743 reply = sd_bus_message_unref(reply);
744
745 master = fcntl(master, F_DUPFD_CLOEXEC, 3);
746 if (master < 0)
747 return log_error_errno(errno, "Failed to duplicate master fd: %m");
748
749 pty_path = strdup(s);
750 if (!pty_path)
751 return log_oom();
752 } else
753 assert_not_reached("Can't allocate tty via ssh");
754 }
755
756 if (!arg_no_block) {
757 r = bus_wait_for_jobs_new(bus, &w);
758 if (r < 0)
759 return log_error_errno(r, "Could not watch jobs: %m");
760 }
761
762 if (arg_unit) {
763 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
764 if (r < 0)
765 return log_error_errno(r, "Failed to mangle unit name: %m");
766 } else if (asprintf(&service, "run-"PID_FMT".service", getpid()) < 0)
767 return log_oom();
768
769 r = sd_bus_message_new_method_call(
770 bus,
771 &m,
772 "org.freedesktop.systemd1",
773 "/org/freedesktop/systemd1",
774 "org.freedesktop.systemd1.Manager",
775 "StartTransientUnit");
776 if (r < 0)
777 return bus_log_create_error(r);
778
779 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
780 if (r < 0)
781 return bus_log_create_error(r);
782
783 /* Name and mode */
784 r = sd_bus_message_append(m, "ss", service, "fail");
785 if (r < 0)
786 return bus_log_create_error(r);
787
788 /* Properties */
789 r = sd_bus_message_open_container(m, 'a', "(sv)");
790 if (r < 0)
791 return bus_log_create_error(r);
792
793 r = transient_service_set_properties(m, argv, pty_path);
794 if (r < 0)
795 return bus_log_create_error(r);
796
797 r = sd_bus_message_close_container(m);
798 if (r < 0)
799 return bus_log_create_error(r);
800
801 /* Auxiliary units */
802 r = sd_bus_message_append(m, "a(sa(sv))", 0);
803 if (r < 0)
804 return bus_log_create_error(r);
805
806 polkit_agent_open_if_enabled();
807
808 r = sd_bus_call(bus, m, 0, &error, &reply);
809 if (r < 0)
810 return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
811
812 if (w) {
813 const char *object;
814
815 r = sd_bus_message_read(reply, "o", &object);
816 if (r < 0)
817 return bus_log_parse_error(r);
818
819 r = bus_wait_for_jobs_one(w, object, arg_quiet);
820 if (r < 0)
821 return r;
822 }
823
824 if (master >= 0) {
825 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
826 _cleanup_event_unref_ sd_event *event = NULL;
827 char last_char = 0;
828
829 r = sd_event_default(&event);
830 if (r < 0)
831 return log_error_errno(r, "Failed to get event loop: %m");
832
833 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
834
835 (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
836 (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
837
838 if (!arg_quiet)
839 log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
840
841 r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward);
842 if (r < 0)
843 return log_error_errno(r, "Failed to create PTY forwarder: %m");
844
845 r = sd_event_loop(event);
846 if (r < 0)
847 return log_error_errno(r, "Failed to run event loop: %m");
848
849 pty_forward_get_last_char(forward, &last_char);
850
851 forward = pty_forward_free(forward);
852
853 if (!arg_quiet && last_char != '\n')
854 fputc('\n', stdout);
855
856 } else if (!arg_quiet)
857 log_info("Running as unit %s.", service);
858
859 return 0;
860 }
861
862 static int start_transient_scope(
863 sd_bus *bus,
864 char **argv) {
865
866 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
867 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
868 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
869 _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
870 _cleanup_free_ char *scope = NULL;
871 const char *object = NULL;
872 int r;
873
874 assert(bus);
875 assert(argv);
876
877 r = bus_wait_for_jobs_new(bus, &w);
878 if (r < 0)
879 return log_oom();
880
881 if (arg_unit) {
882 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
883 if (r < 0)
884 return log_error_errno(r, "Failed to mangle scope name: %m");
885 } else if (asprintf(&scope, "run-"PID_FMT".scope", getpid()) < 0)
886 return log_oom();
887
888 r = sd_bus_message_new_method_call(
889 bus,
890 &m,
891 "org.freedesktop.systemd1",
892 "/org/freedesktop/systemd1",
893 "org.freedesktop.systemd1.Manager",
894 "StartTransientUnit");
895 if (r < 0)
896 return bus_log_create_error(r);
897
898 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
899 if (r < 0)
900 return bus_log_create_error(r);
901
902 /* Name and Mode */
903 r = sd_bus_message_append(m, "ss", scope, "fail");
904 if (r < 0)
905 return bus_log_create_error(r);
906
907 /* Properties */
908 r = sd_bus_message_open_container(m, 'a', "(sv)");
909 if (r < 0)
910 return bus_log_create_error(r);
911
912 r = transient_scope_set_properties(m);
913 if (r < 0)
914 return bus_log_create_error(r);
915
916 r = sd_bus_message_close_container(m);
917 if (r < 0)
918 return bus_log_create_error(r);
919
920 /* Auxiliary units */
921 r = sd_bus_message_append(m, "a(sa(sv))", 0);
922 if (r < 0)
923 return bus_log_create_error(r);
924
925 polkit_agent_open_if_enabled();
926
927 r = sd_bus_call(bus, m, 0, &error, &reply);
928 if (r < 0) {
929 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
930 return r;
931 }
932
933 if (arg_nice_set) {
934 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
935 return log_error_errno(errno, "Failed to set nice level: %m");
936 }
937
938 if (arg_exec_group) {
939 gid_t gid;
940
941 r = get_group_creds(&arg_exec_group, &gid);
942 if (r < 0)
943 return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
944
945 if (setresgid(gid, gid, gid) < 0)
946 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
947 }
948
949 if (arg_exec_user) {
950 const char *home, *shell;
951 uid_t uid;
952 gid_t gid;
953
954 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
955 if (r < 0)
956 return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
957
958 r = strv_extendf(&user_env, "HOME=%s", home);
959 if (r < 0)
960 return log_oom();
961
962 r = strv_extendf(&user_env, "SHELL=%s", shell);
963 if (r < 0)
964 return log_oom();
965
966 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
967 if (r < 0)
968 return log_oom();
969
970 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
971 if (r < 0)
972 return log_oom();
973
974 if (!arg_exec_group) {
975 if (setresgid(gid, gid, gid) < 0)
976 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
977 }
978
979 if (setresuid(uid, uid, uid) < 0)
980 return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
981 }
982
983 env = strv_env_merge(3, environ, user_env, arg_environment);
984 if (!env)
985 return log_oom();
986
987 r = sd_bus_message_read(reply, "o", &object);
988 if (r < 0)
989 return bus_log_parse_error(r);
990
991 r = bus_wait_for_jobs_one(w, object, arg_quiet);
992 if (r < 0)
993 return r;
994
995 if (!arg_quiet)
996 log_info("Running scope as unit %s.", scope);
997
998 execvpe(argv[0], argv, env);
999
1000 return log_error_errno(errno, "Failed to execute: %m");
1001 }
1002
1003 static int start_transient_timer(
1004 sd_bus *bus,
1005 char **argv) {
1006
1007 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1008 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1009 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1010 _cleanup_free_ char *timer = NULL, *service = NULL;
1011 const char *object = NULL;
1012 int r;
1013
1014 assert(bus);
1015 assert(argv);
1016
1017 r = bus_wait_for_jobs_new(bus, &w);
1018 if (r < 0)
1019 return log_oom();
1020
1021 if (arg_unit) {
1022 switch (unit_name_to_type(arg_unit)) {
1023
1024 case UNIT_SERVICE:
1025 service = strdup(arg_unit);
1026 if (!service)
1027 return log_oom();
1028
1029 r = unit_name_change_suffix(service, ".timer", &timer);
1030 if (r < 0)
1031 return log_error_errno(r, "Failed to change unit suffix: %m");
1032 break;
1033
1034 case UNIT_TIMER:
1035 timer = strdup(arg_unit);
1036 if (!timer)
1037 return log_oom();
1038
1039 r = unit_name_change_suffix(timer, ".service", &service);
1040 if (r < 0)
1041 return log_error_errno(r, "Failed to change unit suffix: %m");
1042 break;
1043
1044 default:
1045 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
1046 if (r < 0)
1047 return log_error_errno(r, "Failed to mangle unit name: %m");
1048
1049 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
1050 if (r < 0)
1051 return log_error_errno(r, "Failed to mangle unit name: %m");
1052
1053 break;
1054 }
1055 } else if ((asprintf(&service, "run-"PID_FMT".service", getpid()) < 0) ||
1056 (asprintf(&timer, "run-"PID_FMT".timer", getpid()) < 0))
1057 return log_oom();
1058
1059 r = sd_bus_message_new_method_call(
1060 bus,
1061 &m,
1062 "org.freedesktop.systemd1",
1063 "/org/freedesktop/systemd1",
1064 "org.freedesktop.systemd1.Manager",
1065 "StartTransientUnit");
1066 if (r < 0)
1067 return bus_log_create_error(r);
1068
1069 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1070 if (r < 0)
1071 return bus_log_create_error(r);
1072
1073 /* Name and Mode */
1074 r = sd_bus_message_append(m, "ss", timer, "fail");
1075 if (r < 0)
1076 return bus_log_create_error(r);
1077
1078 /* Properties */
1079 r = sd_bus_message_open_container(m, 'a', "(sv)");
1080 if (r < 0)
1081 return bus_log_create_error(r);
1082
1083 r = transient_timer_set_properties(m);
1084 if (r < 0)
1085 return bus_log_create_error(r);
1086
1087 r = sd_bus_message_close_container(m);
1088 if (r < 0)
1089 return bus_log_create_error(r);
1090
1091 r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1092 if (r < 0)
1093 return bus_log_create_error(r);
1094
1095 if (argv[0]) {
1096 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1097 if (r < 0)
1098 return bus_log_create_error(r);
1099
1100 r = sd_bus_message_append(m, "s", service);
1101 if (r < 0)
1102 return bus_log_create_error(r);
1103
1104 r = sd_bus_message_open_container(m, 'a', "(sv)");
1105 if (r < 0)
1106 return bus_log_create_error(r);
1107
1108 r = transient_service_set_properties(m, argv, NULL);
1109 if (r < 0)
1110 return bus_log_create_error(r);
1111
1112 r = sd_bus_message_close_container(m);
1113 if (r < 0)
1114 return bus_log_create_error(r);
1115
1116 r = sd_bus_message_close_container(m);
1117 if (r < 0)
1118 return bus_log_create_error(r);
1119 }
1120
1121 r = sd_bus_message_close_container(m);
1122 if (r < 0)
1123 return bus_log_create_error(r);
1124
1125 polkit_agent_open_if_enabled();
1126
1127 r = sd_bus_call(bus, m, 0, &error, &reply);
1128 if (r < 0) {
1129 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
1130 return r;
1131 }
1132
1133 r = sd_bus_message_read(reply, "o", &object);
1134 if (r < 0)
1135 return bus_log_parse_error(r);
1136
1137 r = bus_wait_for_jobs_one(w, object, arg_quiet);
1138 if (r < 0)
1139 return r;
1140
1141 log_info("Running timer as unit %s.", timer);
1142 if (argv[0])
1143 log_info("Will run service as unit %s.", service);
1144
1145 return 0;
1146 }
1147
1148 int main(int argc, char* argv[]) {
1149 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1150 _cleanup_free_ char *description = NULL, *command = NULL;
1151 int r;
1152
1153 log_parse_environment();
1154 log_open();
1155
1156 r = parse_argv(argc, argv);
1157 if (r <= 0)
1158 goto finish;
1159
1160 if (argc > optind && arg_transport == BUS_TRANSPORT_LOCAL) {
1161 /* Patch in an absolute path */
1162
1163 r = find_binary(argv[optind], &command);
1164 if (r < 0) {
1165 log_error_errno(r, "Failed to find executable %s: %m", argv[optind]);
1166 goto finish;
1167 }
1168
1169 argv[optind] = command;
1170 }
1171
1172 if (!arg_description) {
1173 description = strv_join(argv + optind, " ");
1174 if (!description) {
1175 r = log_oom();
1176 goto finish;
1177 }
1178
1179 if (arg_unit && isempty(description)) {
1180 r = free_and_strdup(&description, arg_unit);
1181 if (r < 0)
1182 goto finish;
1183 }
1184
1185 arg_description = description;
1186 }
1187
1188 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1189 if (r < 0) {
1190 log_error_errno(r, "Failed to create bus connection: %m");
1191 goto finish;
1192 }
1193
1194 if (arg_scope)
1195 r = start_transient_scope(bus, argv + optind);
1196 else if (with_timer())
1197 r = start_transient_timer(bus, argv + optind);
1198 else
1199 r = start_transient_service(bus, argv + optind);
1200
1201 finish:
1202 strv_free(arg_environment);
1203 strv_free(arg_property);
1204 strv_free(arg_timer_property);
1205
1206 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1207 }