• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.04
/src/systemctl/systemctl.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <getopt.h>
4
#include <signal.h>
5
#include <unistd.h>
6

7
#include "argv-util.h"
8
#include "build.h"
9
#include "bus-print-properties.h"
10
#include "bus-util.h"
11
#include "capsule-util.h"
12
#include "extract-word.h"
13
#include "image-policy.h"
14
#include "install.h"
15
#include "output-mode.h"
16
#include "pager.h"
17
#include "parse-argument.h"
18
#include "parse-util.h"
19
#include "pretty-print.h"
20
#include "static-destruct.h"
21
#include "string-table.h"
22
#include "string-util.h"
23
#include "strv.h"
24
#include "systemctl.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-logind.h"
30
#include "time-util.h"
31

32
char **arg_types = NULL;
33
char **arg_states = NULL;
34
char **arg_properties = NULL;
35
bool arg_all = false;
36
enum dependency arg_dependency = DEPENDENCY_FORWARD;
37
const char *_arg_job_mode = NULL;
38
RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
39
bool arg_wait = false;
40
bool arg_no_block = false;
41
int arg_legend = -1; /* -1: true, unless --quiet is passed, 1: true */
42
PagerFlags arg_pager_flags = 0;
43
bool arg_no_wtmp = false;
44
bool arg_no_sync = false;
45
bool arg_no_wall = false;
46
bool arg_no_reload = false;
47
BusPrintPropertyFlags arg_print_flags = 0;
48
bool arg_show_types = false;
49
int arg_check_inhibitors = -1;
50
bool arg_dry_run = false;
51
bool arg_quiet = false;
52
bool arg_verbose = false;
53
bool arg_no_warn = false;
54
bool arg_full = false;
55
bool arg_recursive = false;
56
bool arg_with_dependencies = false;
57
bool arg_show_transaction = false;
58
int arg_force = 0;
59
bool arg_ask_password = false;
60
bool arg_runtime = false;
61
UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
62
char **arg_wall = NULL;
63
const char *arg_kill_whom = NULL;
64
int arg_signal = SIGTERM;
65
int arg_kill_value;
66
bool arg_kill_value_set = false;
67
char *arg_root = NULL;
68
char *arg_image = NULL;
69
usec_t arg_when = 0;
70
bool arg_stdin = false;
71
const char *arg_reboot_argument = NULL;
72
enum action arg_action = ACTION_SYSTEMCTL;
73
BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
74
const char *arg_host = NULL;
75
unsigned arg_lines = 10;
76
OutputMode arg_output = OUTPUT_SHORT;
77
bool arg_plain = false;
78
bool arg_firmware_setup = false;
79
usec_t arg_boot_loader_menu = USEC_INFINITY;
80
const char *arg_boot_loader_entry = NULL;
81
bool arg_now = false;
82
bool arg_jobs_before = false;
83
bool arg_jobs_after = false;
84
char **arg_clean_what = NULL;
85
TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
86
bool arg_read_only = false;
87
bool arg_mkdir = false;
88
bool arg_marked = false;
89
const char *arg_drop_in = NULL;
90
ImagePolicy *arg_image_policy = NULL;
91

92
STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
11,298✔
93
STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
11,298✔
94
STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep);
11,298✔
95
STATIC_DESTRUCTOR_REGISTER(_arg_job_mode, unsetp);
11,298✔
96
STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
11,298✔
97
STATIC_DESTRUCTOR_REGISTER(arg_kill_whom, unsetp);
11,298✔
98
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
11,298✔
99
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
11,298✔
100
STATIC_DESTRUCTOR_REGISTER(arg_reboot_argument, unsetp);
11,298✔
101
STATIC_DESTRUCTOR_REGISTER(arg_host, unsetp);
11,298✔
102
STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp);
11,298✔
103
STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
11,298✔
104
STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp);
11,298✔
105
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
11,298✔
106

