f1bba12892
char ** and return a pointer to the item added instead of the new list head. This is so we can easily tell if the item was successfully added or not instead of iterating through the list looking for it. list = rc_strlist_add (list, item); becomes rc_strlist_add (&list, item);
348 lines
7.6 KiB
C
348 lines
7.6 KiB
C
/*
|
|
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
|
|
|
|
*/
|
|
|
|
#define APPLET "env-update"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "builtins.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"
|
|
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
#define LD_MESSAGE "Regenerating /var/run/ld-elf.so.hints"
|
|
#define LD_SYSTEM "/sbin/ldconfig -elf -i '" LDSOCONF "'"
|
|
#else
|
|
#define LD_MESSAGE "Regenerating /etc/ld.so.cache"
|
|
#define LD_SYSTEM "/sbin/ldconfig"
|
|
#endif
|
|
|
|
static const char *colon_separated[] = {
|
|
"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 *space_separated[] = {
|
|
"CONFIG_PROTECT",
|
|
"CONFIG_PROTECT_MASK",
|
|
NULL,
|
|
};
|
|
|
|
static char *applet = NULL;
|
|
|
|
#include "_usage.h"
|
|
#define getoptstring "lL" getoptstring_COMMON
|
|
static struct option longopts[] = {
|
|
{ "fork-ldconfig", 0, NULL, 'l'},
|
|
{ "no-ldconfig", 0, NULL, 'L'},
|
|
longopts_COMMON
|
|
{ NULL, 0, NULL, 0}
|
|
};
|
|
#include "_usage.c"
|
|
|
|
int env_update (int argc, char **argv)
|
|
{
|
|
char **files = rc_ls_dir (NULL, ENVDIR, 0);
|
|
char *file;
|
|
char **envs = NULL;
|
|
char *env;
|
|
int i = 0;
|
|
int j;
|
|
FILE *fp;
|
|
bool ld = true;
|
|
char *ldent;
|
|
char **ldents = NULL;
|
|
char **config = NULL;
|
|
char *entry;
|
|
char **mycolons = NULL;
|
|
char **myspaces = NULL;
|
|
int opt;
|
|
bool ldconfig = true;
|
|
bool fork_ldconfig = false;
|
|
int nents = 0;
|
|
|
|
applet = argv[0];
|
|
|
|
while ((opt = getopt_long (argc, argv, getoptstring,
|
|
longopts, (int *) 0)) != -1)
|
|
{
|
|
switch (opt) {
|
|
case 'l':
|
|
fork_ldconfig = true;
|
|
break;
|
|
case 'L':
|
|
ldconfig = false;
|
|
break;
|
|
|
|
case_RC_COMMON_GETOPT
|
|
}
|
|
}
|
|
|
|
if (! files)
|
|
eerrorx ("%s: no files in " ENVDIR " to process", applet);
|
|
|
|
STRLIST_FOREACH (files, file, i) {
|
|
char *path = rc_strcatpaths (ENVDIR, file, (char *) NULL);
|
|
char **entries = NULL;
|
|
|
|
j = strlen (file);
|
|
if (! rc_is_dir (path) &&
|
|
j > 2 &&
|
|
*file >= '0' &&
|
|
*file <= '9' &&
|
|
*(file + 1) >= '0' &&
|
|
*(file + 1) <= '9' &&
|
|
*(file + j - 1) != '~' &&
|
|
(j < 4 || strcmp (file + j - 4, ".bak") != 0) &&
|
|
(j < 5 || strcmp (file + j - 5, ".core") != 0))
|
|
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, "=");
|
|
|
|
if (strcmp (var, "COLON_SEPARATED") == 0)
|
|
while ((var = strsep (&value, " ")))
|
|
rc_strlist_addu (&mycolons, var);
|
|
else if (strcmp (var, "SPACE_SEPARATED") == 0)
|
|
while ((var = strsep (&value, " ")))
|
|
rc_strlist_addu (&myspaces, var);
|
|
else
|
|
rc_strlist_add (&config, entry);
|
|
free (tmpent);
|
|
}
|
|
|
|
rc_strlist_free (entries);
|
|
}
|
|
|
|
STRLIST_FOREACH (config, entry, i) {
|
|
char *tmpent = rc_xstrdup (entry);
|
|
char *value = tmpent;
|
|
char *var = strsep (&value, "=");
|
|
char *match;
|
|
bool colon = false;
|
|
bool space = false;
|
|
bool replaced = false;
|
|
|
|
for (j = 0; colon_separated[j]; j++)
|
|
if (strcmp (colon_separated[j], var) == 0) {
|
|
colon = true;
|
|
break;
|
|
}
|
|
|
|
if (! colon)
|
|
STRLIST_FOREACH (mycolons, match, j) {
|
|
if (strcmp (match, var) == 0) {
|
|
colon = true;
|
|
break;
|
|
} }
|
|
|
|
if (! colon)
|
|
for (j = 0; space_separated[j]; j++)
|
|
if (strcmp (space_separated[j], var) == 0) {
|
|
space = true;
|
|
break;
|
|
}
|
|
|
|
if (! colon && ! space)
|
|
STRLIST_FOREACH (myspaces, match, j)
|
|
if (strcmp (match, var) == 0) {
|
|
space = true;
|
|
break;
|
|
}
|
|
|
|
/* Skip blank vars */
|
|
if ((colon || space) &&
|
|
(! value || strlen (value)) == 0)
|
|
{
|
|
free (tmpent);
|
|
continue;
|
|
}
|
|
|
|
STRLIST_FOREACH (envs, env, j) {
|
|
char *tmpenv = rc_xstrdup (env);
|
|
char *tmpvalue = tmpenv;
|
|
char *tmpentry = strsep (&tmpvalue, "=");
|
|
|
|
if (strcmp (tmpentry, var) == 0) {
|
|
if (colon || space) {
|
|
int len = strlen (envs[j - 1]) + strlen (entry) + 1;
|
|
envs[j - 1] = rc_xrealloc (envs[j - 1], len);
|
|
snprintf (envs[j - 1] + strlen (envs[j - 1]), len,
|
|
"%s%s", colon ? ":" : " ", value);
|
|
} else {
|
|
free (envs[j - 1]);
|
|
envs[j - 1] = rc_xstrdup (entry);
|
|
}
|
|
replaced = true;
|
|
}
|
|
free (tmpenv);
|
|
|
|
if (replaced)
|
|
break;
|
|
}
|
|
|
|
if (! replaced)
|
|
rc_strlist_addsort (&envs, entry);
|
|
|
|
free (tmpent);
|
|
}
|
|
rc_strlist_free (mycolons);
|
|
rc_strlist_free (myspaces);
|
|
rc_strlist_free (config);
|
|
rc_strlist_free (files);
|
|
|
|
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) {
|
|
if (*value == '$')
|
|
fprintf (fp, "export %s=%s\n", var, value);
|
|
else
|
|
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) {
|
|
if (*value == '$')
|
|
fprintf (fp, "setenv %s %s\n", var, value);
|
|
else
|
|
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))
|
|
{
|
|
rc_strlist_free (envs);
|
|
return (EXIT_SUCCESS);
|
|
}
|
|
|
|
while ((file = strsep (&ldent, ":"))) {
|
|
if (strlen (file) == 0)
|
|
continue;
|
|
|
|
if (rc_strlist_addu (&ldents, file))
|
|
nents++;
|
|
}
|
|
|
|
if (ldconfig) {
|
|
/* 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;
|
|
}
|
|
rc_strlist_free (lines);
|
|
if (i - 1 != nents)
|
|
ld = true;
|
|
}
|
|
|
|
if (ld) {
|
|
int retval = 0;
|
|
pid_t pid = 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);
|
|
|
|
ebegin (LD_MESSAGE);
|
|
if (fork_ldconfig) {
|
|
if ((pid = fork ()) == -1)
|
|
eerror ("%s: failed to fork: %s", applet,
|
|
strerror (errno));
|
|
else if (pid == 0) {
|
|
/* Become a proper daemon for a little bit */
|
|
int fd = open ("/dev/null", O_RDWR);
|
|
setsid ();
|
|
dup2 (fd, fileno (stdin));
|
|
dup2 (fd, fileno (stdout));
|
|
dup2 (fd, fileno (stderr));
|
|
}
|
|
}
|
|
|
|
if (pid == 0)
|
|
retval = system (LD_SYSTEM);
|
|
eend (retval, NULL);
|
|
}
|
|
}
|
|
|
|
rc_strlist_free (ldents);
|
|
rc_strlist_free (envs);
|
|
return(EXIT_SUCCESS);
|
|
}
|