Don't link to rt anymore as it makes dlopen leak - we now use nanosleeps to achieve the same goal (a loop + timeout). No longer put / at the end of directories, instead prefix like so RC_LIBDIR "/foo" to ensure more robust code.

This commit is contained in:
Roy Marples 2007-08-09 14:33:20 +00:00
parent 9072ce748f
commit 0084bc41ef
11 changed files with 120 additions and 166 deletions

View File

@ -70,7 +70,6 @@ endif
ifeq ($(OS),Linux)
LDLIBS_RC = -ldl
LDLIBS_RS = -ldl
LDLIBS_SSD = -lrt
# Shouldn't need this, but it's the easiest workaround for silly
# Linux headers that don't work with -std=c99
override CPPFLAGS += -D_GNU_SOURCE

View File

@ -582,17 +582,17 @@ static const deppair_t deppairs[] = {
static const char *depdirs[] =
{
RC_SVCDIR "starting",
RC_SVCDIR "started",
RC_SVCDIR "stopping",
RC_SVCDIR "inactive",
RC_SVCDIR "wasinactive",
RC_SVCDIR "failed",
RC_SVCDIR "coldplugged",
RC_SVCDIR "daemons",
RC_SVCDIR "options",
RC_SVCDIR "exclusive",
RC_SVCDIR "scheduled",
RC_SVCDIR "/starting",
RC_SVCDIR "/started",
RC_SVCDIR "/stopping",
RC_SVCDIR "/inactive",
RC_SVCDIR "/wasinactive",
RC_SVCDIR "/failed",
RC_SVCDIR "/coldplugged",
RC_SVCDIR "/daemons",
RC_SVCDIR "/options",
RC_SVCDIR "/exclusive",
RC_SVCDIR "/scheduled",
NULL
};

View File

@ -9,11 +9,11 @@
#define ERRX eerrorx("out of memory");
#define PROFILE_ENV "/etc/profile.env"
#define SYS_WHITELIST RC_LIBDIR "conf.d/env_whitelist"
#define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist"
#define USR_WHITELIST "/etc/conf.d/env_whitelist"
#define RC_CONFIG "/etc/conf.d/rc"
#define PATH_PREFIX RC_LIBDIR "bin:/bin:/sbin:/usr/bin:/usr/sbin"
#define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
#ifndef S_IXUGO
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
@ -95,30 +95,33 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
if (! path1 || ! paths)
return (NULL);
length = strlen (path1) + strlen (paths) + 3;
i = 0;
va_start (ap, paths);
while ((p = va_arg (ap, char *)) != NULL)
length += strlen (p) + 1;
va_end (ap);
path = rc_xmalloc (length);
memset (path, 0, length);
memcpy (path, path1, strlen (path1));
pathp = path + strlen (path1) - 1;
if (*pathp != '/') {
pathp++;
*pathp++ = '/';
}
else
pathp++;
memcpy (pathp, paths, strlen (paths));
pathp += strlen (paths);
length = strlen (path1) + strlen (paths) + 1;
if (*paths != '/')
length ++;
va_start (ap, paths);
while ((p = va_arg (ap, char *)) != NULL) {
if (*pathp != '/')
*pathp++ = '/';
if (*p != '/')
length ++;
length += strlen (p);
}
va_end (ap);
pathp = path = rc_xmalloc (length * sizeof (char *));
memset (path, 0, length);
i = strlen (path1);
memcpy (path, path1, i);
pathp += i;
if (*paths != '/')
*pathp ++ = '/';
i = strlen (paths);
memcpy (pathp, paths, i);
pathp += i;
va_start (ap, paths);
while ((p = va_arg (ap, char *)) != NULL) {
if (*p != '/')
*pathp ++= '/';
i = strlen (p);
memcpy (pathp, p, i);
pathp += i;
@ -615,14 +618,14 @@ char **rc_config_env (char **env)
rc_strlist_free (config);
/* One char less to drop the trailing / */
i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR);
i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1;
line = rc_xmalloc (sizeof (char *) * i);
snprintf (line, i, "RC_LIBDIR=" RC_LIBDIR);
env = rc_strlist_add (env, line);
free (line);
/* One char less to drop the trailing / */
i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR);
i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1;
line = rc_xmalloc (sizeof (char *) * i);
snprintf (line, i, "RC_SVCDIR=" RC_SVCDIR);
env = rc_strlist_add (env, line);

View File