UNCOV
107
static int systemctl_help(void) {
×
108
        _cleanup_free_ char *link = NULL;
×
109
        int r;
×
110

UNCOV
111
        pager_open(arg_pager_flags);
×
112

UNCOV
113
        r = terminal_urlify_man("systemctl", "1", &link);
×
114
        if (r < 0)
×
115
                return log_oom();
×
116

UNCOV
117
        printf("%1$s [OPTIONS...] COMMAND ...\n\n"
×
118
               "%5$sQuery or send control commands to the system manager.%6$s\n"
119
               "\n%3$sUnit Commands:%4$s\n"
120
               "  list-units [PATTERN...]             List units currently in memory\n"
121
               "  list-automounts [PATTERN...]        List automount units currently in memory,\n"
122
               "                                      ordered by path\n"
123
               "  list-paths [PATTERN...]             List path units currently in memory,\n"
124
               "                                      ordered by path\n"
125
               "  list-sockets [PATTERN...]           List socket units currently in memory,\n"
126
               "                                      ordered by address\n"
127
               "  list-timers [PATTERN...]            List timer units currently in memory,\n"
128
               "                                      ordered by next elapse\n"
129
               "  is-active PATTERN...                Check whether units are active\n"
130
               "  is-failed [PATTERN...]              Check whether units are failed or\n"
131
               "                                      system is in degraded state\n"
132
               "  status [PATTERN...|PID...]          Show runtime status of one or more units\n"
133
               "  show [PATTERN...|JOB...]            Show properties of one or more\n"
134
               "                                      units/jobs or the manager\n"
135
               "  cat PATTERN...                      Show files and drop-ins of specified units\n"
136
               "  help PATTERN...|PID...              Show manual for one or more units\n"
137
               "  list-dependencies [UNIT...]         Recursively show units which are required\n"
138
               "                                      or wanted by the units or by which those\n"
139
               "                                      units are required or wanted\n"
140
               "  start UNIT...                       Start (activate) one or more units\n"
141
               "  stop UNIT...                        Stop (deactivate) one or more units\n"
142
               "  reload UNIT...                      Reload one or more units\n"
143
               "  restart UNIT...                     Start or restart one or more units\n"
144
               "  try-restart UNIT...                 Restart one or more units if active\n"
145
               "  reload-or-restart UNIT...           Reload one or more units if possible,\n"
146
               "                                      otherwise start or restart\n"
147
               "  try-reload-or-restart UNIT...       If active, reload one or more units,\n"
148
               "                                      if supported, otherwise restart\n"
149
               "  isolate UNIT                        Start one unit and stop all others\n"
150
               "  kill UNIT...                        Send signal to processes of a unit\n"
151
               "  clean UNIT...                       Clean runtime, cache, state, logs or\n"
152
               "                                      configuration of unit\n"
153
               "  freeze PATTERN...                   Freeze execution of unit processes\n"
154
               "  thaw PATTERN...                     Resume execution of a frozen unit\n"
155
               "  set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
156
               "  bind UNIT PATH [PATH]               Bind-mount a path from the host into a\n"
157
               "                                      unit's namespace\n"
158
               "  mount-image UNIT PATH [PATH [OPTS]] Mount an image from the host into a\n"
159
               "                                      unit's namespace\n"
160
               "  service-log-level SERVICE [LEVEL]   Get/set logging threshold for service\n"
161
               "  service-log-target SERVICE [TARGET] Get/set logging target for service\n"
162
               "  reset-failed [PATTERN...]           Reset failed state for all, one, or more\n"
163
               "                                      units\n"
164
               "  whoami [PID...]                     Return unit caller or specified PIDs are\n"
165
               "                                      part of\n"
166
               "\n%3$sUnit File Commands:%4$s\n"
167
               "  list-unit-files [PATTERN...]        List installed unit files\n"
168
               "  enable [UNIT...|PATH...]            Enable one or more unit files\n"
169
               "  disable UNIT...                     Disable one or more unit files\n"
170
               "  reenable UNIT...                    Reenable one or more unit files\n"
171
               "  preset UNIT...                      Enable/disable one or more unit files\n"
172
               "                                      based on preset configuration\n"
173
               "  preset-all                          Enable/disable all unit files based on\n"
174
               "                                      preset configuration\n"
175
               "  is-enabled UNIT...                  Check whether unit files are enabled\n"
176
               "  mask UNIT...                        Mask one or more units\n"
177
               "  unmask UNIT...                      Unmask one or more units\n"
178
               "  link PATH...                        Link one or more units files into\n"
179
               "                                      the search path\n"
180
               "  revert UNIT...                      Revert one or more unit files to vendor\n"
181
               "                                      version\n"
182
               "  add-wants TARGET UNIT...            Add 'Wants' dependency for the target\n"
183
               "                                      on specified one or more units\n"
184
               "  add-requires TARGET UNIT...         Add 'Requires' dependency for the target\n"
185
               "                                      on specified one or more units\n"
186
               "  edit UNIT...                        Edit one or more unit files\n"
187
               "  get-default                         Get the name of the default target\n"
188
               "  set-default TARGET                  Set the default target\n"
189
               "\n%3$sMachine Commands:%4$s\n"
190
               "  list-machines [PATTERN...]          List local containers and host\n"
191
               "\n%3$sJob Commands:%4$s\n"
192
               "  list-jobs [PATTERN...]              List jobs\n"
193
               "  cancel [JOB...]                     Cancel all, one, or more jobs\n"
194
               "\n%3$sEnvironment Commands:%4$s\n"
195
               "  show-environment                    Dump environment\n"
196
               "  set-environment VARIABLE=VALUE...   Set one or more environment variables\n"
197
               "  unset-environment VARIABLE...       Unset one or more environment variables\n"
198
               "  import-environment VARIABLE...      Import all or some environment variables\n"
199
               "\n%3$sManager State Commands:%4$s\n"
200
               "  daemon-reload                       Reload systemd manager configuration\n"
201
               "  daemon-reexec                       Reexecute systemd manager\n"
202
               "  log-level [LEVEL]                   Get/set logging threshold for manager\n"
203
               "  log-target [TARGET]                 Get/set logging target for manager\n"
204
               "  service-watchdogs [BOOL]            Get/set service watchdog state\n"
205
               "\n%3$sSystem Commands:%4$s\n"
206
               "  is-system-running                   Check whether system is fully running\n"
207
               "  default                             Enter system default mode\n"
208
               "  rescue                              Enter system rescue mode\n"
209
               "  emergency                           Enter system emergency mode\n"
210
               "  halt                                Shut down and halt the system\n"
211
               "  poweroff                            Shut down and power-off the system\n"
212
               "  reboot                              Shut down and reboot the system\n"
213
               "  kexec                               Shut down and reboot the system with kexec\n"
214
               "  soft-reboot                         Shut down and reboot userspace\n"
215
               "  exit [EXIT_CODE]                    Request user instance or container exit\n"
216
               "  switch-root [ROOT [INIT]]           Change to a different root file system\n"
217
               "  sleep                               Put the system to sleep (through one of\n"
218
               "                                      the operations below)\n"
219
               "  suspend                             Suspend the system\n"
220
               "  hibernate                           Hibernate the system\n"
221
               "  hybrid-sleep                        Hibernate and suspend the system\n"
222
               "  suspend-then-hibernate              Suspend the system, wake after a period of\n"
223
               "                                      time, and hibernate"
224
               "\n%3$sOptions:%4$s\n"
225
               "  -h --help              Show this help\n"
226
               "     --version           Show package version\n"
227
               "     --system            Connect to system manager\n"
228
               "     --user              Connect to user service manager\n"
229
               "  -C --capsule=NAME      Connect to service manager of specified capsule\n"
230
               "  -H --host=[USER@]HOST  Operate on remote host\n"
231
               "  -M --machine=CONTAINER Operate on a local container\n"
232
               "  -t --type=TYPE         List units of a particular type\n"
233
               "     --state=STATE       List units with particular LOAD or SUB or ACTIVE state\n"
234
               "     --failed            Shortcut for --state=failed\n"
235
               "  -p --property=NAME     Show only properties by this name\n"
236
               "  -P NAME                Equivalent to --value --property=NAME\n"
237
               "  -a --all               Show all properties/all units currently in memory,\n"
238
               "                         including dead/empty ones. To list all units installed\n"
239
               "                         on the system, use 'list-unit-files' instead.\n"
240
               "  -l --full              Don't ellipsize unit names on output\n"
241
               "  -r --recursive         Show unit list of host and local containers\n"
242
               "     --reverse           Show reverse dependencies with 'list-dependencies'\n"
243
               "     --before            Show units ordered before with 'list-dependencies'\n"
244
               "     --after             Show units ordered after with 'list-dependencies'\n"
245
               "     --with-dependencies Show unit dependencies with 'status', 'cat',\n"
246
               "                         'list-units', and 'list-unit-files'.\n"
247
               "     --job-mode=MODE     Specify how to deal with already queued jobs, when\n"
248
               "                         queueing a new job\n"
249
               "  -T --show-transaction  When enqueuing a unit job, show full transaction\n"
250
               "     --show-types        When showing sockets, explicitly show their type\n"
251
               "     --value             When showing properties, only print the value\n"
252
               "     --check-inhibitors=MODE\n"
253
               "                         Whether to check inhibitors before shutting down,\n"
254
               "                         sleeping, or hibernating\n"
255
               "  -i                     Shortcut for --check-inhibitors=no\n"
256
               "     --kill-whom=WHOM    Whom to send signal to\n"
257
               "     --kill-value=INT    Signal value to enqueue\n"
258
               "  -s --signal=SIGNAL     Which signal to send\n"
259
               "     --what=RESOURCES    Which types of resources to remove\n"
260
               "     --now               Start or stop unit after enabling or disabling it\n"
261
               "     --dry-run           Only print what would be done\n"
262
               "                         Currently supported by verbs: halt, poweroff, reboot,\n"
263
               "                             kexec, soft-reboot, suspend, hibernate, \n"
264
               "                             suspend-then-hibernate, hybrid-sleep, default,\n"
265
               "                             rescue, emergency, and exit.\n"
266
               "  -q --quiet             Suppress output\n"
267
               "  -v --verbose           Show unit logs while executing operation\n"
268
               "     --no-warn           Suppress several warnings shown by default\n"
269
               "     --wait              For (re)start, wait until service stopped again\n"
270
               "                         For is-system-running, wait until startup is completed\n"
271
               "                         For kill, wait until service stopped\n"
272
               "     --no-block          Do not wait until operation finished\n"
273
               "     --no-wall           Don't send wall message before halt/power-off/reboot\n"
274
               "     --message=MESSAGE   Specify human readable reason for system shutdown\n"
275
               "     --no-reload         Don't reload daemon after en-/dis-abling unit files\n"
276
               "     --legend=BOOL       Enable/disable the legend (column headers and hints)\n"
277
               "     --no-pager          Do not pipe output into a pager\n"
278
               "     --no-ask-password   Do not ask for system passwords\n"
279
               "     --global            Edit/enable/disable/mask default user unit files\n"
280
               "                         globally\n"
281
               "     --runtime           Edit/enable/disable/mask unit files temporarily until\n"
282
               "                         next 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         Edit/enable/disable/mask unit files in the specified\n"
287
               "                         root directory\n"
288
               "     --image=PATH        Edit/enable/disable/mask unit files in the specified\n"
289
               "                         disk image\n"
290
               "     --image-policy=POLICY\n"
291
               "                         Specify disk image dissection policy\n"
292
               "  -n --lines=INTEGER     Number of journal entries to show\n"
293
               "  -o --output=STRING     Change journal output mode (short, short-precise,\n"
294
               "                             short-iso, short-iso-precise, short-full,\n"
295
               "                             short-monotonic, short-unix, short-delta,\n"
296
               "                             verbose, export, json, json-pretty, json-sse, cat)\n"
297
               "     --firmware-setup    Tell the firmware to show the setup menu on next boot\n"
298
               "     --boot-loader-menu=TIME\n"
299
               "                         Boot into boot loader menu on next boot\n"
300
               "     --boot-loader-entry=NAME\n"
301
               "                         Boot into a specific boot loader entry on next boot\n"
302
               "     --reboot-argument=ARG\n"
303
               "                         Specify argument string to pass to reboot()\n"
304
               "     --plain             Print unit dependencies as a list instead of a tree\n"
305
               "     --timestamp=FORMAT  Change format of printed timestamps (pretty, unix,\n"
306
               "                             us, utc, us+utc)\n"
307
               "     --read-only         Create read-only bind mount\n"
308
               "     --mkdir             Create directory before mounting, if missing\n"
309
               "     --marked            Restart/reload previously marked units\n"
310
               "     --drop-in=NAME      Edit unit files using the specified drop-in file name\n"
311
               "     --when=TIME         Schedule halt/power-off/reboot/kexec action after\n"
312
               "                         a certain timestamp\n"
313
               "     --stdin             Read new contents of edited file from stdin\n"
314
               "\nSee the %2$s for details.\n",
315
               program_invocation_short_name,
316
               link,
317
               ansi_underline(),
318
               ansi_normal(),
319
               ansi_highlight(),
320
               ansi_normal());
321

322
        return 0;
323
}
324

