diff options
Diffstat (limited to 'src/env-update.c')
-rw-r--r-- | src/env-update.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/env-update.c b/src/env-update.c new file mode 100644 index 00000000..c04974b1 --- /dev/null +++ b/src/env-update.c @@ -0,0 +1,247 @@ +/* + env-update + Create /etc/profile.env (sh), /etc/csh.env from /etc/env.d + Run ldconfig as required + + Copyright 2007 Gentoo Foundation + Released under the GPLv2 + */ + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "einfo.h" +#include "rc.h" +#include "rc-misc.h" +#include "strlist.h" + +#define ENVDIR "/etc/env.d" +#define PROFILE_ENV "/etc/profile.env" +#define CSH_ENV "/etc/csh.env" +#define LDSOCONF "/etc/ld.so.conf" + +#define NOTICE "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n" \ + "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n" \ + "# GO INTO %s NOT %s\n\n" + +#define LDNOTICE "# ld.so.conf autogenerated by env-update; make all\n" \ + "# changes to contents of /etc/env.d directory\n" + +static const char *specials[] = +{ + "ADA_INCLUDE_PATH", + "ADA_OBJECTS_PATH", + "CLASSPATH", + "INFOPATH", + "KDEDIRS", + "LDPATH", + "MANPATH", + "PATH", + "PKG_CONFIG_PATH", + "PRELINK_PATH", + "PRELINK_PATH_MASK", + "PYTHONPATH", + "ROOTPATH", + NULL +}; + +static const char *special_spaces[] = +{ + "CONFIG_PROTECT", + "CONFIG_PROTECT_MASK", + NULL, +}; + +static char *applet = NULL; + +int main (int argc, char **argv) +{ + char **files = rc_ls_dir (NULL, ENVDIR, 0); + char *file; + char **envs = NULL; + char *env; + int i = 0; + FILE *fp; + bool ld = true; + char *ldent; + char **ldents = NULL; + int nents = 0; + + applet = argv[0]; + + if (! files) + eerrorx ("%s: no files in " ENVDIR " to process", applet); + + STRLIST_FOREACH (files, file, i) + { + char *path = rc_strcatpaths (ENVDIR, file, NULL); + char **entries = NULL; + char *entry; + int j; + + if (! rc_is_dir (path)) + entries = rc_get_config (NULL, path); + free (path); + + STRLIST_FOREACH (entries, entry, j) + { + char *tmpent = rc_xstrdup (entry); + char *value = tmpent; + char *var = strsep (&value, "="); + int k; + bool isspecial = false; + bool isspecial_spaced = false; + bool replaced = false; + + for (k = 0; special_spaces[k]; k++) + if (strcmp (special_spaces[k], var) == 0) + { + isspecial = true; + isspecial_spaced = true; + break; + } + + if (! isspecial) + { + for (k = 0; specials[k]; k++) + if (strcmp (specials[k], var) == 0) + { + isspecial = true; + break; + } + } + + /* Skip blank vars */ + if (isspecial && + (! value || strlen (value)) == 0) + { + free (tmpent); + continue; + } + + STRLIST_FOREACH (envs, env, k) + { + char *tmpenv = rc_xstrdup (env); + char *tmpvalue = tmpenv; + char *tmpentry = strsep (&tmpvalue, "="); + + if (strcmp (tmpentry, var) == 0) + { + if (isspecial) + { + envs[k - 1] = rc_xrealloc (envs[k - 1], + strlen (envs[k - 1]) + + strlen (entry) + 1); + sprintf (envs[k - 1] + strlen (envs[k - 1]), + "%s%s", isspecial_spaced ? " " : ":", value); + } + else + { + free (envs[k - 1]); + envs[k - 1] = strdup (entry); + } + replaced = true; + } + free (tmpenv); + + if (replaced) + break; + } + + if (! replaced) + envs = rc_strlist_addsort (envs, entry); + + free (tmpent); + } + } + + if ((fp = fopen (PROFILE_ENV, "w")) == NULL) + eerrorx ("%s: fopen `%s': %s", applet, PROFILE_ENV, strerror (errno)); + fprintf (fp, NOTICE, "/etc/profile", PROFILE_ENV); + STRLIST_FOREACH (envs, env, i) + { + char *tmpent = rc_xstrdup (env); + char *value = tmpent; + char *var = strsep (&value, "="); + if (strcmp (var, "LDPATH") != 0) + fprintf (fp, "export %s='%s'\n", var, value); + free (tmpent); + } + fclose (fp); + + if ((fp = fopen (CSH_ENV, "w")) == NULL) + eerrorx ("%s: fopen `%s': %s", applet, PROFILE_ENV, strerror (errno)); + fprintf (fp, NOTICE, "/etc/csh.cshrc", PROFILE_ENV); + STRLIST_FOREACH (envs, env, i) + { + char *tmpent = rc_xstrdup (env); + char *value = tmpent; + char *var = strsep (&value, "="); + if (strcmp (var, "LDPATH") != 0) + fprintf (fp, "setenv %s '%s'\n", var, value); + free (tmpent); + } + fclose (fp); + + ldent = rc_get_config_entry (envs, "LDPATH"); + + if (! ldent || + (argc > 1 && argv[1] && strcmp (argv[1], "--no-ldconfig") == 0)) + { + free (envs); + return (EXIT_SUCCESS); + } + + while ((file = strsep (&ldent, ":"))) + { + if (strlen (file) == 0) + continue; + + ldents = rc_strlist_add (ldents, file); + nents++; + } + + /* Update ld.so.conf only if different */ + if (rc_exists (LDSOCONF)) + { + char **lines = rc_get_list (NULL, LDSOCONF); + char *line; + ld = false; + STRLIST_FOREACH (lines, line, i) + if (i > nents || strcmp (line, ldents[i - 1]) != 0) + { + ld = true; + break; + } + if (i - 1 != nents) + ld = true; + } + + if (ld) + { + int retval = 0; + + if ((fp = fopen (LDSOCONF, "w")) == NULL) + eerrorx ("%s: fopen `%s': %s", applet, LDSOCONF, strerror (errno)); + fprintf (fp, LDNOTICE); + STRLIST_FOREACH (ldents, ldent, i) + fprintf (fp, "%s\n", ldent); + fclose (fp); + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + ebegin ("Regenerating /var/run/ld-elf.so.hints"); + retval = system ("/sbin/ldconfig -elf -i '" LDSOCONF "'"); +#else + ebegin ("Regenerating /etc/ld.so.cache"); + retval = system ("/sbin/ldconfig"); +#endif + eend (retval, NULL); + } + + return(EXIT_SUCCESS); +} |