Merge branch 'dev'

This commit is contained in:
Joachim Nilsson
2018-07-10 22:38:45 +02:00
16 changed files with 186 additions and 143 deletions
+9 -3
View File
@@ -10,6 +10,9 @@ endif
bin_PROGRAMS = logit
sbin_PROGRAMS = finit initctl reboot
if WATCHDOGD
pkglibexec_PROGRAMS = watchdogd
endif
logit_SOURCES = logit.c
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
@@ -36,9 +39,6 @@ pkginclude_HEADERS = cond.h finit.h helpers.h inetd.h log.h plugin.h svc.h
if INETD
finit_SOURCES += inetd.c inetd.h
endif
if WATCHDOGD
finit_SOURCES += watchdog.c watchdog.h
endif
finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
@@ -63,6 +63,12 @@ reboot_LDADD = $(lite_LIBS)
INIT_LNKS = telinit init
REBOOT_LNKS = shutdown halt poweroff suspend
if WATCHDOGD
watchdogd_SOURCES = watchdog.c watchdog.h
watchdogd_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
#log.c log.h
endif
# Hook in install to add finit and reboot symlink(s)
install-exec-hook:
@$(INSTALL_DATA) $(srcdir)/rescue.conf $(DESTDIR)$(pkglibdir)
+26 -12
View File
@@ -44,6 +44,7 @@
#include "service.h"
#include "util.h"
extern svc_t *wdog;
static uev_t api_watcher;
static int call(int (*action)(svc_t *), char *buf, size_t len)
@@ -51,7 +52,7 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
return svc_parse_jobstr(buf, len, action, NULL);
}
static int service_stop(svc_t *svc)
static int stop(svc_t *svc)
{
if (!svc)
return 1;
@@ -62,7 +63,7 @@ static int service_stop(svc_t *svc)
return 0;
}
static int service_start(svc_t *svc)
static int start(svc_t *svc)
{
if (!svc)
return 1;
@@ -73,20 +74,23 @@ static int service_start(svc_t *svc)
return 0;
}
static int service_restart(svc_t *svc)
static int restart(svc_t *svc)
{
if (!svc)
return 1;
if (svc_is_blocked(svc))
svc_start(svc);
svc_mark_dirty(svc);
service_step(svc);
return 0;
}
static int do_start (char *buf, size_t len) { return call(service_start, buf, len); }
static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); }
static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); }
static int do_start (char *buf, size_t len) { return call(start, buf, len); }
static int do_stop (char *buf, size_t len) { return call(stop, buf, len); }
static int do_restart(char *buf, size_t len) { return call(restart, buf, len); }
static char query_buf[368];
static int missing(char *job, int id)
@@ -337,13 +341,23 @@ static void api_cb(uev_t *w, void *arg, int events)
break;
}
if (wdogpid > 0 && wdogpid != rq.runlevel) {
_d("Sending SIGTERM to %d", wdogpid);
kill(wdogpid, SIGTERM);
do_sleep(1);
_e("Request to hand-over wdog ... to PID %d", rq.runlevel);
svc = svc_find_by_pid(rq.runlevel);
if (!svc) {
logit(LOG_ERR, "Cannot find PID %d, not registered.", rq.runlevel);
break;
}
_d("wdog was %d, now %d is in charge", wdogpid, rq.runlevel);
wdogpid = rq.runlevel;
/* Disable and allow Finit to collect bundled watchdog */
if (wdog) {
logit(LOG_NOTICE, "Stopping and removing %s (PID:%d)", wdog->cmd, wdog->pid);
stop(wdog);
if (wdog->protected) {
wdog->protected = 0;
wdog->runlevels = 0;
}
}
wdog = svc;
break;
case INIT_CMD_SVC_ITER:
+6 -2
View File
@@ -31,12 +31,16 @@
#include "pid.h"
#include "service.h"
static int cond_set_gen(const char *path, unsigned int gen)
static int cond_set_gen(const char *file, unsigned int gen)
{
char *ptr, path[256];
FILE *fp;
int ret;
fp = fopen(path, "w");
/* /var/run --> /run symlink may not exist (yet) */
ptr = pid_runpath(file, path, sizeof(path));
fp = fopen(ptr, "w");
if (!fp)
return -1;
+6 -2
View File
@@ -51,13 +51,17 @@ const char *cond_path(const char *name)
return pid_runpath(tmp, file, sizeof(file));
}
unsigned int cond_get_gen(const char *path)
unsigned int cond_get_gen(const char *file)
{
char *ptr, path[256];
unsigned int gen;
FILE *fp;
int ret;
fp = fopen(path, "r");
/* /var/run --> /run symlink may not exist (yet) */
ptr = pid_runpath(file, path, sizeof(path));
fp = fopen(ptr, "r");
if (!fp)
return 0;
+1 -1
View File
@@ -363,7 +363,7 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait, stru
if (!pid) {
speed_t speed = B38400;
if (baud) {
if (baud && baud[0]) {
speed = stty_parse_speed(baud);
if (B0 == speed)
logit(LOG_CRIT, "TTY %s: Invalid speed %s", tty, baud);
+13 -4
View File
@@ -47,9 +47,7 @@
#include "tty.h"
#include "util.h"
#include "utmp-api.h"
#include "watchdog.h"
int wdogpid = 0; /* No watchdog by default */
int runlevel = 0; /* Bootstrap 'S' */
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
int prevlevel = -1;
@@ -63,6 +61,7 @@ char *rcsd = FINIT_RCSD;
char *runparts = NULL;
uev_ctx_t *ctx = NULL; /* Main loop context */
svc_t *wdog = NULL; /* No watchdog by default */
/*
* Show user configured banner before service bootstrap progress
@@ -214,6 +213,15 @@ static void emergency_shell(void)
*/
static void finalize(void)
{
svc_t *svc;
/*
* Track bundled watchdogd in case a better one turns up
*/
svc = svc_find(FINIT_LIBPATH_ "/watchdogd", 1);
if (svc)
wdog = svc;
/*
* Run startup scripts in the runparts directory, if any.
*/
@@ -412,9 +420,10 @@ int main(int argc, char* argv[])
}
/*
* Start built-in watchdog as soon as possible, if enabled
* Start bundled watchdogd as soon as possible, if enabled
*/
wdogpid = watchdog(argv[0]);
if (which(FINIT_LIBPATH_ "/watchdogd"))
service_register(SVC_TYPE_SERVICE, FINIT_LIBPATH_ "/watchdogd", global_rlimit, NULL);
/*
* Mount filesystems
-1
View File
@@ -92,7 +92,6 @@ struct init_request {
char data[368];
};
extern int wdogpid;
extern int runlevel;
extern int cfglevel;
extern int prevlevel;
+1 -1
View File
@@ -237,7 +237,7 @@ int getty(char *tty, speed_t speed, char *term, char *user)
stty(fd, speed);
close(fd);
if (term)
if (term && term[0])
setenv("TERM", term, 1);
return do_login(name);
+11 -1
View File
@@ -34,7 +34,17 @@ char *pid_file (svc_t *svc);
int pid_file_create (svc_t *svc);
int pid_file_parse (svc_t *svc, char *arg);
static inline char *pid_runpath(char *file, char *path, size_t len)
/**
* pid_runpath - Adjust /var/run --> /run path depending on system
* @file: Path to file in /run/path or /var/run/path
* @path: Pointer to buffer to write correct path
* @len: Length, in bytes, of @path buffer
*
* Returns:
* Always returns a valid pointer, which can be either @path with a /run
* or /var/run prefix to @file, or it may be @file if the prefix is OK.
*/
static inline char *pid_runpath(const char *file, char *path, size_t len)
{
static int unknown = 1;
static char *prefix = "/var/run";
+6 -4
View File
@@ -83,6 +83,8 @@
#include "util.h"
#include "utmp-api.h"
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
@@ -185,8 +187,8 @@ void do_shutdown(shutop_t op)
return;
}
if (wdogpid) {
print(kill(wdogpid, SIGPWR) == 1, "Advising watchdog, system going down");
if (wdog) {
print(kill(wdog->pid, SIGPWR) == 1, "Advising watchdog, system going down");
do_sleep(2);
}
@@ -208,11 +210,11 @@ void do_shutdown(shutop_t op)
/* Reboot via watchdog or kernel, or shutdown? */
if (op == SHUT_REBOOT) {
if (wdogpid) {
if (wdog) {
int timeout = 10;
/* Wait here until the WDT reboots, or timeout with fallback */
print(kill(wdogpid, SIGTERM) == 1, "Pending watchdog reboot");
print(kill(wdog->pid, SIGTERM) == 1, "Pending watchdog reboot");
while (timeout--)
do_sleep(1);
}
+44 -50
View File
@@ -41,7 +41,7 @@
#ifdef FALLBACK_SHELL
static pid_t fallback = 0;
#endif
static LIST_HEAD(, tty_node) tty_list = LIST_HEAD_INITIALIZER();
static LIST_HEAD(, tty) tty_list = LIST_HEAD_INITIALIZER();
static char *canonicalize(char *tty)
{
@@ -88,7 +88,7 @@ static char *canonicalize(char *tty)
void tty_mark(void)
{
tty_node_t *tty;
struct tty *tty;
LIST_FOREACH(tty, &tty_list, link)
tty->dirty = -1;
@@ -96,17 +96,17 @@ void tty_mark(void)
void tty_sweep(void)
{
tty_node_t *tty, *tmp;
struct tty *tty, *tmp;
LIST_FOREACH_SAFE(tty, &tty_list, link, tmp) {
if (!tty->dirty)
continue;
_d("TTY %s dirty, stopping ...", tty->data.name);
tty_stop(&tty->data);
_d("TTY %s dirty, stopping ...", tty->name);
tty_stop(tty);
if (tty->dirty == -1) {
_d("TTY %s removed, cleaning up.", tty->data.name);
_d("TTY %s removed, cleaning up.", tty->name);
tty_unregister(tty);
}
}
@@ -136,7 +136,7 @@ void tty_sweep(void)
*/
int tty_register(char *line, struct rlimit rlimit[], char *file)
{
tty_node_t *entry;
struct tty *entry;
int insert = 0, noclear = 0, nowait = 0, nologin = 0;
size_t i, num = 0;
char *tok, *cmd = NULL, *args[TTY_MAX_ARGS];
@@ -238,13 +238,13 @@ int tty_register(char *line, struct rlimit rlimit[], char *file)
}
}
entry->data.name = dev;
entry->data.baud = baud ? strdup(baud) : NULL;
entry->data.term = term ? strdup(term) : NULL;
entry->data.noclear = noclear;
entry->data.nowait = nowait;
entry->data.nologin = nologin;
entry->data.runlevels = conf_parse_runlevels(runlevels);
strlcpy(entry->name, dev, sizeof(entry->name));
strlcpy(entry->baud, baud ? baud : "", sizeof(entry->baud));
strlcpy(entry->term, term ? term : "", sizeof(entry->term));
entry->noclear = noclear;
entry->nowait = nowait;
entry->nologin = nologin;
entry->runlevels = conf_parse_runlevels(runlevels);
/* External getty */
if (cmd) {
@@ -255,12 +255,12 @@ int tty_register(char *line, struct rlimit rlimit[], char *file)
tok = cmd;
else
tok++;
entry->data.cmd = cmd;
entry->cmd = cmd;
args[1] = strdup(tok);
for (i = 1; i < num; i++)
entry->data.args[j++] = strdup(args[i]);
entry->data.args[++j] = NULL;
entry->args[j++] = strdup(args[i]);
entry->args[++j] = NULL;
}
_d("Registering %s getty on TTY %s at %s baud with term %s on runlevels %s",
@@ -270,7 +270,7 @@ int tty_register(char *line, struct rlimit rlimit[], char *file)
LIST_INSERT_HEAD(&tty_list, entry, link);
/* Register configured limits */
memcpy(entry->data.rlimit, rlimit, sizeof(entry->data.rlimit));
memcpy(entry->rlimit, rlimit, sizeof(entry->rlimit));
if (file && conf_changed(file))
entry->dirty = 1; /* Modified, restart */
@@ -281,7 +281,7 @@ int tty_register(char *line, struct rlimit rlimit[], char *file)
return 0;
}
int tty_unregister(tty_node_t *tty)
int tty_unregister(struct tty *tty)
{
if (!tty) {
_e("Missing argument");
@@ -290,20 +290,14 @@ int tty_unregister(tty_node_t *tty)
LIST_REMOVE(tty, link);
if (tty->data.name)
free(tty->data.name);
if (tty->data.baud)
free(tty->data.baud);
if (tty->data.term)
free(tty->data.term);
if (tty->data.cmd) {
if (tty->cmd) {
int i;
free(tty->data.cmd);
free(tty->cmd);
for (i = 0; i < TTY_MAX_ARGS; i++) {
if (tty->data.args[i])
free(tty->data.args[i]);
tty->data.args[i] = NULL;
if (tty->args[i])
free(tty->args[i]);
tty->args[i] = NULL;
}
}
free(tty);
@@ -311,12 +305,12 @@ int tty_unregister(tty_node_t *tty)
return 0;
}
tty_node_t *tty_find(char *dev)
struct tty *tty_find(char *dev)
{
tty_node_t *entry;
struct tty *entry;
LIST_FOREACH(entry, &tty_list, link) {
if (!strcmp(dev, entry->data.name))
if (!strcmp(dev, entry->name))
return entry;
}
@@ -326,7 +320,7 @@ tty_node_t *tty_find(char *dev)
size_t tty_num(void)
{
size_t num = 0;
tty_node_t *entry;
struct tty *entry;
LIST_FOREACH(entry, &tty_list, link)
num++;
@@ -337,22 +331,22 @@ size_t tty_num(void)
size_t tty_num_active(void)
{
size_t num = 0;
tty_node_t *entry;
struct tty *entry;
LIST_FOREACH(entry, &tty_list, link) {
if (entry->data.pid)
if (entry->pid)
num++;
}
return num;
}
tty_node_t *tty_find_by_pid(pid_t pid)
struct tty *tty_find_by_pid(pid_t pid)
{
tty_node_t *entry;
struct tty *entry;
LIST_FOREACH(entry, &tty_list, link) {
if (entry->data.pid == pid)
if (entry->pid == pid)
return entry;
}
@@ -375,7 +369,7 @@ static int tty_exist(char *dev)
return result;
}
void tty_start(finit_tty_t *tty)
void tty_start(struct tty *tty)
{
char *dev;
@@ -408,7 +402,7 @@ void tty_start(finit_tty_t *tty)
tty->pid = run_getty2(dev, tty->cmd, tty->args, tty->noclear, tty->nowait, tty->rlimit);
}
void tty_stop(finit_tty_t *tty)
void tty_stop(struct tty *tty)
{
if (!tty->pid)
return;
@@ -425,7 +419,7 @@ void tty_stop(finit_tty_t *tty)
tty->pid = 0;
}
int tty_enabled(finit_tty_t *tty)
int tty_enabled(struct tty *tty)
{
if (!tty)
return 0;
@@ -473,12 +467,12 @@ int tty_fallback(pid_t lost)
return 0;
}
static void tty_action(tty_node_t *tty)
static void tty_action(struct tty *tty)
{
if (!tty_enabled(&tty->data))
tty_stop(&tty->data);
if (!tty_enabled(tty))
tty_stop(tty);
else
tty_start(&tty->data);
tty_start(tty);
}
/*
@@ -486,7 +480,7 @@ static void tty_action(tty_node_t *tty)
*/
int tty_respawn(pid_t pid)
{
tty_node_t *tty = tty_find_by_pid(pid);
struct tty *tty = tty_find_by_pid(pid);
if (!tty)
return tty_fallback(pid);
@@ -495,7 +489,7 @@ int tty_respawn(pid_t pid)
utmp_set_dead(pid);
/* Clear PID to be able to respawn it. */
tty->data.pid = 0;
tty->pid = 0;
tty_action(tty);
return 1;
@@ -506,7 +500,7 @@ int tty_respawn(pid_t pid)
*/
void tty_reload(char *dev)
{
tty_node_t *tty;
struct tty *tty;
if (dev) {
tty = tty_find(dev);
@@ -531,7 +525,7 @@ void tty_reload(char *dev)
/* Start all TTYs that exist in the system and are allowed at this runlevel */
void tty_runlevel(void)
{
tty_node_t *tty;
struct tty *tty;
LIST_FOREACH(tty, &tty_list, link)
tty_action(tty);
+15 -21
View File
@@ -32,10 +32,12 @@
#define TTY_MAX_ARGS 16
#define EVENT_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1))
typedef struct {
char *name;
char *baud;
char *term;
struct tty {
LIST_ENTRY(tty) link;
char name[42];
char baud[10];
char term[10];
int noclear;
int nowait;
int nologin;
@@ -48,32 +50,24 @@ typedef struct {
/* Limits and scoping */
struct rlimit rlimit[RLIMIT_NLIMITS];
} finit_tty_t;
typedef struct tty_node {
LIST_ENTRY(tty_node) link;
finit_tty_t data;
/* XXX: Yes, TTYs should be refactored into a separate SVC type. */
int dirty; /* Set if old mtime != new mtime => reloaded,
* or -1 when marked for removal */
} tty_node_t;
//extern LIST_HEAD(, tty_node) tty_list;
/* Set if modified => reloaded, or -1 when marked for removal */
int dirty;
};
void tty_mark (void);
void tty_sweep (void);
int tty_register (char *line, struct rlimit rlimit[], char *file);
int tty_unregister (tty_node_t *tty);
int tty_unregister (struct tty *tty);
tty_node_t *tty_find (char *dev);
struct tty *tty_find (char *dev);
size_t tty_num (void);
size_t tty_num_active (void);
tty_node_t *tty_find_by_pid (pid_t pid);
void tty_start (finit_tty_t *tty);
void tty_stop (finit_tty_t *tty);
int tty_enabled (finit_tty_t *tty);
struct tty *tty_find_by_pid (pid_t pid);
void tty_start (struct tty *tty);
void tty_stop (struct tty *tty);
int tty_enabled (struct tty *tty);
int tty_respawn (pid_t pid);
void tty_reload (char *dev);
void tty_runlevel (void);
+37 -32
View File
@@ -1,6 +1,6 @@
/* Built-in watchdog daemon
*
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
* Copyright (c) 2016-2018 Joachim Nilsson <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
@@ -9,24 +9,30 @@
* 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 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.
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>
#include "finit.h"
#include "log.h"
#include "watchdog.h"
int running = 1;
@@ -51,6 +57,9 @@ static int init(char *progname, char *devnode)
signal(SIGTERM, sighandler);
signal(SIGPWR, sighandler);
openlog(&progname[1], LOG_CONS | LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "Finit v%s basic watchdogd starting ...", VERSION);
fd = open(devnode, O_WRONLY);
if (fd == -1)
return -1;
@@ -78,6 +87,7 @@ static int loop(int fd, int timeout)
/* External watchdogd wants to take over ... */
if (handover) {
syslog(LOG_INFO, "Handing over %s and exiting ...", WDT_DEVNODE);
ioctl(fd, WDIOC_KEEPALIVE, &dummy);
return !write(fd, "V", 1);
}
@@ -85,35 +95,30 @@ static int loop(int fd, int timeout)
return 0;
}
int watchdog(char *progname)
int main(int argc, char *argv[])
{
int pid;
int fd, ret;
pid = fork();
if (pid == 0) {
int fd, ret;
fd = init(progname, WDT_DEVNODE);
if (fd == -1) {
if (ENOENT != errno)
_pe("Failed connecting to watchdog %s", WDT_DEVNODE);
_exit(1);
}
ret = loop(fd, WDT_TIMEOUT);
while (!handover) {
/* Waiting for SIGTERM ... */
sleep(1);
/* Set lowest possible timeout on SIGTERM */
ioctl(fd, WDIOC_SETTIMEOUT, &shutdown);
}
close(fd);
_exit(ret);
fd = init(argv[0], WDT_DEVNODE);
if (fd == -1) {
if (ENOENT != errno)
syslog(LOG_CRIT, "Failed connecting to watchdog %s", WDT_DEVNODE);
return 1;
}
return pid;
ret = loop(fd, WDT_TIMEOUT);
while (!handover) {
syslog(LOG_ALERT, "System going down ...");
/* Waiting for SIGTERM ... */
sleep(1);
/* Set lowest possible timeout on SIGTERM */
ioctl(fd, WDIOC_SETTIMEOUT, &shutdown);
}
close(fd);
return ret;
}
/**