1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <getopt.h>
4 #include <locale.h>
5 #include <unistd.h>
6 
7 #include "sd-daemon.h"
8 
9 #include "bus-util.h"
10 #include "install.h"
11 #include "main-func.h"
12 #include "output-mode.h"
13 #include "pager.h"
14 #include "parse-argument.h"
15 #include "path-util.h"
16 #include "pretty-print.h"
17 #include "process-util.h"
18 #include "rlimit-util.h"
19 #include "sigbus.h"
20 #include "signal-util.h"
21 #include "string-table.h"
22 #include "systemctl-add-dependency.h"
23 #include "systemctl-cancel-job.h"
24 #include "systemctl-clean-or-freeze.h"
25 #include "systemctl-compat-halt.h"
26 #include "systemctl-compat-runlevel.h"
27 #include "systemctl-compat-shutdown.h"
28 #include "systemctl-compat-telinit.h"
29 #include "systemctl-daemon-reload.h"
30 #include "systemctl-edit.h"
31 #include "systemctl-enable.h"
32 #include "systemctl-is-active.h"
33 #include "systemctl-is-enabled.h"
34 #include "systemctl-is-system-running.h"
35 #include "systemctl-kill.h"
36 #include "systemctl-list-dependencies.h"
37 #include "systemctl-list-jobs.h"
38 #include "systemctl-list-machines.h"
39 #include "systemctl-list-unit-files.h"
40 #include "systemctl-list-units.h"
41 #include "systemctl-log-setting.h"
42 #include "systemctl-logind.h"
43 #include "systemctl-mount.h"
44 #include "systemctl-preset-all.h"
45 #include "systemctl-reset-failed.h"
46 #include "systemctl-service-watchdogs.h"
47 #include "systemctl-set-default.h"
48 #include "systemctl-set-environment.h"
49 #include "systemctl-set-property.h"
50 #include "systemctl-show.h"
51 #include "systemctl-start-special.h"
52 #include "systemctl-start-unit.h"
53 #include "systemctl-switch-root.h"
54 #include "systemctl-sysv-compat.h"
55 #include "systemctl-trivial-method.h"
56 #include "systemctl-util.h"
57 #include "systemctl.h"
58 #include "terminal-util.h"
59 #include "time-util.h"
60 #include "verbs.h"
61 #include "virt.h"
62 
63 char **arg_types = NULL;
64 char **arg_states = NULL;
65 char **arg_properties = NULL;
66 bool arg_all = false;
67 enum dependency arg_dependency = DEPENDENCY_FORWARD;
68 const char *_arg_job_mode = NULL;
69 LookupScope arg_scope = LOOKUP_SCOPE_SYSTEM;
70 bool arg_wait = false;
71 bool arg_no_block = false;
72 int arg_legend = -1; /* -1: true, unless --quiet is passed, 1: true */
73 PagerFlags arg_pager_flags = 0;
74 bool arg_no_wtmp = false;
75 bool arg_no_sync = false;
76 bool arg_no_wall = false;
77 bool arg_no_reload = false;
78 BusPrintPropertyFlags arg_print_flags = 0;
79 bool arg_show_types = false;
80 int arg_check_inhibitors = -1;
81 bool arg_dry_run = false;
82 bool arg_quiet = false;
83 bool arg_full = false;
84 bool arg_recursive = false;
85 bool arg_with_dependencies = false;
86 bool arg_show_transaction = false;
87 int arg_force = 0;
88 bool arg_ask_password = false;
89 bool arg_runtime = false;
90 UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
91 char **arg_wall = NULL;
92 const char *arg_kill_who = NULL;
93 int arg_signal = SIGTERM;
94 char *arg_root = NULL;
95 usec_t arg_when = 0;
96 const char *arg_reboot_argument = NULL;
97 enum action arg_action = ACTION_SYSTEMCTL;
98 BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
99 const char *arg_host = NULL;
100 unsigned arg_lines = 10;
101 OutputMode arg_output = OUTPUT_SHORT;
102 bool arg_plain = false;
103 bool arg_firmware_setup = false;
104 usec_t arg_boot_loader_menu = USEC_INFINITY;
105 const char *arg_boot_loader_entry = NULL;
106 bool arg_now = false;
107 bool arg_jobs_before = false;
108 bool arg_jobs_after = false;
109 char **arg_clean_what = NULL;
110 TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
111 bool arg_read_only = false;
112 bool arg_mkdir = false;
113 bool arg_marked = false;
114 
115 STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
116 STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
117 STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep);
118 STATIC_DESTRUCTOR_REGISTER(_arg_job_mode, unsetp);
119 STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
120 STATIC_DESTRUCTOR_REGISTER(arg_kill_who, unsetp);
121 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
122 STATIC_DESTRUCTOR_REGISTER(arg_reboot_argument, unsetp);
123 STATIC_DESTRUCTOR_REGISTER(arg_host, unsetp);
124 STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp);
125 STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
126 
systemctl_help(void)127 static int systemctl_help(void) {
128         _cleanup_free_ char *link = NULL;
129         int r;
130 
131         pager_open(arg_pager_flags);
132 
133         r = terminal_urlify_man("systemctl", "1", &link);
134         if (r < 0)
135                 return log_oom();
136 
137         printf("%1$s [OPTIONS...] COMMAND ...\n\n"
138                "%5$sQuery or send control commands to the system manager.%6$s\n"
139                "\n%3$sUnit Commands:%4$s\n"
140                "  list-units [PATTERN...]             List units currently in memory\n"
141                "  list-sockets [PATTERN...]           List socket units currently in memory,\n"
142                "                                      ordered by address\n"
143                "  list-timers [PATTERN...]            List timer units currently in memory,\n"
144                "                                      ordered by next elapse\n"
145                "  is-active PATTERN...                Check whether units are active\n"
146                "  is-failed PATTERN...                Check whether units are failed\n"
147                "  status [PATTERN...|PID...]          Show runtime status of one or more units\n"
148                "  show [PATTERN...|JOB...]            Show properties of one or more\n"
149                "                                      units/jobs or the manager\n"
150                "  cat PATTERN...                      Show files and drop-ins of specified units\n"
151                "  help PATTERN...|PID...              Show manual for one or more units\n"
152                "  list-dependencies [UNIT...]         Recursively show units which are required\n"
153                "                                      or wanted by the units or by which those\n"
154                "                                      units are required or wanted\n"
155                "  start UNIT...                       Start (activate) one or more units\n"
156                "  stop UNIT...                        Stop (deactivate) one or more units\n"
157                "  reload UNIT...                      Reload one or more units\n"
158                "  restart UNIT...                     Start or restart one or more units\n"
159                "  try-restart UNIT...                 Restart one or more units if active\n"
160                "  reload-or-restart UNIT...           Reload one or more units if possible,\n"
161                "                                      otherwise start or restart\n"
162                "  try-reload-or-restart UNIT...       If active, reload one or more units,\n"
163                "                                      if supported, otherwise restart\n"
164                "  isolate UNIT                        Start one unit and stop all others\n"
165                "  kill UNIT...                        Send signal to processes of a unit\n"
166                "  clean UNIT...                       Clean runtime, cache, state, logs or\n"
167                "                                      configuration of unit\n"
168                "  freeze PATTERN...                   Freeze execution of unit processes\n"
169                "  thaw PATTERN...                     Resume execution of a frozen unit\n"
170                "  set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
171                "  bind UNIT PATH [PATH]               Bind-mount a path from the host into a\n"
172                "                                      unit's namespace\n"
173                "  mount-image UNIT PATH [PATH [OPTS]] Mount an image from the host into a\n"
174                "                                      unit's namespace\n"
175                "  service-log-level SERVICE [LEVEL]   Get/set logging threshold for service\n"
176                "  service-log-target SERVICE [TARGET] Get/set logging target for service\n"
177                "  reset-failed [PATTERN...]           Reset failed state for all, one, or more\n"
178                "                                      units"
179                "\n%3$sUnit File Commands:%4$s\n"
180                "  list-unit-files [PATTERN...]        List installed unit files\n"
181                "  enable [UNIT...|PATH...]            Enable one or more unit files\n"
182                "  disable UNIT...                     Disable one or more unit files\n"
183                "  reenable UNIT...                    Reenable one or more unit files\n"
184                "  preset UNIT...                      Enable/disable one or more unit files\n"
185                "                                      based on preset configuration\n"
186                "  preset-all                          Enable/disable all unit files based on\n"
187                "                                      preset configuration\n"
188                "  is-enabled UNIT...                  Check whether unit files are enabled\n"
189                "  mask UNIT...                        Mask one or more units\n"
190                "  unmask UNIT...                      Unmask one or more units\n"
191                "  link PATH...                        Link one or more units files into\n"
192                "                                      the search path\n"
193                "  revert UNIT...                      Revert one or more unit files to vendor\n"
194                "                                      version\n"
195                "  add-wants TARGET UNIT...            Add 'Wants' dependency for the target\n"
196                "                                      on specified one or more units\n"
197                "  add-requires TARGET UNIT...         Add 'Requires' dependency for the target\n"
198                "                                      on specified one or more units\n"
199                "  edit UNIT...                        Edit one or more unit files\n"
200                "  get-default                         Get the name of the default target\n"
201                "  set-default TARGET                  Set the default target\n"
202                "\n%3$sMachine Commands:%4$s\n"
203                "  list-machines [PATTERN...]          List local containers and host\n"
204                "\n%3$sJob Commands:%4$s\n"
205                "  list-jobs [PATTERN...]              List jobs\n"
206                "  cancel [JOB...]                     Cancel all, one, or more jobs\n"
207                "\n%3$sEnvironment Commands:%4$s\n"
208                "  show-environment                    Dump environment\n"
209                "  set-environment VARIABLE=VALUE...   Set one or more environment variables\n"
210                "  unset-environment VARIABLE...       Unset one or more environment variables\n"
211                "  import-environment VARIABLE...      Import all or some environment variables\n"
212                "\n%3$sManager State Commands:%4$s\n"
213                "  daemon-reload                       Reload systemd manager configuration\n"
214                "  daemon-reexec                       Reexecute systemd manager\n"
215                "  log-level [LEVEL]                   Get/set logging threshold for manager\n"
216                "  log-target [TARGET]                 Get/set logging target for manager\n"
217                "  service-watchdogs [BOOL]            Get/set service watchdog state\n"
218                "\n%3$sSystem Commands:%4$s\n"
219                "  is-system-running                   Check whether system is fully running\n"
220                "  default                             Enter system default mode\n"
221                "  rescue                              Enter system rescue mode\n"
222                "  emergency                           Enter system emergency mode\n"
223                "  halt                                Shut down and halt the system\n"
224                "  poweroff                            Shut down and power-off the system\n"
225                "  reboot                              Shut down and reboot the system\n"
226                "  kexec                               Shut down and reboot the system with kexec\n"
227                "  exit [EXIT_CODE]                    Request user instance or container exit\n"
228                "  switch-root ROOT [INIT]             Change to a different root file system\n"
229                "  suspend                             Suspend the system\n"
230                "  hibernate                           Hibernate the system\n"
231                "  hybrid-sleep                        Hibernate and suspend the system\n"
232                "  suspend-then-hibernate              Suspend the system, wake after a period of\n"
233                "                                      time, and hibernate"
234                "\n%3$sOptions:%4$s\n"
235                "  -h --help              Show this help\n"
236                "     --version           Show package version\n"
237                "     --system            Connect to system manager\n"
238                "     --user              Connect to user service manager\n"
239                "  -H --host=[USER@]HOST  Operate on remote host\n"
240                "  -M --machine=CONTAINER Operate on a local container\n"
241                "  -t --type=TYPE         List units of a particular type\n"
242                "     --state=STATE       List units with particular LOAD or SUB or ACTIVE state\n"
243                "     --failed            Shortcut for --state=failed\n"
244                "  -p --property=NAME     Show only properties by this name\n"
245                "  -P NAME                Equivalent to --value --property=NAME\n"
246                "  -a --all               Show all properties/all units currently in memory,\n"
247                "                         including dead/empty ones. To list all units installed\n"
248                "                         on the system, use 'list-unit-files' instead.\n"
249                "  -l --full              Don't ellipsize unit names on output\n"
250                "  -r --recursive         Show unit list of host and local containers\n"
251                "     --reverse           Show reverse dependencies with 'list-dependencies'\n"
252                "     --with-dependencies Show unit dependencies with 'status', 'cat',\n"
253                "                         'list-units', and 'list-unit-files'.\n"
254                "     --job-mode=MODE     Specify how to deal with already queued jobs, when\n"
255                "                         queueing a new job\n"
256                "  -T --show-transaction  When enqueuing a unit job, show full transaction\n"
257                "     --show-types        When showing sockets, explicitly show their type\n"
258                "     --value             When showing properties, only print the value\n"
259                "     --check-inhibitors=MODE\n"
260                "                         Specify if checking inhibitors before shutting down,\n"
261                "                         sleeping or hibernating\n"
262                "  -i                     Shortcut for --check-inhibitors=no\n"
263                "     --kill-who=WHO      Whom to send signal to\n"
264                "  -s --signal=SIGNAL     Which signal to send\n"
265                "     --what=RESOURCES    Which types of resources to remove\n"
266                "     --now               Start or stop unit after enabling or disabling it\n"
267                "     --dry-run           Only print what would be done\n"
268                "                         Currently supported by verbs: halt, poweroff, reboot,\n"
269                "                             kexec, suspend, hibernate, suspend-then-hibernate,\n"
270                "                             hybrid-sleep, default, rescue, emergency, and exit.\n"
271                "  -q --quiet             Suppress output\n"
272                "     --wait              For (re)start, wait until service stopped again\n"
273                "                         For is-system-running, wait until startup is completed\n"
274                "     --no-block          Do not wait until operation finished\n"
275                "     --no-wall           Don't send wall message before halt/power-off/reboot\n"
276                "     --no-reload         Don't reload daemon after en-/dis-abling unit files\n"
277                "     --legend=BOOL       Enable/disable the legend (column headers and hints)\n"
278                "     --no-pager          Do not pipe output into a pager\n"
279                "     --no-ask-password   Do not ask for system passwords\n"
280                "     --global            Enable/disable/mask default user unit files globally\n"
281                "     --runtime           Enable/disable/mask unit files temporarily until next\n"
282                "                         reboot\n"
283                "  -f --force             When enabling unit files, override existing symlinks\n"
284                "                         When shutting down, execute action immediately\n"
285                "     --preset-mode=      Apply only enable, only disable, or all presets\n"
286                "     --root=PATH         Enable/disable/mask unit files in the specified root\n"
287                "                         directory\n"
288                "  -n --lines=INTEGER     Number of journal entries to show\n"
289                "  -o --output=STRING     Change journal output mode (short, short-precise,\n"
290                "                             short-iso, short-iso-precise, short-full,\n"
291                "                             short-monotonic, short-unix,\n"
292                "                             verbose, export, json, json-pretty, json-sse, cat)\n"
293                "     --firmware-setup    Tell the firmware to show the setup menu on next boot\n"
294                "     --boot-loader-menu=TIME\n"
295                "                         Boot into boot loader menu on next boot\n"
296                "     --boot-loader-entry=NAME\n"
297                "                         Boot into a specific boot loader entry on next boot\n"
298                "     --plain             Print unit dependencies as a list instead of a tree\n"
299                "     --timestamp=FORMAT  Change format of printed timestamps (pretty, unix,\n"
300                "                             us, utc, us+utc)\n"
301                "     --read-only         Create read-only bind mount\n"
302                "     --mkdir             Create directory before mounting, if missing\n"
303                "     --marked            Restart/reload previously marked units\n"
304                "\nSee the %2$s for details.\n",
305                program_invocation_short_name,
306                link,
307                ansi_underline(),
308                ansi_normal(),
309                ansi_highlight(),
310                ansi_normal());
311 
312         return 0;
313 }
314 
help_types(void)315 static void help_types(void) {
316         if (arg_legend != 0)
317                 puts("Available unit types:");
318 
319         DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
320 }
321 
help_states(void)322 static void help_states(void) {
323         if (arg_legend != 0)
324                 puts("Available unit load states:");
325         DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
326 
327         if (arg_legend != 0)
328                 puts("\nAvailable unit active states:");
329         DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
330 
331         if (arg_legend != 0)
332                 puts("\nAvailable unit file states:");
333         DUMP_STRING_TABLE(unit_file_state, UnitFileState, _UNIT_FILE_STATE_MAX);
334 
335         if (arg_legend != 0)
336                 puts("\nAvailable automount unit substates:");
337         DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
338 
339         if (arg_legend != 0)
340                 puts("\nAvailable device unit substates:");
341         DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
342 
343         if (arg_legend != 0)
344                 puts("\nAvailable mount unit substates:");
345         DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
346 
347         if (arg_legend != 0)
348                 puts("\nAvailable path unit substates:");
349         DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
350 
351         if (arg_legend != 0)
352                 puts("\nAvailable scope unit substates:");
353         DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
354 
355         if (arg_legend != 0)
356                 puts("\nAvailable service unit substates:");
357         DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
358 
359         if (arg_legend != 0)
360                 puts("\nAvailable slice unit substates:");
361         DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
362 
363         if (arg_legend != 0)
364                 puts("\nAvailable socket unit substates:");
365         DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
366 
367         if (arg_legend != 0)
368                 puts("\nAvailable swap unit substates:");
369         DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
370 
371         if (arg_legend != 0)
372                 puts("\nAvailable target unit substates:");
373         DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
374 
375         if (arg_legend != 0)
376                 puts("\nAvailable timer unit substates:");
377         DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
378 }
379 
systemctl_parse_argv(int argc,char * argv[])380 static int systemctl_parse_argv(int argc, char *argv[]) {
381         enum {
382                 ARG_FAIL = 0x100,            /* compatibility only */
383                 ARG_REVERSE,
384                 ARG_AFTER,
385                 ARG_BEFORE,
386                 ARG_CHECK_INHIBITORS,
387                 ARG_DRY_RUN,
388                 ARG_SHOW_TYPES,
389                 ARG_IRREVERSIBLE,            /* compatibility only */
390                 ARG_IGNORE_DEPENDENCIES,     /* compatibility only */
391                 ARG_VALUE,
392                 ARG_VERSION,
393                 ARG_USER,
394                 ARG_SYSTEM,
395                 ARG_GLOBAL,
396                 ARG_NO_BLOCK,
397                 ARG_LEGEND,
398                 ARG_NO_LEGEND,                /* compatibility only */
399                 ARG_NO_PAGER,
400                 ARG_NO_WALL,
401                 ARG_ROOT,
402                 ARG_NO_RELOAD,
403                 ARG_KILL_WHO,
404                 ARG_NO_ASK_PASSWORD,
405                 ARG_FAILED,
406                 ARG_RUNTIME,
407                 ARG_PLAIN,
408                 ARG_STATE,
409                 ARG_JOB_MODE,
410                 ARG_PRESET_MODE,
411                 ARG_FIRMWARE_SETUP,
412                 ARG_BOOT_LOADER_MENU,
413                 ARG_BOOT_LOADER_ENTRY,
414                 ARG_NOW,
415                 ARG_MESSAGE,
416                 ARG_WITH_DEPENDENCIES,
417                 ARG_WAIT,
418                 ARG_WHAT,
419                 ARG_REBOOT_ARG,
420                 ARG_TIMESTAMP_STYLE,
421                 ARG_READ_ONLY,
422                 ARG_MKDIR,
423                 ARG_MARKED,
424         };
425 
426         static const struct option options[] = {
427                 { "help",                no_argument,       NULL, 'h'                     },
428                 { "version",             no_argument,       NULL, ARG_VERSION             },
429                 { "type",                required_argument, NULL, 't'                     },
430                 { "property",            required_argument, NULL, 'p'                     },
431                 { "all",                 no_argument,       NULL, 'a'                     },
432                 { "reverse",             no_argument,       NULL, ARG_REVERSE             },
433                 { "after",               no_argument,       NULL, ARG_AFTER               },
434                 { "before",              no_argument,       NULL, ARG_BEFORE              },
435                 { "show-types",          no_argument,       NULL, ARG_SHOW_TYPES          },
436                 { "failed",              no_argument,       NULL, ARG_FAILED              },
437                 { "full",                no_argument,       NULL, 'l'                     },
438                 { "job-mode",            required_argument, NULL, ARG_JOB_MODE            },
439                 { "fail",                no_argument,       NULL, ARG_FAIL                }, /* compatibility only */
440                 { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        }, /* compatibility only */
441                 { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
442                 { "ignore-inhibitors",   no_argument,       NULL, 'i'                     }, /* compatibility only */
443                 { "check-inhibitors",    required_argument, NULL, ARG_CHECK_INHIBITORS    },
444                 { "value",               no_argument,       NULL, ARG_VALUE               },
445                 { "user",                no_argument,       NULL, ARG_USER                },
446                 { "system",              no_argument,       NULL, ARG_SYSTEM              },
447                 { "global",              no_argument,       NULL, ARG_GLOBAL              },
448                 { "wait",                no_argument,       NULL, ARG_WAIT                },
449                 { "no-block",            no_argument,       NULL, ARG_NO_BLOCK            },
450                 { "legend",              required_argument, NULL, ARG_LEGEND              },
451                 { "no-legend",           no_argument,       NULL, ARG_NO_LEGEND           }, /* compatibility only */
452                 { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
453                 { "no-wall",             no_argument,       NULL, ARG_NO_WALL             },
454                 { "dry-run",             no_argument,       NULL, ARG_DRY_RUN             },
455                 { "quiet",               no_argument,       NULL, 'q'                     },
456                 { "root",                required_argument, NULL, ARG_ROOT                },
457                 { "force",               no_argument,       NULL, 'f'                     },
458                 { "no-reload",           no_argument,       NULL, ARG_NO_RELOAD           },
459                 { "kill-who",            required_argument, NULL, ARG_KILL_WHO            },
460                 { "signal",              required_argument, NULL, 's'                     },
461                 { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
462                 { "host",                required_argument, NULL, 'H'                     },
463                 { "machine",             required_argument, NULL, 'M'                     },
464                 { "runtime",             no_argument,       NULL, ARG_RUNTIME             },
465                 { "lines",               required_argument, NULL, 'n'                     },
466                 { "output",              required_argument, NULL, 'o'                     },
467                 { "plain",               no_argument,       NULL, ARG_PLAIN               },
468                 { "state",               required_argument, NULL, ARG_STATE               },
469                 { "recursive",           no_argument,       NULL, 'r'                     },
470                 { "with-dependencies",   no_argument,       NULL, ARG_WITH_DEPENDENCIES   },
471                 { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
472                 { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
473                 { "boot-loader-menu",    required_argument, NULL, ARG_BOOT_LOADER_MENU    },
474                 { "boot-loader-entry",   required_argument, NULL, ARG_BOOT_LOADER_ENTRY   },
475                 { "now",                 no_argument,       NULL, ARG_NOW                 },
476                 { "message",             required_argument, NULL, ARG_MESSAGE             },
477                 { "show-transaction",    no_argument,       NULL, 'T'                     },
478                 { "what",                required_argument, NULL, ARG_WHAT                },
479                 { "reboot-argument",     required_argument, NULL, ARG_REBOOT_ARG          },
480                 { "timestamp",           required_argument, NULL, ARG_TIMESTAMP_STYLE     },
481                 { "read-only",           no_argument,       NULL, ARG_READ_ONLY           },
482                 { "mkdir",               no_argument,       NULL, ARG_MKDIR               },
483                 { "marked",              no_argument,       NULL, ARG_MARKED              },
484                 {}
485         };
486 
487         int c, r;
488 
489         assert(argc >= 0);
490         assert(argv);
491 
492         /* We default to allowing interactive authorization only in systemctl (not in the legacy commands) */
493         arg_ask_password = true;
494 
495         while ((c = getopt_long(argc, argv, "ht:p:P:alqfs:H:M:n:o:iTr.::", options, NULL)) >= 0)
496 
497                 switch (c) {
498 
499                 case 'h':
500                         return systemctl_help();
501 
502                 case ARG_VERSION:
503                         return version();
504 
505                 case 't':
506                         if (isempty(optarg))
507                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
508                                                        "--type= requires arguments.");
509 
510                         for (const char *p = optarg;;) {
511                                 _cleanup_free_ char *type = NULL;
512 
513                                 r = extract_first_word(&p, &type, ",", 0);
514                                 if (r < 0)
515                                         return log_error_errno(r, "Failed to parse type: %s", optarg);
516                                 if (r == 0)
517                                         break;
518 
519                                 if (streq(type, "help")) {
520                                         help_types();
521                                         return 0;
522                                 }
523 
524                                 if (unit_type_from_string(type) >= 0) {
525                                         if (strv_consume(&arg_types, TAKE_PTR(type)) < 0)
526                                                 return log_oom();
527                                         continue;
528                                 }
529 
530                                 /* It's much nicer to use --state= for load states, but let's support this in
531                                  * --types= too for compatibility with old versions */
532                                 if (unit_load_state_from_string(type) >= 0) {
533                                         if (strv_consume(&arg_states, TAKE_PTR(type)) < 0)
534                                                 return log_oom();
535                                         continue;
536                                 }
537 
538                                 log_error("Unknown unit type or load state '%s'.", type);
539                                 return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
540                                                       "Use -t help to see a list of allowed values.");
541                         }
542 
543                         break;
544 
545                 case 'P':
546                         SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
547                         _fallthrough_;
548 
549                 case 'p':
550                         /* Make sure that if the empty property list was specified, we won't show any
551                            properties. */
552                         if (isempty(optarg) && !arg_properties) {
553                                 arg_properties = new0(char*, 1);
554                                 if (!arg_properties)
555                                         return log_oom();
556                         } else
557                                 for (const char *p = optarg;;) {
558                                         _cleanup_free_ char *prop = NULL;
559 
560                                         r = extract_first_word(&p, &prop, ",", 0);
561                                         if (r < 0)
562                                                 return log_error_errno(r, "Failed to parse property: %s", optarg);
563                                         if (r == 0)
564                                                 break;
565 
566                                         if (strv_consume(&arg_properties, TAKE_PTR(prop)) < 0)
567                                                 return log_oom();
568                                 }
569 
570                         /* If the user asked for a particular property, show it, even if it is empty. */
571                         SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
572 
573                         break;
574 
575                 case 'a':
576                         SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
577                         arg_all = true;
578                         break;
579 
580                 case ARG_REVERSE:
581                         arg_dependency = DEPENDENCY_REVERSE;
582                         break;
583 
584                 case ARG_AFTER:
585                         arg_dependency = DEPENDENCY_AFTER;
586                         arg_jobs_after = true;
587                         break;
588 
589                 case ARG_BEFORE:
590                         arg_dependency = DEPENDENCY_BEFORE;
591                         arg_jobs_before = true;
592                         break;
593 
594                 case ARG_SHOW_TYPES:
595                         arg_show_types = true;
596                         break;
597 
598                 case ARG_VALUE:
599                         SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
600                         break;
601 
602                 case ARG_JOB_MODE:
603                         _arg_job_mode = optarg;
604                         break;
605 
606                 case ARG_FAIL:
607                         _arg_job_mode = "fail";
608                         break;
609 
610                 case ARG_IRREVERSIBLE:
611                         _arg_job_mode = "replace-irreversibly";
612                         break;
613 
614                 case ARG_IGNORE_DEPENDENCIES:
615                         _arg_job_mode = "ignore-dependencies";
616                         break;
617 
618                 case ARG_USER:
619                         arg_scope = LOOKUP_SCOPE_USER;
620                         break;
621 
622                 case ARG_SYSTEM:
623                         arg_scope = LOOKUP_SCOPE_SYSTEM;
624                         break;
625 
626                 case ARG_GLOBAL:
627                         arg_scope = LOOKUP_SCOPE_GLOBAL;
628                         break;
629 
630                 case ARG_WAIT:
631                         arg_wait = true;
632                         break;
633 
634                 case ARG_NO_BLOCK:
635                         arg_no_block = true;
636                         break;
637 
638                 case ARG_NO_LEGEND:
639                         arg_legend = false;
640                         break;
641 
642                 case ARG_LEGEND:
643                         r = parse_boolean_argument("--legend", optarg, NULL);
644                         if (r < 0)
645                                 return r;
646                         arg_legend = r;
647                         break;
648 
649                 case ARG_NO_PAGER:
650                         arg_pager_flags |= PAGER_DISABLE;
651                         break;
652 
653                 case ARG_NO_WALL:
654                         arg_no_wall = true;
655                         break;
656 
657                 case ARG_ROOT:
658                         r = parse_path_argument(optarg, false, &arg_root);
659                         if (r < 0)
660                                 return r;
661                         break;
662 
663                 case 'l':
664                         arg_full = true;
665                         break;
666 
667                 case ARG_FAILED:
668                         if (strv_extend(&arg_states, "failed") < 0)
669                                 return log_oom();
670 
671                         break;
672 
673                 case ARG_DRY_RUN:
674                         arg_dry_run = true;
675                         break;
676 
677                 case 'q':
678                         arg_quiet = true;
679 
680                         if (arg_legend < 0)
681                                 arg_legend = false;
682 
683                         break;
684 
685                 case 'f':
686                         arg_force++;
687                         break;
688 
689                 case ARG_NO_RELOAD:
690                         arg_no_reload = true;
691                         break;
692 
693                 case ARG_KILL_WHO:
694                         arg_kill_who = optarg;
695                         break;
696 
697                 case 's':
698                         r = parse_signal_argument(optarg, &arg_signal);
699                         if (r <= 0)
700                                 return r;
701                         break;
702 
703                 case ARG_NO_ASK_PASSWORD:
704                         arg_ask_password = false;
705                         break;
706 
707                 case 'H':
708                         arg_transport = BUS_TRANSPORT_REMOTE;
709                         arg_host = optarg;
710                         break;
711 
712                 case 'M':
713                         arg_transport = BUS_TRANSPORT_MACHINE;
714                         arg_host = optarg;
715                         break;
716 
717                 case ARG_RUNTIME:
718                         arg_runtime = true;
719                         break;
720 
721                 case 'n':
722                         if (safe_atou(optarg, &arg_lines) < 0)
723                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
724                                                        "Failed to parse lines '%s'",
725                                                        optarg);
726                         break;
727 
728                 case 'o':
729                         if (streq(optarg, "help")) {
730                                 DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
731                                 return 0;
732                         }
733 
734                         arg_output = output_mode_from_string(optarg);
735                         if (arg_output < 0)
736                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
737                                                        "Unknown output '%s'.",
738                                                        optarg);
739 
740                         if (OUTPUT_MODE_IS_JSON(arg_output)) {
741                                 arg_legend = false;
742                                 arg_plain = true;
743                         }
744                         break;
745 
746                 case 'i':
747                         arg_check_inhibitors = 0;
748                         break;
749 
750                 case ARG_CHECK_INHIBITORS:
751                         if (streq(optarg, "auto"))
752                                 arg_check_inhibitors = -1;
753                         else {
754                                 r = parse_boolean(optarg);
755                                 if (r < 0)
756                                         return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
757                                 arg_check_inhibitors = r;
758                         }
759                         break;
760 
761                 case ARG_PLAIN:
762                         arg_plain = true;
763                         break;
764 
765                 case ARG_FIRMWARE_SETUP:
766                         arg_firmware_setup = true;
767                         break;
768 
769                 case ARG_BOOT_LOADER_MENU:
770 
771                         r = parse_sec(optarg, &arg_boot_loader_menu);
772                         if (r < 0)
773                                 return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
774 
775                         break;
776 
777                 case ARG_BOOT_LOADER_ENTRY:
778 
779                         if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
780                                 r = help_boot_loader_entry();
781                                 if (r < 0)
782                                         return r;
783 
784                                 return 0;
785                         }
786 
787                         arg_boot_loader_entry = empty_to_null(optarg);
788                         break;
789 
790                 case ARG_STATE:
791                         if (isempty(optarg))
792                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
793                                                        "--state= requires arguments.");
794 
795                         for (const char *p = optarg;;) {
796                                 _cleanup_free_ char *s = NULL;
797 
798                                 r = extract_first_word(&p, &s, ",", 0);
799                                 if (r < 0)
800                                         return log_error_errno(r, "Failed to parse state: %s", optarg);
801                                 if (r == 0)
802                                         break;
803 
804                                 if (streq(s, "help")) {
805                                         help_states();
806                                         return 0;
807                                 }
808 
809                                 if (strv_consume(&arg_states, TAKE_PTR(s)) < 0)
810                                         return log_oom();
811                         }
812                         break;
813 
814                 case 'r':
815                         if (geteuid() != 0)
816                                 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
817                                                        "--recursive requires root privileges.");
818 
819                         arg_recursive = true;
820                         break;
821 
822                 case ARG_PRESET_MODE:
823                         if (streq(optarg, "help")) {
824                                 DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
825                                 return 0;
826                         }
827 
828                         arg_preset_mode = unit_file_preset_mode_from_string(optarg);
829                         if (arg_preset_mode < 0)
830                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
831                                                        "Failed to parse preset mode: %s.", optarg);
832 
833                         break;
834 
835                 case ARG_NOW:
836                         arg_now = true;
837                         break;
838 
839                 case ARG_MESSAGE:
840                         if (strv_extend(&arg_wall, optarg) < 0)
841                                 return log_oom();
842                         break;
843 
844                 case 'T':
845                         arg_show_transaction = true;
846                         break;
847 
848                 case ARG_WITH_DEPENDENCIES:
849                         arg_with_dependencies = true;
850                         break;
851 
852                 case ARG_WHAT:
853                         if (isempty(optarg))
854                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments.");
855 
856                         for (const char *p = optarg;;) {
857                                 _cleanup_free_ char *k = NULL;
858 
859                                 r = extract_first_word(&p, &k, ",", 0);
860                                 if (r < 0)
861                                         return log_error_errno(r, "Failed to parse directory type: %s", optarg);
862                                 if (r == 0)
863                                         break;
864 
865                                 if (streq(k, "help")) {
866                                         puts("runtime\n"
867                                              "state\n"
868                                              "cache\n"
869                                              "logs\n"
870                                              "configuration");
871                                         return 0;
872                                 }
873 
874                                 r = strv_consume(&arg_clean_what, TAKE_PTR(k));
875                                 if (r < 0)
876                                         return log_oom();
877                         }
878 
879                         break;
880 
881                 case ARG_REBOOT_ARG:
882                         arg_reboot_argument = optarg;
883                         break;
884 
885                 case ARG_TIMESTAMP_STYLE:
886                         if (streq(optarg, "help")) {
887                                 DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX);
888                                 return 0;
889                         }
890 
891                         arg_timestamp_style = timestamp_style_from_string(optarg);
892                         if (arg_timestamp_style < 0)
893                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
894                                                        "Invalid value: %s.", optarg);
895 
896                         break;
897 
898                 case ARG_READ_ONLY:
899                         arg_read_only = true;
900                         break;
901 
902                 case ARG_MKDIR:
903                         arg_mkdir = true;
904                         break;
905 
906                 case ARG_MARKED:
907                         arg_marked = true;
908                         break;
909 
910                 case '.':
911                         /* Output an error mimicking getopt, and print a hint afterwards */
912                         log_error("%s: invalid option -- '.'", program_invocation_name);
913                         log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
914                                    "      %s [OPTIONS...] COMMAND -- -.%s ...",
915                                    program_invocation_name, optarg ?: "mount");
916                         _fallthrough_;
917 
918                 case '?':
919                         return -EINVAL;
920 
921                 default:
922                         assert_not_reached();
923                 }
924 
925         /* If we are in --user mode, there's no point in talking to PolicyKit or the infra to query system
926          * passwords */
927         if (arg_scope != LOOKUP_SCOPE_SYSTEM)
928                 arg_ask_password = false;
929 
930         if (arg_transport == BUS_TRANSPORT_REMOTE && arg_scope != LOOKUP_SCOPE_SYSTEM)
931                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
932                                        "Cannot access user instance remotely.");
933 
934         if (arg_wait && arg_no_block)
935                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
936                                        "--wait may not be combined with --no-block.");
937 
938         bool do_reload_or_restart = streq_ptr(argv[optind], "reload-or-restart");
939         if (arg_marked) {
940                 if (!do_reload_or_restart)
941                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
942                                                "--marked may only be used with 'reload-or-restart'.");
943                 if (optind + 1 < argc)
944                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
945                                                "No additional arguments allowed with 'reload-or-restart --marked'.");
946                 if (arg_wait)
947                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
948                                                "--marked --wait is not supported.");
949                 if (arg_show_transaction)
950                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
951                                                "--marked --show-transaction is not supported.");
952 
953         } else if (do_reload_or_restart) {
954                 if (optind + 1 >= argc)
955                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
956                                                "List of units to restart/reload is required.");
957         }
958 
959         return 1;
960 }
961 
systemctl_dispatch_parse_argv(int argc,char * argv[])962 int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
963         assert(argc >= 0);
964         assert(argv);
965 
966         if (invoked_as(argv, "halt")) {
967                 arg_action = ACTION_HALT;
968                 return halt_parse_argv(argc, argv);
969 
970         } else if (invoked_as(argv, "poweroff")) {
971                 arg_action = ACTION_POWEROFF;
972                 return halt_parse_argv(argc, argv);
973 
974         } else if (invoked_as(argv, "reboot")) {
975                 if (kexec_loaded())
976                         arg_action = ACTION_KEXEC;
977                 else
978                         arg_action = ACTION_REBOOT;
979                 return halt_parse_argv(argc, argv);
980 
981         } else if (invoked_as(argv, "shutdown")) {
982                 arg_action = ACTION_POWEROFF;
983                 return shutdown_parse_argv(argc, argv);
984 
985         } else if (invoked_as(argv, "init")) {
986 
987                 /* Matches invocations as "init" as well as "telinit", which are synonymous when run
988                  * as PID != 1 on SysV.
989                  *
990                  * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
991                  * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
992                  * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
993                  * for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
994                  * immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
995                  * get "systemctl". In both cases we shall do the same thing, which is why we do
996                  * invoked_as(argv, "init") here, as a quick way to match both.
997                  *
998                  * Also see redirect_telinit() in src/core/main.c. */
999 
1000                 if (sd_booted() > 0) {
1001                         arg_action = _ACTION_INVALID;
1002                         return telinit_parse_argv(argc, argv);
1003                 } else {
1004                         /* Hmm, so some other init system is running, we need to forward this request to it.
1005                          */
1006                         arg_action = ACTION_TELINIT;
1007                         return 1;
1008                 }
1009 
1010         } else if (invoked_as(argv, "runlevel")) {
1011                 arg_action = ACTION_RUNLEVEL;
1012                 return runlevel_parse_argv(argc, argv);
1013         }
1014 
1015         arg_action = ACTION_SYSTEMCTL;
1016         return systemctl_parse_argv(argc, argv);
1017 }
1018 
1019 #ifndef FUZZ_SYSTEMCTL_PARSE_ARGV
systemctl_main(int argc,char * argv[])1020 static int systemctl_main(int argc, char *argv[]) {
1021         static const Verb verbs[] = {
1022                 { "list-units",            VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, verb_list_units },
1023                 { "list-unit-files",       VERB_ANY, VERB_ANY, 0,                verb_list_unit_files         },
1024                 { "list-sockets",          VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_sockets            },
1025                 { "list-timers",           VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_timers             },
1026                 { "list-jobs",             VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_jobs               },
1027                 { "list-machines",         VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_machines           },
1028                 { "clear-jobs",            VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_trivial_method          },
1029                 { "cancel",                VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_cancel                  },
1030                 { "start",                 2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1031                 { "stop",                  2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1032                 { "condstop",              2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   }, /* For compatibility with ALTLinux */
1033                 { "reload",                2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1034                 { "restart",               2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1035                 { "try-restart",           2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1036                 { "reload-or-restart",     VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1037                 { "reload-or-try-restart", 2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   }, /* For compatibility with old systemctl <= 228 */
1038                 { "try-reload-or-restart", 2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   },
1039                 { "force-reload",          2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   }, /* For compatibility with SysV */
1040                 { "condreload",            2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   }, /* For compatibility with ALTLinux */
1041                 { "condrestart",           2,        VERB_ANY, VERB_ONLINE_ONLY, verb_start                   }, /* For compatibility with RH */
1042                 { "isolate",               2,        2,        VERB_ONLINE_ONLY, verb_start                   },
1043                 { "kill",                  2,        VERB_ANY, VERB_ONLINE_ONLY, verb_kill                    },
1044                 { "clean",                 2,        VERB_ANY, VERB_ONLINE_ONLY, verb_clean_or_freeze         },
1045                 { "freeze",                2,        VERB_ANY, VERB_ONLINE_ONLY, verb_clean_or_freeze         },
1046                 { "thaw",                  2,        VERB_ANY, VERB_ONLINE_ONLY, verb_clean_or_freeze         },
1047                 { "is-active",             2,        VERB_ANY, VERB_ONLINE_ONLY, verb_is_active               },
1048                 { "check",                 2,        VERB_ANY, VERB_ONLINE_ONLY, verb_is_active               }, /* deprecated alias of is-active */
1049                 { "is-failed",             2,        VERB_ANY, VERB_ONLINE_ONLY, verb_is_failed               },
1050                 { "show",                  VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_show                    },
1051                 { "cat",                   2,        VERB_ANY, VERB_ONLINE_ONLY, verb_cat                     },
1052                 { "status",                VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_show                    },
1053                 { "help",                  VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_show                    },
1054                 { "daemon-reload",         1,        1,        VERB_ONLINE_ONLY, verb_daemon_reload           },
1055                 { "daemon-reexec",         1,        1,        VERB_ONLINE_ONLY, verb_daemon_reload           },
1056                 { "log-level",             VERB_ANY, 2,        VERB_ONLINE_ONLY, verb_log_setting             },
1057                 { "log-target",            VERB_ANY, 2,        VERB_ONLINE_ONLY, verb_log_setting             },
1058                 { "service-log-level",     2,        3,        VERB_ONLINE_ONLY, verb_service_log_setting     },
1059                 { "service-log-target",    2,        3,        VERB_ONLINE_ONLY, verb_service_log_setting     },
1060                 { "service-watchdogs",     VERB_ANY, 2,        VERB_ONLINE_ONLY, verb_service_watchdogs       },
1061                 { "show-environment",      VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_show_environment        },
1062                 { "set-environment",       2,        VERB_ANY, VERB_ONLINE_ONLY, verb_set_environment         },
1063                 { "unset-environment",     2,        VERB_ANY, VERB_ONLINE_ONLY, verb_set_environment         },
1064                 { "import-environment",    VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_import_environment      },
1065                 { "halt",                  VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1066                 { "poweroff",              VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1067                 { "reboot",                VERB_ANY, 2,        VERB_ONLINE_ONLY, verb_start_system_special    },
1068                 { "kexec",                 VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1069                 { "suspend",               VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1070                 { "hibernate",             VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1071                 { "hybrid-sleep",          VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1072                 { "suspend-then-hibernate",VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1073                 { "default",               VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_special           },
1074                 { "rescue",                VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1075                 { "emergency",             VERB_ANY, 1,        VERB_ONLINE_ONLY, verb_start_system_special    },
1076                 { "exit",                  VERB_ANY, 2,        VERB_ONLINE_ONLY, verb_start_special           },
1077                 { "reset-failed",          VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_reset_failed            },
1078                 { "enable",                2,        VERB_ANY, 0,                verb_enable                  },
1079                 { "disable",               2,        VERB_ANY, 0,                verb_enable                  },
1080                 { "is-enabled",            2,        VERB_ANY, 0,                verb_is_enabled              },
1081                 { "reenable",              2,        VERB_ANY, 0,                verb_enable                  },
1082                 { "preset",                2,        VERB_ANY, 0,                verb_enable                  },
1083                 { "preset-all",            VERB_ANY, 1,        0,                verb_preset_all              },
1084                 { "mask",                  2,        VERB_ANY, 0,                verb_enable                  },
1085                 { "unmask",                2,        VERB_ANY, 0,                verb_enable                  },
1086                 { "link",                  2,        VERB_ANY, 0,                verb_enable                  },
1087                 { "revert",                2,        VERB_ANY, 0,                verb_enable                  },
1088                 { "switch-root",           2,        VERB_ANY, VERB_ONLINE_ONLY, verb_switch_root             },
1089                 { "list-dependencies",     VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_dependencies       },
1090                 { "set-default",           2,        2,        0,                verb_set_default             },
1091                 { "get-default",           VERB_ANY, 1,        0,                verb_get_default             },
1092                 { "set-property",          3,        VERB_ANY, VERB_ONLINE_ONLY, verb_set_property            },
1093                 { "is-system-running",     VERB_ANY, 1,        0,                verb_is_system_running       },
1094                 { "add-wants",             3,        VERB_ANY, 0,                verb_add_dependency          },
1095                 { "add-requires",          3,        VERB_ANY, 0,                verb_add_dependency          },
1096                 { "edit",                  2,        VERB_ANY, VERB_ONLINE_ONLY, verb_edit                    },
1097                 { "bind",                  3,        4,        VERB_ONLINE_ONLY, verb_bind                    },
1098                 { "mount-image",           4,        5,        VERB_ONLINE_ONLY, verb_mount_image             },
1099                 {}
1100         };
1101 
1102         const Verb *verb = verbs_find_verb(argv[optind], verbs);
1103         if (verb && (verb->flags & VERB_ONLINE_ONLY) && arg_root)
1104                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1105                                        "Verb '%s' cannot be used with --root=.",
1106                                        argv[optind] ?: verb->verb);
1107 
1108         return dispatch_verb(argc, argv, verbs, NULL);
1109 }
1110 
run(int argc,char * argv[])1111 static int run(int argc, char *argv[]) {
1112         int r;
1113 
1114         setlocale(LC_ALL, "");
1115         log_parse_environment();
1116         log_open();
1117 
1118         /* The journal merging logic potentially needs a lot of fds. */
1119         (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
1120 
1121         sigbus_install();
1122 
1123         r = systemctl_dispatch_parse_argv(argc, argv);
1124         if (r <= 0)
1125                 goto finish;
1126 
1127         if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
1128                 if (!arg_quiet)
1129                         log_info("Running in chroot, ignoring request.");
1130                 r = 0;
1131                 goto finish;
1132         }
1133 
1134         /* systemctl_main() will print an error message for the bus connection, but only if it needs to */
1135 
1136         switch (arg_action) {
1137 
1138         case ACTION_SYSTEMCTL:
1139                 r = systemctl_main(argc, argv);
1140                 break;
1141 
1142         /* Legacy command aliases set arg_action. They provide some fallbacks, e.g. to tell sysvinit to
1143          * reboot after you have installed systemd binaries. */
1144 
1145         case ACTION_HALT:
1146         case ACTION_POWEROFF:
1147         case ACTION_REBOOT:
1148         case ACTION_KEXEC:
1149                 r = halt_main();
1150                 break;
1151 
1152         case ACTION_RUNLEVEL2:
1153         case ACTION_RUNLEVEL3:
1154         case ACTION_RUNLEVEL4:
1155         case ACTION_RUNLEVEL5:
1156         case ACTION_RESCUE:
1157                 r = start_with_fallback();
1158                 break;
1159 
1160         case ACTION_RELOAD:
1161         case ACTION_REEXEC:
1162                 r = reload_with_fallback();
1163                 break;
1164 
1165         case ACTION_CANCEL_SHUTDOWN:
1166                 r = logind_cancel_shutdown();
1167                 break;
1168 
1169         case ACTION_SHOW_SHUTDOWN:
1170                 r = logind_show_shutdown();
1171                 break;
1172 
1173         case ACTION_RUNLEVEL:
1174                 r = runlevel_main();
1175                 break;
1176 
1177         case ACTION_TELINIT:
1178                 r = exec_telinit(argv);
1179                 break;
1180 
1181         case ACTION_EXIT:
1182         case ACTION_SUSPEND:
1183         case ACTION_HIBERNATE:
1184         case ACTION_HYBRID_SLEEP:
1185         case ACTION_SUSPEND_THEN_HIBERNATE:
1186         case ACTION_EMERGENCY:
1187         case ACTION_DEFAULT:
1188                 /* systemctl verbs with no equivalent in the legacy commands. These cannot appear in
1189                  * arg_action. Fall through. */
1190 
1191         case _ACTION_INVALID:
1192         default:
1193                 assert_not_reached();
1194         }
1195 
1196 finish:
1197         release_busses();
1198 
1199         /* Note that we return r here, not 0, so that we can implement the LSB-like return codes */
1200         return r;
1201 }
1202 
1203 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
1204 #endif
1205