provide our own setenv/unsetenv/putenv that operates on own env pointer.
Make sync_env() inline in setenv/unsetenv/putenv functions.
dnl check for isblank(3)
dnl
AC_DEFUN([SUDO_FUNC_ISBLANK],
- [AC_CACHE_CHECK([for isblank], sudo_cv_func_isblank,
+ [AC_CACHE_CHECK([for isblank], [sudo_cv_func_isblank],
[AC_TRY_LINK([#include <ctype.h>], [return (isblank('a'));],
sudo_cv_func_isblank=yes, sudo_cv_func_isblank=no)])
] [
fi
])
+dnl
+dnl check unsetenv() return value
+dnl
+AC_DEFUN([SUDO_FUNC_UNSETENV_VOID],
+ [AC_CACHE_CHECK([whether unsetenv returns void], [sudo_cv_func_unsetenv_void],
+ [AC_RUN_IFELSE([AC_LANG_PROGRAM(
+ [AC_INCLUDES_DEFAULT
+ int unsetenv();
+ ], [
+ [return unsetenv("FOO") != 0;]
+ ])
+ ],
+ [sudo_cv_func_unsetenv_void=no],
+ [sudo_cv_func_unsetenv_void=yes],
+ [sudo_cv_func_unsetenv_void=yes])])
+ if test $sudo_cv_func_unsetenv_void = yes; then
+ AC_DEFINE(UNSETENV_VOID, 1,
+ [Define to 1 if the `unsetenv' function returns void instead of `int'.])
+ fi
+ ])
+
+dnl
+dnl check putenv() argument for const
+dnl
+AC_DEFUN([SUDO_FUNC_PUTENV_CONST],
+[AC_CACHE_CHECK([whether putenv has a const argument],
+sudo_cv_func_putenv_const,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [
+int putenv(const char *string) {return 0;}
+])],
+ [sudo_cv_func_putenv_const=yes],
+ [sudo_cv_func_putenv_const=no])
+ ])
+ if test $sudo_cv_func_putenv_const = yes; then
+ AC_DEFINE(PUTENV_CONST, 1, [Define to 1 if the `putenv' has a const argument.])
+ fi
+])
+
dnl
dnl check for sa_len field in struct sockaddr
dnl
sudo_auth *auth;
{
/* Unset AUTHSTATE as it may not be correct for the runas user. */
- sudo_unsetenv("AUTHSTATE");
+ unsetenv("AUTHSTATE");
return(AUTH_SUCCESS);
}
/* Define to 1 to enable SELinux RBAC support. */
#undef HAVE_SELINUX
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
/* Define to 1 if you have the `seteuid' function. */
#undef HAVE_SETEUID
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
/* Define to 1 if you have the `utimes' function. */
#undef HAVE_UTIMES
/* The syslog priority sudo will use for successful attempts. */
#undef PRI_SUCCESS
+/* Define to 1 if the `putenv' has a const argument. */
+#undef PUTENV_CONST
+
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* The number of tries a user gets to enter their password. */
#undef TRIES_FOR_PASSWORD
+/* Define to 1 if the `unsetenv' function returns void instead of `int'. */
+#undef UNSETENV_VOID
+
/* Define to 1 if you want to insult the user for entering an incorrect
password. */
#undef USE_INSULTS
+
for ac_func in strchr strrchr memchr memcpy memset sysconf tzset \
strftime setrlimit initgroups getgroups fstat gettimeofday \
- setlocale getaddrinfo setsid
+ setlocale getaddrinfo setsid setenv
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
fi
done
+
+for ac_func in unsetenv
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ { echo "$as_me:$LINENO: checking whether unsetenv returns void" >&5
+echo $ECHO_N "checking whether unsetenv returns void... $ECHO_C" >&6; }
+if test "${sudo_cv_func_unsetenv_void+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ sudo_cv_func_unsetenv_void=yes
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ int unsetenv();
+
+int
+main ()
+{
+
+ return unsetenv("FOO") != 0;
+
+ ;
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ sudo_cv_func_unsetenv_void=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+sudo_cv_func_unsetenv_void=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $sudo_cv_func_unsetenv_void" >&5
+echo "${ECHO_T}$sudo_cv_func_unsetenv_void" >&6; }
+ if test $sudo_cv_func_unsetenv_void = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define UNSETENV_VOID 1
+_ACEOF
+
+ fi
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking whether putenv has a const argument" >&5
+echo $ECHO_N "checking whether putenv has a const argument... $ECHO_C" >&6; }
+if test "${sudo_cv_func_putenv_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+int putenv(const char *string) {return 0;}
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ sudo_cv_func_putenv_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ sudo_cv_func_putenv_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $sudo_cv_func_putenv_const" >&5
+echo "${ECHO_T}$sudo_cv_func_putenv_const" >&6; }
+ if test $sudo_cv_func_putenv_const = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define PUTENV_CONST 1
+_ACEOF
+
+ fi
+
if test -z "$SKIP_SETRESUID"; then
for ac_func in setresuid
AC_FUNC_GETGROUPS
AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \
strftime setrlimit initgroups getgroups fstat gettimeofday \
- setlocale getaddrinfo setsid)
+ setlocale getaddrinfo setsid setenv)
+AC_CHECK_FUNCS(unsetenv, SUDO_FUNC_UNSETENV_VOID)
+SUDO_FUNC_PUTENV_CONST
if test -z "$SKIP_SETRESUID"; then
AC_CHECK_FUNCS(setresuid, [SKIP_SETREUID=yes])
fi
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
+#include <errno.h>
#include <pwd.h>
#include "sudo.h"
* Prototypes
*/
void rebuild_env __P((int, int));
-void sudo_setenv __P((const char *, const char *, int));
-void sudo_unsetenv __P((const char *));
static void _sudo_setenv __P((const char *, const char *, int));
-static void insert_env __P((char *, int, int));
-static void sync_env __P((void));
+static void sudo_putenv __P((char *, int, int));
extern char **environ; /* global environment */
NULL
};
-/*
- * Syncronize our private copy of the environment with what is
- * in environ.
- */
-static void
-sync_env()
-{
- size_t evlen;
- char **ep;
-
- for (ep = environ; *ep != NULL; ep++)
- continue;
- evlen = ep - environ;
- if (evlen + 1 > env.env_size) {
- efree(env.envp);
- env.env_size = evlen + 1 + 128;
- env.envp = emalloc2(env.env_size, sizeof(char *));
- }
- memcpy(env.envp, environ, (evlen + 1) * sizeof(char *));
- env.env_len = evlen;
- environ = env.envp;
-}
-
/*
* Similar to setenv(3) but operates on sudo's private copy of the environment
* and it always overwrites. The dupcheck param determines whether we need
errorx(1, "internal error, sudo_setenv() overflow");
}
- insert_env(estring, dupcheck, FALSE);
+ sudo_putenv(estring, dupcheck, TRUE);
}
-#ifdef HAVE_LDAP
/*
- * External version of sudo_setenv() that keeps things in sync with
- * the environ pointer.
+ * Version of setenv(3) that uses our own environ pointer.
*/
-void
-sudo_setenv(var, val, dupcheck)
+int
+setenv(var, val, overwrite)
const char *var;
const char *val;
- int dupcheck;
+ int overwrite;
{
char *estring;
size_t esize;
- /* Make sure we are operating on the current environment. */
- if (env.envp != environ)
- sync_env();
-
esize = strlen(var) + 1 + strlen(val) + 1;
estring = emalloc(esize);
errorx(1, "internal error, sudo_setenv() overflow");
}
- insert_env(estring, dupcheck, TRUE);
+ sudo_putenv(estring, TRUE, overwrite);
+ return(0);
}
-#endif /* HAVE_LDAP */
-#if defined(HAVE_LDAP) || defined(HAVE_AIXAUTH)
/*
- * Similar to unsetenv(3) but operates on sudo's private copy of the
- * environment.
+ * Version of unsetenv(3) that uses our own environ pointer.
*/
+#ifdef UNSETENV_VOID
void
-sudo_unsetenv(var)
+#else
+int
+#endif
+unsetenv(var)
const char *var;
{
- char **nep;
- size_t varlen;
+ char **ep;
+ size_t len;
/* Make sure we are operating on the current environment. */
- if (env.envp != environ)
- sync_env();
-
- varlen = strlen(var);
- for (nep = env.envp; *nep; nep++) {
- if (strncmp(var, *nep, varlen) == 0 && (*nep)[varlen] == '=') {
- /* Found it; move everything over by one and update len. */
- memmove(nep, nep + 1,
- (env.env_len - (nep - env.envp)) * sizeof(char *));
+ if (env.envp != environ) {
+ for (ep = environ; *ep != NULL; ep++)
+ continue;
+ len = ep - environ;
+ if (len + 1 > env.env_size) {
+ efree(env.envp);
+ env.env_size = len + 1 + 128;
+ env.envp = emalloc2(env.env_size, sizeof(char *));
+ }
+ memcpy(env.envp, environ, (len + 1) * sizeof(char *));
+ env.env_len = len;
+ environ = env.envp;
+ }
+
+ len = strlen(var);
+ for (ep = env.envp; *ep; ep++) {
+ if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
+ /* Found it; shift remainder + NULL over by one and update len. */
+ memmove(ep, ep + 1,
+ (env.env_len - (ep - env.envp)) * sizeof(char *));
env.env_len--;
- return;
+ break;
}
}
+#ifndef UNSETENV_VOID
+ return(0);
+#endif
+}
+
+int
+#ifdef PUTENV_CONST
+putenv(const char *string)
+#else
+putenv(char *string)
+#endif
+{
+ if (strchr(string, '=') == NULL) {
+ errno = EINVAL;
+ return(-1);
+ }
+ sudo_putenv((char *)string, TRUE, TRUE);
+ return(0);
}
-#endif /* HAVE_LDAP || HAVE_AIXAUTH */
/*
- * Insert str into env.envp, assumes str has an '=' in it.
+ * Insert str into env.envp, assumes str has an '=' in it and wset dupcheck
*/
static void
-insert_env(str, dupcheck, dosync)
+sudo_putenv(str, dupcheck, overwrite)
char *str;
int dupcheck;
- int dosync;
+ int overwrite;
{
- char **nep;
- size_t varlen;
+ char **ep;
+ size_t len;
/* Make sure there is room for the new entry plus a NULL. */
- if (env.env_len + 2 > env.env_size) {
+ if (env.envp != environ) {
+ for (ep = environ; *ep != NULL; ep++)
+ continue;
+ len = ep - environ;
+ if (len + 2 > env.env_size) {
+ efree(env.envp);
+ env.env_size = len + 2 + 128;
+ env.envp = emalloc2(env.env_size, sizeof(char *));
+ }
+ memcpy(env.envp, environ, len * sizeof(char *));
+ env.envp[len] = NULL;
+ env.env_len = len;
+ environ = env.envp;
+ } else if (env.env_len + 2 > env.env_size) {
env.env_size += 128;
env.envp = erealloc3(env.envp, env.env_size, sizeof(char *));
- if (dosync)
- environ = env.envp;
+ environ = env.envp;
}
if (dupcheck) {
- varlen = (strchr(str, '=') - str) + 1;
-
- for (nep = env.envp; *nep; nep++) {
- if (strncmp(str, *nep, varlen) == 0) {
- if (dupcheck != -1)
- *nep = str;
+ len = (strchr(str, '=') - str) + 1;
+ for (ep = env.envp; *ep; ep++) {
+ if (strncmp(str, *ep, len) == 0) {
+ if (overwrite)
+ *ep = str;
return;
}
}
} else
- nep = env.envp + env.env_len;
+ ep = env.envp + env.env_len;
env.env_len++;
- *nep++ = str;
- *nep = NULL;
+ *ep++ = str;
+ *ep = NULL;
}
/*
SET(didvar, DID_USERNAME);
break;
}
- insert_env(*ep, FALSE, FALSE);
+ sudo_putenv(*ep, FALSE, FALSE);
}
}
didvar |= didvar << 8; /* convert DID_* to KEPT_* */
SET(didvar, DID_PATH);
else if (strncmp(*ep, "TERM=", 5) == 0)
SET(didvar, DID_TERM);
- insert_env(*ep, FALSE, FALSE);
+ sudo_putenv(*ep, FALSE, FALSE);
}
}
}
/* Provide default values for $TERM and $PATH if they are not set. */
if (!ISSET(didvar, DID_TERM))
- insert_env("TERM=unknown", FALSE, FALSE);
+ sudo_putenv("TERM=unknown", FALSE, FALSE);
if (!ISSET(didvar, DID_PATH))
_sudo_setenv("PATH", _PATH_DEFPATH, FALSE);
/* Set PS1 if SUDO_PS1 is set. */
if (ps1 != NULL)
- insert_env(ps1, TRUE, FALSE);
+ sudo_putenv(ps1, TRUE, TRUE);
/* Add the SUDO_COMMAND envariable (cmnd + args). */
if (user_args) {
if (env_vars == NULL)
return;
- /* Make sure we are operating on the current environment. */
- if (env.envp != environ)
- sync_env();
-
/* Add user-specified environment variables. */
for (cur = env_vars; cur != NULL; cur = cur->next)
- insert_env(cur->value, TRUE, TRUE);
+ sudo_putenv(cur->value, TRUE, TRUE);
}
/*
* character are skipped.
*/
void
-read_env_file(path, replace)
+read_env_file(path, overwrite)
const char *path;
- int replace;
+ int overwrite;
{
FILE *fp;
char *cp;
if ((fp = fopen(path, "r")) == NULL)
return;
- /* Make sure we are operating on the current environment. */
- if (env.envp != environ)
- sync_env();
-
while ((cp = sudo_parseln(fp)) != NULL) {
/* Skip blank or comment lines */
if (*cp == '\0')
if (strchr(cp, '=') == NULL)
continue;
- insert_env(estrdup(cp), replace ? TRUE : -1, TRUE);
+ sudo_putenv(estrdup(cp), TRUE, overwrite);
}
fclose(fp);
}
DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
}
#else
- sudo_setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE);
+ setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE);
#endif
}
rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI",
DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
#else
if (old_ccname != NULL)
- sudo_setenv("KRB5CCNAME", old_ccname, TRUE);
+ setenv("KRB5CCNAME", old_ccname, TRUE);
else
- sudo_unsetenv("KRB5CCNAME");
+ unsetenv("KRB5CCNAME");
#endif
}
if (rc != LDAP_SUCCESS) {
/* Prevent reading of user ldaprc and system defaults. */
if (getenv("LDAPNOINIT") == NULL) {
ldapnoinit = TRUE;
- sudo_setenv("LDAPNOINIT", "1", TRUE);
+ setenv("LDAPNOINIT", "1", TRUE);
}
/* Connect to LDAP server */
}
if (ldapnoinit)
- sudo_unsetenv("LDAPNOINIT");
+ unsetenv("LDAPNOINIT");
/* Set LDAP options */
if (sudo_ldap_set_options(ld) < 0)
#ifndef HAVE_MKSTEMP
int mkstemp __P((char *));
#endif
+#ifndef HAVE_SETENV
+int setenv __P((const char *, const char *, int));
+#endif
+#ifndef HAVE_UNSETENV
+int unsetenv __P((const char *));
+#endif
char *sudo_goodpath __P((const char *, struct stat *));
char *tgetpass __P((const char *, int, int));
int find_path __P((char *, char **, struct stat *, char *));
int display_cmnd __P((struct sudo_nss_list *, struct passwd *));
int get_ttycols __P((void));
char *sudo_parseln __P((FILE *));
-void sudo_setenv __P((const char *, const char *, int));
-void sudo_unsetenv __P((const char *));
void sudo_setgrent __P((void));
void sudo_endgrent __P((void));
void sudo_setpwent __P((void));