]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl-compat-shutdown.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / systemctl / systemctl-compat-shutdown.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4
5 #include "alloc-util.h"
6 #include "pretty-print.h"
7 #include "systemctl-compat-shutdown.h"
8 #include "systemctl-sysv-compat.h"
9 #include "systemctl.h"
10 #include "terminal-util.h"
11
12 static int shutdown_help(void) {
13 _cleanup_free_ char *link = NULL;
14 int r;
15
16 r = terminal_urlify_man("shutdown", "8", &link);
17 if (r < 0)
18 return log_oom();
19
20 printf("%s [OPTIONS...] [TIME] [WALL...]\n"
21 "\n%sShut down the system.%s\n"
22 "\nOptions:\n"
23 " --help Show this help\n"
24 " -H --halt Halt the machine\n"
25 " -P --poweroff Power-off the machine\n"
26 " -r --reboot Reboot the machine\n"
27 " -h Equivalent to --poweroff, overridden by --halt\n"
28 " -k Don't halt/power-off/reboot, just send warnings\n"
29 " --no-wall Don't send wall message before halt/power-off/reboot\n"
30 " -c Cancel a pending shutdown\n"
31 "\nSee the %s for details.\n"
32 , program_invocation_short_name
33 , ansi_highlight(), ansi_normal()
34 , link
35 );
36
37 return 0;
38 }
39
40 int shutdown_parse_argv(int argc, char *argv[]) {
41 enum {
42 ARG_HELP = 0x100,
43 ARG_NO_WALL
44 };
45
46 static const struct option options[] = {
47 { "help", no_argument, NULL, ARG_HELP },
48 { "halt", no_argument, NULL, 'H' },
49 { "poweroff", no_argument, NULL, 'P' },
50 { "reboot", no_argument, NULL, 'r' },
51 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
52 { "no-wall", no_argument, NULL, ARG_NO_WALL },
53 {}
54 };
55
56 char **wall = NULL;
57 int c, r;
58
59 assert(argc >= 0);
60 assert(argv);
61
62 while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0)
63 switch (c) {
64
65 case ARG_HELP:
66 return shutdown_help();
67
68 case 'H':
69 arg_action = ACTION_HALT;
70 break;
71
72 case 'P':
73 arg_action = ACTION_POWEROFF;
74 break;
75
76 case 'r':
77 if (kexec_loaded())
78 arg_action = ACTION_KEXEC;
79 else
80 arg_action = ACTION_REBOOT;
81 break;
82
83 case 'K':
84 arg_action = ACTION_KEXEC;
85 break;
86
87 case 'h':
88 if (arg_action != ACTION_HALT)
89 arg_action = ACTION_POWEROFF;
90 break;
91
92 case 'k':
93 arg_dry_run = true;
94 break;
95
96 case ARG_NO_WALL:
97 arg_no_wall = true;
98 break;
99
100 case 'a':
101 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
102 case 'f':
103 case 'F':
104 /* Compatibility nops */
105 break;
106
107 case 'c':
108 arg_action = ACTION_CANCEL_SHUTDOWN;
109 break;
110
111 case '?':
112 return -EINVAL;
113
114 default:
115 assert_not_reached("Unhandled option");
116 }
117
118 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
119 r = parse_shutdown_time_spec(argv[optind], &arg_when);
120 if (r < 0) {
121 log_error("Failed to parse time specification: %s", argv[optind]);
122 return r;
123 }
124 } else
125 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
126
127 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
128 /* No time argument for shutdown cancel */
129 wall = argv + optind;
130 else if (argc > optind + 1)
131 /* We skip the time argument */
132 wall = argv + optind + 1;
133
134 if (wall) {
135 arg_wall = strv_copy(wall);
136 if (!arg_wall)
137 return log_oom();
138 }
139
140 optind = argc;
141
142 return 1;
143 }