chiark / gitweb /
32191a6ac0444643f69bf6eb740d39317ffb5bea
[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                         if (strv_extend(&arg_environment, optarg) < 0)
245                                 return log_oom();
246
247                         break;
248
249                 case 'p':
250                         if (strv_extend(&arg_property, optarg) < 0)
251                                 return log_oom();
252
253                         break;
254
255                 case 't':
256                         arg_pty = true;
257                         break;
258
259                 case 'q':
260                         arg_quiet = true;
261                         break;
262
263                 case ARG_ON_ACTIVE:
264
265                         r = parse_sec(optarg, &arg_on_active);
266                         if (r < 0) {
267                                 log_error("Failed to parse timer value: %s", optarg);
268                                 return r;
269                         }
270
271                         break;
272
273                 case ARG_ON_BOOT:
274
275                         r = parse_sec(optarg, &arg_on_boot);
276                         if (r < 0) {
277                                 log_error("Failed to parse timer value: %s", optarg);
278                                 return r;
279                         }
280
281                         break;
282
283                 case ARG_ON_STARTUP:
284
285                         r = parse_sec(optarg, &arg_on_startup);
286                         if (r < 0) {
287                                 log_error("Failed to parse timer value: %s", optarg);
288                                 return r;
289                         }
290
291                         break;
292
293                 case ARG_ON_UNIT_ACTIVE:
294
295                         r = parse_sec(optarg, &arg_on_unit_active);
296                         if (r < 0) {
297                                 log_error("Failed to parse timer value: %s", optarg);
298                                 return r;
299                         }
300
301                         break;
302
303                 case ARG_ON_UNIT_INACTIVE:
304
305                         r = parse_sec(optarg, &arg_on_unit_inactive);
306                         if (r < 0) {
307                                 log_error("Failed to parse timer value: %s", optarg);
308                                 return r;
309                         }
310
311                         break;
312
313                 case ARG_ON_CALENDAR:
314
315                         r = calendar_spec_from_string(optarg, &spec);
316                         if (r < 0) {
317                                 log_error("Invalid calendar spec: %s", optarg);
318                                 return r;
319                         }
320                         free(spec);
321                         arg_on_calendar = optarg;
322                         break;
323
324                 case ARG_TIMER_PROPERTY:
325
326                         if (strv_extend(&arg_timer_property, optarg) < 0)
327                                 return log_oom();
328
329                         break;
330
331                 case '?':
332                         return -EINVAL;
333
334                 default:
335                         assert_not_reached("Unhandled option");
336                 }
337
338         if ((optind >= argc) && (!arg_unit || !with_timer())) {
339                 log_error("Command line to execute required.");
340                 return -EINVAL;
341         }
342
343         if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
344                 log_error("Execution in user context is not supported on non-local systems.");
345                 return -EINVAL;
346         }
347
348         if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
349                 log_error("Scope execution is not supported on non-local systems.");
350                 return -EINVAL;
351         }
352
353         if (arg_scope && (arg_remain_after_exit || arg_service_type)) {
354                 log_error("--remain-after-exit and --service-type= are not supported in --scope mode.");
355                 return -EINVAL;
356         }
357
358         if (arg_pty && (with_timer() || arg_scope)) {
359                 log_error("--pty is not compatible in timer or --scope mode.");
360                 return -EINVAL;
361         }
362
363         if (arg_scope && with_timer()) {
364                 log_error("Timer options are not supported in --scope mode.");
365                 return -EINVAL;
366         }
367
368         if (arg_timer_property && !with_timer()) {
369                 log_error("--timer-property= has no effect without any other timer options.");
370                 return -EINVAL;
371         }
372
373         return 1;
374 }
375
376 static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
377         char **i;
378         int r;
379
380         r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
381         if (r < 0)
382                 return r;
383
384         STRV_FOREACH(i, properties) {
385                 r = sd_bus_message_open_container(m, 'r', "sv");
386                 if (r < 0)
387                         return r;
388
389                 r = bus_append_unit_property_assignment(m, *i);
390                 if (r < 0)
391                         return r;
392
393                 r = sd_bus_message_close_container(m);
394                 if (r < 0)
395                         return r;
396         }
397
398         return 0;
399 }
400
401 static int transient_cgroup_set_properties(sd_bus_message *m) {
402         int r;
403         assert(m);
404
405         if (!isempty(arg_slice)) {
406                 _cleanup_free_ char *slice;
407
408                 slice = unit_name_mangle_with_suffix(arg_slice, MANGLE_NOGLOB, ".slice");
409                 if (!slice)
410                         return -ENOMEM;
411
412                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
413                 if (r < 0)
414                         return r;
415         }
416
417         return 0;
418 }
419
420 static int transient_kill_set_properties(sd_bus_message *m) {
421         assert(m);
422
423         if (arg_send_sighup)
424                 return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
425         else
426                 return 0;
427 }
428
429 static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
430         int r;
431
432         assert(m);
433
434         r = transient_unit_set_properties(m, arg_property);
435         if (r < 0)
436                 return r;
437
438         r = transient_kill_set_properties(m);
439         if (r < 0)
440                 return r;
441
442         r = transient_cgroup_set_properties(m);
443         if (r < 0)
444                 return r;
445
446         if (arg_remain_after_exit) {
447                 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
448                 if (r < 0)
449                         return r;
450         }
451
452         if (arg_service_type) {
453                 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
454                 if (r < 0)
455                         return r;
456         }
457
458         if (arg_exec_user) {
459                 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
460                 if (r < 0)
461                         return r;
462         }
463
464         if (arg_exec_group) {
465                 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
466                 if (r < 0)
467                         return r;
468         }
469
470         if (arg_nice_set) {
471                 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
472                 if (r < 0)
473                         return r;
474         }
475
476         if (pty_path) {
477                 const char *e;
478
479                 r = sd_bus_message_append(m,
480                                           "(sv)(sv)(sv)(sv)",
481                                           "StandardInput", "s", "tty",
482                                           "StandardOutput", "s", "tty",
483                                           "StandardError", "s", "tty",
484                                           "TTYPath", "s", pty_path);
485                 if (r < 0)
486                         return r;
487
488                 e = getenv("TERM");
489                 if (e) {
490                         char *n;
491
492                         n = strjoina("TERM=", e);
493                         r = sd_bus_message_append(m,
494                                                   "(sv)",
495                                                   "Environment", "as", 1, n);
496                         if (r < 0)
497                                 return r;
498                 }
499         }
500
501         if (!strv_isempty(arg_environment)) {
502                 r = sd_bus_message_open_container(m, 'r', "sv");
503                 if (r < 0)
504                         return r;
505
506                 r = sd_bus_message_append(m, "s", "Environment");
507                 if (r < 0)
508                         return r;
509
510                 r = sd_bus_message_open_container(m, 'v', "as");
511                 if (r < 0)
512                         return r;
513
514                 r = sd_bus_message_append_strv(m, arg_environment);
515                 if (r < 0)
516                         return r;
517
518                 r = sd_bus_message_close_container(m);
519                 if (r < 0)
520                         return r;
521
522                 r = sd_bus_message_close_container(m);
523                 if (r < 0)
524                         return r;
525         }
526
527         /* Exec container */
528         {
529                 r = sd_bus_message_open_container(m, 'r', "sv");
530                 if (r < 0)
531                         return r;
532
533                 r = sd_bus_message_append(m, "s", "ExecStart");
534                 if (r < 0)
535                         return r;
536
537                 r = sd_bus_message_open_container(m, 'v', "a(sasb)");
538                 if (r < 0)
539                         return r;
540
541                 r = sd_bus_message_open_container(m, 'a', "(sasb)");
542                 if (r < 0)
543                         return r;
544
545                 r = sd_bus_message_open_container(m, 'r', "sasb");
546                 if (r < 0)
547                         return r;
548
549                 r = sd_bus_message_append(m, "s", argv[0]);
550                 if (r < 0)
551                         return r;
552
553                 r = sd_bus_message_append_strv(m, argv);
554                 if (r < 0)
555                         return r;
556
557                 r = sd_bus_message_append(m, "b", false);
558                 if (r < 0)
559                         return r;
560
561                 r = sd_bus_message_close_container(m);
562                 if (r < 0)
563                         return r;
564
565                 r = sd_bus_message_close_container(m);
566                 if (r < 0)
567                         return r;
568
569                 r = sd_bus_message_close_container(m);
570                 if (r < 0)
571                         return r;
572
573                 r = sd_bus_message_close_container(m);
574                 if (r < 0)
575                         return r;
576         }
577
578         return 0;
579 }
580
581 static int transient_scope_set_properties(sd_bus_message *m) {
582         int r;
583
584         assert(m);
585
586         r = transient_unit_set_properties(m, arg_property);
587         if (r < 0)
588                 return r;
589
590         r = transient_kill_set_properties(m);
591         if (r < 0)
592                 return r;
593
594         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
595         if (r < 0)
596                 return r;
597
598         return 0;
599 }
600
601 static int transient_timer_set_properties(sd_bus_message *m) {
602         int r;
603
604         assert(m);
605
606         r = transient_unit_set_properties(m, arg_timer_property);
607         if (r < 0)
608                 return r;
609
610         if (arg_on_active) {
611                 r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active);
612                 if (r < 0)
613                         return r;
614         }
615
616         if (arg_on_boot) {
617                 r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot);
618                 if (r < 0)
619                         return r;
620         }
621
622         if (arg_on_startup) {
623                 r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup);
624                 if (r < 0)
625                         return r;
626         }
627
628         if (arg_on_unit_active) {
629                 r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active);
630                 if (r < 0)
631                         return r;
632         }
633
634         if (arg_on_unit_inactive) {
635                 r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive);
636                 if (r < 0)
637                         return r;
638         }
639
640         if (arg_on_calendar) {
641                 r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar);
642                 if (r < 0)
643                         return r;
644         }
645
646         return 0;
647 }
648
649 static int start_transient_service(
650                 sd_bus *bus,
651                 char **argv) {
652
653         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
654         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
655         _cleanup_free_ char *service = NULL, *pty_path = NULL;
656         _cleanup_close_ int master = -1;
657         int r;
658
659         assert(bus);
660         assert(argv);
661
662         if (arg_pty) {
663
664                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
665                         master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
666                         if (master < 0)
667                                 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
668
669                         r = ptsname_malloc(master, &pty_path);
670                         if (r < 0)
671                                 return log_error_errno(r, "Failed to determine tty name: %m");
672
673                 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
674                         _cleanup_bus_unref_ sd_bus *system_bus = NULL;
675                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
676                         const char *s;
677
678                         r = sd_bus_open_system(&system_bus);
679                         if (r < 0)
680                                 log_error_errno(r, "Failed to connect to system bus: %m");
681
682                         r = sd_bus_call_method(system_bus,
683                                                "org.freedesktop.machine1",
684                                                "/org/freedesktop/machine1",
685                                                "org.freedesktop.machine1.Manager",
686                                                "OpenMachinePTY",
687                                                &error,
688                                                &reply,
689                                                "s", arg_host);
690                         if (r < 0) {
691                                 log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
692                                 return r;
693                         }
694
695                         r = sd_bus_message_read(reply, "hs", &master, &s);
696                         if (r < 0)
697                                 return bus_log_parse_error(r);
698
699                         master = fcntl(master, F_DUPFD_CLOEXEC, 3);
700                         if (master < 0)
701                                 return log_error_errno(errno, "Failed to duplicate master fd: %m");
702
703                         pty_path = strdup(s);
704                         if (!pty_path)
705                                 return log_oom();
706                 } else
707                         assert_not_reached("Can't allocate tty via ssh");
708
709                 if (unlockpt(master) < 0)
710                         return log_error_errno(errno, "Failed to unlock tty: %m");
711         }
712
713         if (arg_unit) {
714                 service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
715                 if (!service)
716                         return log_oom();
717         } else if (asprintf(&service, "run-"PID_FMT".service", getpid()) < 0)
718                 return log_oom();
719
720         r = sd_bus_message_new_method_call(
721                         bus,
722                         &m,
723                         "org.freedesktop.systemd1",
724                         "/org/freedesktop/systemd1",
725                         "org.freedesktop.systemd1.Manager",
726                         "StartTransientUnit");
727         if (r < 0)
728                 return bus_log_create_error(r);
729
730         /* Name and mode */
731         r = sd_bus_message_append(m, "ss", service, "fail");
732         if (r < 0)
733                 return bus_log_create_error(r);
734
735         /* Properties */
736         r = sd_bus_message_open_container(m, 'a', "(sv)");
737         if (r < 0)
738                 return bus_log_create_error(r);
739
740         r = transient_service_set_properties(m, argv, pty_path);
741         if (r < 0)
742                 return bus_log_create_error(r);
743
744         r = sd_bus_message_close_container(m);
745         if (r < 0)
746                 return bus_log_create_error(r);
747
748         /* Auxiliary units */
749         r = sd_bus_message_append(m, "a(sa(sv))", 0);
750         if (r < 0)
751                 return bus_log_create_error(r);
752
753         r = sd_bus_call(bus, m, 0, &error, NULL);
754         if (r < 0) {
755                 log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r));
756                 return r;
757         }
758
759         if (master >= 0) {
760                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
761                 _cleanup_event_unref_ sd_event *event = NULL;
762                 sigset_t mask;
763                 char last_char = 0;
764
765                 r = sd_event_default(&event);
766                 if (r < 0)
767                         return log_error_errno(r, "Failed to get event loop: %m");
768
769                 assert_se(sigemptyset(&mask) == 0);
770                 sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
771                 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
772
773                 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
774                 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
775
776                 if (!arg_quiet)
777                         log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
778
779                 r = pty_forward_new(event, master, false, &forward);
780                 if (r < 0)
781                         return log_error_errno(r, "Failed to create PTY forwarder: %m");
782
783                 r = sd_event_loop(event);
784                 if (r < 0)
785                         return log_error_errno(r, "Failed to run event loop: %m");
786
787                 pty_forward_get_last_char(forward, &last_char);
788
789                 forward = pty_forward_free(forward);
790
791                 if (!arg_quiet && last_char != '\n')
792                         fputc('\n', stdout);
793
794         } else if (!arg_quiet)
795                 log_info("Running as unit %s.", service);
796
797         return 0;
798 }
799
800 static int start_transient_scope(
801                 sd_bus *bus,
802                 char **argv) {
803
804         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
805         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
806         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
807         _cleanup_free_ char *scope = NULL;
808         int r;
809
810         assert(bus);
811         assert(argv);
812
813         if (arg_unit) {
814                 scope = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".scope");
815                 if (!scope)
816                         return log_oom();
817         } else if (asprintf(&scope, "run-"PID_FMT".scope", getpid()) < 0)
818                 return log_oom();
819
820         r = sd_bus_message_new_method_call(
821                         bus,
822                         &m,
823                         "org.freedesktop.systemd1",
824                         "/org/freedesktop/systemd1",
825                         "org.freedesktop.systemd1.Manager",
826                         "StartTransientUnit");
827         if (r < 0)
828                 return bus_log_create_error(r);
829
830         /* Name and Mode */
831         r = sd_bus_message_append(m, "ss", scope, "fail");
832         if (r < 0)
833                 return bus_log_create_error(r);
834
835         /* Properties */
836         r = sd_bus_message_open_container(m, 'a', "(sv)");
837         if (r < 0)
838                 return bus_log_create_error(r);
839
840         r = transient_scope_set_properties(m);
841         if (r < 0)
842                 return bus_log_create_error(r);
843
844         r = sd_bus_message_close_container(m);
845         if (r < 0)
846                 return bus_log_create_error(r);
847
848         /* Auxiliary units */
849         r = sd_bus_message_append(m, "a(sa(sv))", 0);
850         if (r < 0)
851                 return bus_log_create_error(r);
852
853         r = sd_bus_call(bus, m, 0, &error, NULL);
854         if (r < 0) {
855                 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
856                 return r;
857         }
858
859         if (arg_nice_set) {
860                 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
861                         return log_error_errno(errno, "Failed to set nice level: %m");
862         }
863
864         if (arg_exec_group) {
865                 gid_t gid;
866
867                 r = get_group_creds(&arg_exec_group, &gid);
868                 if (r < 0)
869                         return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
870
871                 if (setresgid(gid, gid, gid) < 0)
872                         return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
873         }
874
875         if (arg_exec_user) {
876                 const char *home, *shell;
877                 uid_t uid;
878                 gid_t gid;
879
880                 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
881                 if (r < 0)
882                         return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
883
884                 r = strv_extendf(&user_env, "HOME=%s", home);
885                 if (r < 0)
886                         return log_oom();
887
888                 r = strv_extendf(&user_env, "SHELL=%s", shell);
889                 if (r < 0)
890                         return log_oom();
891
892                 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
893                 if (r < 0)
894                         return log_oom();
895
896                 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
897                 if (r < 0)
898                         return log_oom();
899
900                 if (!arg_exec_group) {
901                         if (setresgid(gid, gid, gid) < 0)
902                                 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
903                 }
904
905                 if (setresuid(uid, uid, uid) < 0)
906                         return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
907         }
908
909         env = strv_env_merge(3, environ, user_env, arg_environment);
910         if (!env)
911                 return log_oom();
912
913         if (!arg_quiet)
914                 log_info("Running as unit %s.", scope);
915
916         execvpe(argv[0], argv, env);
917
918         return log_error_errno(errno, "Failed to execute: %m");
919 }
920
921 static int start_transient_timer(
922                 sd_bus *bus,
923                 char **argv) {
924
925         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
926         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
927         _cleanup_free_ char *timer = NULL, *service = NULL;
928         int r;
929
930         assert(bus);
931         assert(argv);
932
933         if (arg_unit) {
934                 switch(unit_name_to_type(arg_unit)) {
935
936                 case UNIT_SERVICE:
937                         service = strdup(arg_unit);
938                         if (!service)
939                                 return log_oom();
940
941                         timer = unit_name_change_suffix(service, ".timer");
942                         if (!timer)
943                                 return log_oom();
944                         break;
945
946                 case UNIT_TIMER:
947                         timer = strdup(arg_unit);
948                         if (!timer)
949                                 return log_oom();
950
951                         service = unit_name_change_suffix(timer, ".service");
952                         if (!service)
953                                 return log_oom();
954                         break;
955
956                 default:
957                         service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
958                         if (!service)
959                                 return log_oom();
960
961                         timer = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".timer");
962                         if (!timer)
963                                 return log_oom();
964
965                         break;
966                 }
967         } else if ((asprintf(&service, "run-"PID_FMT".service", getpid()) < 0) ||
968                    (asprintf(&timer, "run-"PID_FMT".timer", getpid()) < 0))
969                 return log_oom();
970
971         r = sd_bus_message_new_method_call(
972                         bus,
973                         &m,
974                         "org.freedesktop.systemd1",
975                         "/org/freedesktop/systemd1",
976                         "org.freedesktop.systemd1.Manager",
977                         "StartTransientUnit");
978         if (r < 0)
979                 return bus_log_create_error(r);
980
981         /* Name and Mode */
982         r = sd_bus_message_append(m, "ss", timer, "fail");
983         if (r < 0)
984                 return bus_log_create_error(r);
985
986         /* Properties */
987         r = sd_bus_message_open_container(m, 'a', "(sv)");
988         if (r < 0)
989                 return bus_log_create_error(r);
990
991         r = transient_timer_set_properties(m);
992         if (r < 0)
993                 return bus_log_create_error(r);
994
995         r = sd_bus_message_close_container(m);
996         if (r < 0)
997                 return bus_log_create_error(r);
998
999         r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1000         if (r < 0)
1001                 return bus_log_create_error(r);
1002
1003         if (argv[0]) {
1004                 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1005                 if (r < 0)
1006                         return bus_log_create_error(r);
1007
1008                 r = sd_bus_message_append(m, "s", service);
1009                 if (r < 0)
1010                         return bus_log_create_error(r);
1011
1012                 r = sd_bus_message_open_container(m, 'a', "(sv)");
1013                 if (r < 0)
1014                         return bus_log_create_error(r);
1015
1016                 r = transient_service_set_properties(m, argv, NULL);
1017                 if (r < 0)
1018                         return bus_log_create_error(r);
1019
1020                 r = sd_bus_message_close_container(m);
1021                 if (r < 0)
1022                         return bus_log_create_error(r);
1023
1024                 r = sd_bus_message_close_container(m);
1025                 if (r < 0)
1026                         return bus_log_create_error(r);
1027         }
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_call(bus, m, 0, &error, NULL);
1034         if (r < 0) {
1035                 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
1036                 return r;
1037         }
1038
1039         log_info("Running as unit %s.", timer);
1040         if (argv[0])
1041                 log_info("Will run as unit %s.", service);
1042
1043         return 0;
1044 }
1045
1046 int main(int argc, char* argv[]) {
1047         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1048         _cleanup_free_ char *description = NULL, *command = NULL;
1049         int r;
1050
1051         log_parse_environment();
1052         log_open();
1053
1054         r = parse_argv(argc, argv);
1055         if (r <= 0)
1056                 goto finish;
1057
1058         if (argc > optind) {
1059                 r = find_binary(argv[optind], arg_transport == BUS_TRANSPORT_LOCAL, &command);
1060                 if (r < 0) {
1061                         log_error_errno(r, "Failed to find executable %s%s: %m",
1062                                         argv[optind],
1063                                         arg_transport == BUS_TRANSPORT_LOCAL ? "" : " on local system");
1064                         goto finish;
1065                 }
1066                 argv[optind] = command;
1067         }
1068
1069         if (!arg_description) {
1070                 description = strv_join(argv + optind, " ");
1071                 if (!description) {
1072                         r = log_oom();
1073                         goto finish;
1074                 }
1075
1076                 if (arg_unit && isempty(description)) {
1077                         free(description);
1078                         description = strdup(arg_unit);
1079
1080                         if (!description) {
1081                                 r = log_oom();
1082                                 goto finish;
1083                         }
1084                 }
1085
1086                 arg_description = description;
1087         }
1088
1089         r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1090         if (r < 0) {
1091                 log_error_errno(r, "Failed to create bus connection: %m");
1092                 goto finish;
1093         }
1094
1095         if (arg_scope)
1096                 r = start_transient_scope(bus, argv + optind);
1097         else if (with_timer())
1098                 r = start_transient_timer(bus, argv + optind);
1099         else
1100                 r = start_transient_service(bus, argv + optind);
1101
1102 finish:
1103         strv_free(arg_environment);
1104         strv_free(arg_property);
1105         strv_free(arg_timer_property);
1106
1107         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1108 }