diff --git a/man/systemd.xml b/man/systemd.xml
index 30ae385029..557cd76648 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -994,12 +994,11 @@
emergency
rd.emergency
- -b
- Boot into emergency mode. This is equivalent
- to systemd.unit=emergency.target or
- rd.systemd.unit=emergency.target, respectively, and
- provided for compatibility reasons and to be easier to type.
+ Boot into emergency mode. Those options are equivalent to
+ systemd.unit=emergency.target or
+ rd.systemd.unit=emergency.target, respectively. They were initially
+ provided for compatibility with SysV, but are retained as convenient shortcuts.
@@ -1008,29 +1007,24 @@
rescue
rd.rescue
single
- s
- S
1
- Boot into rescue mode. This is equivalent to
- systemd.unit=rescue.target or
- rd.systemd.unit=rescue.target, respectively, and
- provided for compatibility reasons and to be easier to type.
+ Boot into rescue mode. Those options are equivalent to either
+ systemd.unit=rescue.target or rd.systemd.unit=rescue.target.
+ They were initially provided for compatibility with SysV, but are retained as convenient
+ shortcuts.
- 2
3
- 4
5
- Boot into the specified legacy SysV runlevel.
- 2, 3, and 4 are equivalent to
- systemd.unit=multi-user.target; and 5 is equivalent to
- systemd.unit=graphical.target, and provided for compatibility reasons and to be
- easier to type.
+ Shortcuts to boot into specific targets: 3 is equivalent to
+ systemd.unit=multi-user.target and 5 is equivalent to
+ systemd.unit=graphical.target. Those options were initially provided for
+ compatibility with SysV, but are retained as convenient shortcuts.
diff --git a/src/core/main.c b/src/core/main.c
index 7815691133..419316e25f 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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.");
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c
index 3328293c5d..c5ace49f60 100644
--- a/src/shared/pretty-print.c
+++ b/src/shared/pretty-print.c
@@ -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);
}
diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h
index 6b759dd346..44cc692011 100644
--- a/src/shared/pretty-print.h
+++ b/src/shared/pretty-print.h
@@ -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,