summaryrefslogtreecommitdiff
path: root/lib/putenv.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2012-12-08 09:19:51 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2012-12-08 09:19:51 -0800
commit5745a7df2b4abe06d032820f6ec7ddbac9ad5028 (patch)
tree5deecfc1b7b7c789abf9df72c177380d2cbef905 /lib/putenv.c
parentc56efa40745336c8067f047fe8f736821ddb3791 (diff)
downloademacs-5745a7df2b4abe06d032820f6ec7ddbac9ad5028.tar.gz
Use putenv+unsetenv instead of modifying environ directly.
* admin/merge-gnulib (GNULIB_MODULES): Add putenv, unsetenv. * lib/putenv.c, lib/unsetenv.c, m4/putenv.m4, m4/setenv.m4: New files, copied automatically from gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * src/alloc.c (xputenv): New function. * src/dbusbind.c (Fdbus_init_bus): * src/emacs.c (main): * src/xterm.c (x_term_init): Use xputenv instead of setenv or putenv, to detect memory exhaustion. * src/editfns.c (initial_tz): Move static var decl up. (tzvalbuf_in_environ): New static var. (init_editfns): Initialize these two static vars. (Fencode_time): Don't assume arbitrary limit on EMACS_INT width. Save old TZ value on stack, if it's small. (Fencode_time, set_time_zone_rule): Don't modify 'environ' directly; instead, use xputenv+unsetenv to set and restore TZ. (environbuf): Remove static var. All uses removed. (Fset_time_zone_rule): Do not save TZ and environ; no longer needed here. (set_time_zone_rule_tz1, set_time_zone_rule_tz2) [LOCALTIME_CACHE]: Move to inside set_time_zone_rule; they don't need file scope any more. (set_time_zone_rule): Maintain the TZ=value string separately. (syms_of_editfns): Don't initialize initial_tz; init_editfns now does it. * src/emacs.c (dump_tz) [HAVE_TZSET]: Now const. * src/lisp.h (xputenv): New decl. Fixes: debbugs:13070
Diffstat (limited to 'lib/putenv.c')
-rw-r--r--lib/putenv.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/lib/putenv.c b/lib/putenv.c
new file mode 100644
index 00000000000..3c0f7ead330
--- /dev/null
+++ b/lib/putenv.c
@@ -0,0 +1,134 @@
+/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2012 Free Software
+ Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+#include <stddef.h>
+
+/* Include errno.h *after* sys/types.h to work around header problems
+ on AIX 3.2.5. */
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#include <string.h>
+#include <unistd.h>
+
+#if _LIBC
+# if HAVE_GNU_LD
+# define environ __environ
+# else
+extern char **environ;
+# endif
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of 'environ'. */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK __libc_lock_lock (envlock)
+# define UNLOCK __libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static int
+_unsetenv (const char *name)
+{
+ size_t len;
+ char **ep;
+
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ len = strlen (name);
+
+ LOCK;
+
+ ep = environ;
+ while (*ep != NULL)
+ if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+ {
+ /* Found it. Remove this pointer by moving later ones back. */
+ char **dp = ep;
+
+ do
+ dp[0] = dp[1];
+ while (*dp++);
+ /* Continue the loop in case NAME appears again. */
+ }
+ else
+ ++ep;
+
+ UNLOCK;
+
+ return 0;
+}
+
+
+/* Put STRING, which is of the form "NAME=VALUE", in the environment.
+ If STRING contains no '=', then remove STRING from the environment. */
+int
+putenv (char *string)
+{
+ const char *const name_end = strchr (string, '=');
+ register size_t size;
+ register char **ep;
+
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ return _unsetenv (string);
+ }
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp (*ep, string, name_end - string) &&
+ (*ep)[name_end - string] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL)
+ {
+ static char **last_environ = NULL;
+ char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
+ if (new_environ == NULL)
+ return -1;
+ (void) memcpy ((void *) new_environ, (void *) environ,
+ size * sizeof (char *));
+ new_environ[size] = (char *) string;
+ new_environ[size + 1] = NULL;
+ free (last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ }
+ else
+ *ep = string;
+
+ return 0;
+}