325
static void help_types(void) {
1✔
326
        if (arg_legend != 0)
1✔
327
                puts("Available unit types:");
1✔
328

329
        DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
12✔
330
}
1✔
331

332
static void help_states(void) {
1✔
333
        if (arg_legend != 0)
1✔
334
                puts("Available unit load states:");
1✔
335
        DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
8✔
336

337
        if (arg_legend != 0)
1✔
338
                puts("\nAvailable unit active states:");
1✔
339
        DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
9✔
340

341
        if (arg_legend != 0)
1✔
342
                puts("\nAvailable unit file states:");
1✔
343
        DUMP_STRING_TABLE(unit_file_state, UnitFileState, _UNIT_FILE_STATE_MAX);
14✔
344

345
        if (arg_legend != 0)
1✔
346
                puts("\nAvailable automount unit substates:");
1✔
347
        DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
5✔
348

349
        if (arg_legend != 0)
1✔
350
                puts("\nAvailable device unit substates:");
1✔
351
        DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
4✔
352

353
        if (arg_legend != 0)
1✔
354
                puts("\nAvailable mount unit substates:");
1✔
355
        DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
13✔
356

357
        if (arg_legend != 0)
1✔
358
                puts("\nAvailable path unit substates:");
1✔
359
        DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
5✔
360

361
        if (arg_legend != 0)
1✔
362
                puts("\nAvailable scope unit substates:");
1✔
363
        DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
8✔
364

365
        if (arg_legend != 0)
1✔
366
                puts("\nAvailable service unit substates:");
1✔
367
        DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
28✔
368

369
        if (arg_legend != 0)
1✔
370
                puts("\nAvailable slice unit substates:");
1✔
371
        DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
3✔
372

373
        if (arg_legend != 0)
1✔
374
                puts("\nAvailable socket unit substates:");
1✔
375
        DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
16✔
376

377
        if (arg_legend != 0)
1✔
378
                puts("\nAvailable swap unit substates:");
1✔
379
        DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
10✔
380

381
        if (arg_legend != 0)
1✔
382
                puts("\nAvailable target unit substates:");
1✔
383
        DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
3✔
384

385
        if (arg_legend != 0)
1✔
386
                puts("\nAvailable timer unit substates:");
1✔
387
        DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
6✔
388
}
1✔
389

