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