diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 13:00:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 13:00:47 +0000 |
commit | 2cb7e0aaedad73b076ea18c6900b0e86c5760d79 (patch) | |
tree | da68ca54bb79f4080079bf0828acda937593a4e1 /src/systemctl/systemctl-compat-telinit.c | |
parent | Initial commit. (diff) | |
download | systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.tar.xz systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.zip |
Adding upstream version 247.3.upstream/247.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/systemctl/systemctl-compat-telinit.c')
-rw-r--r-- | src/systemctl/systemctl-compat-telinit.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/systemctl/systemctl-compat-telinit.c b/src/systemctl/systemctl-compat-telinit.c new file mode 100644 index 0000000..148574d --- /dev/null +++ b/src/systemctl/systemctl-compat-telinit.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <getopt.h> + +#include "alloc-util.h" +#include "pretty-print.h" +#include "systemctl-compat-telinit.h" +#include "systemctl-daemon-reload.h" +#include "systemctl-start-unit.h" +#include "systemctl-sysv-compat.h" +#include "systemctl.h" +#include "terminal-util.h" + +static int telinit_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("telinit", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND\n\n" + "%sSend control commands to the init daemon.%s\n" + "\nCommands:\n" + " 0 Power-off the machine\n" + " 6 Reboot the machine\n" + " 2, 3, 4, 5 Start runlevelX.target unit\n" + " 1, s, S Enter rescue mode\n" + " q, Q Reload init daemon configuration\n" + " u, U Reexecute init daemon\n" + "\nOptions:\n" + " --help Show this help\n" + " --no-wall Don't send wall message before halt/power-off/reboot\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +int telinit_parse_argv(int argc, char *argv[]) { + enum { + ARG_HELP = 0x100, + ARG_NO_WALL + }; + + static const struct option options[] = { + { "help", no_argument, NULL, ARG_HELP }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + {} + }; + + static const struct { + char from; + enum action to; + } table[] = { + { '0', ACTION_POWEROFF }, + { '6', ACTION_REBOOT }, + { '1', ACTION_RESCUE }, + { '2', ACTION_RUNLEVEL2 }, + { '3', ACTION_RUNLEVEL3 }, + { '4', ACTION_RUNLEVEL4 }, + { '5', ACTION_RUNLEVEL5 }, + { 's', ACTION_RESCUE }, + { 'S', ACTION_RESCUE }, + { 'q', ACTION_RELOAD }, + { 'Q', ACTION_RELOAD }, + { 'u', ACTION_REEXEC }, + { 'U', ACTION_REEXEC } + }; + + unsigned i; + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) { + + case ARG_HELP: + return telinit_help(); + + case ARG_NO_WALL: + arg_no_wall = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: required argument missing.", + program_invocation_short_name); + + if (optind + 1 < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + if (strlen(argv[optind]) != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected single character argument."); + + for (i = 0; i < ELEMENTSOF(table); i++) + if (table[i].from == argv[optind][0]) + break; + + if (i >= ELEMENTSOF(table)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown command '%s'.", argv[optind]); + + arg_action = table[i].to; + + optind++; + + return 1; +} + +int start_with_fallback(void) { + /* First, try systemd via D-Bus. */ + if (start_unit(0, NULL, NULL) == 0) + return 0; + +#if HAVE_SYSV_COMPAT + /* Nothing else worked, so let's try /dev/initctl */ + if (talk_initctl(action_to_runlevel()) > 0) + return 0; +#endif + + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to talk to init daemon."); +} + +int reload_with_fallback(void) { + /* First, try systemd via D-Bus. */ + if (daemon_reload(0, NULL, NULL) >= 0) + return 0; + + /* Nothing else worked, so let's try signals */ + assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC)); + + if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) + return log_error_errno(errno, "kill() failed: %m"); + + return 0; +} |