390
static int systemctl_parse_argv(int argc, char *argv[]) {
11,286✔
391
        enum {
11,286✔
392
                ARG_FAIL = 0x100,            /* compatibility only */
393
                ARG_REVERSE,
394
                ARG_AFTER,
395
                ARG_BEFORE,
396
                ARG_CHECK_INHIBITORS,
397
                ARG_DRY_RUN,
398
                ARG_SHOW_TYPES,
399
                ARG_IRREVERSIBLE,            /* compatibility only */
400
                ARG_IGNORE_DEPENDENCIES,     /* compatibility only */
401
                ARG_VALUE,
402
                ARG_VERSION,
403
                ARG_USER,
404
                ARG_SYSTEM,
405
                ARG_GLOBAL,
406
                ARG_NO_BLOCK,
407
                ARG_LEGEND,
408
                ARG_NO_LEGEND,                /* compatibility only */
409
                ARG_NO_PAGER,
410
                ARG_NO_WALL,
411
                ARG_ROOT,
412
                ARG_IMAGE,
413
                ARG_IMAGE_POLICY,
414
                ARG_NO_RELOAD,
415
                ARG_KILL_WHOM,
416
                ARG_KILL_VALUE,
417
                ARG_NO_ASK_PASSWORD,
418
                ARG_FAILED,
419
                ARG_RUNTIME,
420
                ARG_PLAIN,
421
                ARG_STATE,
422
                ARG_JOB_MODE,
423
                ARG_PRESET_MODE,
424
                ARG_FIRMWARE_SETUP,
425
                ARG_BOOT_LOADER_MENU,
426
                ARG_BOOT_LOADER_ENTRY,
427
                ARG_NOW,
428
                ARG_MESSAGE,
429
                ARG_WITH_DEPENDENCIES,
430
                ARG_WAIT,
431
                ARG_WHAT,
432
                ARG_REBOOT_ARG,
433
                ARG_TIMESTAMP_STYLE,
434
                ARG_READ_ONLY,
435
                ARG_MKDIR,
436
                ARG_MARKED,
437
                ARG_NO_WARN,
438
                ARG_DROP_IN,
439
                ARG_WHEN,
440
                ARG_STDIN,
441
        };
442

443
        static const struct option options[] = {
11,286✔
444
                { "help",                no_argument,       NULL, 'h'                     },
445
                { "version",             no_argument,       NULL, ARG_VERSION             },
446
                { "type",                required_argument, NULL, 't'                     },
447
                { "property",            required_argument, NULL, 'p'                     },
448
                { "all",                 no_argument,       NULL, 'a'                     },
449
                { "reverse",             no_argument,       NULL, ARG_REVERSE             },
450
                { "after",               no_argument,       NULL, ARG_AFTER               },
451
                { "before",              no_argument,       NULL, ARG_BEFORE              },
452
                { "show-types",          no_argument,       NULL, ARG_SHOW_TYPES          },
453
                { "failed",              no_argument,       NULL, ARG_FAILED              },
454
                { "full",                no_argument,       NULL, 'l'                     },
455
                { "job-mode",            required_argument, NULL, ARG_JOB_MODE            },
456
                { "fail",                no_argument,       NULL, ARG_FAIL                }, /* compatibility only */
457
                { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        }, /* compatibility only */
458
                { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
459
                { "ignore-inhibitors",   no_argument,       NULL, 'i'                     }, /* compatibility only */
460
                { "check-inhibitors",    required_argument, NULL, ARG_CHECK_INHIBITORS    },
461
                { "value",               no_argument,       NULL, ARG_VALUE               },
462
                { "user",                no_argument,       NULL, ARG_USER                },
463
                { "system",              no_argument,       NULL, ARG_SYSTEM              },
464
                { "global",              no_argument,       NULL, ARG_GLOBAL              },
465
                { "capsule",             required_argument, NULL, 'C'                     },
466
                { "wait",                no_argument,       NULL, ARG_WAIT                },
467
                { "no-block",            no_argument,       NULL, ARG_NO_BLOCK            },
468
                { "legend",              required_argument, NULL, ARG_LEGEND              },
469
                { "no-legend",           no_argument,       NULL, ARG_NO_LEGEND           }, /* compatibility only */
470
                { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
471
                { "no-wall",             no_argument,       NULL, ARG_NO_WALL             },
472
                { "dry-run",             no_argument,       NULL, ARG_DRY_RUN             },
473
                { "quiet",               no_argument,       NULL, 'q'                     },
474
                { "verbose",             no_argument,       NULL, 'v'                     },
475
                { "no-warn",             no_argument,       NULL, ARG_NO_WARN             },
476
                { "root",                required_argument, NULL, ARG_ROOT                },
477
                { "image",               required_argument, NULL, ARG_IMAGE               },
478
                { "image-policy",        required_argument, NULL, ARG_IMAGE_POLICY        },
479
                { "force",               no_argument,       NULL, 'f'                     },
480
                { "no-reload",           no_argument,       NULL, ARG_NO_RELOAD           },
481
                { "kill-whom",           required_argument, NULL, ARG_KILL_WHOM           },
482
                { "kill-value",          required_argument, NULL, ARG_KILL_VALUE          },
483
                { "signal",              required_argument, NULL, 's'                     },
484
                { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
485
                { "host",                required_argument, NULL, 'H'                     },
486
                { "machine",             required_argument, NULL, 'M'                     },
487
                { "runtime",             no_argument,       NULL, ARG_RUNTIME             },
488
                { "lines",               required_argument, NULL, 'n'                     },
489
                { "output",              required_argument, NULL, 'o'                     },
490
                { "plain",               no_argument,       NULL, ARG_PLAIN               },
491
                { "state",               required_argument, NULL, ARG_STATE               },
492
                { "recursive",           no_argument,       NULL, 'r'                     },
493
                { "with-dependencies",   no_argument,       NULL, ARG_WITH_DEPENDENCIES   },
494
                { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
495
                { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
496
                { "boot-loader-menu",    required_argument, NULL, ARG_BOOT_LOADER_MENU    },
497
                { "boot-loader-entry",   required_argument, NULL, ARG_BOOT_LOADER_ENTRY   },
498
                { "now",                 no_argument,       NULL, ARG_NOW                 },
499
                { "message",             required_argument, NULL, ARG_MESSAGE             },
500
                { "show-transaction",    no_argument,       NULL, 'T'                     },
501
                { "what",                required_argument, NULL, ARG_WHAT                },
502
                { "reboot-argument",     required_argument, NULL, ARG_REBOOT_ARG          },
503
                { "timestamp",           required_argument, NULL, ARG_TIMESTAMP_STYLE     },
504
                { "read-only",           no_argument,       NULL, ARG_READ_ONLY           },
505
                { "mkdir",               no_argument,       NULL, ARG_MKDIR               },
506
                { "marked",              no_argument,       NULL, ARG_MARKED              },
507
                { "drop-in",             required_argument, NULL, ARG_DROP_IN             },
508
                { "when",                required_argument, NULL, ARG_WHEN                },
509
                { "stdin",               no_argument,       NULL, ARG_STDIN               },
510
                {}
511
        };
512

513
        int c, r;
11,286✔
514

515
        assert(argc >= 0);
11,286✔
516
        assert(argv);
11,286✔
517

518
        /* We default to allowing interactive authorization only in systemctl (not in the legacy commands) */
519
        arg_ask_password = true;
11,286✔
520

521
        while ((c = getopt_long(argc, argv, "hC:t:p:P:alqvfs:H:M:n:o:iTr.::", options, NULL)) >= 0)
35,877✔
522

523
                switch (c) {
13,315✔
524

UNCOV
525
                case 'h':
×
526
                        return systemctl_help();
×
527

528
                case ARG_VERSION:
7✔
529
                        return version();
7✔
530

531
                case 't':
53✔
532
                        if (isempty(optarg))
53✔
UNCOV
533
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
534
                                                       "--type= requires arguments.");
535

536
                        for (const char *p = optarg;;) {
53✔
537
                                _cleanup_free_ char *type = NULL;
56✔
538

539
                                r = extract_first_word(&p, &type, ",", 0);
108✔
540
                                if (r < 0)
108✔
UNCOV
541
                                        return log_error_errno(r, "Failed to parse type: %s", optarg);
×
542
                                if (r == 0)
108✔
543
                                        break;
544

545
                                if (streq(type, "help")) {
56✔
546
                                        help_types();
1✔
547
                                        return 0;
548
                                }
549

550
                                if (unit_type_from_string(type) >= 0) {
55✔
551
                                        if (strv_consume(&arg_types, TAKE_PTR(type)) < 0)
53✔
UNCOV
552
                                                return log_oom();
×
553
                                        continue;
53✔
554
                                }
555

556
                                /* It's much nicer to use --state= for load states, but let's support this in
557
                                 * --types= too for compatibility with old versions */
558
                                if (unit_load_state_from_string(type) >= 0) {
2✔
559
                                        if (strv_consume(&arg_states, TAKE_PTR(type)) < 0)
2✔
UNCOV
560
                                                return log_oom();
×
561
                                        continue;
2✔
562
                                }
563

UNCOV
564
                                log_error("Unknown unit type or load state '%s'.", type);
×
565
                                return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
×
566
                                                      "Use -t help to see a list of allowed values.");
567
                        }
568

569
                        break;
52✔
570

571
                case 'P':
237✔
572
                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
237✔
573
                        _fallthrough_;
5,387✔
574

575
                case 'p':
5,387✔
576
                        /* Make sure that if the empty property list was specified, we won't show any
577
                           properties. */
578
                        if (isempty(optarg) && !arg_properties) {
5,388✔
579
                                arg_properties = new0(char*, 1);
1✔
580
                                if (!arg_properties)
1✔
UNCOV
581
                                        return log_oom();
×
582
                        } else
583
                                for (const char *p = optarg;;) {
5,386✔
584
                                        _cleanup_free_ char *prop = NULL;
10,782✔
585

586
                                        r = extract_first_word(&p, &prop, ",", 0);
10,782✔
587
                                        if (r < 0)
10,782✔
UNCOV
588
                                                return log_error_errno(r, "Failed to parse property: %s", optarg);
×
589
                                        if (r == 0)
10,782✔
590
                                                break;
591

592
                                        if (strv_consume(&arg_properties, TAKE_PTR(prop)) < 0)
5,396✔
UNCOV
593
                                                return log_oom();
×
594
                                }
595

596
                        /* If the user asked for a particular property, show it, even if it is empty. */
597
                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
5,387✔
598

599
                        break;
5,387✔
600

601
                case 'a':
54✔
602
                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
54✔
603
                        arg_all = true;
54✔
604
                        break;
54✔
605

606
                case ARG_REVERSE:
3✔
607
                        arg_dependency = DEPENDENCY_REVERSE;
3✔
608
                        break;
3✔
609

610
                case ARG_AFTER:
5✔
611
                        arg_dependency = DEPENDENCY_AFTER;
5✔
612
                        arg_jobs_after = true;
5✔
613
                        break;
5✔
614

615
                case ARG_BEFORE:
5✔
616
                        arg_dependency = DEPENDENCY_BEFORE;
5✔
617
                        arg_jobs_before = true;
5✔
618
                        break;
5✔
619

620
                case ARG_SHOW_TYPES:
1✔
621
                        arg_show_types = true;
1✔
622
                        break;
1✔
623

624
                case ARG_VALUE:
5,045✔
625
                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
5,045✔
626
                        break;
5,045✔
627

628
                case ARG_JOB_MODE:
16✔
629
                        _arg_job_mode = optarg;
16✔
630
                        break;
16✔
631

UNCOV
632
                case ARG_FAIL:
×
633
                        _arg_job_mode = "fail";
×
634
                        break;
×
635

UNCOV
636
                case ARG_IRREVERSIBLE:
×
637
                        _arg_job_mode = "replace-irreversibly";
×
638
                        break;
×
639

UNCOV
640
                case ARG_IGNORE_DEPENDENCIES:
×
641
                        _arg_job_mode = "ignore-dependencies";
×
642
                        break;
×
643

644
                case ARG_USER:
197✔
645
                        arg_runtime_scope = RUNTIME_SCOPE_USER;
197✔
646
                        break;
197✔
647

UNCOV
648
                case ARG_SYSTEM:
×
649
                        arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
×
650
                        break;
×
651

UNCOV
652
                case ARG_GLOBAL:
×
653
                        arg_runtime_scope = RUNTIME_SCOPE_GLOBAL;
×
654
                        break;
×
655

656
                case 'C':
3✔
657
                        r = capsule_name_is_valid(optarg);
3✔
658
                        if (r < 0)
3✔
UNCOV
659
                                return log_error_errno(r, "Unable to validate capsule name '%s': %m", optarg);
×
660
                        if (r == 0)
3✔
UNCOV
661
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid capsule name: %s", optarg);
×
662

663
                        arg_host = optarg;
3✔
664
                        arg_transport = BUS_TRANSPORT_CAPSULE;
3✔
665
                        arg_runtime_scope = RUNTIME_SCOPE_USER;
3✔
666
                        break;
3✔
667

668
                case ARG_WAIT:
14✔
669
                        arg_wait = true;
14✔
670
                        break;
14✔
671

672
                case ARG_NO_BLOCK:
110✔
673
                        arg_no_block = true;
110✔
674
                        break;
110✔
675

676
                case ARG_NO_LEGEND:
54✔
677
                        arg_legend = false;
54✔
678
                        break;
54✔
679

680
                case ARG_LEGEND:
3✔
681
                        r = parse_boolean_argument("--legend", optarg, NULL);
3✔
682
                        if (r < 0)
3✔
683
                                return r;
684
                        arg_legend = r;
3✔
685
                        break;
3✔
686

687
                case ARG_NO_PAGER:
7✔
688
                        arg_pager_flags |= PAGER_DISABLE;
7✔
689
                        break;
7✔
690

691
                case ARG_NO_WALL:
3✔
692
                        arg_no_wall = true;
3✔
693
                        break;
3✔
694

695
                case ARG_ROOT:
41✔
696
                        r = parse_path_argument(optarg, false, &arg_root);
41✔
697
                        if (r < 0)
41✔
698
                                return r;
699
                        break;
700

UNCOV
701
                case ARG_IMAGE:
×
702
                        r = parse_path_argument(optarg, false, &arg_image);
×
703
                        if (r < 0)
×
704
                                return r;
705
                        break;
706

UNCOV
707
                case ARG_IMAGE_POLICY:
×
708
                        r = parse_image_policy_argument(optarg, &arg_image_policy);
×
709
                        if (r < 0)
×
710
                                return r;
711
                        break;
712

713
                case 'l':
5✔
714
                        arg_full = true;
5✔
715
                        break;
5✔
716

717
                case ARG_FAILED:
718
                        if (strv_extend(&arg_states, "failed") < 0)
1✔
UNCOV
719
                                return log_oom();
×
720

721
                        break;
722

723
                case ARG_DRY_RUN:
23✔
724
                        arg_dry_run = true;
23✔
725
                        break;
23✔
726

727
                case 'q':
2,088✔
728
                        arg_quiet = true;
2,088✔
729

730
                        if (arg_legend < 0)
2,088✔
731
                                arg_legend = false;
2,088✔
732

733
                        break;
734

UNCOV
735
                case 'v':
×
736
                        arg_verbose = true;
×
737
                        break;
×
738

739
                case 'f':
13✔
740
                        arg_force++;
13✔
741
                        break;
13✔
742

UNCOV
743
                case ARG_NO_RELOAD:
×
744
                        arg_no_reload = true;
×
745
                        break;
×
746

747
                case ARG_KILL_WHOM:
9✔
748
                        arg_kill_whom = optarg;
9✔
749
                        break;
9✔
750

751
                case ARG_KILL_VALUE: {
6✔
752
                        unsigned u;
6✔
753

754
                        if (isempty(optarg)) {
6✔
UNCOV
755
                                arg_kill_value_set = false;
×
756
                                return 0;
×
757
                        }
758

759
                        /* First, try to parse unsigned, so that we can support the prefixes 0x, 0o, 0b */
760
                        r = safe_atou_full(optarg, 0, &u);
6✔
761
                        if (r < 0)
6✔
762
                                /* If this didn't work, try as signed integer, without those prefixes */
UNCOV
763
                                r = safe_atoi(optarg, &arg_kill_value);
×
764
                        else if (u > INT_MAX)
6✔
765
                                r = -ERANGE;
766
                        else
767
                                arg_kill_value = (int) u;
6✔
768
                        if (r < 0)
6✔
UNCOV
769
                                return log_error_errno(r, "Unable to parse signal queue value: %s", optarg);
×
770

771
                        arg_kill_value_set = true;
6✔
772
                        break;
6✔
773
                }
774

775
                case 's':
22✔
776
                        r = parse_signal_argument(optarg, &arg_signal);
22✔
777
                        if (r <= 0)
22✔
778
                                return r;
779
                        break;
780

UNCOV
781
                case ARG_NO_ASK_PASSWORD:
×
782
                        arg_ask_password = false;
×
783
                        break;
×
784

UNCOV
785
                case 'H':
×
786
                        arg_transport = BUS_TRANSPORT_REMOTE;
×
787
                        arg_host = optarg;
×
788
                        break;
×
789

790
                case 'M':
21✔
791
                        arg_transport = BUS_TRANSPORT_MACHINE;
21✔
792
                        arg_host = optarg;
21✔
793
                        break;
21✔
794

795
                case ARG_RUNTIME:
16✔
796
                        arg_runtime = true;
16✔
797
                        break;
16✔
798

799
                case 'n':
9✔
800
                        if (safe_atou(optarg, &arg_lines) < 0)
9✔
UNCOV
801
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
802
                                                       "Failed to parse lines '%s'",
803
                                                       optarg);
804
                        break;
805

806
                case 'o':
1✔
807
                        if (streq(optarg, "help")) {
1✔
UNCOV
808
                                DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
×
809
                                return 0;
×
810
                        }
811

812
                        arg_output = output_mode_from_string(optarg);
1✔
813
                        if (arg_output < 0)
1✔
UNCOV
814
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
815
                                                       "Unknown output '%s'.",
816
                                                       optarg);
817

818
                        if (OUTPUT_MODE_IS_JSON(arg_output)) {
24,592✔
819
                                arg_legend = false;
1✔
820
                                arg_plain = true;
1✔
821
                        }
822
                        break;
823

UNCOV
824
                case 'i':
×
825
                        arg_check_inhibitors = 0;
×
826
                        break;
×
827

UNCOV
828
                case ARG_CHECK_INHIBITORS:
×
829
                        r = parse_tristate_full(optarg, "auto", &arg_check_inhibitors);
×
830
                        if (r < 0)
×
831
                                return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
×
832
                        break;
833

834
                case ARG_PLAIN:
1✔
835
                        arg_plain = true;
1✔
836
                        break;
1✔
837

UNCOV
838
                case ARG_FIRMWARE_SETUP:
×
839
                        arg_firmware_setup = true;
×
840
                        break;
×
841

UNCOV
842
                case ARG_BOOT_LOADER_MENU:
×
843

UNCOV
844
                        r = parse_sec(optarg, &arg_boot_loader_menu);
×
845
                        if (r < 0)
×
846
                                return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
×
847

848
                        break;
849

UNCOV
850
                case ARG_BOOT_LOADER_ENTRY:
×
851

UNCOV
852
                        if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
×
853
                                r = help_boot_loader_entry();
×
854
                                if (r < 0)
×
855
                                        return r;
856

UNCOV
857
                                return 0;
×
858
                        }
859

UNCOV
860
                        arg_boot_loader_entry = empty_to_null(optarg);
×
861
                        break;
×
862

863
                case ARG_STATE:
10✔
864
                        if (isempty(optarg))
10✔
UNCOV
865
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
866
                                                       "--state= requires arguments.");
867

868
                        for (const char *p = optarg;;) {
10✔
869
                                _cleanup_free_ char *s = NULL;
12✔
870

871
                                r = extract_first_word(&p, &s, ",", 0);
21✔
872
                                if (r < 0)
21✔
UNCOV
873
                                        return log_error_errno(r, "Failed to parse state: %s", optarg);
×
874
                                if (r == 0)
21✔
875
                                        break;
876

877
                                if (streq(s, "help")) {
12✔
878
                                        help_states();
1✔
879
                                        return 0;
880
                                }
881

882
                                if (strv_consume(&arg_states, TAKE_PTR(s)) < 0)
11✔
UNCOV
883
                                        return log_oom();
×
884
                        }
885
                        break;
9✔
886

887
                case 'r':
1✔
888
                        if (geteuid() != 0)
1✔
UNCOV
889
                                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
×
890
                                                       "--recursive requires root privileges.");
