From e7dab9bb91344476603cc01a9db95c891e01085d Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 8 Oct 2007 11:07:39 +0000 Subject: Move rc_env_filter and rc_env_config out of librc and into rc --- src/Makefile | 4 +- src/librc-misc.c | 287 ---------------------------------------------------- src/librc.h | 8 -- src/rc-misc.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rc-misc.h | 3 + src/rc.c | 6 +- src/rc.h | 8 -- src/rc.map | 2 - src/runscript.c | 4 +- 9 files changed, 313 insertions(+), 312 deletions(-) create mode 100644 src/rc-misc.c diff --git a/src/Makefile b/src/Makefile index 9ed2f06c..58f4032e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -57,8 +57,8 @@ LIBRCOBJS = librc.o librc-depend.o librc-daemon.o librc-misc.o librc-strlist.o LDLIBS_LIBRC = RCOBJS = checkown.o env-update.o fstabinfo.o mountinfo.o \ - rc-depend.o rc-plugin.o rc-status.o rc-update.o runscript.o \ - start-stop-daemon.o rc.o + rc-depend.o rc-misc.o rc-plugin.o rc-status.o rc-update.o \ + runscript.o start-stop-daemon.o rc.o LDLIBS_RC = -leinfo -lrc -lutil LIB_TARGETS = $(LIBEINFOSO) $(LIBRCSO) diff --git a/src/librc-misc.c b/src/librc-misc.c index 4a97ae00..01baf4a5 100644 --- a/src/librc-misc.c +++ b/src/librc-misc.c @@ -6,15 +6,6 @@ #include "librc.h" - -#define PROFILE_ENV "/etc/profile.env" -#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" - - bool rc_env_bool (const char *var) { char *v; @@ -228,281 +219,3 @@ char **rc_config_list (const char *file) return (list); } librc_hidden_def(rc_config_list) - -char **rc_env_filter (void) -{ - char **env = NULL; - char **whitelist = NULL; - char *env_name = NULL; - char **profile = NULL; - int count = 0; - bool got_path = false; - char *env_var; - int env_len; - char *p; - char *token; - char *sep; - char *e; - int pplen = strlen (PATH_PREFIX); - - whitelist = rc_config_list (SYS_WHITELIST); - if (! whitelist) - fprintf (stderr, "system environment whitelist (" SYS_WHITELIST ") missing\n"); - - env = rc_config_list (USR_WHITELIST); - rc_strlist_join (&whitelist, env); - rc_strlist_free (env); - env = NULL; - - if (! whitelist) - return (NULL); - - if (rc_exists (PROFILE_ENV)) - profile = rc_config_load (PROFILE_ENV); - - STRLIST_FOREACH (whitelist, env_name, count) { - char *space = strchr (env_name, ' '); - if (space) - *space = 0; - - env_var = getenv (env_name); - - if (! env_var && profile) { - env_len = strlen (env_name) + strlen ("export ") + 1; - p = rc_xmalloc (sizeof (char *) * env_len); - snprintf (p, env_len, "export %s", env_name); - env_var = rc_config_value (profile, p); - free (p); - } - - if (! env_var) - continue; - - /* Ensure our PATH is prefixed with the system locations first - for a little extra security */ - if (strcmp (env_name, "PATH") == 0 && - strncmp (PATH_PREFIX, env_var, pplen) != 0) - { - got_path = true; - env_len = strlen (env_name) + strlen (env_var) + pplen + 2; - e = p = rc_xmalloc (sizeof (char *) * env_len); - p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX); - - /* Now go through the env var and only add bits not in our PREFIX */ - sep = env_var; - while ((token = strsep (&sep, ":"))) { - char *np = rc_xstrdup (PATH_PREFIX); - char *npp = np; - char *tok = NULL; - while ((tok = strsep (&npp, ":"))) - if (strcmp (tok, token) == 0) - break; - if (! tok) - p += snprintf (p, env_len - (p - e), ":%s", token); - free (np); - } - *p++ = 0; - } else { - env_len = strlen (env_name) + strlen (env_var) + 2; - e = rc_xmalloc (sizeof (char *) * env_len); - snprintf (e, env_len, "%s=%s", env_name, env_var); - } - - rc_strlist_add (&env, e); - free (e); - } - - /* We filtered the env but didn't get a PATH? Very odd. - However, we do need a path, so use a default. */ - if (! got_path) { - env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 2; - p = rc_xmalloc (sizeof (char *) * env_len); - snprintf (p, env_len, "PATH=%s", PATH_PREFIX); - rc_strlist_add (&env, p); - free (p); - } - - rc_strlist_free (whitelist); - rc_strlist_free (profile); - - return (env); -} -librc_hidden_def(rc_env_filter) - -/* Other systems may need this at some point, but for now it's Linux only */ -#ifdef __linux__ -static bool file_regex (const char *file, const char *regex) -{ - FILE *fp; - char buffer[RC_LINEBUFFER]; - regex_t re; - bool retval = false; - int result; - - if (! (fp = fopen (file, "r"))) - return (false); - - if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { - fclose (fp); - regerror (result, &re, buffer, sizeof (buffer)); - fprintf (stderr, "file_regex: %s", buffer); - return (false); - } - - while (fgets (buffer, RC_LINEBUFFER, fp)) { - if (regexec (&re, buffer, 0, NULL, 0) == 0) - { - retval = true; - break; - } - } - fclose (fp); - regfree (&re); - - return (retval); -} -#endif - -char **rc_env_config (void) -{ - char **env = NULL; - char *line; - int i; - char *p; - char **config; - char *e; -#ifdef __linux__ - char sys[6]; -#endif - struct utsname uts; - bool has_net_fs_list = false; - FILE *fp; - char buffer[PATH_MAX]; - char *runlevel = rc_runlevel_get (); - - /* Don't trust environ for softlevel yet */ - snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, runlevel); - if (rc_exists (buffer)) - config = rc_config_load (buffer); - else - config = rc_config_load (RC_CONFIG); - - STRLIST_FOREACH (config, line, i) { - p = strchr (line, '='); - if (! p) - continue; - - *p = 0; - e = getenv (line); - if (! e) { - *p = '='; - rc_strlist_add (&env, line); - } else { - int len = strlen (line) + strlen (e) + 2; - char *new = rc_xmalloc (sizeof (char *) * len); - snprintf (new, len, "%s=%s", line, e); - rc_strlist_add (&env, new); - free (new); - } - } - rc_strlist_free (config); - - /* One char less to drop the trailing / */ - i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_LIBDIR=" RC_LIBDIR); - rc_strlist_add (&env, line); - free (line); - - /* One char less to drop the trailing / */ - i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_SVCDIR=" RC_SVCDIR); - rc_strlist_add (&env, line); - free (line); - - rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT); - - i = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_SOFTLEVEL=%s", runlevel); - rc_strlist_add (&env, line); - free (line); - - if ((fp = fopen (RC_KSOFTLEVEL, "r"))) { - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, sizeof (buffer), fp)) { - i = strlen (buffer) - 1; - if (buffer[i] == '\n') - buffer[i] = 0; - i += strlen ("RC_DEFAULTLEVEL=") + 2; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer); - rc_strlist_add (&env, line); - free (line); - } - fclose (fp); - } else - rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT); - - -#ifdef __linux__ - /* Linux can run some funky stuff like Xen, VServer, UML, etc - We store this special system in RC_SYS so our scripts run fast */ - memset (sys, 0, sizeof (sys)); - - if (rc_exists ("/proc/xen")) { - if ((fp = fopen ("/proc/xen/capabilities", "r"))) { - fclose (fp); - if (file_regex ("/proc/xen/capabilities", "control_d")) - snprintf (sys, sizeof (sys), "XENU"); - } - if (! sys[0]) - snprintf (sys, sizeof (sys), "XEN0"); - } else if (file_regex ("/proc/cpuinfo", "UML")) { - snprintf (sys, sizeof (sys), "UML"); - } else if (file_regex ("/proc/self/status", - "(s_context|VxID|envID):[[:space:]]*[1-9]")) - { - snprintf (sys, sizeof (sys), "VPS"); - } - - if (sys[0]) { - i = strlen ("RC_SYS=") + strlen (sys) + 2; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_SYS=%s", sys); - rc_strlist_add (&env, line); - free (line); - } - -#endif - - /* Only add a NET_FS list if not defined */ - STRLIST_FOREACH (env, line, i) - if (strncmp (line, "RC_NET_FS_LIST=", strlen ("RC_NET_FS_LIST=")) == 0) { - has_net_fs_list = true; - break; - } - - if (! has_net_fs_list) { - i = strlen ("RC_NET_FS_LIST=") + strlen (RC_NET_FS_LIST_DEFAULT) + 1; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_NET_FS_LIST=%s", RC_NET_FS_LIST_DEFAULT); - rc_strlist_add (&env, line); - free (line); - } - - /* Some scripts may need to take a different code path if Linux/FreeBSD, etc - To save on calling uname, we store it in an environment variable */ - if (uname (&uts) == 0) { - i = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_UNAME=%s", uts.sysname); - rc_strlist_add (&env, line); - free (line); - } - - free (runlevel); - return (env); -} -librc_hidden_def(rc_env_config) diff --git a/src/librc.h b/src/librc.h index 7d88ab28..0012d903 100644 --- a/src/librc.h +++ b/src/librc.h @@ -13,13 +13,8 @@ #include #include #include -#include #include -#ifdef __linux__ -#include -#endif - #include #include #include @@ -61,9 +56,6 @@ librc_hidden_proto(rc_deptree_order_services) librc_hidden_proto(rc_deptree_update) librc_hidden_proto(rc_deptree_update_needed) librc_hidden_proto(rc_env_bool) -librc_hidden_proto(rc_env_config) -librc_hidden_proto(rc_env_filter) -librc_hidden_proto(rc_exists) librc_hidden_proto(rc_find_pids) librc_hidden_proto(rc_runlevel_exists) librc_hidden_proto(rc_runlevel_get) diff --git a/src/rc-misc.c b/src/rc-misc.c new file mode 100644 index 00000000..4bae93c7 --- /dev/null +++ b/src/rc-misc.c @@ -0,0 +1,303 @@ +/* + librc-misc.c + rc misc functions + Copyright 2007 Gentoo Foundation + */ + +#ifdef __linux__ +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "rc.h" +#include "rc-misc.h" +#include "strlist.h" + +#define PROFILE_ENV "/etc/profile.env" +#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" + +char **env_filter (void) +{ + char **env = NULL; + char **whitelist = NULL; + char *env_name = NULL; + char **profile = NULL; + int count = 0; + bool got_path = false; + char *env_var; + int env_len; + char *p; + char *token; + char *sep; + char *e; + int pplen = strlen (PATH_PREFIX); + + whitelist = rc_config_list (SYS_WHITELIST); + if (! whitelist) + fprintf (stderr, "system environment whitelist (" SYS_WHITELIST ") missing\n"); + + env = rc_config_list (USR_WHITELIST); + rc_strlist_join (&whitelist, env); + rc_strlist_free (env); + env = NULL; + + if (! whitelist) + return (NULL); + + if (rc_exists (PROFILE_ENV)) + profile = rc_config_load (PROFILE_ENV); + + STRLIST_FOREACH (whitelist, env_name, count) { + char *space = strchr (env_name, ' '); + if (space) + *space = 0; + + env_var = getenv (env_name); + + if (! env_var && profile) { + env_len = strlen (env_name) + strlen ("export ") + 1; + p = rc_xmalloc (sizeof (char *) * env_len); + snprintf (p, env_len, "export %s", env_name); + env_var = rc_config_value (profile, p); + free (p); + } + + if (! env_var) + continue; + + /* Ensure our PATH is prefixed with the system locations first + for a little extra security */ + if (strcmp (env_name, "PATH") == 0 && + strncmp (PATH_PREFIX, env_var, pplen) != 0) + { + got_path = true; + env_len = strlen (env_name) + strlen (env_var) + pplen + 2; + e = p = rc_xmalloc (sizeof (char *) * env_len); + p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX); + + /* Now go through the env var and only add bits not in our PREFIX */ + sep = env_var; + while ((token = strsep (&sep, ":"))) { + char *np = rc_xstrdup (PATH_PREFIX); + char *npp = np; + char *tok = NULL; + while ((tok = strsep (&npp, ":"))) + if (strcmp (tok, token) == 0) + break; + if (! tok) + p += snprintf (p, env_len - (p - e), ":%s", token); + free (np); + } + *p++ = 0; + } else { + env_len = strlen (env_name) + strlen (env_var) + 2; + e = rc_xmalloc (sizeof (char *) * env_len); + snprintf (e, env_len, "%s=%s", env_name, env_var); + } + + rc_strlist_add (&env, e); + free (e); + } + + /* We filtered the env but didn't get a PATH? Very odd. + However, we do need a path, so use a default. */ + if (! got_path) { + env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 2; + p = rc_xmalloc (sizeof (char *) * env_len); + snprintf (p, env_len, "PATH=%s", PATH_PREFIX); + rc_strlist_add (&env, p); + free (p); + } + + rc_strlist_free (whitelist); + rc_strlist_free (profile); + + return (env); +} + + /* Other systems may need this at some point, but for now it's Linux only */ +#ifdef __linux__ +static bool file_regex (const char *file, const char *regex) +{ + FILE *fp; + char buffer[RC_LINEBUFFER]; + regex_t re; + bool retval = false; + int result; + + if (! (fp = fopen (file, "r"))) + return (false); + + if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { + fclose (fp); + regerror (result, &re, buffer, sizeof (buffer)); + fprintf (stderr, "file_regex: %s", buffer); + return (false); + } + + while (fgets (buffer, RC_LINEBUFFER, fp)) { + if (regexec (&re, buffer, 0, NULL, 0) == 0) + { + retval = true; + break; + } + } + fclose (fp); + regfree (&re); + + return (retval); +} +#endif + +char **env_config (void) +{ + char **env = NULL; + char *line; + int i; + char *p; + char **config; + char *e; +#ifdef __linux__ + char sys[6]; +#endif + struct utsname uts; + bool has_net_fs_list = false; + FILE *fp; + char buffer[PATH_MAX]; + char *runlevel = rc_runlevel_get (); + + /* Don't trust environ for softlevel yet */ + snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, runlevel); + if (rc_exists (buffer)) + config = rc_config_load (buffer); + else + config = rc_config_load (RC_CONFIG); + + STRLIST_FOREACH (config, line, i) { + p = strchr (line, '='); + if (! p) + continue; + + *p = 0; + e = getenv (line); + if (! e) { + *p = '='; + rc_strlist_add (&env, line); + } else { + int len = strlen (line) + strlen (e) + 2; + char *new = rc_xmalloc (sizeof (char *) * len); + snprintf (new, len, "%s=%s", line, e); + rc_strlist_add (&env, new); + free (new); + } + } + rc_strlist_free (config); + + /* One char less to drop the trailing / */ + i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_LIBDIR=" RC_LIBDIR); + rc_strlist_add (&env, line); + free (line); + + /* One char less to drop the trailing / */ + i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_SVCDIR=" RC_SVCDIR); + rc_strlist_add (&env, line); + free (line); + + rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT); + + i = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_SOFTLEVEL=%s", runlevel); + rc_strlist_add (&env, line); + free (line); + + if ((fp = fopen (RC_KSOFTLEVEL, "r"))) { + memset (buffer, 0, sizeof (buffer)); + if (fgets (buffer, sizeof (buffer), fp)) { + i = strlen (buffer) - 1; + if (buffer[i] == '\n') + buffer[i] = 0; + i += strlen ("RC_DEFAULTLEVEL=") + 2; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer); + rc_strlist_add (&env, line); + free (line); + } + fclose (fp); + } else + rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT); + + +#ifdef __linux__ + /* Linux can run some funky stuff like Xen, VServer, UML, etc + We store this special system in RC_SYS so our scripts run fast */ + memset (sys, 0, sizeof (sys)); + + if (rc_exists ("/proc/xen")) { + if ((fp = fopen ("/proc/xen/capabilities", "r"))) { + fclose (fp); + if (file_regex ("/proc/xen/capabilities", "control_d")) + snprintf (sys, sizeof (sys), "XENU"); + } + if (! sys[0]) + snprintf (sys, sizeof (sys), "XEN0"); + } else if (file_regex ("/proc/cpuinfo", "UML")) { + snprintf (sys, sizeof (sys), "UML"); + } else if (file_regex ("/proc/self/status", + "(s_context|VxID|envID):[[:space:]]*[1-9]")) + { + snprintf (sys, sizeof (sys), "VPS"); + } + + if (sys[0]) { + i = strlen ("RC_SYS=") + strlen (sys) + 2; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_SYS=%s", sys); + rc_strlist_add (&env, line); + free (line); + } + +#endif + + /* Only add a NET_FS list if not defined */ + STRLIST_FOREACH (env, line, i) + if (strncmp (line, "RC_NET_FS_LIST=", strlen ("RC_NET_FS_LIST=")) == 0) { + has_net_fs_list = true; + break; + } + + if (! has_net_fs_list) { + i = strlen ("RC_NET_FS_LIST=") + strlen (RC_NET_FS_LIST_DEFAULT) + 1; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_NET_FS_LIST=%s", RC_NET_FS_LIST_DEFAULT); + rc_strlist_add (&env, line); + free (line); + } + + /* Some scripts may need to take a different code path if Linux/FreeBSD, etc + To save on calling uname, we store it in an environment variable */ + if (uname (&uts) == 0) { + i = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_UNAME=%s", uts.sysname); + rc_strlist_add (&env, line); + free (line); + } + + free (runlevel); + return (env); +} diff --git a/src/rc-misc.h b/src/rc-misc.h index 5f7e55dd..e7bef747 100644 --- a/src/rc-misc.h +++ b/src/rc-misc.h @@ -87,4 +87,7 @@ static inline bool rc_exists (const char *pathname) return (stat (pathname, &buf) == 0); } +char **env_filter (void); +char **env_config (void); + #endif diff --git a/src/rc.c b/src/rc.c index aa3e4373..c71284da 100644 --- a/src/rc.c +++ b/src/rc.c @@ -485,7 +485,7 @@ static void sulogin (bool cont) } #endif - newenv = rc_env_filter (); + newenv = env_filter (); if (cont) { int status = 0; @@ -839,8 +839,8 @@ int main (int argc, char **argv) /* Ensure our environment is pure Also, add our configuration to it */ - env = rc_env_filter (); - tmplist = rc_env_config (); + env = env_filter (); + tmplist = env_config (); rc_strlist_join (&env, tmplist); rc_strlist_free (tmplist); diff --git a/src/rc.h b/src/rc.h index 1ca1c33a..049e56b7 100644 --- a/src/rc.h +++ b/src/rc.h @@ -334,14 +334,6 @@ char **rc_config_load (const char *file); /*! Return the value of the entry from a key=value list. */ char *rc_config_value (char **list, const char *entry); -/*! Return a NULL terminated string list of variables allowed through - * from the current environemnt. */ -char **rc_env_filter (void); - -/*! Return a NULL terminated string list of enviroment variables made from - * our configuration files. */ -char **rc_env_config (void); - /*! Check if an environment variable is a boolean and return it's value. * If variable is not a boolean then we set errno to be ENOENT when it does * not exist or EINVAL if it's not a boolean. diff --git a/src/rc.map b/src/rc.map index 8dc35c76..387a185e 100644 --- a/src/rc.map +++ b/src/rc.map @@ -10,8 +10,6 @@ global: rc_deptree_update; rc_deptree_update_needed; rc_env_bool; - rc_env_config; - rc_env_filter; rc_environ_fd; rc_find_pids; rc_runlevel_exists; diff --git a/src/runscript.c b/src/runscript.c index bfec680c..ffb55103 100644 --- a/src/runscript.c +++ b/src/runscript.c @@ -1046,8 +1046,8 @@ int runscript (int argc, char **argv) if ((softlevel = rc_xstrdup (getenv ("RC_SOFTLEVEL"))) == NULL) { /* Ensure our environment is pure Also, add our configuration to it */ - tmplist = rc_env_config (); - env = rc_env_filter (); + tmplist = env_config (); + env = env_filter (); rc_strlist_join (&env, tmplist); rc_strlist_free (tmplist); tmplist = NULL; -- cgit v1.2.3