From 0084bc41ef5db968cac0f64ae9d0b31dc7621818 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 9 Aug 2007 14:33:20 +0000 Subject: [PATCH] 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. --- src/Makefile | 1 - src/librc-depend.c | 22 +++++----- src/librc-misc.c | 53 +++++++++++++----------- src/librc.c | 59 +++++++++----------------- src/librc.h | 1 - src/rc-misc.h | 22 +++++----- src/rc-plugin.c | 4 +- src/rc.c | 13 ++---- src/rc.h | 1 + src/runscript.c | 19 +++++---- src/start-stop-daemon.c | 91 +++++++++++++++-------------------------- 11 files changed, 120 insertions(+), 166 deletions(-) diff --git a/src/Makefile b/src/Makefile index 5c50cfd4..dc6d86f5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/librc-depend.c b/src/librc-depend.c index c8dfd02a..b51fc3cb 100644 --- a/src/librc-depend.c +++ b/src/librc-depend.c @@ -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 }; diff --git a/src/librc-misc.c b/src/librc-misc.c index b52c2507..2aee5d43 100644 --- a/src/librc-misc.c +++ b/src/librc-misc.c @@ -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); diff --git a/src/librc.c b/src/librc.c index 5b815720..9b48b6bb 100644 --- a/src/librc.c +++ b/src/librc.c @@ -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); diff --git a/src/librc.h b/src/librc.h index ec126aba..6118f48b 100644 --- a/src/librc.h +++ b/src/librc.h @@ -8,7 +8,6 @@ #ifndef _LIBRC_H_ #define _LIBRC_H_ -#include #include #include #include diff --git a/src/rc-misc.h b/src/rc-misc.h index 20dc74f7..6ffc868f 100644 --- a/src/rc-misc.h +++ b/src/rc-misc.h @@ -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 diff --git a/src/rc-plugin.c b/src/rc-plugin.c index d8db975a..1103e469 100644 --- a/src/rc-plugin.c +++ b/src/rc-plugin.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/src/rc.c b/src/rc.c index f7c4f98a..c8bbb2e9 100644 --- a/src/rc.c +++ b/src/rc.c @@ -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" diff --git a/src/rc.h b/src/rc.h index 9920901c..829f8b95 100644 --- a/src/rc.h +++ b/src/rc.h @@ -19,6 +19,7 @@ #include #include +#include /* Special level names */ #define RC_LEVEL_SYSINIT "sysinit" diff --git a/src/runscript.c b/src/runscript.c index 14d3c7bf..20e7561d 100644 --- a/src/runscript.c +++ b/src/runscript.c @@ -8,6 +8,7 @@ #define APPLET "runscript" +#include #include #include #include @@ -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); } diff --git a/src/start-stop-daemon.c b/src/start-stop-daemon.c index 05325dfb..ddf55e25 100644 --- a/src/start-stop-daemon.c +++ b/src/start-stop-daemon.c @@ -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 #include @@ -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) {