@ -8,12 +8,12 @@
#include "librc.h"
/* usecs to wait while we poll the fifo */
#define WAIT_INTERVAL 20000
#define WAIT_INTERVAL 20000000
/* max secs to wait until a service comes up */
#define WAIT_MAX 60
/* max nsecs to wait until a service comes up */
#define WAIT_MAX 60000000000
#define SOFTLEVEL RC_SVCDIR "softlevel"
#define SOFTLEVEL RC_SVCDIR "/softlevel"
/* File stream used for plugins to write environ vars to */
FILE *rc_environ_fd = NULL;
@ -33,13 +33,13 @@ static const char *rc_service_state_names[] = {
bool rc_runlevel_starting (void)
{
return (rc_is_dir (RC_SVCDIR "softscripts.old"));
return (rc_is_dir (RC_SVCDIR "/softscripts.old"));
}
librc_hidden_def(rc_runlevel_starting)
bool rc_runlevel_stopping (void)
{
return (rc_is_dir (RC_SVCDIR "softscripts.new"));
return (rc_is_dir (RC_SVCDIR "/softscripts.new"));
}
librc_hidden_def(rc_runlevel_stopping)
@ -142,7 +142,7 @@ char *rc_resolve_service (const char *service)
return (rc_xstrdup (buffer));
}
snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service);
snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service);
return (strdup (buffer));
}
librc_hidden_def(rc_resolve_service)
@ -639,32 +639,13 @@ void rc_schedule_clear (const char *service)
}
librc_hidden_def(rc_schedule_clear)
static time_t get_uptime(void)
{
#ifdef __linux__
struct sysinfo info;
sysinfo (&info);
return (time_t) info.uptime;
#else
struct timespec tp;
if (clock_gettime (CLOCK_MONOTONIC, &tp) == -1) {
eerror ("clock_gettime: %s", strerror (errno));
return -1;
}
return tp.tv_sec;
#endif
}
bool rc_wait_service (const char *service)
{
char *svc;
char *base;
char *fifo;
struct timeval tv;
time_t start = get_uptime ();
struct timespec ts;
int nloops = WAIT_MAX / WAIT_INTERVAL;
bool retval = false;
bool forever = false;
@ -680,26 +661,24 @@ bool rc_wait_service (const char *service)
forever = true;
free (svc);
while (true) {
ts.tv_sec = 0;
ts.tv_nsec = WAIT_INTERVAL;
while (nloops) {
if (! rc_exists (fifo)) {
retval = true;
break;
}
tv.tv_sec = 0;
tv.tv_usec = WAIT_INTERVAL;
if (select (0, 0, 0, 0, &tv) < 0) {
if (nanosleep (&ts, NULL) == -1) {
if (errno != EINTR) {
eerror ("select: %s",strerror (errno));
eerror ("nanosleep: %s", strerror (errno));
break;
}
}
if (! forever) {
time_t now = get_uptime();
if (now - start > WAIT_MAX)
break;
}
if (! forever)
nloops --;
}
free (fifo);
@ -819,13 +798,13 @@ librc_hidden_def(rc_service_delete)
char **rc_services_scheduled_by (const char *service)
{
char **dirs = rc_ls_dir (NULL, RC_SVCDIR "scheduled", 0);
char **dirs = rc_ls_dir (NULL, RC_SVCDIR "/scheduled", 0);
char **list = NULL;
char *dir;
int i;
STRLIST_FOREACH (dirs, dir, i) {
char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service,
char *file = rc_strcatpaths (RC_SVCDIR, "scheduled", dir, service,
(char *) NULL);
if (rc_exists (file))
list = rc_strlist_add (list, file);

View File

@ -8,7 +8,6 @@
#ifndef _LIBRC_H_
#define _LIBRC_H_
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

View File

@ -11,19 +11,19 @@
# define LIB "lib"
#endif
#define RC_LIBDIR "/" LIB "/rcscripts/"
#define RC_SVCDIR RC_LIBDIR "init.d/"
#define RC_DEPTREE RC_SVCDIR "deptree"
#define RC_RUNLEVELDIR "/etc/runlevels/"
#define RC_INITDIR "/etc/init.d/"
#define RC_CONFDIR "/etc/conf.d/"
#define RC_LIBDIR "/" LIB "/rcscripts"
#define RC_SVCDIR RC_LIBDIR "/init.d"
#define RC_DEPTREE RC_SVCDIR "/deptree"
#define RC_RUNLEVELDIR "/etc/runlevels"
#define RC_INITDIR "/etc/init.d"
#define RC_CONFDIR "/etc/conf.d"
#define RC_SVCDIR_STARTING RC_SVCDIR "starting/"
#define RC_SVCDIR_INACTIVE RC_SVCDIR "inactive/"
#define RC_SVCDIR_STARTED RC_SVCDIR "started/"
#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "coldplugged/"
#define RC_SVCDIR_STARTING RC_SVCDIR "/starting"
#define RC_SVCDIR_INACTIVE RC_SVCDIR "/inactive"
#define RC_SVCDIR_STARTED RC_SVCDIR "/started"
#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "/coldplugged"
#define RC_PLUGINDIR RC_LIBDIR "plugins/"
#define RC_PLUGINDIR RC_LIBDIR "/plugins"
/* Max buffer to read a line from a file */
#define RC_LINEBUFFER 4096

View File

@ -8,6 +8,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -69,9 +70,9 @@ void rc_plugin_load (void)
int (*fptr) (rc_hook_t, const char *);
int len;
free (p);
if (! h) {
eerror ("dlopen: %s", dlerror ());
free (p);
continue;
}
@ -99,7 +100,6 @@ void rc_plugin_load (void)
}
free (func);
free (p);
}
rc_strlist_free (files);

View File

@ -37,17 +37,12 @@
#include "rc-plugin.h"
#include "strlist.h"
#define INITSH RC_LIBDIR "sh/init.sh"
#define INITEARLYSH RC_LIBDIR "sh/init-early.sh"
#define HALTSH RC_INITDIR "halt.sh"
#define INITSH RC_LIBDIR "/sh/init.sh"
#define INITEARLYSH RC_LIBDIR "/sh/init-early.sh"
#define HALTSH RC_INITDIR "/halt.sh"
#define SULOGIN "/sbin/sulogin"
#define RC_SVCDIR_STARTING RC_SVCDIR "starting/"
#define RC_SVCDIR_INACTIVE RC_SVCDIR "inactive/"
#define RC_SVCDIR_STARTED RC_SVCDIR "started/"
#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "coldplugged/"
#define INTERACTIVE RC_SVCDIR "interactive"
#define INTERACTIVE RC_SVCDIR "/interactive"
#define DEVBOOT "/dev/.rcboot"

View File

@ -19,6 +19,7 @@
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
/* Special level names */
#define RC_LEVEL_SYSINIT "sysinit"

View File

@ -8,6 +8,7 @@
#define APPLET "runscript"
#include <sys/select.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
@ -81,8 +82,10 @@ static void setup_selinux (int argc, char **argv)
return;
}
selinux_run_init_old = (void (*)(void)) dlfunc (lib_handle, "selinux_runscript");
selinux_run_init_new = (void (*)(int, char **)) dlfunc (lib_handle, "selinux_runscript2");
selinux_run_init_old = (void (*)(void))
dlfunc (lib_handle, "selinux_runscript");
selinux_run_init_new = (void (*)(int, char **))
dlfunc (lib_handle, "selinux_runscript2");
/* Use new run_init if it rc_exists, else fall back to old */
if (selinux_run_init_new)
@ -198,7 +201,7 @@ static bool in_control ()
static void uncoldplug ()
{
char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", applet, (char *) NULL);
char *cold = rc_strcatpaths (RC_SVCDIR, "coldplugged", applet, (char *) NULL);
if (rc_exists (cold) && unlink (cold) != 0)
eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
free (cold);
@ -368,16 +371,16 @@ static bool svc_exec (const char *arg1, const char *arg2)
eerror ("fcntl: %s", strerror (errno));
}
if (rc_exists (RC_SVCDIR "runscript.sh")) {
execl (RC_SVCDIR "runscript.sh", service, service, arg1, arg2,
if (rc_exists (RC_SVCDIR "/runscript.sh")) {
execl (RC_SVCDIR "/runscript.sh", service, service, arg1, arg2,
(char *) NULL);
eerror ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
eerror ("%s: exec `" RC_SVCDIR "/runscript.sh': %s",
service, strerror (errno));
_exit (EXIT_FAILURE);
} else {
execl (RC_LIBDIR "sh/runscript.sh", service, service, arg1, arg2,
execl (RC_LIBDIR "/sh/runscript.sh", service, service, arg1, arg2,
(char *) NULL);
eerror ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
eerror ("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s",
service, strerror (errno));
_exit (EXIT_FAILURE);
}

View File

@ -9,8 +9,10 @@
system so we can monitor daemons a little.
*/
#define POLL_INTERVAL 20000
#define START_WAIT 100000
/* nano seconds */
#define POLL_INTERVAL 20000000
#define START_WAIT 100000000
#define ONE_SECOND 1000000000
#include <sys/types.h>
#include <sys/ioctl.h>
@ -92,20 +94,6 @@ static void cleanup (void)
rc_strlist_free (newenv);
}
static int get_time(struct timeval *tp)
{
struct timespec ts;
if (clock_gettime (CLOCK_MONOTONIC, &ts) == -1) {
eerror ("clock_gettime: %s", strerror (errno));
return (-1);
}
tp->tv_sec = ts.tv_sec;
tp->tv_usec = ts.tv_nsec / 1000;
return (0);
}
static int parse_signal (const char *sig)
{
typedef struct signalpair
@ -347,9 +335,8 @@ static int run_stop_schedule (const char *exec, const char *cmd,
int nkilled = 0;
int tkilled = 0;
int nrunning = 0;
struct timeval tv;
struct timeval now;
struct timeval stopat;
long nloops;
struct timespec ts;
if (verbose) {
if (pidfile)
@ -390,30 +377,24 @@ static int run_stop_schedule (const char *exec, const char *cmd,
break;
}
if (get_time (&stopat) != 0)
return (0);
nloops = (ONE_SECOND / POLL_INTERVAL) * item->value;
ts.tv_sec = 0;
ts.tv_nsec = POLL_INTERVAL;
stopat.tv_sec += item->value;
while (1) {
while (nloops) {
if ((nrunning = do_stop (exec, cmd, pidfile,
uid, 0, true, false, true)) == 0)
return (true);
tv.tv_sec = 0;
tv.tv_usec = POLL_INTERVAL;
if (select (0, 0, 0, 0, &tv) < 0) {
if (nanosleep (&ts, NULL) == -1) {
if (errno == EINTR)
eerror ("%s: caught an interupt", progname);
else {
eerror ("%s: select: %s", progname, strerror (errno));
eerror ("%s: nanosleep: %s", progname, strerror (errno));
return (0);
}
}
if (get_time (&now) != 0)
return (0);
if (timercmp (&now, &stopat, >))
break;
nloops --;
}
break;
@ -538,7 +519,6 @@ int start_stop_daemon (int argc, char **argv)
int stdout_fd;
int stderr_fd;
pid_t pid;
struct timeval tv;
int i;
char *svcname = getenv ("SVCNAME");
char *env;
@ -733,7 +713,7 @@ int start_stop_daemon (int argc, char **argv)
argc -= optind;
argv += optind;
/* Validate that the binary rc_exists if we are starting */
/* Validate that the binary exists if we are starting */
if (exec && start) {
char *tmp;
if (ch_root)
@ -893,14 +873,14 @@ int start_stop_daemon (int argc, char **argv)
/* Clean the environment of any RC_ variables */
STRLIST_FOREACH (environ, env, i)
if (env && strncmp (env, "RC_", 3) != 0) {
/* For the path character, remove the rcscript bin dir from it */
if (strncmp (env, "PATH=" RC_LIBDIR "bin:",
strlen ("PATH=" RC_LIBDIR "bin:")) == 0)
/* For the path r, remove the rcscript bin dir from it */
if (strncmp (env, "PATH=" RC_LIBDIR "/bin:",
strlen ("PATH=" RC_LIBDIR "/bin:")) == 0)
{
char *path = env;
char *newpath;
int len;
path += strlen ("PATH=" RC_LIBDIR "bin:");
path += strlen ("PATH=" RC_LIBDIR "/bin:");
len = sizeof (char *) * strlen (path) + 6;
newpath = rc_xmalloc (len);
snprintf (newpath, len, "PATH=%s", path);
@ -974,24 +954,24 @@ int start_stop_daemon (int argc, char **argv)
/* Wait a little bit and check that process is still running
We do this as some badly written daemons fork and then barf */
if (START_WAIT > 0) {
struct timeval stopat;
struct timeval now;
struct timespec ts;
int nloops = START_WAIT / POLL_INTERVAL;
bool alive = false;
bool retestpid = false;
ts.tv_sec = 0;
ts.tv_nsec = POLL_INTERVAL;
if (get_time (&stopat) != 0)
exit (EXIT_FAILURE);
stopat.tv_usec += START_WAIT;
while (1) {
bool alive = false;
tv.tv_sec = 0;
tv.tv_usec = POLL_INTERVAL;
if (select (0, 0, 0, 0, &tv) < 0) {
/* Let our signal handler handle the interupt */
if (errno != EINTR)
eerrorx ("%s: select: %s", progname, strerror (errno));
while (nloops) {
if (nanosleep (&ts, NULL) == -1) {
if (errno == EINTR)
eerror ("%s: caught an interupt", progname);
else {
eerror ("%s: nanosleep: %s", progname, strerror (errno));
return (0);
}
}
nloops --;
/* This is knarly.
If we backgrounded then we know the exact pid.
@ -1023,11 +1003,6 @@ int start_stop_daemon (int argc, char **argv)
if (! alive)
eerrorx ("%s: %s died", progname, exec);
if (get_time (&now) != 0)
exit (EXIT_FAILURE);
if (timercmp (&now, &stopat, >))
break;
}
if (retestpid) {