chiark / gitweb /
723e0cb31a090f8b64ae1f86c937ef23a16e2740
[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=SECONDS          Run after SECONDS delay\n"
90                "     --on-boot=SECONDS            Run SECONDS after machine was booted up\n"
91                "     --on-startup=SECONDS         Run SECONDS after systemd activation\n"
92                "     --on-unit-active=SECONDS     Run SECONDS after the last activation\n"
93                "     --on-unit-inactive=SECONDS   Run SECONDS after 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_MACHINE;
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         assert(m);
427
428         if (arg_send_sighup)
429                 return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
430         else
431                 return 0;
432 }
433
434 static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
435         int r;
436
437         assert(m);
438
439         r = transient_unit_set_properties(m, arg_property);
440         if (r < 0)
441                 return r;
442
443         r = transient_kill_set_properties(m);
444         if (r < 0)
445                 return r;
446
447         r = transient_cgroup_set_properties(m);
448         if (r < 0)
449                 return r;
450
451         if (arg_remain_after_exit) {
452                 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
453                 if (r < 0)
454                         return r;
455         }
456
457         if (arg_service_type) {
458                 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
459                 if (r < 0)
460                         return r;
461         }
462
463         if (arg_exec_user) {
464                 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
465                 if (r < 0)
466                         return r;
467         }
468
469         if (arg_exec_group) {
470                 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
471                 if (r < 0)
472                         return r;
473         }
474
475         if (arg_nice_set) {
476                 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
477                 if (r < 0)
478                         return r;
479         }
480
481         if (pty_path) {
482                 const char *e;
483
484                 r = sd_bus_message_append(m,
485                                           "(sv)(sv)(sv)(sv)",
486                                           "StandardInput", "s", "tty",
487                                           "StandardOutput", "s", "tty",
488                                           "StandardError", "s", "tty",
489                                           "TTYPath", "s", pty_path);
490                 if (r < 0)
491                         return r;
492
493                 e = getenv("TERM");
494                 if (e) {
495                         char *n;
496
497                         n = strappenda("TERM=", e);
498                         r = sd_bus_message_append(m,
499                                                   "(sv)",
500                                                   "Environment", "as", 1, n);
501                         if (r < 0)
502                                 return r;
503                 }
504         }
505
506         if (!strv_isempty(arg_environment)) {
507                 r = sd_bus_message_open_container(m, 'r', "sv");
508                 if (r < 0)
509                         return r;
510
511                 r = sd_bus_message_append(m, "s", "Environment");
512                 if (r < 0)
513                         return r;
514
515                 r = sd_bus_message_open_container(m, 'v', "as");
516                 if (r < 0)
517                         return r;
518
519                 r = sd_bus_message_append_strv(m, arg_environment);
520                 if (r < 0)
521                         return r;
522
523                 r = sd_bus_message_close_container(m);
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
532         /* Exec container */
533         {
534                 r = sd_bus_message_open_container(m, 'r', "sv");
535                 if (r < 0)
536                         return r;
537
538                 r = sd_bus_message_append(m, "s", "ExecStart");
539                 if (r < 0)
540                         return r;
541
542                 r = sd_bus_message_open_container(m, 'v', "a(sasb)");
543                 if (r < 0)
544                         return r;
545
546                 r = sd_bus_message_open_container(m, 'a', "(sasb)");
547                 if (r < 0)
548                         return r;
549
550                 r = sd_bus_message_open_container(m, 'r', "sasb");
551                 if (r < 0)
552                         return r;
553
554                 r = sd_bus_message_append(m, "s", argv[0]);
555                 if (r < 0)
556                         return r;
557
558                 r = sd_bus_message_append_strv(m, argv);
559                 if (r < 0)
560                         return r;
561
562                 r = sd_bus_message_append(m, "b", false);
563                 if (r < 0)
564                         return r;
565
566                 r = sd_bus_message_close_container(m);
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
583         return 0;
584 }
585
586 static int transient_scope_set_properties(sd_bus_message *m) {
587         int r;
588
589         assert(m);
590
591         r = transient_unit_set_properties(m, arg_property);
592         if (r < 0)
593                 return r;
594
595         r = transient_kill_set_properties(m);
596         if (r < 0)
597                 return r;
598
599         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
600         if (r < 0)
601                 return r;
602
603         return 0;
604 }
605
606 static int transient_timer_set_properties(sd_bus_message *m) {
607         int r;
608
609         assert(m);
610
611         r = transient_unit_set_properties(m, arg_timer_property);
612         if (r < 0)
613                 return r;
614
615         if (arg_on_active) {
616                 r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
617                 if (r < 0)
618                         return r;
619         }
620
621         if (arg_on_boot) {
622                 r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
623                 if (r < 0)
624                         return r;
625         }
626
627         if (arg_on_startup) {
628                 r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
629                 if (r < 0)
630                         return r;
631         }
632
633         if (arg_on_unit_active) {
634                 r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
635                 if (r < 0)
636                         return r;
637         }
638
639         if (arg_on_unit_inactive) {
640                 r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
641                 if (r < 0)
642                         return r;
643         }
644
645         if (arg_on_calendar) {
646                 r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
647                 if (r < 0)
648                         return r;
649         }
650
651         return 0;
652 }
653
654 static int start_transient_service(
655                 sd_bus *bus,
656                 char **argv) {
657
658         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
659         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
660         _cleanup_free_ char *service = NULL, *pty_path = NULL;
661         _cleanup_close_ int master = -1;
662         int r;
663
664         assert(bus);
665         assert(argv);
666
667         if (arg_pty) {
668
669                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
670                         master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
671                         if (master < 0)
672                                 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
673
674                         r = ptsname_malloc(master, &pty_path);
675                         if (r < 0)
676                                 return log_error_errno(r, "Failed to determine tty name: %m");
677
678                 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
679                         _cleanup_bus_unref_ sd_bus *system_bus = NULL;
680                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
681                         const char *s;
682
683                         r = sd_bus_open_system(&system_bus);
684                         if (r < 0)
685                                 log_error_errno(r, "Failed to connect to system bus: %m");
686
687                         r = sd_bus_call_method(system_bus,
688                                                "org.freedesktop.machine1",
689                                                "/org/freedesktop/machine1",
690                                                "org.freedesktop.machine1.Manager",
691                                                "OpenMachinePTY",
692                                                &error,
693                                                &reply,
694                                                "s", arg_host);
695                         if (r < 0) {
696                                 log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
697                                 return r;
698                         }
699
700                         r = sd_bus_message_read(reply, "hs", &master, &s);
701                         if (r < 0)
702                                 return bus_log_parse_error(r);
703
704                         master = fcntl(master, F_DUPFD_CLOEXEC, 3);
705                         if (master < 0)
706                                 return log_error_errno(errno, "Failed to duplicate master fd: %m");
707
708                         pty_path = strdup(s);
709                         if (!pty_path)
710                                 return log_oom();
711                 } else
712                         assert_not_reached("Can't allocate tty via ssh");
713
714                 if (unlockpt(master) < 0)
715                         return log_error_errno(errno, "Failed to unlock tty: %m");
716         }
717
718         if (arg_unit) {
719                 service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
720                 if (!service)
721                         return log_oom();
722         } else if (asprintf(&service, "run-"PID_FMT".service", getpid()) < 0)
723                 return log_oom();
724
725         r = sd_bus_message_new_method_call(
726                         bus,
727                         &m,
728                         "org.freedesktop.systemd1",
729                         "/org/freedesktop/systemd1",
730                         "org.freedesktop.systemd1.Manager",
731                         "StartTransientUnit");
732         if (r < 0)
733                 return bus_log_create_error(r);
734
735         /* Name and mode */
736         r = sd_bus_message_append(m, "ss", service, "fail");
737         if (r < 0)
738                 return bus_log_create_error(r);
739
740         /* Properties */
741         r = sd_bus_message_open_container(m, 'a', "(sv)");
742         if (r < 0)
743                 return bus_log_create_error(r);
744
745         r = transient_service_set_properties(m, argv, pty_path);
746         if (r < 0)
747                 return bus_log_create_error(r);
748
749         r = sd_bus_message_close_container(m);
750         if (r < 0)
751                 return bus_log_create_error(r);
752
753         /* Auxiliary units */
754         r = sd_bus_message_append(m, "a(sa(sv))", 0);
755         if (r < 0)
756                 return bus_log_create_error(r);
757
758         r = sd_bus_call(bus, m, 0, &error, NULL);
759         if (r < 0) {
760                 log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r));
761                 return r;
762         }
763
764         if (master >= 0) {
765                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
766                 _cleanup_event_unref_ sd_event *event = NULL;
767                 sigset_t mask;
768                 char last_char = 0;
769
770                 r = sd_event_default(&event);
771                 if (r < 0)
772                         return log_error_errno(r, "Failed to get event loop: %m");
773
774                 assert_se(sigemptyset(&mask) == 0);
775                 sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
776                 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
777
778                 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
779                 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
780
781                 if (!arg_quiet)
782                         log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
783
784                 r = pty_forward_new(event, master, false, &forward);
785                 if (r < 0)
786                         return log_error_errno(r, "Failed to create PTY forwarder: %m");
787
788                 r = sd_event_loop(event);
789                 if (r < 0)
790                         return log_error_errno(r, "Failed to run event loop: %m");
791
792                 pty_forward_get_last_char(forward, &last_char);
793
794                 forward = pty_forward_free(forward);
795
796                 if (!arg_quiet && last_char != '\n')
797                         fputc('\n', stdout);
798
799         } else if (!arg_quiet)
800                 log_info("Running as unit %s.", service);
801
802         return 0;
803 }
804
805 static int start_transient_scope(
806                 sd_bus *bus,
807                 char **argv) {
808
809         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
810         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
811         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
812         _cleanup_free_ char *scope = NULL;
813         int r;
814
815         assert(bus);
816         assert(argv);
817
818         if (arg_unit) {
819                 scope = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".scope");
820                 if (!scope)
821                         return log_oom();
822         } else if (asprintf(&scope, "run-"PID_FMT".scope", getpid()) < 0)
823                 return log_oom();
824
825         r = sd_bus_message_new_method_call(
826                         bus,
827                         &m,
828                         "org.freedesktop.systemd1",
829                         "/org/freedesktop/systemd1",
830                         "org.freedesktop.systemd1.Manager",
831                         "StartTransientUnit");
832         if (r < 0)
833                 return bus_log_create_error(r);
834
835         /* Name and Mode */
836         r = sd_bus_message_append(m, "ss", scope, "fail");
837         if (r < 0)
838                 return bus_log_create_error(r);
839
840         /* Properties */
841         r = sd_bus_message_open_container(m, 'a', "(sv)");
842         if (r < 0)
843                 return bus_log_create_error(r);
844
845         r = transient_scope_set_properties(m);
846         if (r < 0)
847                 return bus_log_create_error(r);
848
849         r = sd_bus_message_close_container(m);
850         if (r < 0)
851                 return bus_log_create_error(r);
852
853         /* Auxiliary units */
854         r = sd_bus_message_append(m, "a(sa(sv))", 0);
855         if (r < 0)
856                 return bus_log_create_error(r);
857
858         r = sd_bus_call(bus, m, 0, &error, NULL);
859         if (r < 0) {
860                 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
861                 return r;
862         }
863
864         if (arg_nice_set) {
865                 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
866                         return log_error_errno(errno, "Failed to set nice level: %m");
867         }
868
869         if (arg_exec_group) {
870                 gid_t gid;
871
872                 r = get_group_creds(&arg_exec_group, &gid);
873                 if (r < 0)
874                         return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
875
876                 if (setresgid(gid, gid, gid) < 0)
877                         return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
878         }
879
880         if (arg_exec_user) {
881                 const char *home, *shell;
882                 uid_t uid;
883                 gid_t gid;
884
885                 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
886                 if (r < 0)
887                         return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
888
889                 r = strv_extendf(&user_env, "HOME=%s", home);
890                 if (r < 0)
891                         return log_oom();
892
893                 r = strv_extendf(&user_env, "SHELL=%s", shell);
894                 if (r < 0)
895                         return log_oom();
896
897                 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
898                 if (r < 0)
899                         return log_oom();
900
901                 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
902                 if (r < 0)
903                         return log_oom();
904
905                 if (!arg_exec_group) {
906                         if (setresgid(gid, gid, gid) < 0)
907                                 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
908                 }
909
910                 if (setresuid(uid, uid, uid) < 0)
911                         return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
912         }
913
914         env = strv_env_merge(3, environ, user_env, arg_environment);
915         if (!env)
916                 return log_oom();
917
918         if (!arg_quiet)
919                 log_info("Running as unit %s.", scope);
920
921         execvpe(argv[0], argv, env);
922
923         return log_error_errno(errno, "Failed to execute: %m");
924 }
925
926 static int start_transient_timer(
927                 sd_bus *bus,
928                 char **argv) {
929
930         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
931         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
932         _cleanup_free_ char *timer = NULL, *service = NULL;
933         int r;
934
935         assert(bus);
936         assert(argv);
937
938         if (arg_unit) {
939                 switch(unit_name_to_type(arg_unit)) {
940
941                 case UNIT_SERVICE:
942                         service = strdup(arg_unit);
943                         if (!service)
944                                 return log_oom();
945
946                         timer = unit_name_change_suffix(service, ".timer");
947                         if (!timer)
948                                 return log_oom();
949                         break;
950
951                 case UNIT_TIMER:
952                         timer = strdup(arg_unit);
953                         if (!timer)
954                                 return log_oom();
955
956                         service = unit_name_change_suffix(timer, ".service");
957                         if (!service)
958                                 return log_oom();
959                         break;
960
961                 default:
962                         service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
963                         if (!service)
964                                 return log_oom();
965
966                         timer = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".timer");
967                         if (!timer)
968                                 return log_oom();
969
970                         break;
971                 }
972         } else if ((asprintf(&service, "run-"PID_FMT".service", getpid()) < 0) ||
973                    (asprintf(&timer, "run-"PID_FMT".timer", getpid()) < 0))
974                 return log_oom();
975
976         r = sd_bus_message_new_method_call(
977                         bus,
978                         &m,
979                         "org.freedesktop.systemd1",
980                         "/org/freedesktop/systemd1",
981                         "org.freedesktop.systemd1.Manager",
982                         "StartTransientUnit");
983         if (r < 0)
984                 return bus_log_create_error(r);
985
986         /* Name and Mode */
987         r = sd_bus_message_append(m, "ss", timer, "fail");
988         if (r < 0)
989                 return bus_log_create_error(r);
990
991         /* Properties */
992         r = sd_bus_message_open_container(m, 'a', "(sv)");
993         if (r < 0)
994                 return bus_log_create_error(r);
995
996         r = transient_timer_set_properties(m);
997         if (r < 0)
998                 return bus_log_create_error(r);
999
1000         r = sd_bus_message_close_container(m);
1001         if (r < 0)
1002                 return bus_log_create_error(r);
1003
1004         r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1005         if (r < 0)
1006                 return bus_log_create_error(r);
1007
1008         if (argv[0]) {
1009                 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1010                 if (r < 0)
1011                         return bus_log_create_error(r);
1012
1013                 r = sd_bus_message_append(m, "s", service);
1014                 if (r < 0)
1015                         return bus_log_create_error(r);
1016
1017                 r = sd_bus_message_open_container(m, 'a', "(sv)");
1018                 if (r < 0)
1019                         return bus_log_create_error(r);
1020
1021                 r = transient_service_set_properties(m, argv, NULL);
1022                 if (r < 0)
1023                         return bus_log_create_error(r);
1024
1025                 r = sd_bus_message_close_container(m);
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
1034         r = sd_bus_message_close_container(m);
1035         if (r < 0)
1036                 return bus_log_create_error(r);
1037
1038         r = sd_bus_call(bus, m, 0, &error, NULL);
1039         if (r < 0) {
1040                 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
1041                 return r;
1042         }
1043
1044         log_info("Running as unit %s.", timer);
1045         if (argv[0])
1046                 log_info("Will run as unit %s.", service);
1047
1048         return 0;
1049 }
1050
1051 int main(int argc, char* argv[]) {
1052         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1053         _cleanup_free_ char *description = NULL, *command = NULL;
1054         int r;
1055
1056         log_parse_environment();
1057         log_open();
1058
1059         r = parse_argv(argc, argv);
1060         if (r <= 0)
1061                 goto finish;
1062
1063         if (argc > optind) {
1064                 r = find_binary(argv[optind], arg_transport == BUS_TRANSPORT_LOCAL, &command);
1065                 if (r < 0) {
1066                         log_error_errno(r, "Failed to find executable %s%s: %m",
1067                                         argv[optind],
1068                                         arg_transport == BUS_TRANSPORT_LOCAL ? "" : " on local system");
1069                         goto finish;
1070                 }
1071                 argv[optind] = command;
1072         }
1073
1074         if (!arg_description) {
1075                 description = strv_join(argv + optind, " ");
1076                 if (!description) {
1077                         r = log_oom();
1078                         goto finish;
1079                 }
1080
1081                 if (arg_unit && isempty(description)) {
1082                         free(description);
1083                         description = strdup(arg_unit);
1084
1085                         if (!description) {
1086                                 r = log_oom();
1087                                 goto finish;
1088                         }
1089                 }
1090
1091                 arg_description = description;
1092         }
1093
1094         r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1095         if (r < 0) {
1096                 log_error_errno(r, "Failed to create bus connection: %m");
1097                 goto finish;
1098         }
1099
1100         if (arg_scope)
1101                 r = start_transient_scope(bus, argv + optind);
1102         else if (with_timer())
1103                 r = start_transient_timer(bus, argv + optind);
1104         else
1105                 r = start_transient_service(bus, argv + optind);
1106
1107 finish:
1108         strv_free(arg_environment);
1109         strv_free(arg_property);
1110         strv_free(arg_timer_property);
1111
1112         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1113 }