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:
Joachim Nilsson committed 2013-05-19 19:01:44 +02:00
1 parent ec95243dad
commit c3b76fdccf
7 files changed
+237 -57

No files matched your search

+91 -11
View File
@@ -32,6 +32,10 @@
#include "lite.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
* by 3rd party APIs. Mostly because of the ability to, from the outside, query
* liveness state of all daemons that should run. */
@@ -121,6 +125,44 @@ svc_t *svc_iterator(int restart)
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
* @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
* 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
* left out the daemon is started as root.
* If the username is left out the daemon is started as root. The []
* brackets are there to denote the allowed runlevels.
*
* Returns:
* POSIX OK(0) on success, or non-zero errno exit status on failure.
*/
int svc_register(char *line, char *username)
{
int i = 0;
char *cmd, *desc;
int i = 0, not = 0;
char *cmd, *desc, *runlevels = NULL;
svc_t *svc;
if (!line) {
@@ -159,8 +201,13 @@ int svc_register(char *line, char *username)
return errno = ENOENT;
}
if (cmd[0] == '@') { /* @username */
username = &cmd[1];
while (cmd) {
if (cmd[0] == '@') /* @username */
username = &cmd[1];
else if (cmd[0] == '[') /* [runlevels] */
runlevels = &cmd[0];
else
break;
/* Check if valid command follows... */
cmd = strtok(NULL, " ");
@@ -170,7 +217,7 @@ int svc_register(char *line, char *username)
svc = svc_new();
if (!svc) {
_e("Out of memorym, cannot register service %s", cmd);
_e("Out of memory, cannot register service %s", cmd);
return errno = ENOMEM;
}
@@ -185,6 +232,34 @@ int svc_register(char *line, char *username)
strlcpy(svc->args[i++], cmd, sizeof(svc->args[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;
}
@@ -210,6 +285,9 @@ svc_cmd_t svc_enabled(svc_t *svc, int event, void *arg)
return SVC_STOP;
}
if (!ISSET(svc->runlevels, runlevel))
return SVC_STOP;
/* Is there a service plugin registered? */
if (svc->cb)
return svc->cb(svc, event, arg);
@@ -333,7 +411,7 @@ int svc_start(svc_t *svc)
int fd;
char buf[CMD_SIZE] = "";
fd = open (CONSOLE, O_WRONLY | O_APPEND);
fd = open(CONSOLE, O_WRONLY | O_APPEND);
if (-1 != fd) {
dup2(STDOUT_FILENO, fd);
dup2(STDERR_FILENO, fd);
@@ -389,10 +467,12 @@ int svc_stop(svc_t *svc)
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));
res = kill(svc->pid, SIGTERM);
print_result(res);
if (runlevel != 1)
print_result(res);
svc->pid = 0;
svc->stat_restart_counter = 0;