Emit a hint when called with the legacy telinit syntax (#42404)

This commit is contained in:
Yu Watanabe
2026-06-02 11:02:09 +09:00
committed by GitHub
4 changed files with 48 additions and 21 deletions
+12 -18
View File
@@ -994,12 +994,11 @@
<varlistentry>
<term><varname>emergency</varname></term>
<term><varname>rd.emergency</varname></term>
<term><varname>-b</varname></term>
<listitem><para>Boot into emergency mode. This is equivalent
to <varname>systemd.unit=emergency.target</varname> or
<varname>rd.systemd.unit=emergency.target</varname>, respectively, and
provided for compatibility reasons and to be easier to type.</para>
<listitem><para>Boot into emergency mode. Those options are equivalent to
<varname>systemd.unit=emergency.target</varname> or
<varname>rd.systemd.unit=emergency.target</varname>, respectively. They were initially
provided for compatibility with SysV, but are retained as convenient shortcuts.</para>
<xi:include href="version-info.xml" xpointer="v186"/></listitem>
</varlistentry>
@@ -1008,29 +1007,24 @@
<term><varname>rescue</varname></term>
<term><varname>rd.rescue</varname></term>
<term><varname>single</varname></term>
<term><varname>s</varname></term>
<term><varname>S</varname></term>
<term><varname>1</varname></term>
<listitem><para>Boot into rescue mode. This is equivalent to
<varname>systemd.unit=rescue.target</varname> or
<varname>rd.systemd.unit=rescue.target</varname>, respectively, and
provided for compatibility reasons and to be easier to type.</para>
<listitem><para>Boot into rescue mode. Those options are equivalent to either
<varname>systemd.unit=rescue.target</varname> or <varname>rd.systemd.unit=rescue.target</varname>.
They were initially provided for compatibility with SysV, but are retained as convenient
shortcuts.</para>
<xi:include href="version-info.xml" xpointer="v186"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>2</varname></term>
<term><varname>3</varname></term>
<term><varname>4</varname></term>
<term><varname>5</varname></term>
<listitem><para>Boot into the specified legacy SysV runlevel.
<varname>2</varname>, <varname>3</varname>, and <varname>4</varname> are equivalent to
<varname>systemd.unit=multi-user.target</varname>; and <varname>5</varname> is equivalent to
<varname>systemd.unit=graphical.target</varname>, and provided for compatibility reasons and to be
easier to type.</para>
<listitem><para>Shortcuts to boot into specific targets: <varname>3</varname> is equivalent to
<varname>systemd.unit=multi-user.target</varname> and <varname>5</varname> is equivalent to
<varname>systemd.unit=graphical.target</varname>. Those options were initially provided for
compatibility with SysV, but are retained as convenient shortcuts.</para>
<xi:include href="version-info.xml" xpointer="v186"/></listitem>
</varlistentry>
+30
View File
@@ -89,6 +89,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "pidfd-util.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "random-util.h"
@@ -1004,6 +1005,31 @@ static void set_manager_settings(Manager *m) {
m->restrict_filesystem_access = arg_restrict_filesystem_access;
}
static int redirect_telinit(char *argv[], char **args) {
/* Check if we are invoked through the legacy interface, where init would be symlinked as telinit
* and allow users to call 'init 0' and such. If we detect such use, tell the user that this is not
* supported anymore. */
if (getpid_cached() == 1 || !invoked_as(argv, "init"))
return 0;
/* Check if the user specified one of the telinit commands in args. */
if (!strv_overlap(args,
STRV_MAKE("0", "1", "2", "3", "4", "5", "6",
"s", "S", "q", "Q", "u", "U")))
return 0;
_cleanup_free_ char *a = NULL, *b = NULL, *c = NULL;
(void) terminal_urlify_man_full("shutdown", "8", /* suffix= */ NULL, &a);
(void) terminal_urlify_man_full("reboot", "8", /* suffix= */ NULL, &b);
(void) terminal_urlify_man_full("systemctl", "1", /* suffix= */ NULL, &c);
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Program 'systemd' called as 'init' with a legacy telinit command.\n"
"Call %s, %s, or %s instead.",
strnull(a), strnull(b), strnull(c));
}
static int parse_argv(int argc, char *argv[]) {
bool user_arg_seen = false;
int r;
@@ -1234,6 +1260,10 @@ static int parse_argv(int argc, char *argv[]) {
return 0;
}
r = redirect_telinit(argv, option_parser_get_args(&opts));
if (r < 0)
return r;
if (option_parser_get_n_args(&opts) > 0 && getpid_cached() != 1)
/* Hmm, when we aren't run as init system let's complain about excess arguments */
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Excess arguments.");
+2 -2
View File
@@ -177,11 +177,11 @@ int terminal_urlify_path(const char *path, const char *text, char **ret) {
return terminal_urlify(url, text, ret);
}
int terminal_urlify_man(const char *page, const char *section, char **ret) {
int terminal_urlify_man_full(const char *page, const char *section, const char *suffix, char **ret) {
const char *url, *text;
url = strjoina("man:", page, "(", section, ")");
text = strjoina(page, "(", section, ") man page");
text = strjoina(page, "(", section, ")", suffix);
return terminal_urlify(url, text, ret);
}
+4 -1
View File
@@ -21,7 +21,10 @@ bool urlify_enabled(void);
int terminal_urlify(const char *url, const char *text, char **ret);
int terminal_urlify_path(const char *path, const char *text, char **ret);
int terminal_urlify_man(const char *page, const char *section, char **ret);
int terminal_urlify_man_full(const char *page, const char *section, const char *suffix, char **ret);
static inline int terminal_urlify_man(const char *page, const char *section, char **ret) {
return terminal_urlify_man_full(page, section, " man page", ret);
}
typedef enum CatFlags {
CAT_CONFIG_OFF = 0,