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