Fix #136: drop old init client tool

The SysV API compatibility layer gives too little value to be worth
the effort of maintaining it. Users are encouraged to use the
`initctl` tool instead.

Signed-off-by: Jacques de Laval <jacques@de-laval.se>
This commit is contained in:
Jacques de Laval committed 2021-02-11 17:52:08 +01:00
1 parent eb6ac5ee22
commit cb64c068e3
13 files changed
+20 -422

No files matched your search

+3 -26
View File
@@ -385,42 +385,19 @@ Rebooting & Halting
Traditionally, rebooting and halting a UNIX system is done by changing Traditionally, rebooting and halting a UNIX system is done by changing
its runlevel. Finit comes with its own tooling providing: `shutdown`, its runlevel. Finit comes with its own tooling providing: `shutdown`,
`reboot`, `poweroff`, and `suspend`, but also the traditional `init` and `reboot`, `poweroff`, and `suspend`, but also the `initctl` tool,
`telinit`, as well as a more modern `initctl` tool, detailed in the next detailed in the next section.
section.
For compatibility reasons Finit listens to the same set of signals as For compatibility reasons Finit listens to the same set of signals as
BusyBox init. This is not 100% compatible with SysV init, but clearly BusyBox init. This is not 100% compatible with SysV init, but clearly
the more common combination for Finit. For more details, see the more common combination for Finit. For more details, see
[doc/signals.md](doc/signals.md). [doc/signals.md](doc/signals.md).
Finit also listens to the classic SysV init FIFO, used by `telinit`.
Support for this is implemented by the `initctl.so` plugin. Hence,
`telinit q` will work as the UNIX beards intended.
```shell
~ # telinit -h
Usage: telinit [OPTIONS] [q | Q | 0-9]
Options:
-h, --help This help text
-V, --version Show Finit version
Commands:
0 Power-off the system, same as initctl poweroff
6 Reboot the system, same as initctl reboot
2, 3, 4, 5 Change runlevel. Starts services in new runlevel, stops any
services in prev. runlevel that are not allowed in new.
q, Q Reload *.conf in /etc/finit.d/, same as initctl reload or
sending SIGHUP to PID 1
1, s, S Enter system rescue mode, runlevel 1
```
Commands & Status Commands & Status
----------------- -----------------
Finit also implements a more modern API to query status, and start/stop Finit also implements a modern API to query status, and start/stop
services, called `initctl`. Unlike `telinit` the `initctl` tool does services, called `initctl`. Unlike `telinit` the `initctl` tool does
not return until the given command has fully completed. not return until the given command has fully completed.
-11
View File
@@ -105,10 +105,6 @@ AC_ARG_WITH(heading,
AS_HELP_STRING([--with-heading=GREET], [Display GREET instead of Finit version at boot]), AS_HELP_STRING([--with-heading=GREET], [Display GREET instead of Finit version at boot]),
[heading=$withval], [heading="$PACKAGE_NAME v$PACKAGE_VERSION"]) [heading=$withval], [heading="$PACKAGE_NAME v$PACKAGE_VERSION"])
AC_ARG_WITH(fifo,
AS_HELP_STRING([--with-fifo=FIFO], [FIFO for init/telinit clients, default /var/run/initctl]),
[fifo=$withval], [fifo=$localstatedir/run/initctl])
AC_ARG_WITH(config, AC_ARG_WITH(config,
AS_HELP_STRING([--with-config=CONFIG], [Finit bootstrap config file, default /etc/finit.conf]), AS_HELP_STRING([--with-config=CONFIG], [Finit bootstrap config file, default /etc/finit.conf]),
[conf=$withval], [conf=$sysconfdir/finit.conf]) [conf=$withval], [conf=$sysconfdir/finit.conf])
@@ -172,12 +168,6 @@ AS_IF([test "x$enable_logrotate" != "xno"], [
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])]) AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
### With features ############################################################################## ### With features ##############################################################################
AS_IF([test "x$with_fifo" != "xno"], [
AS_IF([test "x$fifo" = "xyes"], [
fifo='$localstatedir/run/initctl'])])
AC_EXPAND_DIR(fifo_path, "$fifo")
AC_DEFINE_UNQUOTED(FINIT_FIFO, "$fifo_path", [FIFO for old style init/telinit client programs])
AS_IF([test "x$with_config" != "xno"], [ AS_IF([test "x$with_config" != "xno"], [
AS_IF([test "x$config" = "xyes"], [ AS_IF([test "x$config" = "xyes"], [
conf=$sysconfdir/finit.conf])]) conf=$sysconfdir/finit.conf])])
@@ -248,7 +238,6 @@ cat <<EOF
Exec prefix...........: $eprefix Exec prefix...........: $eprefix
Sysconfdir............: `eval echo $sysconfdir` Sysconfdir............: `eval echo $sysconfdir`
Localstatedir.........: `eval echo $localstatedir` Localstatedir.........: `eval echo $localstatedir`
FIFO path.............: $fifo_path
Finit config file.....: $conf_path Finit config file.....: $conf_path
Finit config.d path...: $rcsd_path Finit config.d path...: $rcsd_path
Finit plugin path.....: $plugin_path Finit plugin path.....: $plugin_path
+4 -6
View File
@@ -47,8 +47,6 @@ For your convenience a set of *optional* plugins are available:
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt. * *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
* *initctl.so*: Extends finit with a traditional `initctl` functionality.
* *modules-load.so*: Scans /etc/modules-load.d for modules to modprobe. * *modules-load.so*: Scans /etc/modules-load.d for modules to modprobe.
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and * *netlink.so*: Listens to Linux kernel Netlink events for gateway and
@@ -113,7 +111,7 @@ Hooks
* `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all * `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all
services are sent `SIGTERM` services are sent `SIGTERM`
Plugins like `initctl.so` and `tty.so` extend finit by acting on events, Plugins like `tty.so` extend finit by acting on events, they are called
they are called I/O plugins and are called from the finit main loop when I/O plugins and are called from the finit main loop when `poll()`
`poll()` detects an event. See the source code for `plugins/*.c` for detects an event. See the source code for `plugins/*.c` for more help
more help and ideas. and ideas.
+2 -2
View File
@@ -7,7 +7,7 @@ AM_CPPFLAGS += $(lite_CFLAGS)
if STATIC if STATIC
noinst_LTLIBRARIES = libplug.la noinst_LTLIBRARIES = libplug.la
libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c initctl.c pidfile.c procps.c tty.c urandom.c libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c pidfile.c procps.c tty.c urandom.c
if BUILD_ALSA_UTILS_PLUGIN if BUILD_ALSA_UTILS_PLUGIN
libplug_la_SOURCES += alsa-utils.c libplug_la_SOURCES += alsa-utils.c
@@ -34,7 +34,7 @@ libplug_la_SOURCES += resolvconf.c
endif endif
else else
pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la initctl.la pidfile.la procps.la tty.la urandom.la pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la pidfile.la procps.la tty.la urandom.la
if BUILD_ALSA_UTILS_PLUGIN if BUILD_ALSA_UTILS_PLUGIN
pkglib_LTLIBRARIES += alsa-utils.la pkglib_LTLIBRARIES += alsa-utils.la
-194
View File
@@ -1,194 +0,0 @@
/* Optional /dev/initctl FIFO monitor, for receiving commands from telinit
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "config.h" /* Generated by configure script */
#include <errno.h>
#include <fcntl.h> /* O_RDONLY et al */
#include <signal.h>
#include <string.h>
#include <unistd.h> /* read() */
#include <sys/stat.h>
#include <lite/lite.h>
#include "finit.h"
#include "conf.h"
#include "helpers.h"
#include "plugin.h"
#include "sig.h"
#include "service.h"
static void parse(void *arg, int fd, int events);
static void setup(void *arg);
static plugin_t plugin = {
.name = __FILE__,
.io = {
.cb = parse,
.flags = PLUGIN_IO_READ,
},
.hook[HOOK_BASEFS_UP] = {
.cb = setup
},
.depends = { "bootmisc", },
};
static void fifo_open(void)
{
plugin.io.fd = open(FINIT_FIFO, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (-1 == plugin.io.fd) {
_e("Failed opening %s FIFO, error %d: %s", FINIT_FIFO, errno, strerror(errno));
return;
}
}
/*
* We only handle INIT_HALT for differentiating between halt/poweroff
*/
static void set_env(char *data)
{
const char *var = "INIT_HALT";
if (strncmp(data, var, strlen(var)))
return;
data += strlen(var);
/*
* No value means unset env, in this case cancel shutdown.
*/
if (data[0] == 0) {
halt = SHUT_DEFAULT;
/* XXX: Cancel timer here, when we get support for timed shutdown */
return;
}
if (string_match(data, "=POWERDOWN"))
halt = SHUT_OFF;
if (string_match(data, "=HALT"))
halt = SHUT_HALT;
/* Now we wait for runlevel change, or cancelled shutdown */
}
/*
* Standard reboot/shutdown utilities talk to init using /run/initctl.
* We should check if the fifo was recreated and reopen it.
*
* For SysV compatibility the default is to halt the system when issuing
* `init 0`, unless INIT_HALT=POWERDOWN, as performed by the SysV utils.
*/
static void parse(void *arg, int fd, int events)
{
int lvl;
struct init_request rq;
while (1) {
ssize_t len = read(fd, &rq, sizeof(rq));
if (len <= 0) {
if (-1 == len) {
if (EINTR == errno)
continue;
if (EAGAIN == errno)
break;
_e("Failed reading initctl request, error %d: %s", errno, strerror(errno));
}
_d("Nothing to do, bailing out.");
break;
}
if (rq.magic != INIT_MAGIC || len != sizeof(rq)) {
_e("Invalid initctl request.");
break;
}
switch (rq.cmd) {
case INIT_CMD_RUNLVL:
switch (rq.runlevel) {
case 's':
case 'S':
rq.runlevel = '1'; /* Single user mode */
/* fallthrough */
case '0'...'9':
_d("Setting new runlevel %c", rq.runlevel);
lvl = rq.runlevel - '0';
if (lvl == 6)
halt = SHUT_REBOOT;
service_runlevel(lvl);
break;
default:
_d("Unsupported runlevel: %d", rq.runlevel);
break;
}
break;
case INIT_CMD_RELOAD:
service_reload_dynamic();
break;
case INIT_CMD_SETENV:
set_env(rq.data);
break;
default:
_d("Unsupported cmd: %d", rq.cmd);
break;
}
}
close(fd);
fifo_open();
}
/* Must run after the base FS is up, needs /run, or /var/run */
static void setup(void *arg)
{
_d("Setting up %s", FINIT_FIFO);
makefifo(FINIT_FIFO, 0600);
fifo_open();
plugin_io_init(&plugin);
}
PLUGIN_INIT(plugin_init)
{
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
plugin_unregister(&plugin);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+1 -2
View File
@@ -22,7 +22,6 @@ endif
finit_SOURCES = api.c cgroup.c cgroup.h \ finit_SOURCES = api.c cgroup.c cgroup.h \
cond.c cond-w.c cond.h \ cond.c cond-w.c cond.h \
telinit.c \
conf.c conf.h \ conf.c conf.h \
exec.c finit.c finit.h \ exec.c finit.c finit.h \
getty.c stty.c \ getty.c stty.c \
@@ -61,7 +60,7 @@ reboot_SOURCES = reboot.c util.c util.h
reboot_CFLAGS = $(lite_CFLAGS) reboot_CFLAGS = $(lite_CFLAGS)
reboot_LDADD = $(lite_LIBS) reboot_LDADD = $(lite_LIBS)
INIT_LNKS = telinit init INIT_LNKS = init
REBOOT_LNKS = shutdown halt poweroff suspend REBOOT_LNKS = shutdown halt poweroff suspend
if WATCHDOGD if WATCHDOGD
-6
View File
@@ -183,12 +183,6 @@ static void send_svc(int sd, svc_t *svc)
_d("Failed sending svc_t to client"); _d("Failed sending svc_t to client");
} }
/*
* In contrast to the SysV compat handling in plugins/initctl.c, when
* `initctl runlevel 0` is issued we default to POWERDOWN the system
* instead of just halting.
*/
static void api_cb(uev_t *w, void *arg, int events) static void api_cb(uev_t *w, void *arg, int events)
{ {
int sd, lvl; int sd, lvl;
+6 -6
View File
@@ -368,12 +368,12 @@ int main(int argc, char *argv[])
}; };
uev_ctx_t loop; uev_ctx_t loop;
/* if (getpid() != 1) {
* finit/init/telinit client tool uses /dev/initctl pipe fprintf(stderr, "Running Finit as anything other than PID 1 "
* for compatibility but initctl client tool uses socket "is not supported.\n"
*/ "The initctl tool is the new command line API.\n");
if (getpid() != 1) return 1;
return client(argc, argv); }
/* /*
* Need /dev, /proc, and /sys for console=, remount and cgroups * Need /dev, /proc, and /sys for console=, remount and cgroups
+1 -5
View File
@@ -49,11 +49,7 @@
#define LINE_SIZE 1024 #define LINE_SIZE 1024
#define BUF_SIZE 4096 #define BUF_SIZE 4096
/* /* We extend the INIT_CMD_ range for the new initctl tool. */
* We extend the INIT_CMD_ range for the new initctl tool, Finit only
* support changing runlevel, reloading the configuration and setenv
* with the old-style /dev/initctl FIFO.
*/
#define INIT_SOCKET _PATH_VARRUN "finit/socket" #define INIT_SOCKET _PATH_VARRUN "finit/socket"
#define INIT_MAGIC 0x03091969 #define INIT_MAGIC 0x03091969
+1 -1
View File
@@ -1,4 +1,4 @@
/* New client tool, complements old /dev/initctl API and telinit tool /* New client tool, replaces old /dev/initctl API and telinit tool
* *
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com> * Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
* *
-2
View File
@@ -31,8 +31,6 @@
int api_init (uev_ctx_t *ctx); int api_init (uev_ctx_t *ctx);
int api_exit (void); int api_exit (void);
int client (int argc, char *argv[]);
void service_monitor (pid_t lost, int status); void service_monitor (pid_t lost, int status);
const char *plugin_hook_str(hook_point_t no); const char *plugin_hook_str(hook_point_t no);
+2 -2
View File
@@ -26,7 +26,7 @@
* the following signals have been adopted: * the following signals have been adopted:
* *
* SIGHUP * SIGHUP
* Same effect as init/telinit q, reloads *.conf in /etc/finit.d/ * Same effect as initctl reload, reloads *.conf in /etc/finit.d/
* Also restarts API (initctl) socket, like SysV init and systemd * Also restarts API (initctl) socket, like SysV init and systemd
* does on USR1 with their FIFO/D-Bus. * does on USR1 with their FIFO/D-Bus.
* *
@@ -88,7 +88,7 @@ extern svc_t *wdog;
/* /*
* Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT", * Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT",
* "=POWERDOWN", or "" to cancel shutdown, before requesting change to * "=POWERDOWN", or "" to cancel shutdown, before requesting change to
* runlevel 6 over the /dev/initctl FIFO. See plugins/initctl.c * runlevel 6 over the /dev/initctl FIFO.
*/ */
shutop_t halt = SHUT_DEFAULT; shutop_t halt = SHUT_DEFAULT;
-159
View File
@@ -1,159 +0,0 @@
/* Simple telinit client
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "config.h" /* Generated by configure script */
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <lite/lite.h>
#include "finit.h"
#include "util.h"
static int do_send(struct init_request *rq)
{
static int fd = -1;
int result = 255;
ssize_t len;
if (fd == -1) {
if (!fexist(FINIT_FIFO)) {
fprintf(stderr, "%s does not support %s!\n", prognm, FINIT_FIFO);
return 1;
}
fd = open(FINIT_FIFO, O_RDWR);
if (-1 == fd) {
perror("Failed opening " FINIT_FIFO);
return 1;
}
}
len = write(fd, rq, sizeof(*rq));
if (sizeof(*rq) == len)
result = 0;
return result;
}
static int do_reload(void)
{
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_RELOAD,
};
return do_send(&rq);
}
static int set_env(int runlevel)
{
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_SETENV,
};
if (runlevel == 0) {
strlcpy(rq.data, "INIT_HALT=POWERDOWN", sizeof(rq.data));
return do_send(&rq);
}
return 0;
}
static int set_runlevel(int runlevel)
{
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_RUNLVL,
.runlevel = runlevel,
};
return set_env(runlevel) || do_send(&rq);
}
/* telinit q | telinit <0-9> */
static int usage(int rc)
{
fprintf(stderr, "Usage: %s [OPTIONS] [q | Q | 0-9]\n\n"
"Options:\n"
" -h, --help This help text\n"
" -V, --version Show Finit version\n\n"
"Commands:\n"
" 0 Power-off the system, same as initctl poweroff\n"
" 6 Reboot the system, same as initctl reboot\n"
" 2, 3, 4, 5 Change runlevel. Starts services in new runlevel, stops any\n"
" services in prev. runlevel that are not allowed in new.\n"
" q, Q Reload *.conf in /etc/finit.d/, same as initctl reload or\n"
" sending SIGHUP to PID 1\n"
" 1, s, S Enter system rescue mode, runlevel 1\n"
"\n", prognm);
return rc;
}
int client(int argc, char *argv[])
{
int c;
struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"version", 0, NULL, 'v'},
{NULL, 0, NULL, 0}
};
progname(argv[0]);
while ((c = getopt_long(argc, argv, "h?v", long_options, NULL)) != EOF) {
switch(c) {
case 'v':
return puts("v" VERSION) == EOF;
case 'h':
case '?':
return usage(0);
}
}
if (optind < argc) {
int req = (int)argv[optind][0];
if (isdigit(req))
return set_runlevel(req);
if (req == 'q' || req == 'Q')
return do_reload();
if (req == 's' || req == 'S')
return set_runlevel(1);
}
return usage(1);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/