Compare commits

...
5 Commits
Author SHA1 Message Date
Joachim Nilsson 685618691d Update ChangeLog and bump version for release. 2012-10-06 18:07:39 +02:00
Joachim Nilsson f29d2733c7 Fix incorrect use of variable arguments in run_parts() and simplify code
The run_parts() implementation used variable arguments in a bad way,
resulting in it not working properly.  Replaced va_*() code with a
simple cmd argument that's passed to each script called.

Also, the opendir()/readdir() code has been replaced with scandir()
using regular alphasort(). This simplifies the code somewhat as well.

Otherwise, minor cleanups.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-10-06 15:45:42 +02:00
Joachim Nilsson af59174e49 Prevent endless restart of non-existing services and support start-stop scripts
Sometimes people type in the wrong path to a service directive in
finit.conf, or the executable isn't installed.  This commit makes
sure to check if the command exists before attempting to start it.
This also means that we now require service commands to start with
/ to indicate an absolute path.  We used to search the PATH for a
suitable executable, using execvp(), but that's rather insecure as
well, so we now use only execv().

Also, added support for adding "start" or "stop" to entries found
in /etc/finit.d starting with SNNname, or KNNname, where NN is a
number.  This makes it possible to simply import sysvinit style
start scripts from /etc/rcS.d and /etc/rcN.d/.