891

892
                        arg_recursive = true;
1✔
893
                        break;
1✔
894

895
                case ARG_PRESET_MODE:
4✔
896
                        if (streq(optarg, "help")) {
4✔
UNCOV
897
                                DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MODE_MAX);
×
898
                                return 0;
×
899
                        }
900

901
                        arg_preset_mode = unit_file_preset_mode_from_string(optarg);
4✔
902
                        if (arg_preset_mode < 0)
4✔
UNCOV
903
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
904
                                                       "Failed to parse preset mode: %s.", optarg);
905

906
                        break;
907

908
                case ARG_NOW:
8✔
909
                        arg_now = true;
8✔
910
                        break;
8✔
911

912
                case ARG_MESSAGE:
3✔
913
                        if (strv_extend(&arg_wall, optarg) < 0)
3✔
UNCOV
914
                                return log_oom();
×
915
                        break;
916

917
                case 'T':
10✔
918
                        arg_show_transaction = true;
10✔
919
                        break;
10✔
920

921
                case ARG_WITH_DEPENDENCIES:
3✔
922
                        arg_with_dependencies = true;
3✔
923
                        break;
3✔
924

925
                case ARG_WHAT:
20✔
926
                        if (isempty(optarg))
20✔
UNCOV
927
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments (see --what=help).");
×
928

