]> git.proxmox.com Git - systemd.git/blob - src/run/run.c
Enable seccomp support on powerpc, ppc64el, and s390x
[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 "parse-util.h"
37 #include "path-util.h"
38 #include "ptyfwd.h"
39 #include "signal-util.h"
40 #include "spawn-polkit-agent.h"
41 #include "strv.h"
42 #include "terminal-util.h"
43 #include "unit-name.h"
44 #include "user-util.h"
45
46 static bool arg_ask_password = true;
47 static bool arg_scope = false;
48 static bool arg_remain_after_exit = false;
49 static bool arg_no_block = false;
50 static 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 /* Automatically clean up our transient timers */
652 r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
653 if (r < 0)
654 return r;
655
656 if (arg_on_active) {
657 r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
658 if (r < 0)
659 return r;
660 }
661
662 if (arg_on_boot) {
663 r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
664 if (r < 0)
665 return r;
666 }
667
668 if (arg_on_startup) {
669 r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
670 if (r < 0)
671 return r;
672 }
673
674 if (arg_on_unit_active) {
675 r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
676 if (r < 0)
677 return r;
678 }
679
680 if (arg_on_unit_inactive) {
681 r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
682 if (r < 0)
683 return r;
684 }
685
686 if (arg_on_calendar) {
687 r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
688 if (r < 0)
689 return r;
690 }
691
692 return 0;
693 }
694
695 static int make_unit_name(sd_bus *bus, UnitType t, char **ret) {
696 const char *unique, *id;
697 char *p;
698 int r;
699
700 assert(bus);
701 assert(t >= 0);
702 assert(t < _UNIT_TYPE_MAX);
703
704 r = sd_bus_get_unique_name(bus, &unique);
705 if (r < 0) {
706 sd_id128_t rnd;
707
708 /* We couldn't get the unique name, which is a pretty
709 * common case if we are connected to systemd
710 * directly. In that case, just pick a random uuid as
711 * name */
712
713 r = sd_id128_randomize(&rnd);
714 if (r < 0)
715 return log_error_errno(r, "Failed to generate random run unit name: %m");
716
717 if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0)
718 return log_oom();
719
720 return 0;
721 }
722
723 /* We managed to get the unique name, then let's use that to
724 * name our transient units. */
725
726 id = startswith(unique, ":1.");
727 if (!id) {
728 log_error("Unique name %s has unexpected format.", unique);
729 return -EINVAL;
730 }
731
732 p = strjoin("run-u", id, ".", unit_type_to_string(t), NULL);
733 if (!p)
734 return log_oom();
735
736 *ret = p;
737 return 0;
738 }
739
740 static int start_transient_service(
741 sd_bus *bus,
742 char **argv) {
743
744 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
745 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
746 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
747 _cleanup_free_ char *service = NULL, *pty_path = NULL;
748 _cleanup_close_ int master = -1;
749 int r;
750
751 assert(bus);
752 assert(argv);
753
754 if (arg_pty) {
755
756 if (arg_transport == BUS_TRANSPORT_LOCAL) {
757 master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
758 if (master < 0)
759 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
760
761 r = ptsname_malloc(master, &pty_path);
762 if (r < 0)
763 return log_error_errno(r, "Failed to determine tty name: %m");
764
765 if (unlockpt(master) < 0)
766 return log_error_errno(errno, "Failed to unlock tty: %m");
767
768 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
769 _cleanup_bus_unref_ sd_bus *system_bus = NULL;
770 const char *s;
771
772 r = sd_bus_default_system(&system_bus);
773 if (r < 0)
774 return log_error_errno(r, "Failed to connect to system bus: %m");
775
776 r = sd_bus_call_method(system_bus,
777 "org.freedesktop.machine1",
778 "/org/freedesktop/machine1",
779 "org.freedesktop.machine1.Manager",
780 "OpenMachinePTY",
781 &error,
782 &reply,
783 "s", arg_host);
784 if (r < 0) {
785 log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
786 return r;
787 }
788
789 r = sd_bus_message_read(reply, "hs", &master, &s);
790 if (r < 0)
791 return bus_log_parse_error(r);
792
793 reply = sd_bus_message_unref(reply);
794
795 master = fcntl(master, F_DUPFD_CLOEXEC, 3);
796 if (master < 0)
797 return log_error_errno(errno, "Failed to duplicate master fd: %m");
798
799 pty_path = strdup(s);
800 if (!pty_path)
801 return log_oom();
802 } else
803 assert_not_reached("Can't allocate tty via ssh");
804 }
805
806 if (!arg_no_block) {
807 r = bus_wait_for_jobs_new(bus, &w);
808 if (r < 0)
809 return log_error_errno(r, "Could not watch jobs: %m");
810 }
811
812 if (arg_unit) {
813 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
814 if (r < 0)
815 return log_error_errno(r, "Failed to mangle unit name: %m");
816 } else {
817 r = make_unit_name(bus, UNIT_SERVICE, &service);
818 if (r < 0)
819 return r;
820 }
821
822 r = sd_bus_message_new_method_call(
823 bus,
824 &m,
825 "org.freedesktop.systemd1",
826 "/org/freedesktop/systemd1",
827 "org.freedesktop.systemd1.Manager",
828 "StartTransientUnit");
829 if (r < 0)
830 return bus_log_create_error(r);
831
832 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
833 if (r < 0)
834 return bus_log_create_error(r);
835
836 /* Name and mode */
837 r = sd_bus_message_append(m, "ss", service, "fail");
838 if (r < 0)
839 return bus_log_create_error(r);
840
841 /* Properties */
842 r = sd_bus_message_open_container(m, 'a', "(sv)");
843 if (r < 0)
844 return bus_log_create_error(r);
845
846 r = transient_service_set_properties(m, argv, pty_path);
847 if (r < 0)
848 return bus_log_create_error(r);
849
850 r = sd_bus_message_close_container(m);
851 if (r < 0)
852 return bus_log_create_error(r);
853
854 /* Auxiliary units */
855 r = sd_bus_message_append(m, "a(sa(sv))", 0);
856 if (r < 0)
857 return bus_log_create_error(r);
858
859 polkit_agent_open_if_enabled();
860
861 r = sd_bus_call(bus, m, 0, &error, &reply);
862 if (r < 0)
863 return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
864
865 if (w) {
866 const char *object;
867
868 r = sd_bus_message_read(reply, "o", &object);
869 if (r < 0)
870 return bus_log_parse_error(r);
871
872 r = bus_wait_for_jobs_one(w, object, arg_quiet);
873 if (r < 0)
874 return r;
875 }
876
877 if (master >= 0) {
878 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
879 _cleanup_event_unref_ sd_event *event = NULL;
880 char last_char = 0;
881
882 r = sd_event_default(&event);
883 if (r < 0)
884 return log_error_errno(r, "Failed to get event loop: %m");
885
886 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
887
888 (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
889 (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
890
891 if (!arg_quiet)
892 log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
893
894 r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward);
895 if (r < 0)
896 return log_error_errno(r, "Failed to create PTY forwarder: %m");
897
898 r = sd_event_loop(event);
899 if (r < 0)
900 return log_error_errno(r, "Failed to run event loop: %m");
901
902 pty_forward_get_last_char(forward, &last_char);
903
904 forward = pty_forward_free(forward);
905
906 if (!arg_quiet && last_char != '\n')
907 fputc('\n', stdout);
908
909 } else if (!arg_quiet)
910 log_info("Running as unit %s.", service);
911
912 return 0;
913 }
914
915 static int start_transient_scope(
916 sd_bus *bus,
917 char **argv) {
918
919 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
920 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
921 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
922 _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
923 _cleanup_free_ char *scope = NULL;
924 const char *object = NULL;
925 int r;
926
927 assert(bus);
928 assert(argv);
929
930 r = bus_wait_for_jobs_new(bus, &w);
931 if (r < 0)
932 return log_oom();
933
934 if (arg_unit) {
935 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
936 if (r < 0)
937 return log_error_errno(r, "Failed to mangle scope name: %m");
938 } else {
939 r = make_unit_name(bus, UNIT_SCOPE, &scope);
940 if (r < 0)
941 return r;
942 }
943
944 r = sd_bus_message_new_method_call(
945 bus,
946 &m,
947 "org.freedesktop.systemd1",
948 "/org/freedesktop/systemd1",
949 "org.freedesktop.systemd1.Manager",
950 "StartTransientUnit");
951 if (r < 0)
952 return bus_log_create_error(r);
953
954 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
955 if (r < 0)
956 return bus_log_create_error(r);
957
958 /* Name and Mode */
959 r = sd_bus_message_append(m, "ss", scope, "fail");
960 if (r < 0)
961 return bus_log_create_error(r);
962
963 /* Properties */
964 r = sd_bus_message_open_container(m, 'a', "(sv)");
965 if (r < 0)
966 return bus_log_create_error(r);
967
968 r = transient_scope_set_properties(m);
969 if (r < 0)
970 return bus_log_create_error(r);
971
972 r = sd_bus_message_close_container(m);
973 if (r < 0)
974 return bus_log_create_error(r);
975
976 /* Auxiliary units */
977 r = sd_bus_message_append(m, "a(sa(sv))", 0);
978 if (r < 0)
979 return bus_log_create_error(r);
980
981 polkit_agent_open_if_enabled();
982
983 r = sd_bus_call(bus, m, 0, &error, &reply);
984 if (r < 0) {
985 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
986 return r;
987 }
988
989 if (arg_nice_set) {
990 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
991 return log_error_errno(errno, "Failed to set nice level: %m");
992 }
993
994 if (arg_exec_group) {
995 gid_t gid;
996
997 r = get_group_creds(&arg_exec_group, &gid);
998 if (r < 0)
999 return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
1000
1001 if (setresgid(gid, gid, gid) < 0)
1002 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1003 }
1004
1005 if (arg_exec_user) {
1006 const char *home, *shell;
1007 uid_t uid;
1008 gid_t gid;
1009
1010 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
1011 if (r < 0)
1012 return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
1013
1014 r = strv_extendf(&user_env, "HOME=%s", home);
1015 if (r < 0)
1016 return log_oom();
1017
1018 r = strv_extendf(&user_env, "SHELL=%s", shell);
1019 if (r < 0)
1020 return log_oom();
1021
1022 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
1023 if (r < 0)
1024 return log_oom();
1025
1026 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
1027 if (r < 0)
1028 return log_oom();
1029
1030 if (!arg_exec_group) {
1031 if (setresgid(gid, gid, gid) < 0)
1032 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1033 }
1034
1035 if (setresuid(uid, uid, uid) < 0)
1036 return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
1037 }
1038
1039 env = strv_env_merge(3, environ, user_env, arg_environment);
1040 if (!env)
1041 return log_oom();
1042
1043 r = sd_bus_message_read(reply, "o", &object);
1044 if (r < 0)
1045 return bus_log_parse_error(r);
1046
1047 r = bus_wait_for_jobs_one(w, object, arg_quiet);
1048 if (r < 0)
1049 return r;
1050
1051 if (!arg_quiet)
1052 log_info("Running scope as unit %s.", scope);
1053
1054 execvpe(argv[0], argv, env);
1055
1056 return log_error_errno(errno, "Failed to execute: %m");
1057 }
1058
1059 static int start_transient_timer(
1060 sd_bus *bus,
1061 char **argv) {
1062
1063 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1064 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1065 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1066 _cleanup_free_ char *timer = NULL, *service = NULL;
1067 const char *object = NULL;
1068 int r;
1069
1070 assert(bus);
1071 assert(argv);
1072
1073 r = bus_wait_for_jobs_new(bus, &w);
1074 if (r < 0)
1075 return log_oom();
1076
1077 if (arg_unit) {
1078 switch (unit_name_to_type(arg_unit)) {
1079
1080 case UNIT_SERVICE:
1081 service = strdup(arg_unit);
1082 if (!service)
1083 return log_oom();
1084
1085 r = unit_name_change_suffix(service, ".timer", &timer);
1086 if (r < 0)
1087 return log_error_errno(r, "Failed to change unit suffix: %m");
1088 break;
1089
1090 case UNIT_TIMER:
1091 timer = strdup(arg_unit);
1092 if (!timer)
1093 return log_oom();
1094
1095 r = unit_name_change_suffix(timer, ".service", &service);
1096 if (r < 0)
1097 return log_error_errno(r, "Failed to change unit suffix: %m");
1098 break;
1099
1100 default:
1101 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
1102 if (r < 0)
1103 return log_error_errno(r, "Failed to mangle unit name: %m");
1104
1105 r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
1106 if (r < 0)
1107 return log_error_errno(r, "Failed to mangle unit name: %m");
1108
1109 break;
1110 }
1111 } else {
1112 r = make_unit_name(bus, UNIT_SERVICE, &service);
1113 if (r < 0)
1114 return r;
1115
1116 r = unit_name_change_suffix(service, ".timer", &timer);
1117 if (r < 0)
1118 return log_error_errno(r, "Failed to change unit suffix: %m");
1119 }
1120
1121 r = sd_bus_message_new_method_call(
1122 bus,
1123 &m,
1124 "org.freedesktop.systemd1",
1125 "/org/freedesktop/systemd1",
1126 "org.freedesktop.systemd1.Manager",
1127 "StartTransientUnit");
1128 if (r < 0)
1129 return bus_log_create_error(r);
1130
1131 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1132 if (r < 0)
1133 return bus_log_create_error(r);
1134
1135 /* Name and Mode */
1136 r = sd_bus_message_append(m, "ss", timer, "fail");
1137 if (r < 0)
1138 return bus_log_create_error(r);
1139
1140 /* Properties */
1141 r = sd_bus_message_open_container(m, 'a', "(sv)");
1142 if (r < 0)
1143 return bus_log_create_error(r);
1144
1145 r = transient_timer_set_properties(m);
1146 if (r < 0)
1147 return bus_log_create_error(r);
1148
1149 r = sd_bus_message_close_container(m);
1150 if (r < 0)
1151 return bus_log_create_error(r);
1152
1153 r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1154 if (r < 0)
1155 return bus_log_create_error(r);
1156
1157 if (argv[0]) {
1158 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1159 if (r < 0)
1160 return bus_log_create_error(r);
1161
1162 r = sd_bus_message_append(m, "s", service);
1163 if (r < 0)
1164 return bus_log_create_error(r);
1165
1166 r = sd_bus_message_open_container(m, 'a', "(sv)");
1167 if (r < 0)
1168 return bus_log_create_error(r);
1169
1170 r = transient_service_set_properties(m, argv, NULL);
1171 if (r < 0)
1172 return bus_log_create_error(r);
1173
1174 r = sd_bus_message_close_container(m);
1175 if (r < 0)
1176 return bus_log_create_error(r);
1177
1178 r = sd_bus_message_close_container(m);
1179 if (r < 0)
1180 return bus_log_create_error(r);
1181 }
1182
1183 r = sd_bus_message_close_container(m);
1184 if (r < 0)
1185 return bus_log_create_error(r);
1186
1187 polkit_agent_open_if_enabled();
1188
1189 r = sd_bus_call(bus, m, 0, &error, &reply);
1190 if (r < 0) {
1191 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
1192 return r;
1193 }
1194
1195 r = sd_bus_message_read(reply, "o", &object);
1196 if (r < 0)
1197 return bus_log_parse_error(r);
1198
1199 r = bus_wait_for_jobs_one(w, object, arg_quiet);
1200 if (r < 0)
1201 return r;
1202
1203 log_info("Running timer as unit %s.", timer);
1204 if (argv[0])
1205 log_info("Will run service as unit %s.", service);
1206
1207 return 0;
1208 }
1209
1210 int main(int argc, char* argv[]) {
1211 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
1212 _cleanup_free_ char *description = NULL, *command = NULL;
1213 int r;
1214
1215 log_parse_environment();
1216 log_open();
1217
1218 r = parse_argv(argc, argv);
1219 if (r <= 0)
1220 goto finish;
1221
1222 if (argc > optind && arg_transport == BUS_TRANSPORT_LOCAL) {
1223 /* Patch in an absolute path */
1224
1225 r = find_binary(argv[optind], &command);
1226 if (r < 0) {
1227 log_error_errno(r, "Failed to find executable %s: %m", argv[optind]);
1228 goto finish;
1229 }
1230
1231 argv[optind] = command;
1232 }
1233
1234 if (!arg_description) {
1235 description = strv_join(argv + optind, " ");
1236 if (!description) {
1237 r = log_oom();
1238 goto finish;
1239 }
1240
1241 if (arg_unit && isempty(description)) {
1242 r = free_and_strdup(&description, arg_unit);
1243 if (r < 0)
1244 goto finish;
1245 }
1246
1247 arg_description = description;
1248 }
1249
1250 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1251 if (r < 0) {
1252 log_error_errno(r, "Failed to create bus connection: %m");
1253 goto finish;
1254 }
1255
1256 if (arg_scope)
1257 r = start_transient_scope(bus, argv + optind);
1258 else if (with_timer())
1259 r = start_transient_timer(bus, argv + optind);
1260 else
1261 r = start_transient_service(bus, argv + optind);
1262
1263 finish:
1264 strv_free(arg_environment);
1265 strv_free(arg_property);
1266 strv_free(arg_timer_property);
1267
1268 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1269 }