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