summaryrefslogtreecommitdiff
path: root/src/env-update.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/env-update.c')
-rw-r--r--src/env-update.c247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/env-update.c b/src/env-update.c
new file mode 100644
index 0000000..c04974b
--- /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);
+}