chiark / gitweb /
systemd-run: add --quiet mode to suppress informational message on TTY usage
[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                 sd_bus_error *error) {
662
663         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
664         _cleanup_free_ char *service = NULL;
665         _cleanup_close_ int master = -1;
666         const char *pty_path = NULL;
667         int r;
668
669         assert(bus);
670         assert(argv);
671
672         if (arg_pty) {
673                 master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
674                 if (master < 0)
675                         return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
676
677                 pty_path = ptsname(master);
678                 if (!pty_path)
679                         return log_error_errno(errno, "Failed to determine tty name: %m");
680
681                 if (unlockpt(master) < 0)
682                         return log_error_errno(errno, "Failed to unlock tty: %m");
683         }
684
685         if (arg_unit) {
686                 service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
687                 if (!service)
688                         return log_oom();
689         } else if (asprintf(&service, "run-"PID_FMT".service", getpid()) < 0)
690                 return log_oom();
691
692         r = sd_bus_message_new_method_call(
693                         bus,
694                         &m,
695                         "org.freedesktop.systemd1",
696                         "/org/freedesktop/systemd1",
697                         "org.freedesktop.systemd1.Manager",
698                         "StartTransientUnit");
699         if (r < 0)
700                 return bus_log_create_error(r);
701
702         /* Name and mode */
703         r = sd_bus_message_append(m, "ss", service, "fail");
704         if (r < 0)
705                 return bus_log_create_error(r);
706
707         /* Properties */
708         r = sd_bus_message_open_container(m, 'a', "(sv)");
709         if (r < 0)
710                 return bus_log_create_error(r);
711
712         r = transient_service_set_properties(m, argv, pty_path);
713         if (r < 0)
714                 return bus_log_create_error(r);
715
716         r = sd_bus_message_close_container(m);
717         if (r < 0)
718                 return bus_log_create_error(r);
719
720         /* Auxiliary units */
721         r = sd_bus_message_append(m, "a(sa(sv))", 0);
722         if (r < 0)
723                 return bus_log_create_error(r);
724
725         r = sd_bus_call(bus, m, 0, error, NULL);
726         if (r < 0)
727                 return bus_log_create_error(r);
728
729         if (master >= 0) {
730                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
731                 _cleanup_event_unref_ sd_event *event = NULL;
732                 sigset_t mask;
733                 char last_char = 0;
734
735                 r = sd_event_default(&event);
736                 if (r < 0)
737                         return log_error_errno(r, "Failed to get event loop: %m");
738
739                 assert_se(sigemptyset(&mask) == 0);
740                 sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
741                 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
742
743                 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
744                 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
745
746                 if (!arg_quiet)
747                         log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
748
749                 r = pty_forward_new(event, master, false, &forward);
750                 if (r < 0)
751                         return log_error_errno(r, "Failed to create PTY forwarder: %m");
752
753                 r = sd_event_loop(event);
754                 if (r < 0)
755                         return log_error_errno(r, "Failed to run event loop: %m");
756
757                 pty_forward_last_char(forward, &last_char);
758
759                 forward = pty_forward_free(forward);
760
761                 if (!arg_quiet && last_char != '\n')
762                         fputc('\n', stdout);
763
764         } else if (!arg_quiet)
765                 log_info("Running as unit %s.", service);
766
767         return 0;
768 }
769
770 static int start_transient_scope(
771                 sd_bus *bus,
772                 char **argv,
773                 sd_bus_error *error) {
774
775         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
776         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
777         _cleanup_free_ char *scope = NULL;
778         int r;
779
780         assert(bus);
781         assert(argv);
782
783         if (arg_unit) {
784                 scope = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".scope");
785                 if (!scope)
786                         return log_oom();
787         } else if (asprintf(&scope, "run-"PID_FMT".scope", getpid()) < 0)
788                 return log_oom();
789
790         r = sd_bus_message_new_method_call(
791                         bus,
792                         &m,
793                         "org.freedesktop.systemd1",
794                         "/org/freedesktop/systemd1",
795                         "org.freedesktop.systemd1.Manager",
796                         "StartTransientUnit");
797         if (r < 0)
798                 return bus_log_create_error(r);
799
800         /* Name and Mode */
801         r = sd_bus_message_append(m, "ss", scope, "fail");
802         if (r < 0)
803                 return bus_log_create_error(r);
804
805         /* Properties */
806         r = sd_bus_message_open_container(m, 'a', "(sv)");
807         if (r < 0)
808                 return bus_log_create_error(r);
809
810         r = transient_scope_set_properties(m);
811         if (r < 0)
812                 return bus_log_create_error(r);
813
814         r = sd_bus_message_close_container(m);
815         if (r < 0)
816                 return bus_log_create_error(r);
817
818         /* aux */
819         r = sd_bus_message_append(m, "a(sa(sv))", 0);
820         if (r < 0)
821                 return bus_log_create_error(r);
822
823         /* send dbus */
824         r = sd_bus_call(bus, m, 0, error, NULL);
825         if (r < 0)
826                 return bus_log_create_error(r);
827
828         if (arg_nice_set) {
829                 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
830                         return log_error_errno(errno, "Failed to set nice level: %m");
831         }
832
833         if (arg_exec_group) {
834                 gid_t gid;
835
836                 r = get_group_creds(&arg_exec_group, &gid);
837                 if (r < 0)
838                         return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
839
840                 if (setresgid(gid, gid, gid) < 0)
841                         return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
842         }
843
844         if (arg_exec_user) {
845                 const char *home, *shell;
846                 uid_t uid;
847                 gid_t gid;
848
849                 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
850                 if (r < 0)
851                         return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
852
853                 r = strv_extendf(&user_env, "HOME=%s", home);
854                 if (r < 0)
855                         return log_oom();
856
857                 r = strv_extendf(&user_env, "SHELL=%s", shell);
858                 if (r < 0)
859                         return log_oom();
860
861                 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
862                 if (r < 0)
863                         return log_oom();
864
865                 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
866                 if (r < 0)
867                         return log_oom();
868
869                 if (!arg_exec_group) {
870                         if (setresgid(gid, gid, gid) < 0)
871                                 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
872                 }
873
874                 if (setresuid(uid, uid, uid) < 0)
875                         return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
876         }
877
878         env = strv_env_merge(3, environ, user_env, arg_environment);
879         if (!env)
880                 return log_oom();
881
882         if (!arg_quiet)
883                 log_info("Running as unit %s.", scope);
884
885         execvpe(argv[0], argv, env);
886
887         return log_error_errno(errno, "Failed to execute: %m");
888 }
889
890 static int start_transient_timer(
891                 sd_bus *bus,
892                 char **argv,
893                 sd_bus_error *error) {
894
895         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
896         _cleanup_free_ char *timer = NULL, *service = NULL;
897         int r;
898
899         assert(bus);
900         assert(argv);
901
902         if (arg_unit) {
903                 switch(unit_name_to_type(arg_unit)) {
904
905                 case UNIT_SERVICE:
906                         service = strdup(arg_unit);
907                         if (!service)
908                                 return log_oom();
909
910                         timer = unit_name_change_suffix(service, ".timer");
911                         if (!timer)
912                                 return log_oom();
913                         break;
914
915                 case UNIT_TIMER:
916                         timer = strdup(arg_unit);
917                         if (!timer)
918                                 return log_oom();
919
920                         service = unit_name_change_suffix(timer, ".service");
921                         if (!service)
922                                 return log_oom();
923                         break;
924
925                 default:
926                         service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
927                         if (!service)
928                                 return log_oom();
929
930                         timer = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".timer");
931                         if (!timer)
932                                 return log_oom();
933
934                         break;
935                 }
936         } else if ((asprintf(&service, "run-"PID_FMT".service", getpid()) < 0) ||
937                    (asprintf(&timer, "run-"PID_FMT".timer", getpid()) < 0))
938                 return log_oom();
939
940         r = sd_bus_message_new_method_call(
941                         bus,
942                         &m,
943                         "org.freedesktop.systemd1",
944                         "/org/freedesktop/systemd1",
945                         "org.freedesktop.systemd1.Manager",
946                         "StartTransientUnit");
947         if (r < 0)
948                 return bus_log_create_error(r);
949
950         /* Name and Mode */
951         r = sd_bus_message_append(m, "ss", timer, "fail");
952         if (r < 0)
953                 return bus_log_create_error(r);
954
955         /* Properties */
956         r = sd_bus_message_open_container(m, 'a', "(sv)");
957         if (r < 0)
958                 return bus_log_create_error(r);
959
960         r = transient_timer_set_properties(m);
961         if (r < 0)
962                 return bus_log_create_error(r);
963
964         r = sd_bus_message_close_container(m);
965         if (r < 0)
966                 return bus_log_create_error(r);
967
968         r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
969         if (r < 0)
970                 return bus_log_create_error(r);
971
972         if (argv[0]) {
973                 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
974                 if (r < 0)
975                         return bus_log_create_error(r);
976
977                 r = sd_bus_message_append(m, "s", service);
978                 if (r < 0)
979                         return bus_log_create_error(r);
980
981                 r = sd_bus_message_open_container(m, 'a', "(sv)");
982                 if (r < 0)
983                         return bus_log_create_error(r);
984
985                 r = transient_service_set_properties(m, argv, NULL);
986                 if (r < 0)
987                         return bus_log_create_error(r);
988
989                 r = sd_bus_message_close_container(m);
990                 if (r < 0)
991                         return bus_log_create_error(r);
992
993                 r = sd_bus_message_close_container(m);
994                 if (r < 0)
995                         return bus_log_create_error(r);
996         }
997
998         r = sd_bus_message_close_container(m);
999         if (r < 0)
1000                 return bus_log_create_error(r);
1001
1002         /* send dbus */
1003         r = sd_bus_call(bus, m, 0, error, NULL);
1004         if (r < 0)
1005                 return bus_log_create_error(r);
1006
1007         log_info("Running as unit %s.", timer);
1008         if (argv[0])
1009                 log_info("Will run as unit %s.", service);
1010
1011         return 0;
1012 }
1013
1014 int main(int argc, char* argv[]) {
1015         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1016         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1017         _cleanup_free_ char *description = NULL, *command = NULL;
1018         int r;
1019
1020         log_parse_environment();
1021         log_open();
1022
1023         r = parse_argv(argc, argv);
1024         if (r <= 0)
1025                 goto finish;
1026
1027         if (argc > optind) {
1028                 r = find_binary(argv[optind], arg_transport == BUS_TRANSPORT_LOCAL, &command);
1029                 if (r < 0) {
1030                         log_error_errno(r, "Failed to find executable %s%s: %m",
1031                                         argv[optind],
1032                                         arg_transport == BUS_TRANSPORT_LOCAL ? "" : " on local system");
1033                         goto finish;
1034                 }
1035                 argv[optind] = command;
1036         }
1037
1038         if (!arg_description) {
1039                 description = strv_join(argv + optind, " ");
1040                 if (!description) {
1041                         r = log_oom();
1042                         goto finish;
1043                 }
1044
1045                 if (arg_unit && isempty(description)) {
1046                         free(description);
1047                         description = strdup(arg_unit);
1048
1049                         if (!description) {
1050                                 r = log_oom();
1051                                 goto finish;
1052                         }
1053                 }
1054
1055                 arg_description = description;
1056         }
1057
1058         r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1059         if (r < 0) {
1060                 log_error_errno(r, "Failed to create bus connection: %m");
1061                 goto finish;
1062         }
1063
1064         if (arg_scope)
1065                 r = start_transient_scope(bus, argv + optind, &error);
1066         else if (with_timer())
1067                 r = start_transient_timer(bus, argv + optind, &error);
1068         else
1069                 r = start_transient_service(bus, argv + optind, &error);
1070
1071 finish:
1072         strv_free(arg_environment);
1073         strv_free(arg_property);
1074         strv_free(arg_timer_property);
1075
1076         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1077 }