929
                        for (const char *p = optarg;;) {
20✔
930
                                _cleanup_free_ char *k = NULL;
20✔
931

932
                                r = extract_first_word(&p, &k, ",", 0);
40✔
933
                                if (r < 0)
40✔
UNCOV
934
                                        return log_error_errno(r, "Failed to parse directory type: %s", optarg);
×
935
                                if (r == 0)
40✔
936
                                        break;
937

938
                                if (streq(k, "help")) {
20✔
UNCOV
939
                                        puts("runtime\n"
×
940
                                             "state\n"
941
                                             "cache\n"
942
                                             "logs\n"
943
                                             "configuration\n"
944
                                             "fdstore\n"
945
                                             "all");
946
                                        return 0;
947
                                }
948

949
                                r = strv_consume(&arg_clean_what, TAKE_PTR(k));
20✔
950
                                if (r < 0)
20✔
UNCOV
951
                                        return log_oom();
×
952
                        }
953

954
                        break;
20✔
955

UNCOV
956
                case ARG_REBOOT_ARG:
×
957
                        arg_reboot_argument = optarg;
×
958
                        break;
×
959

960
                case ARG_TIMESTAMP_STYLE:
6✔
961
                        if (streq(optarg, "help")) {
6✔
UNCOV
962
                                DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX);
