mirror of
https://github.com/troglobit/finit.git
synced 2026-11-15 19:13:11 +00:00
Add basic support for runlevels and bugfix FIFO I/O plugins
Like most other init implementations do, when entering runlevel 1, finit creates the file /etc/nologin to prevent users from logging in during single-user mode, this file is then removed upon leaving runlevel 1. Also, bugfix how FIFO I/O plugins are handled in finit. A FIFO will need to be reopened by the server side when the client closes the pipe. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
1 parent
ec95243dad
commit
c3b76fdccf
7 files changed
+237
-57
No files matched your search
+26
@@ -60,6 +60,31 @@ runs a directory of scripts. This replaces the earlier
|
|||||||
``/usr/sbin/services.sh`` support of the original finit_.
|
``/usr/sbin/services.sh`` support of the original finit_.
|
||||||
|
|
||||||
|
|
||||||
|
Runlevels
|
||||||
|
---------
|
||||||
|
|
||||||
|
Very simple support for runlevels_ exist. Currently the system will
|
||||||
|
always start in runlevel 3 and all services belonging to that runlevel
|
||||||
|
will be started at boot.
|
||||||
|
|
||||||
|
To specify an allowed set of runlevels for a service, add [NNN] to its
|
||||||
|
service stanza in finit.conf, like this:
|
||||||
|
|
||||||
|
service [345] /sbin/klogd -n -x -- Kernel log daemon
|
||||||
|
|
||||||
|
Meaning that klogd is allowed to run in runlevels 3, 4 and 5, only.
|
||||||
|
|
||||||
|
service [!06] /sbin/klogd -n -x -- Kernel log daemon
|
||||||
|
|
||||||
|
Meaning all runlevels *but* 0 and 6.
|
||||||
|
|
||||||
|
Existing finit.conf files that lack runlevel setting will get a default
|
||||||
|
runlevel assigned, [345].
|
||||||
|
|
||||||
|
Switching between runlevels can be done by calling init with a single
|
||||||
|
argument, e.g., 'init 5' switches to runlevel 5.
|
||||||
|
|
||||||
|
|
||||||
Rebooting and Halting
|
Rebooting and Halting
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -191,5 +216,6 @@ Regards
|
|||||||
.. _fastinit: http://wiki.eeeuser.com/boot_process:the_boot_process
|
.. _fastinit: http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
.. _`SysV init`: http://savannah.nongnu.org/projects/sysvinit
|
.. _`SysV init`: http://savannah.nongnu.org/projects/sysvinit
|
||||||
.. _upstart: http://upstart.ubuntu.com/
|
.. _upstart: http://upstart.ubuntu.com/
|
||||||
|
.. _runlevels: http://en.wikipedia.org/wiki/Runlevel
|
||||||
.. _openrc: http://www.gentoo.org/proj/en/base/openrc/
|
.. _openrc: http://www.gentoo.org/proj/en/base/openrc/
|
||||||
.. _`finit-1.3.tar.xz`: http://github.com/downloads/troglobit/finit/finit-1.3.tar.xz
|
.. _`finit-1.3.tar.xz`: http://github.com/downloads/troglobit/finit/finit-1.3.tar.xz
|
||||||
@@ -35,14 +35,16 @@
|
|||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "lite.h"
|
#include "lite.h"
|
||||||
|
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
int verbose = 1;
|
int verbose = 1;
|
||||||
char *sdown = NULL;
|
int runlevel = 3;
|
||||||
char *network = NULL;
|
int prevlevel = 1;
|
||||||
char *username = NULL;
|
char *sdown = NULL;
|
||||||
char *hostname = NULL;
|
char *network = NULL;
|
||||||
char *rcsd = NULL;
|
char *username = NULL;
|
||||||
char *console = NULL;
|
char *hostname = NULL;
|
||||||
|
char *rcsd = NULL;
|
||||||
|
char *console = NULL;
|
||||||
|
|
||||||
static void parse_kernel_cmdline(void)
|
static void parse_kernel_cmdline(void)
|
||||||
{
|
{
|
||||||
@@ -63,6 +65,37 @@ static void parse_kernel_cmdline(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int client(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct init_request rq = {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.cmd = INIT_CMD_RUNLVL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!fexist(FINIT_FIFO)) {
|
||||||
|
fprintf(stderr, "/sbin/init does not support %s!\n", FINIT_FIFO);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Missing argument.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(FINIT_FIFO, O_WRONLY);
|
||||||
|
if (-1 == fd) {
|
||||||
|
perror("Failed opening " FINIT_FIFO);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rq.runlevel = (int)argv[1][0];
|
||||||
|
write(fd, &rq, sizeof(rq));
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int run_loop(void)
|
static int run_loop(void)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -82,8 +115,11 @@ static void banner(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int UNUSED(args), char* UNUSED(argv[]))
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
if (getpid() != 1)
|
||||||
|
return client(argc, argv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initial setup of signals, ignore all until we're up.
|
* Initial setup of signals, ignore all until we're up.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -62,6 +62,19 @@
|
|||||||
#define USERNAME_SIZE 16
|
#define USERNAME_SIZE 16
|
||||||
#define HOSTNAME_SIZE 32
|
#define HOSTNAME_SIZE 32
|
||||||
|
|
||||||
|
#define INIT_MAGIC 0x03091969
|
||||||
|
#define INIT_CMD_RUNLVL 1
|
||||||
|
|
||||||
|
struct init_request {
|
||||||
|
int magic; /* Magic number */
|
||||||
|
int cmd; /* What kind of request */
|
||||||
|
int runlevel; /* Runlevel to change to */
|
||||||
|
int sleeptime; /* Time between TERM and KILL */
|
||||||
|
char data[368];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int runlevel;
|
||||||
|
extern int prevlevel;
|
||||||
extern char *sdown;
|
extern char *sdown;
|
||||||
extern char *network;
|
extern char *network;
|
||||||
extern char *hostname;
|
extern char *hostname;
|
||||||
|
|||||||
@@ -189,15 +189,20 @@ void plugin_run_hooks(hook_point_t no)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generic libev I/O callback, looks up correct plugin and calls its callback */
|
/* Generic libev I/O callback, looks up correct plugin and calls its callback */
|
||||||
static void generic_io_cb(int fd, int events)
|
static void generic_io_cb(struct pollfd *io)
|
||||||
{
|
{
|
||||||
plugin_t *p, *tmp;
|
plugin_t *p, *tmp;
|
||||||
|
|
||||||
/* Find matching plugin, pick first matching fd */
|
/* Find matching plugin, pick first matching fd */
|
||||||
PLUGIN_ITERATOR(p, tmp) {
|
PLUGIN_ITERATOR(p, tmp) {
|
||||||
if (is_io_plugin(p) && p->io.fd == fd) {
|
if (is_io_plugin(p) && p->io.fd == io->fd) {
|
||||||
_d("Calling I/O %s from runloop...", basename(p->name));
|
_d("Calling I/O %s from runloop...", basename(p->name));
|
||||||
p->io.cb(p->io.arg, fd, events);
|
p->io.cb(p->io.arg, io->fd, io->events);
|
||||||
|
|
||||||
|
/* Update fd, may be changed by plugin callback, e.g., if FIFO */
|
||||||
|
io->fd = p->io.fd;
|
||||||
|
io->events = p->io.flags;
|
||||||
|
io->revents = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +226,7 @@ void plugin_monitor(void)
|
|||||||
/* Traverse all I/O fds and run callbacks */
|
/* Traverse all I/O fds and run callbacks */
|
||||||
for (i = 0; i < num_fds; i++) {
|
for (i = 0; i < num_fds; i++) {
|
||||||
if (fds[i].revents)
|
if (fds[i].revents)
|
||||||
generic_io_cb(fds[i].fd, fds[i].revents);
|
generic_io_cb(&fds[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
+51
-33
@@ -32,78 +32,96 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
|
#include "finit.h"
|
||||||
|
|
||||||
#define INIT_MAGIC 0x03091969
|
static void parse(void *arg, int fd, int events);
|
||||||
#define INIT_CMD_RUNLVL 1
|
|
||||||
|
|
||||||
struct init_request {
|
static plugin_t plugin = {
|
||||||
int magic; /* Magic number */
|
.io = {
|
||||||
int cmd; /* What kind of request */
|
.cb = parse,
|
||||||
int runlevel; /* Runlevel to change to */
|
.flags = PLUGIN_IO_READ,
|
||||||
int sleeptime; /* Time between TERM and KILL */
|
},
|
||||||
char data[368];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void fifo_open(void)
|
||||||
|
{
|
||||||
|
plugin.io.fd = open(FINIT_FIFO, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (-1 == plugin.io.fd) {
|
||||||
|
_e("Failed opening %s FIFO, error %d: %s", FINIT_FIFO, errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Standard reboot/shutdown utilities talk to init using /dev/initctl.
|
/* Standard reboot/shutdown utilities talk to init using /dev/initctl.
|
||||||
* We should check if the fifo was recreated and reopen it.
|
* We should check if the fifo was recreated and reopen it.
|
||||||
*/
|
*/
|
||||||
static void read_initctl(void *UNUSED(arg), int fd, int UNUSED(events))
|
static void parse(void *UNUSED(arg), int fd, int UNUSED(events))
|
||||||
{
|
{
|
||||||
struct init_request request;
|
struct init_request rq;
|
||||||
|
|
||||||
_d("Receiving request on %s...", FINIT_FIFO);
|
_d("Receiving request on %s...", FINIT_FIFO);
|
||||||
while (1) {
|
while (1) {
|
||||||
ssize_t len = read(fd, &request, sizeof(request));
|
ssize_t len = read(fd, &rq, sizeof(rq));
|
||||||
|
|
||||||
if (-1 == len) {
|
if (len <= 0) {
|
||||||
_d("Error %d", errno);
|
if (-1 == len) {
|
||||||
break; /* Probably EAGAIN */
|
if (EINTR == errno)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (EAGAIN == errno)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_e("Failed reading initctl request, error %d: %s", errno, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.magic != INIT_MAGIC)
|
if (rq.magic != INIT_MAGIC || len != sizeof(rq)) {
|
||||||
continue;
|
_e("Invalid initctl request.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
_d("Magic OK...");
|
_d("Magic OK...");
|
||||||
if (request.cmd == INIT_CMD_RUNLVL) {
|
if (rq.cmd == INIT_CMD_RUNLVL) {
|
||||||
switch (request.runlevel) {
|
switch (rq.runlevel) {
|
||||||
case '0':
|
case '0':
|
||||||
_d("Halting system (SIGUSR2)");
|
_d("Halting system (SIGUSR2)");
|
||||||
do_shutdown(SIGUSR2);
|
do_shutdown(SIGUSR2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
rq.runlevel = '1';
|
||||||
|
/* Fall through to regular processing */
|
||||||
|
case '1'...'5':
|
||||||
|
_d("Setting new runlevel %c ...", rq.runlevel);
|
||||||
|
svc_runlevel(rq.runlevel - '0');
|
||||||
|
break;
|
||||||
|
|
||||||
case '6':
|
case '6':
|
||||||
_d("Rebooting system (SIGUSR1)");
|
_d("Rebooting system (SIGUSR1)");
|
||||||
do_shutdown(SIGUSR1);
|
do_shutdown(SIGUSR1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("Unsupported runlevel: %d", request.runlevel);
|
_d("Unsupported runlevel: %d", rq.runlevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_d("Unsupported cmd: %d", request.cmd);
|
_d("Unsupported cmd: %d", rq.cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
close(fd);
|
||||||
.io = {
|
fifo_open();
|
||||||
.cb = read_initctl,
|
}
|
||||||
.flags = PLUGIN_IO_READ,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
_d("Setting up %s", FINIT_FIFO);
|
_d("Setting up %s", FINIT_FIFO);
|
||||||
mkfifo(FINIT_FIFO, 0600);
|
mkfifo(FINIT_FIFO, 0600);
|
||||||
|
|
||||||
plugin.io.fd = open(FINIT_FIFO, O_RDONLY | O_NONBLOCK);
|
fifo_open();
|
||||||
if (-1 == plugin.io.fd) {
|
|
||||||
_e("Failed opening %s FIFO, error %d: %s", FINIT_FIFO, errno, strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
#include "lite.h"
|
#include "lite.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
|
#define ISSET(a,i) ((a & (1 << (i)) ? 1 : 0))
|
||||||
|
#define SETBIT(a,i) (a |= (1 << (i)))
|
||||||
|
#define CLRBIT(a,i) (a &= ~(1 << (i)))
|
||||||
|
|
||||||
/* The registered services are kept in shared memory for easy read-only access
|
/* The registered services are kept in shared memory for easy read-only access
|
||||||
* by 3rd party APIs. Mostly because of the ability to, from the outside, query
|
* by 3rd party APIs. Mostly because of the ability to, from the outside, query
|
||||||
* liveness state of all daemons that should run. */
|
* liveness state of all daemons that should run. */
|
||||||
@@ -121,6 +125,44 @@ svc_t *svc_iterator(int restart)
|
|||||||
return &services[i++];
|
return &services[i++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* svc_runlevel - Change to a new runlevel
|
||||||
|
* @newlevel: New runlevel to activate
|
||||||
|
*
|
||||||
|
* Stops all services not in @newlevel and starts, or lets continue to run,
|
||||||
|
* those in @newlevel. Also updates @prevlevel and active @runlevel.
|
||||||
|
*/
|
||||||
|
void svc_runlevel (int newlevel)
|
||||||
|
{
|
||||||
|
svc_t *svc;
|
||||||
|
|
||||||
|
if (runlevel == newlevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (newlevel > 5 || newlevel < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
prevlevel = runlevel;
|
||||||
|
runlevel = newlevel;
|
||||||
|
|
||||||
|
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
|
||||||
|
int run = svc_enabled(svc, 0, NULL);
|
||||||
|
|
||||||
|
if (svc->pid) {
|
||||||
|
if (run == SVC_STOP)
|
||||||
|
svc_stop(svc);
|
||||||
|
} else {
|
||||||
|
if (run == SVC_START)
|
||||||
|
svc_start(svc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runlevel == 1)
|
||||||
|
touch("/etc/nologin"); /* Disable login in single-user mode */
|
||||||
|
else
|
||||||
|
remove("/etc/nologin");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* svc_register - Register a non-backgrounding service to be monitored
|
* svc_register - Register a non-backgrounding service to be monitored
|
||||||
* @line: A complete command line with -- separated description text
|
* @line: A complete command line with -- separated description text
|
||||||
@@ -129,18 +171,18 @@ svc_t *svc_iterator(int restart)
|
|||||||
* Actually, the @line can optionally start with a username, denoted by
|
* Actually, the @line can optionally start with a username, denoted by
|
||||||
* an @ character. Like this:
|
* an @ character. Like this:
|
||||||
*
|
*
|
||||||
* "service [@username] /path/to/daemon -- Description text"
|
* "service @username [!0-6] /path/to/daemon -- Description text"
|
||||||
*
|
*
|
||||||
* The [] brackets means the argument is optional. If the username is
|
* If the username is left out the daemon is started as root. The []
|
||||||
* left out the daemon is started as root.
|
* brackets are there to denote the allowed runlevels.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* POSIX OK(0) on success, or non-zero errno exit status on failure.
|
* POSIX OK(0) on success, or non-zero errno exit status on failure.
|
||||||
*/
|
*/
|
||||||
int svc_register(char *line, char *username)
|
int svc_register(char *line, char *username)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0, not = 0;
|
||||||
char *cmd, *desc;
|
char *cmd, *desc, *runlevels = NULL;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
if (!line) {
|
if (!line) {
|
||||||
@@ -159,8 +201,13 @@ int svc_register(char *line, char *username)
|
|||||||
return errno = ENOENT;
|
return errno = ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd[0] == '@') { /* @username */
|
while (cmd) {
|
||||||
username = &cmd[1];
|
if (cmd[0] == '@') /* @username */
|
||||||
|
username = &cmd[1];
|
||||||
|
else if (cmd[0] == '[') /* [runlevels] */
|
||||||
|
runlevels = &cmd[0];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
/* Check if valid command follows... */
|
/* Check if valid command follows... */
|
||||||
cmd = strtok(NULL, " ");
|
cmd = strtok(NULL, " ");
|
||||||
@@ -170,7 +217,7 @@ int svc_register(char *line, char *username)
|
|||||||
|
|
||||||
svc = svc_new();
|
svc = svc_new();
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
_e("Out of memorym, cannot register service %s", cmd);
|
_e("Out of memory, cannot register service %s", cmd);
|
||||||
return errno = ENOMEM;
|
return errno = ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +232,34 @@ int svc_register(char *line, char *username)
|
|||||||
strlcpy(svc->args[i++], cmd, sizeof(svc->args[0]));
|
strlcpy(svc->args[i++], cmd, sizeof(svc->args[0]));
|
||||||
svc->args[i][0] = 0;
|
svc->args[i][0] = 0;
|
||||||
|
|
||||||
|
if (!runlevels)
|
||||||
|
runlevels = "[234]";
|
||||||
|
i = 1;
|
||||||
|
while (i) {
|
||||||
|
int level;
|
||||||
|
char lvl = runlevels[i++];
|
||||||
|
|
||||||
|
if (']' == lvl || 0 == lvl)
|
||||||
|
break;
|
||||||
|
if ('!' == lvl) {
|
||||||
|
not = 1;
|
||||||
|
svc->runlevels = 0x7E;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ('s' == lvl || 'S' == lvl)
|
||||||
|
lvl = '1';
|
||||||
|
|
||||||
|
level = lvl - '0';
|
||||||
|
if (level > 6 || level < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (not)
|
||||||
|
CLRBIT(svc->runlevels, level);
|
||||||
|
else
|
||||||
|
SETBIT(svc->runlevels, level);
|
||||||
|
}
|
||||||
|
_d("Service %s runlevel 0x%2x", svc->cmd, svc->runlevels);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +285,9 @@ svc_cmd_t svc_enabled(svc_t *svc, int event, void *arg)
|
|||||||
return SVC_STOP;
|
return SVC_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ISSET(svc->runlevels, runlevel))
|
||||||
|
return SVC_STOP;
|
||||||
|
|
||||||
/* Is there a service plugin registered? */
|
/* Is there a service plugin registered? */
|
||||||
if (svc->cb)
|
if (svc->cb)
|
||||||
return svc->cb(svc, event, arg);
|
return svc->cb(svc, event, arg);
|
||||||
@@ -333,7 +411,7 @@ int svc_start(svc_t *svc)
|
|||||||
int fd;
|
int fd;
|
||||||
char buf[CMD_SIZE] = "";
|
char buf[CMD_SIZE] = "";
|
||||||
|
|
||||||
fd = open (CONSOLE, O_WRONLY | O_APPEND);
|
fd = open(CONSOLE, O_WRONLY | O_APPEND);
|
||||||
if (-1 != fd) {
|
if (-1 != fd) {
|
||||||
dup2(STDOUT_FILENO, fd);
|
dup2(STDOUT_FILENO, fd);
|
||||||
dup2(STDERR_FILENO, fd);
|
dup2(STDERR_FILENO, fd);
|
||||||
@@ -389,10 +467,12 @@ int svc_stop(svc_t *svc)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc("Stopping ", svc->desc);
|
if (runlevel != 1)
|
||||||
|
print_desc("Stopping ", svc->desc);
|
||||||
_d("Sending SIGTERM to pid:%d name:'%s'", svc->pid, pid_get_name(svc->pid, NULL, 0));
|
_d("Sending SIGTERM to pid:%d name:'%s'", svc->pid, pid_get_name(svc->pid, NULL, 0));
|
||||||
res = kill(svc->pid, SIGTERM);
|
res = kill(svc->pid, SIGTERM);
|
||||||
print_result(res);
|
if (runlevel != 1)
|
||||||
|
print_result(res);
|
||||||
svc->pid = 0;
|
svc->pid = 0;
|
||||||
svc->stat_restart_counter = 0;
|
svc->stat_restart_counter = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ typedef enum {
|
|||||||
typedef struct svc {
|
typedef struct svc {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int reload;
|
int reload;
|
||||||
|
int runlevels;
|
||||||
unsigned int stat_restart_counter; /* Incremented for each restart by service monitor. */
|
unsigned int stat_restart_counter; /* Incremented for each restart by service monitor. */
|
||||||
char cmd[MAX_ARG_LEN];
|
char cmd[MAX_ARG_LEN];
|
||||||
char args[MAX_NUM_SVC_ARGS][MAX_ARG_LEN];
|
char args[MAX_NUM_SVC_ARGS][MAX_ARG_LEN];
|
||||||
@@ -87,6 +88,7 @@ static inline svc_t *finit_svc_connect(void)
|
|||||||
svc_t *svc_new (void);
|
svc_t *svc_new (void);
|
||||||
svc_t *svc_find (char *name);
|
svc_t *svc_find (char *name);
|
||||||
svc_t *svc_iterator (int restart);
|
svc_t *svc_iterator (int restart);
|
||||||
|
void svc_runlevel (int newlevel);
|
||||||
|
|
||||||
int svc_register (char *line, char *username);
|
int svc_register (char *line, char *username);
|
||||||
int svc_id_by_name (char *name);
|
int svc_id_by_name (char *name);
|
||||||
|
|||||||
Reference in new issue
Block a user