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