The alsa-utils plugin also had some minor fixes, added -g option
to ignore non-existing soundcards and fixed cut-paste bug on the
_d() debug messages.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-10-06 13:56:26 +02:00
Joachim Nilsson 785c21d27b Support for overriding built-in default FINIT_RCSD in finit.conf
This commit adds support for the "runparts <DIR>" directive to
finit.conf.  Enabling the user to override the built-in default,
which by default is /etc/finit.d.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-10-05 18:50:21 +02:00
Joachim Nilsson 40c7a44d4f Skip . and .. in plugin loader and trigger error on failed plugin load.
Fix from field testing.  Need to skip "." and ".." directory entries
when loading plugins from /lib/finit/plugins.  Also, trigger an error
when a required plugin fails to load.  We need to print to console
since syslogd has not started yet.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-10-04 17:22:40 +02:00
12 changed files with 98 additions and 70 deletions
+8
View File
@@ -1,3 +1,11 @@
1.6 (20121006)
- Skip . and .. in plugin loader and display error on failed plugins
- Support for overriding /etc/finit.d with "runparts DIR" in finit.conf
- Revoke support for starting services not starting with a slash.
- Prevent endless restart of non-existing services in finit.conf
- Support for sysvinit style startstop scripts in /etc/finit.d
- Minor fix to alsa-utils plugin to silence on non-existing cards
1.5 (20121003)
- Use bootmisc plugin to setup standard FHS 2.3 structure in /var
- Added FLOG_WARN() syslog macro, for plugins
+1 -1
View File
@@ -29,7 +29,7 @@
ROOTDIR = $(shell pwd)
#VERSION ?= $(shell git tag -l | tail -1)
VERSION ?= 1.5
VERSION ?= 1.6
NAME = finit
PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev
+5
View File
@@ -122,6 +122,11 @@ void parse_finit_conf(char *file)
network = build_cmd(NULL, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "runparts ", x)) {
if (rcsd) free(rcsd);
hostname = build_cmd(NULL, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "startx ", x)) {
svc_register(x, username);
continue;
+6 -2
View File
@@ -33,6 +33,7 @@
#include "plugin.h"
#include "svc.h"
#include "sig.h"
#include "lite.h"
int debug = 0;
int verbose = 1;
@@ -40,6 +41,7 @@ char *sdown = NULL;
char *network = NULL;
char *username = NULL;
char *hostname = NULL;
char *rcsd = FINIT_RCSD;
static void parse_kernel_cmdline(void)
@@ -181,8 +183,10 @@ int main(int UNUSED(args), char *argv[])
/*
* Run startup scripts in /etc/finit.d/, if any.
*/
_d("Running startup scripts in /etc/finit.d/ ...");
run_parts(FINIT_RCSD);
if (rcsd && fisdir(rcsd)) {
_d("Running startup scripts in %s ...", rcsd);
run_parts(rcsd, NULL);
}
/*
* Hooks that should run at the very end
+1
View File
@@ -66,6 +66,7 @@ extern char *sdown;
extern char *network;
extern char *hostname;
extern char *username;
extern char *rcsd;
/* conf.c */
void parse_finit_conf(char *file);
+39 -53
View File
@@ -566,75 +566,61 @@ pid_t run_getty(char *cmd, char *argv[])
return pid;
}
static int cmp(const void *s1, const void *s2)
int run_parts(char *dir, char *cmd)
{
return strcmp(*(char **)s1, *(char **)s2);
}
struct dirent **e;
int i, num;
int run_parts(char *dir, ...)
{
DIR *d;
struct dirent *e;
struct stat st;
char *oldpwd = NULL;
char *ent[NUM_SCRIPTS];
int i, num = 0, argnum = 1;
char *args[NUM_ARGS];
va_list ap;
oldpwd = getcwd (NULL, 0);
if (chdir(dir)) {
if (oldpwd) free(oldpwd);
num = scandir(dir, &e, NULL, alphasort);
if (num < 0) {
_d("No files found in %s, skipping ...", dir);
return -1;
}
if ((d = opendir(dir)) == NULL) {
if (oldpwd) free(oldpwd);
return -1;
}
va_start(ap, dir);
while (argnum < NUM_ARGS && (args[argnum++] = va_arg(ap, char *)));
va_end(ap);
while ((e = readdir(d))) {
if (e->d_type == DT_REG && stat(e->d_name, &st) == 0) {
_d("Found %s/%s ...", dir, e->d_name);
if (st.st_mode & S_IXUSR) {
ent[num++] = strdup(e->d_name);
if (num >= NUM_SCRIPTS)
break;
}
}
}
closedir(d);
if (num == 0) {
if (oldpwd) free(oldpwd);
return 0;
}
qsort(ent, num, sizeof(char *), cmp);
for (i = 0; i < num; i++) {
int j = 0, status;
pid_t pid = 0;
int status;
mode_t mode;
char *args[NUM_ARGS];
char *name = e[i]->d_name;
char path[CMD_SIZE];
args[0] = ent[i];
args[1] = NULL;
snprintf(path, sizeof(path), "%s/%s", dir, name);
mode = fmode(path);
if (!S_ISEXEC(mode) || S_ISDIR(mode)) {
_d("Skipping %s ...", path);
continue;
}
/* Fill in args[], starting with full path to executable */
args[j++] = path;
/* If the callee didn't supply a run_parts() argument */
if (!cmd) {
/* Check if S<NUM>service or K<NUM>service notation is used */
_d("Checking if %s is a sysvinit startstop script ...", name);
if (name[0] == 'S' && isdigit(name[1])) {
args[j++] = "start";
} else if (name[0] == 'K' && isdigit(name[1])) {
args[j++] = "stop";
}
} else {
args[j++] = cmd;
}
args[j++] = NULL;
pid = fork();
if (!pid) {
_d("Calling %s ...", ent[i]);
execv(ent[i], args);
_d("Calling %s ...", path);
execv(path, args);
exit(0);
}
waitpid(pid, &status, 0);
free(ent[i]);
}
chdir(oldpwd);
free(oldpwd);
while (num--)
free(e[num]);
free(e);
return 0;
}
+4 -2
View File
@@ -50,7 +50,9 @@
#ifndef blkdev
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
#endif
#ifndef S_ISEXEC
# define S_ISEXEC(m) (((m) & S_IXUSR) == S_IXUSR)
#endif
#ifndef UNUSED
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#endif
@@ -87,7 +89,7 @@ void set_hostname (char *hostname);
int run (char *cmd);
int run_interactive (char *cmd, char *fmt, ...);
pid_t run_getty (char *cmd, char *argv[]);
int run_parts (char *dir, ...);
int run_parts (char *dir, char *cmd);
/* strlcpy.c */
size_t strlcpy(char *dst, const char *src, size_t siz);
+1 -1
View File
@@ -39,7 +39,7 @@ mode_t fmode(char *file)
if (!file) {
errno = EINVAL;
return 0; /* Doesn't exist ... */
return 0;
}
if (!stat(file, &sb))
+9 -4
View File
@@ -161,7 +161,7 @@ plugin_t *plugin_find(char *name)
if (name[0] != '/') {
int noext;
char path[256];
char path[CMD_SIZE];
noext = strcmp(name + strlen(name) - 3, ".so");
snprintf (path, sizeof(path), "%s%s%s%s", plugpath,
@@ -262,20 +262,22 @@ static void init_plugins(void)
static int load_one(char *path, char *name)
{
int noext;
char plugin[256];
char plugin[CMD_SIZE];
void *handle;
if (!path || !fisdir(path)) {
if (!path || !fisdir(path) || !name) {
errno = EINVAL;
return 1;
}
/* Compose full path, with optional .so extension, to plugin */
noext = strcmp(name + strlen(name) - 3, ".so");
snprintf(plugin, sizeof(plugin), "%s/%s%s", path, name, noext ? ".so" : "");
_d("Loading plugin %s ...", basename(plugin));
handle = dlopen(plugin, RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
_d("Failed loading plugin %s: %s", plugin, dlerror());
_e("Failed loading plugin %s: %s", plugin, dlerror());
return 1;
}
@@ -321,6 +323,9 @@ int plugin_load_all(char *path)
plugpath = path;
while ((entry = readdir(dp))) {
if (entry->d_name[0] == '.')
continue; /* Skip . and .. directories */
// print_desc(" Loading plugin ", basename(plugin));
if (load_one(path, entry->d_name))
fail++;
+4 -4
View File
@@ -27,14 +27,14 @@
static void save(void *UNUSED(arg))
{
_d("Saving system clock to RTC ...");
run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings");
_d("Saving sound settings ...");
run_interactive("/usr/sbin/alsactl -g store", "Saving sound settings");
}
static void restore(void *UNUSED(arg))
{
_d("Restoring system clock from RTC ...");
run_interactive("/usr/sbin/alsactl restore > /dev/null 2>&1", "Restoring sound settings");
_d("Restoring sound settings ...");
run_interactive("/usr/sbin/alsactl -g restore", "Restoring sound settings");
}
static plugin_t plugin = {
+1 -1
View File
@@ -59,7 +59,7 @@ static void setup(void *UNUSED(arg))
touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface");
run_parts("/etc/resolvconf/update.d", "-i", NULL);
run_parts("/etc/resolvconf/update.d", "-i");
chdir("/");
#endif /* USE_ETC_RESOLVCONF_RUN */
}
+19 -2
View File
@@ -273,6 +273,20 @@ int svc_start(svc_t *svc)
sigset_t nmask, omask;
char *args[MAX_NUM_SVC_ARGS];
if (!svc)
return 0;
/* Don't try and start service if it doesn't exist. */
if (!fexist(svc->cmd)) {
char msg[80];
snprintf(msg, sizeof(msg), "Service %s does not exist!", svc->cmd);
print_desc("", msg);
print_result(1);
return 0;
}
/* Ignore if finit is SIGSTOP'ed */
if (is_norespawn())
return 0;
@@ -311,7 +325,7 @@ int svc_start(svc_t *svc)
if (debug) {
int fd;
char buf[256] = "";
char buf[CMD_SIZE] = "";
fd = open (CONSOLE, O_WRONLY | O_APPEND);
if (-1 != fd) {
@@ -329,7 +343,10 @@ int svc_start(svc_t *svc)
_e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf);
}
execvp(svc->cmd, args);
/* XXX: Maybe change to use execve() to be able to launch scripts? */
execv(svc->cmd, args);
/* Only reach this point if exec() fails. */
exit(0);
}
svc->pid = pid;