1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <getopt.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 
9 #include "sd-bus.h"
10 #include "sd-event.h"
11 
12 #include "alloc-util.h"
13 #include "bus-error.h"
14 #include "bus-locator.h"
15 #include "bus-map-properties.h"
16 #include "bus-unit-util.h"
17 #include "bus-wait-for-jobs.h"
18 #include "calendarspec.h"
19 #include "env-util.h"
20 #include "exit-status.h"
21 #include "fd-util.h"
22 #include "format-util.h"
23 #include "main-func.h"
24 #include "parse-argument.h"
25 #include "parse-util.h"
26 #include "path-util.h"
27 #include "pretty-print.h"
28 #include "process-util.h"
29 #include "ptyfwd.h"
30 #include "signal-util.h"
31 #include "spawn-polkit-agent.h"
32 #include "strv.h"
33 #include "terminal-util.h"
34 #include "unit-def.h"
35 #include "unit-name.h"
36 #include "user-util.h"
37 
38 static bool arg_ask_password = true;
39 static bool arg_scope = false;
40 static bool arg_remain_after_exit = false;
41 static bool arg_no_block = false;
42 static bool arg_wait = false;
43 static const char *arg_unit = NULL;
44 static const char *arg_description = NULL;
45 static const char *arg_slice = NULL;
46 static bool arg_slice_inherit = false;
47 static bool arg_send_sighup = false;
48 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
49 static const char *arg_host = NULL;
50 static bool arg_user = false;
51 static const char *arg_service_type = NULL;
52 static const char *arg_exec_user = NULL;
53 static const char *arg_exec_group = NULL;
54 static int arg_nice = 0;
55 static bool arg_nice_set = false;
56 static char **arg_environment = NULL;
57 static char **arg_property = NULL;
58 static enum {
59         ARG_STDIO_NONE,      /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */
60         ARG_STDIO_PTY,       /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */
61         ARG_STDIO_DIRECT,    /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
62         ARG_STDIO_AUTO,      /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
63 } arg_stdio = ARG_STDIO_NONE;
64 static char **arg_path_property = NULL;
65 static char **arg_socket_property = NULL;
66 static char **arg_timer_property = NULL;
67 static bool arg_with_timer = false;
68 static bool arg_quiet = false;
69 static bool arg_aggressive_gc = false;
70 static char *arg_working_directory = NULL;
71 static bool arg_shell = false;
72 static char **arg_cmdline = NULL;
73 
74 STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
75 STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
76 STATIC_DESTRUCTOR_REGISTER(arg_path_property, strv_freep);
77 STATIC_DESTRUCTOR_REGISTER(arg_socket_property, strv_freep);
78 STATIC_DESTRUCTOR_REGISTER(arg_timer_property, strv_freep);
79 STATIC_DESTRUCTOR_REGISTER(arg_working_directory, freep);
80 STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep);
81 
help(void)82 static int help(void) {
83         _cleanup_free_ char *link = NULL;
84         int r;
85 
86         r = terminal_urlify_man("systemd-run", "1", &link);
87         if (r < 0)
88                 return log_oom();
89 
90         printf("%s [OPTIONS...] COMMAND [ARGUMENTS...]\n"
91                "\n%sRun the specified command in a transient scope or service.%s\n\n"
92                "  -h --help                       Show this help\n"
93                "     --version                    Show package version\n"
94                "     --no-ask-password            Do not prompt for password\n"
95                "     --user                       Run as user unit\n"
96                "  -H --host=[USER@]HOST           Operate on remote host\n"
97                "  -M --machine=CONTAINER          Operate on local container\n"
98                "     --scope                      Run this as scope rather than service\n"
99                "  -u --unit=UNIT                  Run under the specified unit name\n"
100                "  -p --property=NAME=VALUE        Set service or scope unit property\n"
101                "     --description=TEXT           Description for unit\n"
102                "     --slice=SLICE                Run in the specified slice\n"
103                "     --slice-inherit              Inherit the slice\n"
104                "     --no-block                   Do not wait until operation finished\n"
105                "  -r --remain-after-exit          Leave service around until explicitly stopped\n"
106                "     --wait                       Wait until service stopped again\n"
107                "     --send-sighup                Send SIGHUP when terminating\n"
108                "     --service-type=TYPE          Service type\n"
109                "     --uid=USER                   Run as system user\n"
110                "     --gid=GROUP                  Run as system group\n"
111                "     --nice=NICE                  Nice level\n"
112                "     --working-directory=PATH     Set working directory\n"
113                "  -d --same-dir                   Inherit working directory from caller\n"
114                "  -E --setenv=NAME[=VALUE]        Set environment variable\n"
115                "  -t --pty                        Run service on pseudo TTY as STDIN/STDOUT/\n"
116                "                                  STDERR\n"
117                "  -P --pipe                       Pass STDIN/STDOUT/STDERR directly to service\n"
118                "  -q --quiet                      Suppress information messages during runtime\n"
119                "  -G --collect                    Unload unit after it ran, even when failed\n"
120                "  -S --shell                      Invoke a $SHELL interactively\n\n"
121                "Path options:\n"
122                "     --path-property=NAME=VALUE   Set path unit property\n\n"
123                "Socket options:\n"
124                "     --socket-property=NAME=VALUE Set socket unit property\n\n"
125                "Timer options:\n"
126                "     --on-active=SECONDS          Run after SECONDS delay\n"
127                "     --on-boot=SECONDS            Run SECONDS after machine was booted up\n"
128                "     --on-startup=SECONDS         Run SECONDS after systemd activation\n"
129                "     --on-unit-active=SECONDS     Run SECONDS after the last activation\n"
130                "     --on-unit-inactive=SECONDS   Run SECONDS after the last deactivation\n"
131                "     --on-calendar=SPEC           Realtime timer\n"
132                "     --on-timezone-change         Run when the timezone changes\n"
133                "     --on-clock-change            Run when the realtime clock jumps\n"
134                "     --timer-property=NAME=VALUE  Set timer unit property\n"
135                "\nSee the %s for details.\n",
136                program_invocation_short_name,
137                ansi_highlight(),
138                ansi_normal(),
139                link);
140 
141         return 0;
142 }
143 
add_timer_property(const char * name,const char * val)144 static int add_timer_property(const char *name, const char *val) {
145         char *p;
146 
147         assert(name);
148         assert(val);
149 
150         p = strjoin(name, "=", val);
151         if (!p)
152                 return log_oom();
153 
154         if (strv_consume(&arg_timer_property, p) < 0)
155                 return log_oom();
156 
157         return 0;
158 }
159 
parse_argv(int argc,char * argv[])160 static int parse_argv(int argc, char *argv[]) {
161 
162         enum {
163                 ARG_VERSION = 0x100,
164                 ARG_USER,
165                 ARG_SYSTEM,
166                 ARG_SCOPE,
167                 ARG_DESCRIPTION,
168                 ARG_SLICE,
169                 ARG_SLICE_INHERIT,
170                 ARG_SEND_SIGHUP,
171                 ARG_SERVICE_TYPE,
172                 ARG_EXEC_USER,
173                 ARG_EXEC_GROUP,
174                 ARG_NICE,
175                 ARG_ON_ACTIVE,
176                 ARG_ON_BOOT,
177                 ARG_ON_STARTUP,
178                 ARG_ON_UNIT_ACTIVE,
179                 ARG_ON_UNIT_INACTIVE,
180                 ARG_ON_CALENDAR,
181                 ARG_ON_TIMEZONE_CHANGE,
182                 ARG_ON_CLOCK_CHANGE,
183                 ARG_TIMER_PROPERTY,
184                 ARG_PATH_PROPERTY,
185                 ARG_SOCKET_PROPERTY,
186                 ARG_NO_BLOCK,
187                 ARG_NO_ASK_PASSWORD,
188                 ARG_WAIT,
189                 ARG_WORKING_DIRECTORY,
190                 ARG_SHELL,
191         };
192 
193         static const struct option options[] = {
194                 { "help",              no_argument,       NULL, 'h'                   },
195                 { "version",           no_argument,       NULL, ARG_VERSION           },
196                 { "user",              no_argument,       NULL, ARG_USER              },
197                 { "system",            no_argument,       NULL, ARG_SYSTEM            },
198                 { "scope",             no_argument,       NULL, ARG_SCOPE             },
199                 { "unit",              required_argument, NULL, 'u'                   },
200                 { "description",       required_argument, NULL, ARG_DESCRIPTION       },
201                 { "slice",             required_argument, NULL, ARG_SLICE             },
202                 { "slice-inherit",     no_argument,       NULL, ARG_SLICE_INHERIT     },
203                 { "remain-after-exit", no_argument,       NULL, 'r'                   },
204                 { "send-sighup",       no_argument,       NULL, ARG_SEND_SIGHUP       },
205                 { "host",              required_argument, NULL, 'H'                   },
206                 { "machine",           required_argument, NULL, 'M'                   },
207                 { "service-type",      required_argument, NULL, ARG_SERVICE_TYPE      },
208                 { "wait",              no_argument,       NULL, ARG_WAIT              },
209                 { "uid",               required_argument, NULL, ARG_EXEC_USER         },
210                 { "gid",               required_argument, NULL, ARG_EXEC_GROUP        },
211                 { "nice",              required_argument, NULL, ARG_NICE              },
212                 { "setenv",            required_argument, NULL, 'E'                   },
213                 { "property",          required_argument, NULL, 'p'                   },
214                 { "tty",               no_argument,       NULL, 't'                   }, /* deprecated alias */
215                 { "pty",               no_argument,       NULL, 't'                   },
216                 { "pipe",              no_argument,       NULL, 'P'                   },
217                 { "quiet",             no_argument,       NULL, 'q'                   },
218                 { "on-active",         required_argument, NULL, ARG_ON_ACTIVE         },
219                 { "on-boot",           required_argument, NULL, ARG_ON_BOOT           },
220                 { "on-startup",        required_argument, NULL, ARG_ON_STARTUP        },
221                 { "on-unit-active",    required_argument, NULL, ARG_ON_UNIT_ACTIVE    },
222                 { "on-unit-inactive",  required_argument, NULL, ARG_ON_UNIT_INACTIVE  },
223                 { "on-calendar",       required_argument, NULL, ARG_ON_CALENDAR       },
224                 { "on-timezone-change",no_argument,       NULL, ARG_ON_TIMEZONE_CHANGE},
225                 { "on-clock-change",   no_argument,       NULL, ARG_ON_CLOCK_CHANGE   },
226                 { "timer-property",    required_argument, NULL, ARG_TIMER_PROPERTY    },
227                 { "path-property",     required_argument, NULL, ARG_PATH_PROPERTY     },
228                 { "socket-property",   required_argument, NULL, ARG_SOCKET_PROPERTY   },
229                 { "no-block",          no_argument,       NULL, ARG_NO_BLOCK          },
230                 { "no-ask-password",   no_argument,       NULL, ARG_NO_ASK_PASSWORD   },
231                 { "collect",           no_argument,       NULL, 'G'                   },
232                 { "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY },
233                 { "same-dir",          no_argument,       NULL, 'd'                   },
234                 { "shell",             no_argument,       NULL, 'S'                   },
235                 {},
236         };
237 
238         bool with_trigger = false;
239         int r, c;
240 
241         assert(argc >= 0);
242         assert(argv);
243 
244         while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0)
245 
246                 switch (c) {
247 
248                 case 'h':
249                         return help();
250 
251                 case ARG_VERSION:
252                         return version();
253 
254                 case ARG_NO_ASK_PASSWORD:
255                         arg_ask_password = false;
256                         break;
257 
258                 case ARG_USER:
259                         arg_user = true;
260                         break;
261 
262                 case ARG_SYSTEM:
263                         arg_user = false;
264                         break;
265 
266                 case ARG_SCOPE:
267                         arg_scope = true;
268                         break;
269 
270                 case 'u':
271                         arg_unit = optarg;
272                         break;
273 
274                 case ARG_DESCRIPTION:
275                         arg_description = optarg;
276                         break;
277 
278                 case ARG_SLICE:
279                         arg_slice = optarg;
280                         break;
281 
282                 case ARG_SLICE_INHERIT:
283                         arg_slice_inherit = true;
284                         break;
285 
286                 case ARG_SEND_SIGHUP:
287                         arg_send_sighup = true;
288                         break;
289 
290                 case 'r':
291                         arg_remain_after_exit = true;
292                         break;
293 
294                 case 'H':
295                         arg_transport = BUS_TRANSPORT_REMOTE;
296                         arg_host = optarg;
297                         break;
298 
299                 case 'M':
300                         arg_transport = BUS_TRANSPORT_MACHINE;
301                         arg_host = optarg;
302                         break;
303 
304                 case ARG_SERVICE_TYPE:
305                         arg_service_type = optarg;
306                         break;
307 
308                 case ARG_EXEC_USER:
309                         arg_exec_user = optarg;
310                         break;
311 
312                 case ARG_EXEC_GROUP:
313                         arg_exec_group = optarg;
314                         break;
315 
316                 case ARG_NICE:
317                         r = parse_nice(optarg, &arg_nice);
318                         if (r < 0)
319                                 return log_error_errno(r, "Failed to parse nice value: %s", optarg);
320 
321                         arg_nice_set = true;
322                         break;
323 
324                 case 'E':
325                         r = strv_env_replace_strdup_passthrough(&arg_environment, optarg);
326                         if (r < 0)
327                                 return log_error_errno(r, "Cannot assign environment variable %s: %m", optarg);
328 
329                         break;
330 
331                 case 'p':
332                         if (strv_extend(&arg_property, optarg) < 0)
333                                 return log_oom();
334 
335                         break;
336 
337                 case 't': /* --pty */
338                         if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */
339                                 arg_stdio = ARG_STDIO_AUTO;
340                         else
341                                 arg_stdio = ARG_STDIO_PTY;
342                         break;
343 
344                 case 'P': /* --pipe */
345                         if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */
346                                 arg_stdio = ARG_STDIO_AUTO;
347                         else
348                                 arg_stdio = ARG_STDIO_DIRECT;
349                         break;
350 
351                 case 'q':
352                         arg_quiet = true;
353                         break;
354 
355                 case ARG_ON_ACTIVE:
356                         r = add_timer_property("OnActiveSec", optarg);
357                         if (r < 0)
358                                 return r;
359 
360                         arg_with_timer = true;
361                         break;
362 
363                 case ARG_ON_BOOT:
364                         r = add_timer_property("OnBootSec", optarg);
365                         if (r < 0)
366                                 return r;
367 
368                         arg_with_timer = true;
369                         break;
370 
371                 case ARG_ON_STARTUP:
372                         r = add_timer_property("OnStartupSec", optarg);
373                         if (r < 0)
374                                 return r;
375 
376                         arg_with_timer = true;
377                         break;
378 
379                 case ARG_ON_UNIT_ACTIVE:
380                         r = add_timer_property("OnUnitActiveSec", optarg);
381                         if (r < 0)
382                                 return r;
383 
384                         arg_with_timer = true;
385                         break;
386 
387                 case ARG_ON_UNIT_INACTIVE:
388                         r = add_timer_property("OnUnitInactiveSec", optarg);
389                         if (r < 0)
390                                 return r;
391 
392                         arg_with_timer = true;
393                         break;
394 
395                 case ARG_ON_CALENDAR: {
396                         _cleanup_(calendar_spec_freep) CalendarSpec *cs = NULL;
397 
398                         r = calendar_spec_from_string(optarg, &cs);
399                         if (r < 0)
400                                 return log_error_errno(r, "Failed to parse calendar event specification: %m");
401 
402                         /* Let's make sure the given calendar event is not in the past */
403                         r = calendar_spec_next_usec(cs, now(CLOCK_REALTIME), NULL);
404                         if (r == -ENOENT)
405                                 /* The calendar event is in the past — let's warn about this, but install it
406                                  * anyway as is. The service manager will trigger the service right away.
407                                  * Moreover, the server side might have a different clock or timezone than we
408                                  * do, hence it should decide when or whether to run something. */
409                                 log_warning("Specified calendar expression is in the past, proceeding anyway.");
410                         else if (r < 0)
411                                 return log_error_errno(r, "Failed to calculate next time calendar expression elapses: %m");
412 
413                         r = add_timer_property("OnCalendar", optarg);
414                         if (r < 0)
415                                 return r;
416 
417                         arg_with_timer = true;
418                         break;
419                 }
420 
421                 case ARG_ON_TIMEZONE_CHANGE:
422                         r = add_timer_property("OnTimezoneChange", "yes");
423                         if (r < 0)
424                                 return r;
425 
426                         arg_with_timer = true;
427                         break;
428 
429                 case ARG_ON_CLOCK_CHANGE:
430                         r = add_timer_property("OnClockChange", "yes");
431                         if (r < 0)
432                                 return r;
433 
434                         arg_with_timer = true;
435                         break;
436 
437                 case ARG_TIMER_PROPERTY:
438 
439                         if (strv_extend(&arg_timer_property, optarg) < 0)
440                                 return log_oom();
441 
442                         arg_with_timer = arg_with_timer ||
443                                 STARTSWITH_SET(optarg,
444                                                "OnActiveSec=",
445                                                "OnBootSec=",
446                                                "OnStartupSec=",
447                                                "OnUnitActiveSec=",
448                                                "OnUnitInactiveSec=",
449                                                "OnCalendar=");
450                         break;
451 
452                 case ARG_PATH_PROPERTY:
453 
454                         if (strv_extend(&arg_path_property, optarg) < 0)
455                                 return log_oom();
456 
457                         break;
458 
459                 case ARG_SOCKET_PROPERTY:
460 
461                         if (strv_extend(&arg_socket_property, optarg) < 0)
462                                 return log_oom();
463 
464                         break;
465 
466                 case ARG_NO_BLOCK:
467                         arg_no_block = true;
468                         break;
469 
470                 case ARG_WAIT:
471                         arg_wait = true;
472                         break;
473 
474                 case ARG_WORKING_DIRECTORY:
475                         r = parse_path_argument(optarg, true, &arg_working_directory);
476                         if (r < 0)
477                                 return r;
478 
479                         break;
480 
481                 case 'd': {
482                         _cleanup_free_ char *p = NULL;
483 
484                         r = safe_getcwd(&p);
485                         if (r < 0)
486                                 return log_error_errno(r, "Failed to get current working directory: %m");
487 
488                         if (empty_or_root(p))
489                                 arg_working_directory = mfree(arg_working_directory);
490                         else
491                                 free_and_replace(arg_working_directory, p);
492                         break;
493                 }
494 
495                 case 'G':
496                         arg_aggressive_gc = true;
497                         break;
498 
499                 case 'S':
500                         arg_shell = true;
501                         break;
502 
503                 case '?':
504                         return -EINVAL;
505 
506                 default:
507                         assert_not_reached();
508                 }
509 
510         /* If we are talking to the per-user instance PolicyKit isn't going to help */
511         if (arg_user)
512                 arg_ask_password = false;
513 
514         with_trigger = !!arg_path_property || !!arg_socket_property || arg_with_timer;
515 
516         /* currently, only single trigger (path, socket, timer) unit can be created simultaneously */
517         if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) arg_with_timer > 1)
518                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
519                                        "Only single trigger (path, socket, timer) unit can be created.");
520 
521         if (arg_shell) {
522                 /* If --shell is imply --pty --pipe --same-dir --service-type=exec --wait --collect, unless otherwise
523                  * specified. */
524 
525                 if (!arg_scope) {
526                         if (arg_stdio == ARG_STDIO_NONE)
527                                 arg_stdio = ARG_STDIO_AUTO;
528 
529                         if (!arg_working_directory) {
530                                 r = safe_getcwd(&arg_working_directory);
531                                 if (r < 0)
532                                         return log_error_errno(r, "Failed to get current working directory: %m");
533                         }
534 
535                         if (!arg_service_type) {
536                                 arg_service_type = strdup("exec");
537                                 if (!arg_service_type)
538                                         return log_oom();
539                         }
540 
541                         arg_wait = true;
542                 }
543 
544                 arg_aggressive_gc = true;
545         }
546 
547         if (arg_stdio == ARG_STDIO_AUTO)
548                 /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
549                  * to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
550                  * pipeline, but we are neatly interactive with tty-level isolation otherwise. */
551                 arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
552                         ARG_STDIO_PTY :
553                         ARG_STDIO_DIRECT;
554 
555         if (argc > optind) {
556                 char **l;
557 
558                 if (arg_shell)
559                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "If --shell is used, no command line is expected.");
560 
561                 l = strv_copy(argv + optind);
562                 if (!l)
563                         return log_oom();
564 
565                 strv_free_and_replace(arg_cmdline, l);
566 
567         } else if (arg_shell) {
568                 _cleanup_free_ char *s = NULL;
569                 char **l;
570 
571                 r = get_shell(&s);
572                 if (r < 0)
573                         return log_error_errno(r, "Failed to determine shell: %m");
574 
575                 l = strv_new(s);
576                 if (!l)
577                         return log_oom();
578 
579                 strv_free_and_replace(arg_cmdline, l);
580 
581         } else if (!arg_unit || !with_trigger)
582                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Command line to execute required.");
583 
584         if (arg_user && arg_transport == BUS_TRANSPORT_REMOTE)
585                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
586                                        "Execution in user context is not supported on remote systems.");
587 
588         if (arg_scope && arg_transport == BUS_TRANSPORT_REMOTE)
589                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
590                                        "Scope execution is not supported on remote systems.");
591 
592         if (arg_scope && (arg_remain_after_exit || arg_service_type))
593                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
594                                        "--remain-after-exit and --service-type= are not supported in --scope mode.");
595 
596         if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope))
597                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
598                                        "--pty/--pipe is not compatible in timer or --scope mode.");
599 
600         if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE)
601                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
602                                        "--pty/--pipe is only supported when connecting to the local system or containers.");
603 
604         if (arg_stdio != ARG_STDIO_NONE && arg_no_block)
605                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
606                                        "--pty/--pipe is not compatible with --no-block.");
607 
608         if (arg_scope && with_trigger)
609                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
610                                        "Path, socket or timer options are not supported in --scope mode.");
611 
612         if (arg_timer_property && !arg_with_timer)
613                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
614                                        "--timer-property= has no effect without any other timer options.");
615 
616         if (arg_wait) {
617                 if (arg_no_block)
618                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
619                                                "--wait may not be combined with --no-block.");
620 
621                 if (with_trigger)
622                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
623                                                "--wait may not be combined with path, socket or timer operations.");
624 
625                 if (arg_scope)
626                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
627                                                "--wait may not be combined with --scope.");
628         }
629 
630         return 1;
631 }
632 
transient_unit_set_properties(sd_bus_message * m,UnitType t,char ** properties)633 static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
634         int r;
635 
636         r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
637         if (r < 0)
638                 return bus_log_create_error(r);
639 
640         if (arg_aggressive_gc) {
641                 r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
642                 if (r < 0)
643                         return bus_log_create_error(r);
644         }
645 
646         r = bus_append_unit_property_assignment_many(m, t, properties);
647         if (r < 0)
648                 return r;
649 
650         return 0;
651 }
652 
transient_cgroup_set_properties(sd_bus_message * m)653 static int transient_cgroup_set_properties(sd_bus_message *m) {
654         _cleanup_free_ char *name = NULL;
655         _cleanup_free_ char *slice = NULL;
656         int r;
657         assert(m);
658 
659         if (arg_slice_inherit) {
660                 char *end;
661 
662                 if (arg_user)
663                         r = cg_pid_get_user_slice(0, &name);
664                 else
665                         r = cg_pid_get_slice(0, &name);
666                 if (r < 0)
667                         return log_error_errno(r, "Failed to get PID slice: %m");
668 
669                 end = endswith(name, ".slice");
670                 if (!end)
671                         return -ENXIO;
672                 *end = 0;
673         }
674 
675         if (!isempty(arg_slice) && !strextend_with_separator(&name, "-", arg_slice))
676                 return log_oom();
677 
678         if (!name)
679                 return 0;
680 
681         r = unit_name_mangle_with_suffix(name, "as slice",
682                                          arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
683                                          ".slice", &slice);
684         if (r < 0)
685                 return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
686 
687         r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
688         if (r < 0)
689                 return bus_log_create_error(r);
690 
691         return 0;
692 }
693 
transient_kill_set_properties(sd_bus_message * m)694 static int transient_kill_set_properties(sd_bus_message *m) {
695         int r;
696 
697         assert(m);
698 
699         if (arg_send_sighup) {
700                 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
701                 if (r < 0)
702                         return bus_log_create_error(r);
703         }
704 
705         return 0;
706 }
707 
transient_service_set_properties(sd_bus_message * m,const char * pty_path)708 static int transient_service_set_properties(sd_bus_message *m, const char *pty_path) {
709         bool send_term = false;
710         int r;
711 
712         assert(m);
713 
714         r = transient_unit_set_properties(m, UNIT_SERVICE, arg_property);
715         if (r < 0)
716                 return r;
717 
718         r = transient_kill_set_properties(m);
719         if (r < 0)
720                 return r;
721 
722         r = transient_cgroup_set_properties(m);
723         if (r < 0)
724                 return r;
725 
726         if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
727                 r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
728                 if (r < 0)
729                         return bus_log_create_error(r);
730         }
731 
732         if (arg_remain_after_exit) {
733                 r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
734                 if (r < 0)
735                         return bus_log_create_error(r);
736         }
737 
738         if (arg_service_type) {
739                 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type);
740                 if (r < 0)
741                         return bus_log_create_error(r);
742         }
743 
744         if (arg_exec_user) {
745                 r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user);
746                 if (r < 0)
747                         return bus_log_create_error(r);
748         }
749 
750         if (arg_exec_group) {
751                 r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group);
752                 if (r < 0)
753                         return bus_log_create_error(r);
754         }
755 
756         if (arg_nice_set) {
757                 r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
758                 if (r < 0)
759                         return bus_log_create_error(r);
760         }
761 
762         if (arg_working_directory) {
763                 r = sd_bus_message_append(m, "(sv)", "WorkingDirectory", "s", arg_working_directory);
764                 if (r < 0)
765                         return bus_log_create_error(r);
766         }
767 
768         if (pty_path) {
769                 r = sd_bus_message_append(m,
770                                           "(sv)(sv)(sv)(sv)",
771                                           "StandardInput", "s", "tty",
772                                           "StandardOutput", "s", "tty",
773                                           "StandardError", "s", "tty",
774                                           "TTYPath", "s", pty_path);
775                 if (r < 0)
776                         return bus_log_create_error(r);
777 
778                 send_term = true;
779 
780         } else if (arg_stdio == ARG_STDIO_DIRECT) {
781                 r = sd_bus_message_append(m,
782                                           "(sv)(sv)(sv)",
783                                           "StandardInputFileDescriptor", "h", STDIN_FILENO,
784                                           "StandardOutputFileDescriptor", "h", STDOUT_FILENO,
785                                           "StandardErrorFileDescriptor", "h", STDERR_FILENO);
786                 if (r < 0)
787                         return bus_log_create_error(r);
788 
789                 send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
790         }
791 
792         if (send_term) {
793                 const char *e;
794 
795                 e = getenv("TERM");
796                 if (e) {
797                         _cleanup_free_ char *n = NULL;
798 
799                         n = strjoin("TERM=", e);
800                         if (!n)
801                                 return log_oom();
802 
803                         r = sd_bus_message_append(m,
804                                                   "(sv)",
805                                                   "Environment", "as", 1, n);
806                         if (r < 0)
807                                 return bus_log_create_error(r);
808                 }
809         }
810 
811         if (!strv_isempty(arg_environment)) {
812                 r = sd_bus_message_open_container(m, 'r', "sv");
813                 if (r < 0)
814                         return bus_log_create_error(r);
815 
816                 r = sd_bus_message_append(m, "s", "Environment");
817                 if (r < 0)
818                         return bus_log_create_error(r);
819 
820                 r = sd_bus_message_open_container(m, 'v', "as");
821                 if (r < 0)
822                         return bus_log_create_error(r);
823 
824                 r = sd_bus_message_append_strv(m, arg_environment);
825                 if (r < 0)
826                         return bus_log_create_error(r);
827 
828                 r = sd_bus_message_close_container(m);
829                 if (r < 0)
830                         return bus_log_create_error(r);
831 
832                 r = sd_bus_message_close_container(m);
833                 if (r < 0)
834                         return bus_log_create_error(r);
835         }
836 
837         /* Exec container */
838         if (!strv_isempty(arg_cmdline)) {
839                 r = sd_bus_message_open_container(m, 'r', "sv");
840                 if (r < 0)
841                         return bus_log_create_error(r);
842 
843                 r = sd_bus_message_append(m, "s", "ExecStart");
844                 if (r < 0)
845                         return bus_log_create_error(r);
846 
847                 r = sd_bus_message_open_container(m, 'v', "a(sasb)");
848                 if (r < 0)
849                         return bus_log_create_error(r);
850 
851                 r = sd_bus_message_open_container(m, 'a', "(sasb)");
852                 if (r < 0)
853                         return bus_log_create_error(r);
854 
855                 r = sd_bus_message_open_container(m, 'r', "sasb");
856                 if (r < 0)
857                         return bus_log_create_error(r);
858 
859                 r = sd_bus_message_append(m, "s", arg_cmdline[0]);
860                 if (r < 0)
861                         return bus_log_create_error(r);
862 
863                 r = sd_bus_message_append_strv(m, arg_cmdline);
864                 if (r < 0)
865                         return bus_log_create_error(r);
866 
867                 r = sd_bus_message_append(m, "b", false);
868                 if (r < 0)
869                         return bus_log_create_error(r);
870 
871                 r = sd_bus_message_close_container(m);
872                 if (r < 0)
873                         return bus_log_create_error(r);
874 
875                 r = sd_bus_message_close_container(m);
876                 if (r < 0)
877                         return bus_log_create_error(r);
878 
879                 r = sd_bus_message_close_container(m);
880                 if (r < 0)
881                         return bus_log_create_error(r);
882 
883                 r = sd_bus_message_close_container(m);
884                 if (r < 0)
885                         return bus_log_create_error(r);
886         }
887 
888         return 0;
889 }
890 
transient_scope_set_properties(sd_bus_message * m)891 static int transient_scope_set_properties(sd_bus_message *m) {
892         int r;
893 
894         assert(m);
895 
896         r = transient_unit_set_properties(m, UNIT_SCOPE, arg_property);
897         if (r < 0)
898                 return r;
899 
900         r = transient_kill_set_properties(m);
901         if (r < 0)
902                 return r;
903 
904         r = transient_cgroup_set_properties(m);
905         if (r < 0)
906                 return r;
907 
908         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached());
909         if (r < 0)
910                 return bus_log_create_error(r);
911 
912         return 0;
913 }
914 
transient_timer_set_properties(sd_bus_message * m)915 static int transient_timer_set_properties(sd_bus_message *m) {
916         int r;
917 
918         assert(m);
919 
920         r = transient_unit_set_properties(m, UNIT_TIMER, arg_timer_property);
921         if (r < 0)
922                 return r;
923 
924         /* Automatically clean up our transient timers */
925         r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false);
926         if (r < 0)
927                 return bus_log_create_error(r);
928 
929         return 0;
930 }
931 
make_unit_name(sd_bus * bus,UnitType t,char ** ret)932 static int make_unit_name(sd_bus *bus, UnitType t, char **ret) {
933         const char *unique, *id;
934         char *p;
935         int r;
936 
937         assert(bus);
938         assert(t >= 0);
939         assert(t < _UNIT_TYPE_MAX);
940 
941         r = sd_bus_get_unique_name(bus, &unique);
942         if (r < 0) {
943                 sd_id128_t rnd;
944 
945                 /* We couldn't get the unique name, which is a pretty
946                  * common case if we are connected to systemd
947                  * directly. In that case, just pick a random uuid as
948                  * name */
949 
950                 r = sd_id128_randomize(&rnd);
951                 if (r < 0)
952                         return log_error_errno(r, "Failed to generate random run unit name: %m");
953 
954                 if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0)
955                         return log_oom();
956 
957                 return 0;
958         }
959 
960         /* We managed to get the unique name, then let's use that to name our transient units. */
961 
962         id = startswith(unique, ":1."); /* let' strip the usual prefix */
963         if (!id)
964                 id = startswith(unique, ":"); /* the spec only requires things to start with a colon, hence
965                                                * let's add a generic fallback for that. */
966         if (!id)
967                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
968                                        "Unique name %s has unexpected format.",
969                                        unique);
970 
971         p = strjoin("run-u", id, ".", unit_type_to_string(t));
972         if (!p)
973                 return log_oom();
974 
975         *ret = p;
976         return 0;
977 }
978 
979 typedef struct RunContext {
980         sd_bus *bus;
981         sd_event *event;
982         PTYForward *forward;
983         sd_bus_slot *match;
984 
985         /* Current state of the unit */
986         char *active_state;
987         bool has_job;
988 
989         /* The exit data of the unit */
990         uint64_t inactive_exit_usec;
991         uint64_t inactive_enter_usec;
992         char *result;
993         uint64_t cpu_usage_nsec;
994         uint64_t ip_ingress_bytes;
995         uint64_t ip_egress_bytes;
996         uint64_t io_read_bytes;
997         uint64_t io_write_bytes;
998         uint32_t exit_code;
999         uint32_t exit_status;
1000 } RunContext;
1001 
run_context_free(RunContext * c)1002 static void run_context_free(RunContext *c) {
1003         assert(c);
1004 
1005         c->forward = pty_forward_free(c->forward);
1006         c->match = sd_bus_slot_unref(c->match);
1007         c->bus = sd_bus_unref(c->bus);
1008         c->event = sd_event_unref(c->event);
1009 
1010         free(c->active_state);
1011         free(c->result);
1012 }
1013 
run_context_check_done(RunContext * c)1014 static void run_context_check_done(RunContext *c) {
1015         bool done;
1016 
1017         assert(c);
1018 
1019         if (c->match)
1020                 done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
1021         else
1022                 done = true;
1023 
1024         if (c->forward && done) /* If the service is gone, it's time to drain the output */
1025                 done = pty_forward_drain(c->forward);
1026 
1027         if (done)
1028                 sd_event_exit(c->event, EXIT_SUCCESS);
1029 }
1030 
map_job(sd_bus * bus,const char * member,sd_bus_message * m,sd_bus_error * error,void * userdata)1031 static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1032         bool *b = userdata;
1033         const char *job;
1034         uint32_t id;
1035         int r;
1036 
1037         r = sd_bus_message_read(m, "(uo)", &id, &job);
1038         if (r < 0)
1039                 return r;
1040 
1041         *b = id != 0 || !streq(job, "/");
1042         return 0;
1043 }
1044 
run_context_update(RunContext * c,const char * path)1045 static int run_context_update(RunContext *c, const char *path) {
1046 
1047         static const struct bus_properties_map map[] = {
1048                 { "ActiveState",                     "s",    NULL,    offsetof(RunContext, active_state)        },
1049                 { "InactiveExitTimestampMonotonic",  "t",    NULL,    offsetof(RunContext, inactive_exit_usec)  },
1050                 { "InactiveEnterTimestampMonotonic", "t",    NULL,    offsetof(RunContext, inactive_enter_usec) },
1051                 { "Result",                          "s",    NULL,    offsetof(RunContext, result)              },
1052                 { "ExecMainCode",                    "i",    NULL,    offsetof(RunContext, exit_code)           },
1053                 { "ExecMainStatus",                  "i",    NULL,    offsetof(RunContext, exit_status)         },
1054                 { "CPUUsageNSec",                    "t",    NULL,    offsetof(RunContext, cpu_usage_nsec)      },
1055                 { "IPIngressBytes",                  "t",    NULL,    offsetof(RunContext, ip_ingress_bytes)    },
1056                 { "IPEgressBytes",                   "t",    NULL,    offsetof(RunContext, ip_egress_bytes)     },
1057                 { "IOReadBytes",                     "t",    NULL,    offsetof(RunContext, io_read_bytes)       },
1058                 { "IOWriteBytes",                    "t",    NULL,    offsetof(RunContext, io_write_bytes)      },
1059                 { "Job",                             "(uo)", map_job, offsetof(RunContext, has_job)             },
1060                 {}
1061         };
1062 
1063         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1064         int r;
1065 
1066         r = bus_map_all_properties(c->bus,
1067                                    "org.freedesktop.systemd1",
1068                                    path,
1069                                    map,
1070                                    BUS_MAP_STRDUP,
1071                                    &error,
1072                                    NULL,
1073                                    c);
1074         if (r < 0) {
1075                 sd_event_exit(c->event, EXIT_FAILURE);
1076                 return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r));
1077         }
1078 
1079         run_context_check_done(c);
1080         return 0;
1081 }
1082 
on_properties_changed(sd_bus_message * m,void * userdata,sd_bus_error * error)1083 static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1084         RunContext *c = userdata;
1085 
1086         assert(m);
1087         assert(c);
1088 
1089         return run_context_update(c, sd_bus_message_get_path(m));
1090 }
1091 
pty_forward_handler(PTYForward * f,int rcode,void * userdata)1092 static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
1093         RunContext *c = userdata;
1094 
1095         assert(f);
1096 
1097         if (rcode < 0) {
1098                 sd_event_exit(c->event, EXIT_FAILURE);
1099                 return log_error_errno(rcode, "Error on PTY forwarding logic: %m");
1100         }
1101 
1102         run_context_check_done(c);
1103         return 0;
1104 }
1105 
start_transient_service(sd_bus * bus,int * retval)1106 static int start_transient_service(
1107                 sd_bus *bus,
1108                 int *retval) {
1109 
1110         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1111         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1112         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1113         _cleanup_free_ char *service = NULL, *pty_path = NULL;
1114         _cleanup_close_ int master = -1;
1115         int r;
1116 
1117         assert(bus);
1118         assert(retval);
1119 
1120         if (arg_stdio == ARG_STDIO_PTY) {
1121 
1122                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
1123                         master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1124                         if (master < 0)
1125                                 return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
1126 
1127                         r = ptsname_malloc(master, &pty_path);
1128                         if (r < 0)
1129                                 return log_error_errno(r, "Failed to determine tty name: %m");
1130 
1131                         if (unlockpt(master) < 0)
1132                                 return log_error_errno(errno, "Failed to unlock tty: %m");
1133 
1134                 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
1135                         _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
1136                         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL;
1137                         const char *s;
1138 
1139                         r = sd_bus_default_system(&system_bus);
1140                         if (r < 0)
1141                                 return log_error_errno(r, "Failed to connect to system bus: %m");
1142 
1143                         r = sd_bus_call_method(system_bus,
1144                                                "org.freedesktop.machine1",
1145                                                "/org/freedesktop/machine1",
1146                                                "org.freedesktop.machine1.Manager",
1147                                                "OpenMachinePTY",
1148                                                &error,
1149                                                &pty_reply,
1150                                                "s", arg_host);
1151                         if (r < 0)
1152                                 return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, r));
1153 
1154                         r = sd_bus_message_read(pty_reply, "hs", &master, &s);
1155                         if (r < 0)
1156                                 return bus_log_parse_error(r);
1157 
1158                         master = fcntl(master, F_DUPFD_CLOEXEC, 3);
1159                         if (master < 0)
1160                                 return log_error_errno(errno, "Failed to duplicate master fd: %m");
1161 
1162                         pty_path = strdup(s);
1163                         if (!pty_path)
1164                                 return log_oom();
1165                 } else
1166                         assert_not_reached();
1167         }
1168 
1169         /* Optionally, wait for the start job to complete. If we are supposed to read the service's stdin
1170          * lets skip this however, because we should start that already when the start job is running, and
1171          * there's little point in waiting for the start job to complete in that case anyway, as we'll wait
1172          * for EOF anyway, which is going to be much later. */
1173         if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) {
1174                 r = bus_wait_for_jobs_new(bus, &w);
1175                 if (r < 0)
1176                         return log_error_errno(r, "Could not watch jobs: %m");
1177         }
1178 
1179         if (arg_unit) {
1180                 r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1181                                                  arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1182                                                  ".service", &service);
1183                 if (r < 0)
1184                         return log_error_errno(r, "Failed to mangle unit name: %m");
1185         } else {
1186                 r = make_unit_name(bus, UNIT_SERVICE, &service);
1187                 if (r < 0)
1188                         return r;
1189         }
1190 
1191         r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1192         if (r < 0)
1193                 return bus_log_create_error(r);
1194 
1195         r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1196         if (r < 0)
1197                 return bus_log_create_error(r);
1198 
1199         /* Name and mode */
1200         r = sd_bus_message_append(m, "ss", service, "fail");
1201         if (r < 0)
1202                 return bus_log_create_error(r);
1203 
1204         /* Properties */
1205         r = sd_bus_message_open_container(m, 'a', "(sv)");
1206         if (r < 0)
1207                 return bus_log_create_error(r);
1208 
1209         r = transient_service_set_properties(m, pty_path);
1210         if (r < 0)
1211                 return r;
1212 
1213         r = sd_bus_message_close_container(m);
1214         if (r < 0)
1215                 return bus_log_create_error(r);
1216 
1217         /* Auxiliary units */
1218         r = sd_bus_message_append(m, "a(sa(sv))", 0);
1219         if (r < 0)
1220                 return bus_log_create_error(r);
1221 
1222         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1223 
1224         r = sd_bus_call(bus, m, 0, &error, &reply);
1225         if (r < 0)
1226                 return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
1227 
1228         if (w) {
1229                 const char *object;
1230 
1231                 r = sd_bus_message_read(reply, "o", &object);
1232                 if (r < 0)
1233                         return bus_log_parse_error(r);
1234 
1235                 r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_user ? STRV_MAKE_CONST("--user") : NULL);
1236                 if (r < 0)
1237                         return r;
1238         }
1239 
1240         if (!arg_quiet)
1241                 log_info("Running as unit: %s", service);
1242 
1243         if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
1244                 _cleanup_(run_context_free) RunContext c = {
1245                         .cpu_usage_nsec = NSEC_INFINITY,
1246                         .ip_ingress_bytes = UINT64_MAX,
1247                         .ip_egress_bytes = UINT64_MAX,
1248                         .io_read_bytes = UINT64_MAX,
1249                         .io_write_bytes = UINT64_MAX,
1250                         .inactive_exit_usec = USEC_INFINITY,
1251                         .inactive_enter_usec = USEC_INFINITY,
1252                 };
1253                 _cleanup_free_ char *path = NULL;
1254 
1255                 c.bus = sd_bus_ref(bus);
1256 
1257                 r = sd_event_default(&c.event);
1258                 if (r < 0)
1259                         return log_error_errno(r, "Failed to get event loop: %m");
1260 
1261                 if (master >= 0) {
1262                         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
1263                         (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
1264                         (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);
1265 
1266                         if (!arg_quiet)
1267                                 log_info("Press ^] three times within 1s to disconnect TTY.");
1268 
1269                         r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward);
1270                         if (r < 0)
1271                                 return log_error_errno(r, "Failed to create PTY forwarder: %m");
1272 
1273                         pty_forward_set_handler(c.forward, pty_forward_handler, &c);
1274 
1275                         /* Make sure to process any TTY events before we process bus events */
1276                         (void) pty_forward_set_priority(c.forward, SD_EVENT_PRIORITY_IMPORTANT);
1277                 }
1278 
1279                 path = unit_dbus_path_from_name(service);
1280                 if (!path)
1281                         return log_oom();
1282 
1283                 r = sd_bus_match_signal_async(
1284                                 bus,
1285                                 &c.match,
1286                                 "org.freedesktop.systemd1",
1287                                 path,
1288                                 "org.freedesktop.DBus.Properties",
1289                                 "PropertiesChanged",
1290                                 on_properties_changed, NULL, &c);
1291                 if (r < 0)
1292                         return log_error_errno(r, "Failed to request properties changed signal match: %m");
1293 
1294                 r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL);
1295                 if (r < 0)
1296                         return log_error_errno(r, "Failed to attach bus to event loop: %m");
1297 
1298                 r = run_context_update(&c, path);
1299                 if (r < 0)
1300                         return r;
1301 
1302                 r = sd_event_loop(c.event);
1303                 if (r < 0)
1304                         return log_error_errno(r, "Failed to run event loop: %m");
1305 
1306                 if (c.forward) {
1307                         char last_char = 0;
1308 
1309                         r = pty_forward_get_last_char(c.forward, &last_char);
1310                         if (r >= 0 && !arg_quiet && last_char != '\n')
1311                                 fputc('\n', stdout);
1312                 }
1313 
1314                 if (arg_wait && !arg_quiet) {
1315 
1316                         /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its
1317                          * original settings (i.e. proper line breaks), so that we can show the summary in a pretty
1318                          * way. */
1319                         c.forward = pty_forward_free(c.forward);
1320 
1321                         if (!isempty(c.result))
1322                                 log_info("Finished with result: %s", strna(c.result));
1323 
1324                         if (c.exit_code == CLD_EXITED)
1325                                 log_info("Main processes terminated with: code=%s/status=%i",
1326                                          sigchld_code_to_string(c.exit_code), c.exit_status);
1327                         else if (c.exit_code > 0)
1328                                 log_info("Main processes terminated with: code=%s/status=%s",
1329                                          sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
1330 
1331                         if (timestamp_is_set(c.inactive_enter_usec) &&
1332                             timestamp_is_set(c.inactive_exit_usec) &&
1333                             c.inactive_enter_usec > c.inactive_exit_usec)
1334                                 log_info("Service runtime: %s",
1335                                          FORMAT_TIMESPAN(c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
1336 
1337                         if (c.cpu_usage_nsec != NSEC_INFINITY)
1338                                 log_info("CPU time consumed: %s",
1339                                          FORMAT_TIMESPAN(DIV_ROUND_UP(c.cpu_usage_nsec, NSEC_PER_USEC), USEC_PER_MSEC));
1340 
1341                         if (c.ip_ingress_bytes != UINT64_MAX)
1342                                 log_info("IP traffic received: %s", FORMAT_BYTES(c.ip_ingress_bytes));
1343 
1344                         if (c.ip_egress_bytes != UINT64_MAX)
1345                                 log_info("IP traffic sent: %s", FORMAT_BYTES(c.ip_egress_bytes));
1346 
1347                         if (c.io_read_bytes != UINT64_MAX)
1348                                 log_info("IO bytes read: %s", FORMAT_BYTES(c.io_read_bytes));
1349 
1350                         if (c.io_write_bytes != UINT64_MAX)
1351                                 log_info("IO bytes written: %s", FORMAT_BYTES(c.io_write_bytes));
1352                 }
1353 
1354                 /* Try to propagate the service's return value. But if the service defines
1355                  * e.g. SuccessExitStatus, honour this, and return 0 to mean "success". */
1356                 if (streq_ptr(c.result, "success"))
1357                         *retval = 0;
1358                 else if (streq_ptr(c.result, "exit-code") && c.exit_status > 0)
1359                         *retval = c.exit_status;
1360                 else if (streq_ptr(c.result, "signal"))
1361                         *retval = EXIT_EXCEPTION;
1362                 else
1363                         *retval = EXIT_FAILURE;
1364         }
1365 
1366         return 0;
1367 }
1368 
acquire_invocation_id(sd_bus * bus,sd_id128_t * ret)1369 static int acquire_invocation_id(sd_bus *bus, sd_id128_t *ret) {
1370         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1371         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1372         const void *p;
1373         size_t l;
1374         int r;
1375 
1376         assert(bus);
1377         assert(ret);
1378 
1379         r = sd_bus_get_property(bus,
1380                                 "org.freedesktop.systemd1",
1381                                 "/org/freedesktop/systemd1/unit/self",
1382                                 "org.freedesktop.systemd1.Unit",
1383                                 "InvocationID",
1384                                 &error,
1385                                 &reply,
1386                                 "ay");
1387         if (r < 0)
1388                 return log_error_errno(r, "Failed to request invocation ID for scope: %s", bus_error_message(&error, r));
1389 
1390         r = sd_bus_message_read_array(reply, 'y', &p, &l);
1391         if (r < 0)
1392                 return bus_log_parse_error(r);
1393 
1394         if (l != sizeof(sd_id128_t))
1395                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid UUID size, %zu != %zu.", l, sizeof(sd_id128_t));
1396 
1397         memcpy(ret, p, l);
1398         return 0;
1399 }
1400 
start_transient_scope(sd_bus * bus)1401 static int start_transient_scope(sd_bus *bus) {
1402         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1403         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1404         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1405         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
1406         _cleanup_free_ char *scope = NULL;
1407         const char *object = NULL;
1408         sd_id128_t invocation_id;
1409         int r;
1410 
1411         assert(bus);
1412         assert(!strv_isempty(arg_cmdline));
1413 
1414         r = bus_wait_for_jobs_new(bus, &w);
1415         if (r < 0)
1416                 return log_oom();
1417 
1418         if (arg_unit) {
1419                 r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1420                                                  arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1421                                                  ".scope", &scope);
1422                 if (r < 0)
1423                         return log_error_errno(r, "Failed to mangle scope name: %m");
1424         } else {
1425                 r = make_unit_name(bus, UNIT_SCOPE, &scope);
1426                 if (r < 0)
1427                         return r;
1428         }
1429 
1430         r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1431         if (r < 0)
1432                 return bus_log_create_error(r);
1433 
1434         r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1435         if (r < 0)
1436                 return bus_log_create_error(r);
1437 
1438         /* Name and Mode */
1439         r = sd_bus_message_append(m, "ss", scope, "fail");
1440         if (r < 0)
1441                 return bus_log_create_error(r);
1442 
1443         /* Properties */
1444         r = sd_bus_message_open_container(m, 'a', "(sv)");
1445         if (r < 0)
1446                 return bus_log_create_error(r);
1447 
1448         r = transient_scope_set_properties(m);
1449         if (r < 0)
1450                 return r;
1451 
1452         r = sd_bus_message_close_container(m);
1453         if (r < 0)
1454                 return bus_log_create_error(r);
1455 
1456         /* Auxiliary units */
1457         r = sd_bus_message_append(m, "a(sa(sv))", 0);
1458         if (r < 0)
1459                 return bus_log_create_error(r);
1460 
1461         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1462 
1463         r = sd_bus_call(bus, m, 0, &error, &reply);
1464         if (r < 0)
1465                 return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, r));
1466 
1467         r = sd_bus_message_read(reply, "o", &object);
1468         if (r < 0)
1469                 return bus_log_parse_error(r);
1470 
1471         r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_user ? STRV_MAKE_CONST("--user") : NULL);
1472         if (r < 0)
1473                 return r;
1474 
1475         r = acquire_invocation_id(bus, &invocation_id);
1476         if (r < 0)
1477                 return r;
1478 
1479         r = strv_extendf(&user_env, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(invocation_id));
1480         if (r < 0)
1481                 return log_oom();
1482 
1483         if (arg_nice_set) {
1484                 if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
1485                         return log_error_errno(errno, "Failed to set nice level: %m");
1486         }
1487 
1488         if (arg_exec_group) {
1489                 gid_t gid;
1490 
1491                 r = get_group_creds(&arg_exec_group, &gid, 0);
1492                 if (r < 0)
1493                         return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);
1494 
1495                 if (setresgid(gid, gid, gid) < 0)
1496                         return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1497         }
1498 
1499         if (arg_exec_user) {
1500                 const char *home, *shell;
1501                 uid_t uid;
1502                 gid_t gid;
1503 
1504                 r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS);
1505                 if (r < 0)
1506                         return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);
1507 
1508                 if (home) {
1509                         r = strv_extendf(&user_env, "HOME=%s", home);
1510                         if (r < 0)
1511                                 return log_oom();
1512                 }
1513 
1514                 if (shell) {
1515                         r = strv_extendf(&user_env, "SHELL=%s", shell);
1516                         if (r < 0)
1517                                 return log_oom();
1518                 }
1519 
1520                 r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
1521                 if (r < 0)
1522                         return log_oom();
1523 
1524                 r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
1525                 if (r < 0)
1526                         return log_oom();
1527 
1528                 if (!arg_exec_group) {
1529                         if (setresgid(gid, gid, gid) < 0)
1530                                 return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
1531                 }
1532 
1533                 if (setresuid(uid, uid, uid) < 0)
1534                         return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
1535         }
1536 
1537         env = strv_env_merge(environ, user_env, arg_environment);
1538         if (!env)
1539                 return log_oom();
1540 
1541         if (!arg_quiet)
1542                 log_info("Running scope as unit: %s", scope);
1543 
1544         execvpe(arg_cmdline[0], arg_cmdline, env);
1545 
1546         return log_error_errno(errno, "Failed to execute: %m");
1547 }
1548 
start_transient_trigger(sd_bus * bus,const char * suffix)1549 static int start_transient_trigger(
1550                 sd_bus *bus,
1551                 const char *suffix) {
1552 
1553         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1554         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1555         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1556         _cleanup_free_ char *trigger = NULL, *service = NULL;
1557         const char *object = NULL;
1558         int r;
1559 
1560         assert(bus);
1561 
1562         r = bus_wait_for_jobs_new(bus, &w);
1563         if (r < 0)
1564                 return log_oom();
1565 
1566         if (arg_unit) {
1567                 switch (unit_name_to_type(arg_unit)) {
1568 
1569                 case UNIT_SERVICE:
1570                         service = strdup(arg_unit);
1571                         if (!service)
1572                                 return log_oom();
1573 
1574                         r = unit_name_change_suffix(service, suffix, &trigger);
1575                         if (r < 0)
1576                                 return log_error_errno(r, "Failed to change unit suffix: %m");
1577                         break;
1578 
1579                 case UNIT_TIMER:
1580                         trigger = strdup(arg_unit);
1581                         if (!trigger)
1582                                 return log_oom();
1583 
1584                         r = unit_name_change_suffix(trigger, ".service", &service);
1585                         if (r < 0)
1586                                 return log_error_errno(r, "Failed to change unit suffix: %m");
1587                         break;
1588 
1589                 default:
1590                         r = unit_name_mangle_with_suffix(arg_unit, "as unit",
1591                                                          arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1592                                                          ".service", &service);
1593                         if (r < 0)
1594                                 return log_error_errno(r, "Failed to mangle unit name: %m");
1595 
1596                         r = unit_name_mangle_with_suffix(arg_unit, "as trigger",
1597                                                          arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
1598                                                          suffix, &trigger);
1599                         if (r < 0)
1600                                 return log_error_errno(r, "Failed to mangle unit name: %m");
1601 
1602                         break;
1603                 }
1604         } else {
1605                 r = make_unit_name(bus, UNIT_SERVICE, &service);
1606                 if (r < 0)
1607                         return r;
1608 
1609                 r = unit_name_change_suffix(service, suffix, &trigger);
1610                 if (r < 0)
1611                         return log_error_errno(r, "Failed to change unit suffix: %m");
1612         }
1613 
1614         r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
1615         if (r < 0)
1616                 return bus_log_create_error(r);
1617 
1618         r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1619         if (r < 0)
1620                 return bus_log_create_error(r);
1621 
1622         /* Name and Mode */
1623         r = sd_bus_message_append(m, "ss", trigger, "fail");
1624         if (r < 0)
1625                 return bus_log_create_error(r);
1626 
1627         /* Properties */
1628         r = sd_bus_message_open_container(m, 'a', "(sv)");
1629         if (r < 0)
1630                 return bus_log_create_error(r);
1631 
1632         if (streq(suffix, ".path"))
1633                 r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property);
1634         else if (streq(suffix, ".socket"))
1635                 r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property);
1636         else if (streq(suffix, ".timer"))
1637                 r = transient_timer_set_properties(m);
1638         else
1639                 assert_not_reached();
1640         if (r < 0)
1641                 return r;
1642 
1643         r = sd_bus_message_close_container(m);
1644         if (r < 0)
1645                 return bus_log_create_error(r);
1646 
1647         r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
1648         if (r < 0)
1649                 return bus_log_create_error(r);
1650 
1651         if (!strv_isempty(arg_cmdline)) {
1652                 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
1653                 if (r < 0)
1654                         return bus_log_create_error(r);
1655 
1656                 r = sd_bus_message_append(m, "s", service);
1657                 if (r < 0)
1658                         return bus_log_create_error(r);
1659 
1660                 r = sd_bus_message_open_container(m, 'a', "(sv)");
1661                 if (r < 0)
1662                         return bus_log_create_error(r);
1663 
1664                 r = transient_service_set_properties(m, NULL);
1665                 if (r < 0)
1666                         return r;
1667 
1668                 r = sd_bus_message_close_container(m);
1669                 if (r < 0)
1670                         return bus_log_create_error(r);
1671 
1672                 r = sd_bus_message_close_container(m);
1673                 if (r < 0)
1674                         return bus_log_create_error(r);
1675         }
1676 
1677         r = sd_bus_message_close_container(m);
1678         if (r < 0)
1679                 return bus_log_create_error(r);
1680 
1681         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1682 
1683         r = sd_bus_call(bus, m, 0, &error, &reply);
1684         if (r < 0)
1685                 return log_error_errno(r, "Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, r));
1686 
1687         r = sd_bus_message_read(reply, "o", &object);
1688         if (r < 0)
1689                 return bus_log_parse_error(r);
1690 
1691         r = bus_wait_for_jobs_one(w, object, arg_quiet, arg_user ? STRV_MAKE_CONST("--user") : NULL);
1692         if (r < 0)
1693                 return r;
1694 
1695         if (!arg_quiet) {
1696                 log_info("Running %s as unit: %s", suffix + 1, trigger);
1697                 if (!strv_isempty(arg_cmdline))
1698                         log_info("Will run service as unit: %s", service);
1699         }
1700 
1701         return 0;
1702 }
1703 
shall_make_executable_absolute(void)1704 static bool shall_make_executable_absolute(void) {
1705         if (strv_isempty(arg_cmdline))
1706                 return false;
1707         if (arg_transport != BUS_TRANSPORT_LOCAL)
1708                 return false;
1709 
1710         FOREACH_STRING(f, "RootDirectory=", "RootImage=", "ExecSearchPath=", "MountImages=", "ExtensionImages=")
1711                 if (strv_find_startswith(arg_property, f))
1712                         return false;
1713 
1714         return true;
1715 }
1716 
run(int argc,char * argv[])1717 static int run(int argc, char* argv[]) {
1718         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1719         _cleanup_free_ char *description = NULL;
1720         int r, retval = EXIT_SUCCESS;
1721 
1722         log_show_color(true);
1723         log_parse_environment();
1724         log_open();
1725 
1726         r = parse_argv(argc, argv);
1727         if (r <= 0)
1728                 return r;
1729 
1730         if (shall_make_executable_absolute()) {
1731                 /* Patch in an absolute path to fail early for user convenience, but only when we can do it
1732                  * (i.e. we will be running from the same file system). This also uses the user's $PATH,
1733                  * while we use a fixed search path in the manager. */
1734 
1735                 _cleanup_free_ char *command = NULL;
1736                 r = find_executable(arg_cmdline[0], &command);
1737                 if (r < 0)
1738                         return log_error_errno(r, "Failed to find executable %s: %m", arg_cmdline[0]);
1739 
1740                 free_and_replace(arg_cmdline[0], command);
1741         }
1742 
1743         if (!arg_description) {
1744                 description = strv_join(arg_cmdline, " ");
1745                 if (!description)
1746                         return log_oom();
1747 
1748                 if (arg_unit && isempty(description)) {
1749                         r = free_and_strdup(&description, arg_unit);
1750                         if (r < 0)
1751                                 return log_oom();
1752                 }
1753 
1754                 arg_description = description;
1755         }
1756 
1757         /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct
1758          * connection */
1759         if (arg_wait || arg_stdio != ARG_STDIO_NONE || (arg_user && arg_transport != BUS_TRANSPORT_LOCAL))
1760                 r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus);
1761         else
1762                 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
1763         if (r < 0)
1764                 return bus_log_connect_error(r, arg_transport);
1765 
1766         if (arg_scope)
1767                 r = start_transient_scope(bus);
1768         else if (arg_path_property)
1769                 r = start_transient_trigger(bus, ".path");
1770         else if (arg_socket_property)
1771                 r = start_transient_trigger(bus, ".socket");
1772         else if (arg_with_timer)
1773                 r = start_transient_trigger(bus, ".timer");
1774         else
1775                 r = start_transient_service(bus, &retval);
1776         if (r < 0)
1777                 return r;
1778 
1779         return retval;
1780 }
1781 
1782 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
1783