×
963
                                return 0;
×
964
                        }
965

966
                        arg_timestamp_style = timestamp_style_from_string(optarg);
6✔
967
                        if (arg_timestamp_style < 0)
6✔
UNCOV
968
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
969
                                                       "Invalid value: %s.", optarg);
970

971
                        break;
972

UNCOV
973
                case ARG_READ_ONLY:
×
974
                        arg_read_only = true;
×
975
                        break;
×
976

977
                case ARG_MKDIR:
6✔
978
                        arg_mkdir = true;
6✔
979
                        break;
6✔
980

981
                case ARG_MARKED:
1✔
982
                        arg_marked = true;
1✔
983
                        break;
1✔
984

UNCOV
985
                case ARG_NO_WARN:
×
986
                        arg_no_warn = true;
×
987
                        break;
×
988

989
                case ARG_DROP_IN:
9✔
990
                        arg_drop_in = optarg;
9✔
991
                        break;
9✔
992

UNCOV
993
                case ARG_WHEN:
×
994
                        if (streq(optarg, "show")) {
×
995
                                arg_action = ACTION_SYSTEMCTL_SHOW_SHUTDOWN;
×
996
                                return 1;
×
997
                        }
998

UNCOV
999
                        if (STR_IN_SET(optarg, "", "cancel")) {
×
1000
                                arg_action = ACTION_CANCEL_SHUTDOWN;
×
1001
                                return 1;
×
1002
                        }
