Merge pull request #113 from srand/master

Bugfixes and features
This commit is contained in:
Joachim Nilsson authored and GitHub committed 2018-10-23 07:15:20 +02:00
commit a36aade7f4
17 files changed
+207 -61

No files matched your search

+1
View File
@@ -95,6 +95,7 @@ AC_PLUGIN([inetd-chargen], [no], [Inetd plugin: character generator, RFC864])
AC_PLUGIN([inetd-daytime], [no], [Inetd plugin: daytime server, RFC867])
AC_PLUGIN([inetd-discard], [no], [Inetd plugin: discard server, RFC863])
AC_PLUGIN([inetd-time], [no], [Inetd plugin: time (rdate) server, RFC868])
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
+13
View File
@@ -185,6 +185,18 @@ Syntax
For a detailed description of conditions, and how to debug them, see
the [Finit Conditions](conditions.md) document.
If a service should not be automatically started, it can be configured
as manual with the optional `manual` argument. The service can then be
started at any time by running `initctl start <service>`.
manual:yes
The name of a service, shown by the `initctl` tool, defaults to the
basename of the service executable. It can be changed with the
optional `name` argument:
name:<service-name>
* `inetd service/proto[@iflist] <wait|nowait> [LVLS] /path/to/daemon args`
Launch a daemon when a client initiates a connection on an Internet
port. Available services are listed in the UNIX `/etc/services` file.
@@ -338,6 +350,7 @@ syslog using the native `logit` tool. The full syntax is:
log:/path/to/file
log:prio:facility.level,tag:ident
log:console
log:null
log
+2
View File
@@ -47,6 +47,8 @@ For your convenience a set of *optional* plugins are available:
* *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
interfaces. These events are then sent to the Finit service monitor
for services that may want to be SIGHUP'ed on new default route or
+8
View File
@@ -39,6 +39,10 @@ libplug_la_SOURCES += time.c
endif
endif
if BUILD_MODULES_LOAD_PLUGIN
libplug_la_SOURCES += modules-load.c
endif
if BUILD_NETLINK_PLUGIN
libplug_la_SOURCES += netlink.c
endif
@@ -80,6 +84,10 @@ pkglib_LTLIBRARIES += time.la
endif
endif
if BUILD_MODULES_LOAD_PLUGIN
pkglib_LTLIBRARIES += modules-load.la
endif
if BUILD_NETLINK_PLUGIN
pkglib_LTLIBRARIES += netlink.la
endif
+107
View File
@@ -0,0 +1,107 @@
/* Scans /etc/modules-load.d for modules to load.
*
* Copyright (c) 2018 Robert Andersson <robert.m.andersson@se.atlascopco.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 <lite/lite.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include "finit.h"
#include "helpers.h"
#include "plugin.h"
#include "service.h"
#include "conf.h"
#define MODULES_LOAD_PATH "/etc/modules-load.d"
#define SERVICE_LINE \
":%d name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s"
static void load(void *arg)
{
FILE *fp;
DIR *dirp;
struct dirent *direntp;
char line[256];
int index = 1;
_d("Scanning " MODULES_LOAD_PATH " for config files ...");
dirp = opendir(MODULES_LOAD_PATH);
if (!dirp) return;
while ((direntp = readdir(dirp)))
{
char module_path[PATH_MAX];
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
strlcat(module_path, direntp->d_name, sizeof(module_path));
fp = fopen(module_path, "r");
if (!fp) continue;
while (fgets(line, sizeof(line), fp)) {
char cmd[CMD_SIZE], *mod, *args;
mod = strip_line(line);
if (!*mod) continue;
mod = chomp(mod);
if (!mod || !*mod) continue;
mod = strtok_r(mod, " ", &args);
snprintf(cmd, sizeof(cmd), SERVICE_LINE,
index, mod, mod, args, mod);
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
index++;
}
fclose(fp);
}
closedir(dirp);
}
static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_BASEFS_UP] = {
.cb = load
},
};
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:
*/
+3 -2
View File
@@ -64,7 +64,7 @@ static void pidfile_callback(void *arg, int fd, int events)
continue;
mkcond(cond, sizeof(cond), svc->cmd);
if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY)) {
if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
svc_started(svc);
cond_set(cond);
} else if (ev->mask & IN_DELETE)
@@ -111,6 +111,7 @@ static void pidfile_init(void *arg)
{
char *path;
struct context *ctx = arg;
uint32_t mask = IN_CREATE | IN_ATTRIB | IN_DELETE | IN_MODIFY | IN_MOVED_TO;
/*
* The bootmisc plugin is responsible for setting up /var/run.
@@ -123,7 +124,7 @@ static void pidfile_init(void *arg)
return;
}
ctx->wd = inotify_add_watch(ctx->fd, path, IN_CREATE | IN_ATTRIB | IN_DELETE | IN_MODIFY);
ctx->wd = inotify_add_watch(ctx->fd, path, mask);
free(path);
if (ctx->wd < 0) {
+2 -2
View File
@@ -352,8 +352,8 @@ static void api_cb(uev_t *w, void *arg, int events)
if (wdog) {
logit(LOG_NOTICE, "Stopping and removing %s (PID:%d)", wdog->cmd, wdog->pid);
stop(wdog);
if (wdog->protected) {
wdog->protected = 0;
if (wdog->protect) {
wdog->protect = 0;
wdog->runlevels = 0;
}
}
+1 -1
View File
@@ -125,7 +125,7 @@ error:
return NULL;
}
svc_t *client_svc_find(char *arg)
svc_t *client_svc_find(const char *arg)
{
int sd = -1;
struct init_request rq = {
+1 -1
View File
@@ -32,6 +32,6 @@ int client_disconnect (void);
int client_send (struct init_request *rq, ssize_t len);
svc_t *client_svc_iterator (int first);
svc_t *client_svc_find (char *arg);
svc_t *client_svc_find (const char *arg);
#endif /* FINIT_CLIENT_H_ */
+2 -2
View File
@@ -101,7 +101,7 @@ enum cond_state cond_get_agg(const char *names)
{
char *cond;
enum cond_state s = COND_ON;
static char conds[MAX_ARG_LEN];
static char conds[MAX_COND_LEN];
if (!names)
return COND_ON;
@@ -116,7 +116,7 @@ enum cond_state cond_get_agg(const char *names)
int cond_affects(const char *name, const char *names)
{
char *cond;
static char conds[MAX_ARG_LEN];
static char conds[MAX_COND_LEN];
if (!name || !names)
return 0;
+16 -19
View File
@@ -30,6 +30,7 @@
#include <lite/lite.h>
#include <lite/queue.h> /* BSD sys/queue.h API */
#include <sys/time.h>
#include <glob.h>
#include "finit.h"
#include "cond.h"
@@ -52,7 +53,7 @@ struct conf_change {
char *name;
};
static uev_t w1, w2, w3;
static uev_t w1, w2, w3, w4;
static TAILQ_HEAD(head, conf_change) conf_change_list = TAILQ_HEAD_INITIALIZER(conf_change_list);
static int parse_conf(char *file);
@@ -577,8 +578,8 @@ static int parse_conf(char *file)
*/
int conf_reload(void)
{
int i, num;
struct dirent **e;
size_t i;
glob_t gl;
/* Mark and sweep */
svc_mark_dynamic();
@@ -601,20 +602,14 @@ int conf_reload(void)
parse_conf(FINIT_CONF);
/* Next, read all *.conf in /etc/finit.d/ */
num = scandir(rcsd, &e, NULL, alphasort);
if (num < 0) {
_d("Skipping %s, no files found ...", rcsd);
goto done;
}
glob("/etc/finit.d/*.conf", 0, NULL, &gl);
glob("/etc/finit.d/enabled/*.conf", GLOB_APPEND, NULL, &gl);
for (i = 0; i < num; i++) {
char *name = e[i]->d_name;
char path[LINE_SIZE];
for (i = 0; i < gl.gl_pathc; i++) {
char *path = gl.gl_pathv[i];
size_t len;
struct stat st;
snprintf(path, sizeof(path), "%s/%s", rcsd, name);
/* Check that it's an actual file ... beyond any symlinks */
if (lstat(path, &st)) {
_d("Skipping %s, cannot access: %s", path, strerror(errno));
@@ -650,9 +645,7 @@ int conf_reload(void)
parse_conf_dynamic(path);
}
while (num--)
free(e[num]);
free(e);
globfree(&gl);
done:
/* Drop record of all .conf changes */
@@ -783,6 +776,9 @@ static void conf_cb(uev_t *w, void *arg, int events)
break;
}
}
if (conf_any_change())
service_reload_dynamic();
}
static int add_watcher(uev_ctx_t *ctx, uev_t *w, char *path, uint32_t opt)
@@ -857,8 +853,9 @@ int conf_monitor(uev_ctx_t *ctx)
* changes to either symlink or target.
*/
rc += add_watcher(ctx, &w1, FINIT_RCSD, 0);
rc += add_watcher(ctx, &w2, FINIT_RCSD "/available", IN_DONT_FOLLOW);
rc += add_watcher(ctx, &w3, FINIT_CONF, 0);
rc += add_watcher(ctx, &w2, FINIT_RCSD "/available/", IN_DONT_FOLLOW);
rc += add_watcher(ctx, &w3, FINIT_RCSD "/enabled/", 0);
rc += add_watcher(ctx, &w4, FINIT_CONF, 0);
return rc + conf_reload();
}
@@ -869,7 +866,7 @@ int conf_monitor(uev_ctx_t *ctx)
int conf_init(void)
{
hostname = strdup(DEFHOST);
w1.fd = w2.fd = w3.fd = -1;
w1.fd = w2.fd = w3.fd = w4.fd = -1;
return conf_monitor(NULL);
}
+1
View File
@@ -226,6 +226,7 @@ static void socket_cb(uev_t *w, void *arg, int events)
strlcpy(task->desc, svc->desc, sizeof(task->desc) - strlen(conn));
strlcat(task->desc, conn, sizeof(task->desc));
strlcpy(task->iifname, iifname, sizeof(task->iifname));
strlcpy(task->name, svc->name, sizeof(task->name));
task->stdin_fd = stdin;
service_step(task);
+2 -9
View File
@@ -173,7 +173,7 @@ static int do_restart(char *arg) { return do_startstop(INIT_CMD_RESTART_SVC, arg
static void show_cond_one(const char *_conds)
{
static char conds[MAX_ARG_LEN];
static char conds[MAX_COND_LEN];
char *cond;
strlcpy(conds, _conds, sizeof(conds));
@@ -459,14 +459,7 @@ static int show_status(char *arg)
if (!verbose) {
int adj = screen_cols - 60;
char *name = strrchr(svc->cmd, '/');
if (!name)
name = svc->cmd;
else
name++;
printf("%-16.16s %-*.*s\n", name, adj, adj, svc->desc);
printf("%-16.16s %-*.*s\n", svc->name, adj, adj, svc->desc);
continue;
}
+4 -4
View File
@@ -120,7 +120,7 @@ int serv_list(char *arg)
if (fisdir(enabled))
do_list("ENABLED ", enabled);
if (fisdir(FINIT_RCSD))
do_list("ENABLED ", FINIT_RCSD);
do_list("STATIC ", FINIT_RCSD);
return 0;
}
@@ -140,11 +140,11 @@ int serv_enable(char *arg)
}
pushd(FINIT_RCSD);
snprintf(path, sizeof(path), "available/%s", arg);
snprintf(path, sizeof(path), "%s/%s", available, arg);
if (!fexist(path))
errx(1, "Cannot find %s", path);
snprintf(link, sizeof(link), "%s/%s", FINIT_RCSD, arg);
snprintf(link, sizeof(link), "%s/%s", enabled, arg);
if (fexist(link))
errx(1, "%s already exists", link);
@@ -165,7 +165,7 @@ int serv_disable(char *arg)
arg = corr;
}
snprintf(link, sizeof(link), "%s/%s", FINIT_RCSD, arg);
snprintf(link, sizeof(link), "%s/%s", enabled, arg);
if (stat(link, &st))
err(1, "Cannot find %s", link);
+37 -3
View File
@@ -139,7 +139,7 @@ static int is_norespawn(void)
* @svc: Service to start
*
* Returns:
* 0 if the service was successfully started. Non-zero otherwise.
* 0 if the service was successfully started. Non-zero otherwise.
*/
static int service_start(svc_t *svc)
{
@@ -243,6 +243,9 @@ static int service_start(svc_t *svc)
redirect_null();
goto logit_done;
}
if (svc->log.console) {
goto logit_done;
}
/*
* Open PTY to connect to logger. A pty isn't buffered
@@ -466,7 +469,7 @@ static int service_stop(svc_t *svc)
*
* This function does some basic checks of the runtime state of Finit
* and a sanity check of the @svc before sending %SIGHUP.
*
*
* Returns:
* POSIX OK(0) or non-zero on error.
*/
@@ -558,6 +561,8 @@ static void parse_log(svc_t *svc, char *arg)
svc->log.enabled = 1;
else if (!strcmp(tok, "null") || !strcmp(tok, "/dev/null"))
svc->log.null = 1;
else if (!strcmp(tok, "console") || !strcmp(tok, "/dev/console"))
svc->log.console = 1;
else if (tok[0] == '/')
strlcpy(svc->log.file, tok, sizeof(svc->log.file));
else if (!strcmp(tok, "priority") || !strcmp(tok, "prio"))
@@ -569,6 +574,23 @@ static void parse_log(svc_t *svc, char *arg)
}
}
/*
* name:<name>
*/
static void parse_name(svc_t *svc, char *arg)
{
char *name = NULL;
if (arg && !strncasecmp(arg, "name:", 5)) {
name = arg + 5;
} else {
name = strrchr(svc->cmd, '/');
name = name ? name + 1 : svc->cmd;
}
strlcpy(svc->name, name, sizeof(svc->name));
}
/**
* parse_cmdline_args - Update the command line args in the svc struct
*
@@ -655,10 +677,12 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
int forking = 0;
#endif
int levels = 0;
int manual = 0;
char *line;
char *username = NULL, *log = NULL, *pid = NULL;
char *service = NULL, *proto = NULL, *ifaces = NULL;
char *cmd, *desc, *runlevels = NULL, *cond = NULL;
char *name = NULL;
svc_t *svc;
plugin_t *plugin = NULL;
@@ -716,6 +740,10 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
log = cmd;
else if (!strncasecmp(cmd, "pid", 3))
pid = cmd;
else if (!strncasecmp(cmd, "name:", 5))
name = cmd;
else if (!strncasecmp(cmd, "manual:yes", 10))
manual = 1;
else if (cmd[0] != '/' && strchr(cmd, '/'))
service = cmd; /* inetd service/proto */
else
@@ -791,6 +819,10 @@ recreate:
free(line);
return errno = ENOMEM;
}
if (type == SVC_TYPE_SERVICE && manual) {
svc_stop(svc);
}
}
#ifdef INETD_ENABLED
else {
@@ -831,6 +863,8 @@ recreate:
conf_parse_cond(svc, cond);
parse_name(svc, name);
if (log)
parse_log(svc, log);
if (desc)
@@ -875,7 +909,7 @@ recreate:
svc_mark_clean(svc);
if (!file)
svc->protected = 1;
svc->protect = 1;
/* Free duped line, from above */
free(line);
+4 -17
View File
@@ -80,7 +80,6 @@ static void svc_gc(void *arg)
svc_t *svc_new(char *cmd, int id, int type)
{
int job = -1;
char *desc;
svc_t *svc, *iter = NULL;
/* Find first job n:o if registering multiple instances */
@@ -103,12 +102,7 @@ svc_t *svc_new(char *cmd, int id, int type)
strlcpy(svc->cmd, cmd, sizeof(svc->cmd));
/* Default description, if missing */
desc = strrchr(cmd, '/');
if (desc)
desc++;
else
desc = cmd;
strlcpy(svc->desc, desc, sizeof(svc->desc));
strlcpy(svc->desc, svc->name, sizeof(svc->desc));
TAILQ_INSERT_TAIL(&svc_list, svc, link);
@@ -204,7 +198,7 @@ svc_t *svc_named_iterator(svc_t **iter, int first, char *cmd)
svc_t *svc;
for (svc = svc_iterator(iter, first); svc; svc = svc_iterator(iter, 0)) {
char *name = basename(svc->cmd);
char *name = svc->name;
if (!strncmp(name, cmd, strlen(name)))
return svc;
@@ -362,17 +356,10 @@ svc_t *svc_find_by_jobid(int job, int id)
*/
svc_t *svc_find_by_nameid(char *name, int id)
{
char *ptr;
svc_t *svc, *iter = NULL;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
ptr = strrchr(svc->cmd, '/');
if (ptr)
ptr++;
else
ptr = svc->cmd;
if (svc->id == id && !strcmp(name, ptr))
if (svc->id == id && !strcmp(name, svc->name))
return svc;
}
@@ -415,7 +402,7 @@ void svc_mark_dynamic(void)
svc_t *svc, *iter = NULL;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (svc->protected)
if (svc->protect)
continue;
if (svc_is_inetd_conn(svc))
continue;
+3 -1
View File
@@ -97,13 +97,14 @@ typedef struct svc {
long start_time; /* Start time, as seconds since boot, from sysinfo() */
const svc_state_t state; /* Paused, Reloading, Restart, Running, ... */
svc_type_t type; /* Service, run, task, inetd, ... */
int protected; /* Services like dbus-daemon & udev by Finit */
int protect; /* Services like dbus-daemon & udev by Finit */
const int dirty; /* -1: removal, 0: unmodified, 1: modified */
int starting; /* ... waiting for pidfile to be re-asserted */
int runlevels;
int sighup; /* This service supports SIGHUP :) */
svc_block_t block; /* Reason that this service is currently stopped */
char cond[MAX_COND_LEN];
char name[MAX_ARG_LEN];
/* Counters */
char once; /* run/task, (at least) once per runlevel */
@@ -118,6 +119,7 @@ typedef struct svc {
struct {
char enabled;
char null;
char console;
char file[64];
char prio[20];
char ident[20];