+ esize = strlen(var) + 1 + strlen(val) + 1;
+ estring = emalloc(esize);
+
+ /* Build environment string and insert it. */
+ if (strlcpy(estring, var, esize) >= esize ||
+ strlcat(estring, "=", esize) >= esize ||
+ strlcat(estring, val, esize) >= esize) {
+
+ errorx(1, "internal error, sudo_setenv() overflow");
+ }
+ sudo_putenv(estring, dupcheck, TRUE);
+}
+
+/*
+ * Version of setenv(3) that uses our own environ pointer.
+ * Will sync with environ as needed.
+ */
+int
+setenv(var, val, overwrite)
+ const char *var;
+ const char *val;
+ int overwrite;
+{
+ char *estring, *ep;
+ const char *cp;
+ size_t esize;
+
+ if (!var || *var == '\0')
+ return(EINVAL);
+
+ /*
+ * 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 "" */
+ }
+
+ /* Allocate and fill in estring. */
+ estring = ep = emalloc(esize);
+ for (cp = var; *cp && *cp != '='; cp++)
+ *ep++ = *cp;
+ *ep++ = '=';
+ if (val) {
+ for (cp = val; *cp; cp++)
+ *ep++ = *cp;
+ }
+ *ep = '\0';
+
+ /* Sync env.envp with environ as needed. */
+ if (env.envp != environ) {
+ char **ep;
+ size_t len;
+
+ 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 *));
+#ifdef ENV_DEBUG
+ memset(env.envp, 0, env.env_size * sizeof(char *));
+#endif
+ }
+ memcpy(env.envp, environ, len * sizeof(char *));
+ env.envp[len] = NULL;
+ env.env_len = len;
+ environ = env.envp;
+#ifdef ENV_DEBUG
+ } else {
+ if (env.envp[env.env_len] != NULL)
+ errorx(1, "setenv: corrupted envp, len mismatch");
+#endif
+ }
+ sudo_putenv(estring, TRUE, overwrite);
+ return(0);
+}
+
+/*
+ * Version of unsetenv(3) that uses our own environ pointer.
+ * Will sync with environ as needed.
+ */
+#ifdef UNSETENV_VOID
+void