1003

UNCOV
1004
                        if (streq(optarg, "auto")) {
×
1005
                                arg_when = USEC_INFINITY; /* logind chooses on server side */
×
1006
                                break;
×
1007
                        }
1008

UNCOV
1009
                        r = parse_timestamp(optarg, &arg_when);
×
1010
                        if (r < 0)
×
1011
                                return log_error_errno(r, "Failed to parse --when= argument '%s': %m", optarg);
×
1012

UNCOV
1013
                        if (!timestamp_is_set(arg_when))
×
1014
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1015
                                                       "Invalid timestamp '%s' specified for --when=.", optarg);
1016

1017
                        break;
1018

1019
                case ARG_STDIN:
11✔
1020
                        arg_stdin = true;
11✔
1021
                        break;
11✔
1022

1023
                case '.':
1024
                        /* Output an error mimicking getopt, and print a hint afterwards */
UNCOV
1025
                        log_error("%s: invalid option -- '.'", program_invocation_name);
×
1026
                        log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
×
1027
                                   "      %s [OPTIONS...] COMMAND -- -.%s ...",
1028
                                   program_invocation_name, optarg ?: "mount");
1029
                        _fallthrough_;
1030

1031
                case '?':
1032
                        return -EINVAL;
1033

UNCOV
1034
                default:
×
1035
                        assert_not_reached();
×
1036
                }
1037

1038
        /* If we are in --user mode, there's no point in talking to PolicyKit or the infra to query system
1039
         * passwords */
1040
        if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
11,276✔
1041
                arg_ask_password = false;
200✔
1042

1043
        if (arg_transport == BUS_TRANSPORT_REMOTE && arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
11,276✔
UNCOV
1044
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1045
                                       "Cannot access user instance remotely.");
1046

1047
        if (arg_transport == BUS_TRANSPORT_CAPSULE && arg_runtime_scope != RUNTIME_SCOPE_USER)
11,276✔
UNCOV
1048
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1049
                                       "Cannot access system instance with --capsule=/-C.");
1050

1051
        if (arg_wait && arg_no_block)
11,276✔
UNCOV
1052
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1053
                                       "--wait may not be combined with --no-block.");
1054

1055
        bool do_reload_or_restart = streq_ptr(argv[optind], "reload-or-restart");
11,276✔
1056
        if (arg_marked) {
11,276✔
1057
                if (!do_reload_or_restart)
1✔
UNCOV
1058
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1059
                                               "--marked may only be used with 'reload-or-restart'.");
1060
                if (optind + 1 < argc)
1✔
UNCOV
1061
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1062
                                               "No additional arguments allowed with 'reload-or-restart --marked'.");
1063
                if (arg_wait)
1✔
UNCOV
1064
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1065
                                               "--marked --wait is not supported.");
1066
                if (arg_show_transaction)
1✔
UNCOV
1067
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1068
                                               "--marked --show-transaction is not supported.");
1069

1070
        } else if (do_reload_or_restart) {
11,275✔
UNCOV
1071
                if (optind + 1 >= argc)
×
1072
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1073
                                               "List of units to restart/reload is required.");
1074
        }
1075

1076
        if (arg_image && arg_root)
11,276✔
UNCOV
1077
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1078
                                       "Please specify either --root= or --image=, the combination of both is not supported.");
1079

1080
        return 1;
1081
}
1082

1083
int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
11,298✔
1084
        assert(argc >= 0);
11,298✔
1085
        assert(argv);
11,298✔
1086

1087
        if (invoked_as(argv, "halt")) {
11,298✔
UNCOV
1088
                arg_action = ACTION_HALT;
×
1089
                return halt_parse_argv(argc, argv);
×
1090

1091
        } else if (invoked_as(argv, "poweroff")) {
11,298✔
UNCOV
1092
                arg_action = ACTION_POWEROFF;
×
1093
                return halt_parse_argv(argc, argv);
×
1094

1095
        } else if (invoked_as(argv, "reboot")) {
11,298✔
1096
                arg_action = ACTION_REBOOT;
5✔
1097
                return halt_parse_argv(argc, argv);
5✔
1098

1099
        } else if (invoked_as(argv, "shutdown")) {
11,293✔
1100
                arg_action = ACTION_POWEROFF;
7✔
1101
                return shutdown_parse_argv(argc, argv);
7✔
1102

1103
        } else if (invoked_as(argv, "init")) {
11,286✔
1104

1105
                /* Matches invocations as "init" as well as "telinit", which are synonymous when run
1106
                 * as PID != 1 on SysV.
1107
                 *
1108
                 * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
1109
                 * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
1110
                 * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
1111
                 * for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
1112
                 * immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
1113
                 * get "systemctl". In both cases we shall do the same thing, which is why we do
1114
                 * invoked_as(argv, "init") here, as a quick way to match both.
1115
                 *
1116
                 * Also see redirect_telinit() in src/core/main.c. */
1117

UNCOV
1118
                arg_action = _ACTION_INVALID; /* telinit_parse_argv() will figure out the actual action we'll execute */
×
1119
                return telinit_parse_argv(argc, argv);
×
1120

1121
        } else if (invoked_as(argv, "runlevel")) {
11,286✔
UNCOV
1122
                arg_action = ACTION_RUNLEVEL;
×
1123
                return runlevel_parse_argv(argc, argv);
×
1124
        }
1125

1126
        arg_action = ACTION_SYSTEMCTL;
11,286✔
1127
        return systemctl_parse_argv(argc, argv);
11,286✔
1128
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc