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) 1.5 (20121003)
- Use bootmisc plugin to setup standard FHS 2.3 structure in /var - Use bootmisc plugin to setup standard FHS 2.3 structure in /var
- Added FLOG_WARN() syslog macro, for plugins - Added FLOG_WARN() syslog macro, for plugins
+1 -1
View File
@@ -29,7 +29,7 @@
ROOTDIR = $(shell pwd) ROOTDIR = $(shell pwd)
#VERSION ?= $(shell git tag -l | tail -1) #VERSION ?= $(shell git tag -l | tail -1)
VERSION ?= 1.5 VERSION ?= 1.6
NAME = finit NAME = finit
PKG = $(NAME)-$(VERSION) PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev DEV = $(NAME)-dev
+5
View File
@@ -122,6 +122,11 @@ void parse_finit_conf(char *file)
network = build_cmd(NULL, x, CMD_SIZE); network = build_cmd(NULL, x, CMD_SIZE);
continue; 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)) { if (MATCH_CMD(line, "startx ", x)) {
svc_register(x, username); svc_register(x, username);
continue; continue;
+6 -2
View File
@@ -33,6 +33,7 @@
#include "plugin.h" #include "plugin.h"
#include "svc.h" #include "svc.h"
#include "sig.h" #include "sig.h"
#include "lite.h"
int debug = 0; int debug = 0;
int verbose = 1; int verbose = 1;
@@ -40,6 +41,7 @@ char *sdown = NULL;
char *network = NULL; char *network = NULL;
char *username = NULL; char *username = NULL;
char *hostname = NULL; char *hostname = NULL;
char *rcsd = FINIT_RCSD;
static void parse_kernel_cmdline(void) 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. * Run startup scripts in /etc/finit.d/, if any.
*/ */
_d("Running startup scripts in /etc/finit.d/ ..."); if (rcsd && fisdir(rcsd)) {
run_parts(FINIT_RCSD); _d("Running startup scripts in %s ...", rcsd);
run_parts(rcsd, NULL);
}
/* /*
* Hooks that should run at the very end * Hooks that should run at the very end
+1
View File
@@ -66,6 +66,7 @@ extern char *sdown;
extern char *network; extern char *network;
extern char *hostname; extern char *hostname;
extern char *username; extern char *username;
extern char *rcsd;
/* conf.c */ /* conf.c */
void parse_finit_conf(char *file); void parse_finit_conf(char *file);
+39 -53
View File
@@ -566,75 +566,61 @@ pid_t run_getty(char *cmd, char *argv[])
return pid; 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, ...) num = scandir(dir, &e, NULL, alphasort);
{ if (num < 0) {
DIR *d; _d("No files found in %s, skipping ...", dir);
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);
return -1; 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++) { for (i = 0; i < num; i++) {
int j = 0, status;
pid_t pid = 0; 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]; snprintf(path, sizeof(path), "%s/%s", dir, name);
args[1] = NULL; 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(); pid = fork();
if (!pid) { if (!pid) {
_d("Calling %s ...", ent[i]); _d("Calling %s ...", path);
execv(ent[i], args); execv(path, args);
exit(0); exit(0);
} }
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
free(ent[i]);
} }
chdir(oldpwd); while (num--)
free(oldpwd); free(e[num]);
free(e);
return 0; return 0;
} }
+4 -2
View File
@@ -50,7 +50,9 @@
#ifndef blkdev #ifndef blkdev
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min))) # define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
#endif #endif
#ifndef S_ISEXEC
# define S_ISEXEC(m) (((m) & S_IXUSR) == S_IXUSR)
#endif
#ifndef UNUSED #ifndef UNUSED
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused)) #define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#endif #endif
@@ -87,7 +89,7 @@ void set_hostname (char *hostname);
int run (char *cmd); int run (char *cmd);
int run_interactive (char *cmd, char *fmt, ...); int run_interactive (char *cmd, char *fmt, ...);
pid_t run_getty (char *cmd, char *argv[]); pid_t run_getty (char *cmd, char *argv[]);
int run_parts (char *dir, ...); int run_parts (char *dir, char *cmd);
/* strlcpy.c */ /* strlcpy.c */
size_t strlcpy(char *dst, const char *src, size_t siz); 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) { if (!file) {
errno = EINVAL; errno = EINVAL;
return 0; /* Doesn't exist ... */ return 0;
} }
if (!stat(file, &sb)) if (!stat(file, &sb))
+9 -4
View File
@@ -161,7 +161,7 @@ plugin_t *plugin_find(char *name)
if (name[0] != '/') { if (name[0] != '/') {
int noext; int noext;
char path[256]; char path[CMD_SIZE];
noext = strcmp(name + strlen(name) - 3, ".so"); noext = strcmp(name + strlen(name) - 3, ".so");
snprintf (path, sizeof(path), "%s%s%s%s", plugpath, 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) static int load_one(char *path, char *name)
{ {
int noext; int noext;
char plugin[256]; char plugin[CMD_SIZE];
void *handle; void *handle;
if (!path || !fisdir(path)) { if (!path || !fisdir(path) || !name) {
errno = EINVAL; errno = EINVAL;
return 1; return 1;
} }
/* Compose full path, with optional .so extension, to plugin */
noext = strcmp(name + strlen(name) - 3, ".so"); noext = strcmp(name + strlen(name) - 3, ".so");
snprintf(plugin, sizeof(plugin), "%s/%s%s", path, name, noext ? ".so" : ""); snprintf(plugin, sizeof(plugin), "%s/%s%s", path, name, noext ? ".so" : "");
_d("Loading plugin %s ...", basename(plugin)); _d("Loading plugin %s ...", basename(plugin));
handle = dlopen(plugin, RTLD_LAZY | RTLD_GLOBAL); handle = dlopen(plugin, RTLD_LAZY | RTLD_GLOBAL);
if (!handle) { if (!handle) {
_d("Failed loading plugin %s: %s", plugin, dlerror()); _e("Failed loading plugin %s: %s", plugin, dlerror());
return 1; return 1;
} }
@@ -321,6 +323,9 @@ int plugin_load_all(char *path)
plugpath = path; plugpath = path;
while ((entry = readdir(dp))) { while ((entry = readdir(dp))) {
if (entry->d_name[0] == '.')
continue; /* Skip . and .. directories */
// print_desc(" Loading plugin ", basename(plugin)); // print_desc(" Loading plugin ", basename(plugin));
if (load_one(path, entry->d_name)) if (load_one(path, entry->d_name))
fail++; fail++;
+4 -4
View File
@@ -27,14 +27,14 @@
static void save(void *UNUSED(arg)) static void save(void *UNUSED(arg))
{ {
_d("Saving system clock to RTC ..."); _d("Saving sound settings ...");
run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings"); run_interactive("/usr/sbin/alsactl -g store", "Saving sound settings");
} }
static void restore(void *UNUSED(arg)) static void restore(void *UNUSED(arg))
{ {
_d("Restoring system clock from RTC ..."); _d("Restoring sound settings ...");
run_interactive("/usr/sbin/alsactl restore > /dev/null 2>&1", "Restoring sound settings"); run_interactive("/usr/sbin/alsactl -g restore", "Restoring sound settings");
} }
static plugin_t plugin = { static plugin_t plugin = {
+1 -1
View File
@@ -59,7 +59,7 @@ static void setup(void *UNUSED(arg))
touch("/etc/resolvconf/run/enable-updates"); touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface"); chdir("/etc/resolvconf/run/interface");
run_parts("/etc/resolvconf/update.d", "-i", NULL); run_parts("/etc/resolvconf/update.d", "-i");
chdir("/"); chdir("/");
#endif /* USE_ETC_RESOLVCONF_RUN */ #endif /* USE_ETC_RESOLVCONF_RUN */
} }
+19 -2
View File
@@ -273,6 +273,20 @@ int svc_start(svc_t *svc)
sigset_t nmask, omask; sigset_t nmask, omask;
char *args[MAX_NUM_SVC_ARGS]; 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 */ /* Ignore if finit is SIGSTOP'ed */
if (is_norespawn()) if (is_norespawn())
return 0; return 0;
@@ -311,7 +325,7 @@ int svc_start(svc_t *svc)
if (debug) { if (debug) {
int fd; int fd;
char buf[256] = ""; char buf[CMD_SIZE] = "";
fd = open (CONSOLE, O_WRONLY | O_APPEND); fd = open (CONSOLE, O_WRONLY | O_APPEND);
if (-1 != fd) { if (-1 != fd) {
@@ -329,7 +343,10 @@ int svc_start(svc_t *svc)
_e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf); _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); exit(0);
} }
svc->pid = pid; svc->pid = pid;