/*
- * Copyright (c) 2000-2005, 2007-2011
+ * Copyright (c) 2000-2005, 2007-2013
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
#include <config.h>
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef STDC_HEADERS
size_t nsize;
if (env.env_size > SIZE_MAX - 128) {
- errorx2(1, _("internal error, %s overflow"),
+ fatalx_nodebug(_("internal error, %s overflow"),
"sudo_putenv_nodebug()");
}
nsize = env.env_size + 128;
if (nsize > SIZE_MAX / sizeof(char *)) {
- errorx2(1, _("internal error, %s overflow"),
+ fatalx_nodebug(_("internal error, %s overflow"),
"sudo_putenv_nodebug()");
}
nenvp = realloc(env.envp, nsize * sizeof(char *));
if (rval == -1) {
#ifdef ENV_DEBUG
if (env.envp[env.env_len] != NULL)
- errorx(1, _("sudo_putenv: corrupted envp, length mismatch"));
+ fatalx(_("sudo_putenv: corrupted envp, length mismatch"));
#endif
- errorx(1, _("unable to allocate memory"));
+ fatalx(NULL);
}
debug_return_int(rval);
}
strlcat(estring, "=", esize) >= esize ||
strlcat(estring, val, esize) >= esize) {
- errorx(1, _("internal error, %s overflow"), "sudo_setenv2()");
+ fatalx(_("internal error, %s overflow"), "sudo_setenv2()");
}
rval = sudo_putenv(estring, dupcheck, overwrite);
if (rval == -1)
debug_return_int(rval);
}
+/*
+ * Similar to setenv(3) but operates on a private copy of the environment.
+ */
+int
+sudo_setenv(const char *var, const char *val, int overwrite)
+{
+ return sudo_setenv2(var, val, true, (bool)overwrite);
+}
+
/*
* Similar to setenv(3) but operates on a private copy of the environment.
* Does not include warnings or debugging to avoid recursive calls.
static int
sudo_setenv_nodebug(const char *var, const char *val, int overwrite)
{
- char *estring;
+ char *ep, *estring = NULL;
+ const char *cp;
size_t esize;
int rval = -1;
- esize = strlen(var) + 1 + strlen(val) + 1;
- if ((estring = malloc(esize)) == NULL) {
- errno = ENOMEM;
+ if (var == NULL || *var == '\0') {
+ errno = EINVAL;
goto done;
}
- /* Build environment string and insert it. */
- if (strlcpy(estring, var, esize) >= esize ||
- strlcat(estring, "=", esize) >= esize ||
- strlcat(estring, val, esize) >= esize) {
+ /*
+ * POSIX says a var name with '=' is an error but BSD
+ * just ignores the '=' and anything after it.
+ */
+ for (cp = var; *cp && *cp != '='; cp++)
+ ;
+ esize = (size_t)(cp - var) + 2;
+ if (val) {
+ esize += strlen(val); /* glibc treats a NULL val as "" */
+ }
- errno = EINVAL;
+ /* Allocate and fill in estring. */
+ if ((estring = ep = malloc(esize)) == NULL) {
+ errno = ENOMEM;
goto done;
}
+ for (cp = var; *cp && *cp != '='; cp++)
+ *ep++ = *cp;
+ *ep++ = '=';
+ if (val) {
+ for (cp = val; *cp; cp++)
+ *ep++ = *cp;
+ }
+ *ep = '\0';
+
rval = sudo_putenv_nodebug(estring, true, overwrite);
done:
if (rval == -1)
- efree(estring);
+ free(estring);
return rval;
}
-/*
- * Similar to setenv(3) but operates on a private copy of the environment.
- */
-int
-sudo_setenv(const char *var, const char *val, int overwrite)
-{
- int rval;
- debug_decl(sudo_setenv, SUDO_DEBUG_ENV)
-
- rval = sudo_setenv_nodebug(var, val, overwrite);
- if (rval == -1) {
- if (errno == EINVAL)
- errorx(1, _("internal error, %s overflow"), "sudo_setenv()");
- errorx(1, _("unable to allocate memory"));
- }
- debug_return_int(rval);
-}
-
/*
* Similar to unsetenv(3) but operates on a private copy of the environment.
* Does not include warnings or debugging to avoid recursive calls.
if (bad != NULL) {
bad[blen - 2] = '\0'; /* remove trailing ", " */
log_fatal(NO_MAIL,
- _("sorry, you are not allowed to set the following environment variables: %s"), bad);
+ N_("sorry, you are not allowed to set the following environment variables: %s"), bad);
/* NOTREACHED */
efree(bad);
}
read_env_file(const char *path, int overwrite)
{
FILE *fp;
- char *cp, *var, *val;
- size_t var_len, val_len;
+ char *cp, *var, *val, *line = NULL;
+ size_t var_len, val_len, linesize = 0;
if ((fp = fopen(path, "r")) == NULL)
return;
- while ((var = sudo_parseln(fp)) != NULL) {
+ while (sudo_parseln(&line, &linesize, NULL, fp) != -1) {
/* Skip blank or comment lines */
- if (*var == '\0')
+ if (*(var = line) == '\0')
continue;
/* Skip optional "export " */
sudo_putenv(cp, true, overwrite);
}
+ free(line);
fclose(fp);
}
return SUDO_HOOK_RET_NEXT;
in_progress = true;
+
+ /* Hack to make GNU gettext() find the sudoers locale when needed. */
+ if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) {
+ if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) {
+ *value = NULL;
+ goto done;
+ }
+ if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) {
+ *value = def_sudoers_locale;
+ goto done;
+ }
+ }
+
*value = sudo_getenv_nodebug(name);
+done:
in_progress = false;
return SUDO_HOOK_RET_STOP;
}