mirror of
https://github.com/troglobit/finit.git
synced 2026-10-11 17:02:42 +07:00
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:
@@ -385,42 +385,19 @@ Rebooting & Halting
|
||||
|
||||
Traditionally, rebooting and halting a UNIX system is done by changing
|
||||
its runlevel. Finit comes with its own tooling providing: `shutdown`,
|
||||
`reboot`, `poweroff`, and `suspend`, but also the traditional `init` and
|
||||
`telinit`, as well as a more modern `initctl` tool, detailed in the next
|
||||
section.
|
||||
`reboot`, `poweroff`, and `suspend`, but also the `initctl` tool,
|
||||
detailed in the next section.
|
||||
|
||||
For compatibility reasons Finit listens to the same set of signals as
|
||||
BusyBox init. This is not 100% compatible with SysV init, but clearly
|
||||
the more common combination for Finit. For more details, see
|
||||
[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
|
||||
-----------------
|
||||
|
||||
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
|
||||
not return until the given command has fully completed.
|
||||
|
||||
|
||||
@@ -105,10 +105,6 @@ AC_ARG_WITH(heading,
|
||||
AS_HELP_STRING([--with-heading=GREET], [Display GREET instead of Finit version at boot]),
|
||||
[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,
|
||||
AS_HELP_STRING([--with-config=CONFIG], [Finit bootstrap config file, default /etc/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.])])
|
||||
|
||||
### 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$config" = "xyes"], [
|
||||
conf=$sysconfdir/finit.conf])])
|
||||
@@ -248,7 +238,6 @@ cat <<EOF
|
||||
Exec prefix...........: $eprefix
|
||||
Sysconfdir............: `eval echo $sysconfdir`
|
||||
Localstatedir.........: `eval echo $localstatedir`
|
||||
FIFO path.............: $fifo_path
|
||||
Finit config file.....: $conf_path
|
||||
Finit config.d path...: $rcsd_path
|
||||
Finit plugin path.....: $plugin_path
|
||||
|
||||
+4
-6
@@ -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.
|
||||
|
||||
* *initctl.so*: Extends finit with a traditional `initctl` functionality.
|
||||
|
||||
* *modules-load.so*: Scans /etc/modules-load.d for modules to modprobe.
|
||||
|
||||
* *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
|
||||
services are sent `SIGTERM`
|
||||
|
||||
Plugins like `initctl.so` and `tty.so` extend finit by acting on events,
|
||||
they are called I/O plugins and are called from the finit main loop when
|
||||
`poll()` detects an event. See the source code for `plugins/*.c` for
|
||||
more help and ideas.
|
||||
Plugins like `tty.so` extend finit by acting on events, they are called
|
||||
I/O plugins and are called from the finit main loop when `poll()`
|
||||
detects an event. See the source code for `plugins/*.c` for more help
|
||||
and ideas.
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ AM_CPPFLAGS += $(lite_CFLAGS)
|
||||
|
||||
if STATIC
|
||||
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
|
||||
libplug_la_SOURCES += alsa-utils.c
|
||||
@@ -34,7 +34,7 @@ libplug_la_SOURCES += resolvconf.c
|
||||
endif
|
||||
|
||||
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
|
||||
pkglib_LTLIBRARIES += alsa-utils.la
|
||||
|
||||
@@ -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
@@ -22,7 +22,6 @@ endif
|
||||
|
||||
finit_SOURCES = api.c cgroup.c cgroup.h \
|
||||
cond.c cond-w.c cond.h \
|
||||
telinit.c \
|
||||
conf.c conf.h \
|
||||
exec.c finit.c finit.h \
|
||||
getty.c stty.c \
|
||||
@@ -61,7 +60,7 @@ reboot_SOURCES = reboot.c util.c util.h
|
||||
reboot_CFLAGS = $(lite_CFLAGS)
|
||||
reboot_LDADD = $(lite_LIBS)
|
||||
|
||||
INIT_LNKS = telinit init
|
||||
INIT_LNKS = init
|
||||
REBOOT_LNKS = shutdown halt poweroff suspend
|
||||
|
||||
if WATCHDOGD
|
||||
|
||||
@@ -183,12 +183,6 @@ static void send_svc(int sd, svc_t *svc)
|
||||
_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)
|
||||
{
|
||||
int sd, lvl;
|
||||
|
||||
+6
-6
@@ -368,12 +368,12 @@ int main(int argc, char *argv[])
|
||||
};
|
||||
uev_ctx_t loop;
|
||||
|
||||
/*
|
||||
* finit/init/telinit client tool uses /dev/initctl pipe
|
||||
* for compatibility but initctl client tool uses socket
|
||||
*/
|
||||
if (getpid() != 1)
|
||||
return client(argc, argv);
|
||||
if (getpid() != 1) {
|
||||
fprintf(stderr, "Running Finit as anything other than PID 1 "
|
||||
"is not supported.\n"
|
||||
"The initctl tool is the new command line API.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need /dev, /proc, and /sys for console=, remount and cgroups
|
||||
|
||||
+1
-5
@@ -49,11 +49,7 @@
|
||||
#define LINE_SIZE 1024
|
||||
#define BUF_SIZE 4096
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* We extend the INIT_CMD_ range for the new initctl tool. */
|
||||
#define INIT_SOCKET _PATH_VARRUN "finit/socket"
|
||||
#define INIT_MAGIC 0x03091969
|
||||
|
||||
|
||||
+1
-1
@@ -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>
|
||||
*
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
int api_init (uev_ctx_t *ctx);
|
||||
int api_exit (void);
|
||||
|
||||
int client (int argc, char *argv[]);
|
||||
|
||||
void service_monitor (pid_t lost, int status);
|
||||
|
||||
const char *plugin_hook_str(hook_point_t no);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* the following signals have been adopted:
|
||||
*
|
||||
* 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
|
||||
* 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",
|
||||
* "=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;
|
||||
|
||||
|
||||
-159
@@ -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:
|
||||
*/
|
||||
Reference in New Issue
Block a user