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