aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2012-12-08 09:19:51 -0800
committerPaul Eggert2012-12-08 09:19:51 -0800
commit5745a7df2b4abe06d032820f6ec7ddbac9ad5028 (patch)
tree5deecfc1b7b7c789abf9df72c177380d2cbef905
parentc56efa40745336c8067f047fe8f736821ddb3791 (diff)
downloademacs-5745a7df2b4abe06d032820f6ec7ddbac9ad5028.tar.gz
emacs-5745a7df2b4abe06d032820f6ec7ddbac9ad5028.zip
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
-rw-r--r--ChangeLog7
-rw-r--r--admin/ChangeLog3
-rwxr-xr-xadmin/merge-gnulib4
-rw-r--r--lib/gnulib.mk20
-rw-r--r--lib/putenv.c134
-rw-r--r--lib/unsetenv.c127
-rw-r--r--m4/gnulib-comp.m417
-rw-r--r--m4/putenv.m450
-rw-r--r--m4/setenv.m4160
-rw-r--r--src/ChangeLog26
-rw-r--r--src/alloc.c9
-rw-r--r--src/dbusbind.c2
-rw-r--r--src/editfns.c204
-rw-r--r--src/emacs.c9
-rw-r--r--src/lisp.h1
-rw-r--r--src/xterm.c5
16 files changed, 657 insertions, 121 deletions
diff --git a/ChangeLog b/ChangeLog
index 1d4fc853693..f31a03833c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
12012-12-08 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
4 * lib/putenv.c, lib/unsetenv.c, m4/putenv.m4, m4/setenv.m4:
5 New files, copied automatically from gnulib.
6 * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
7
12012-12-08 Eli Zaretskii <eliz@gnu.org> 82012-12-08 Eli Zaretskii <eliz@gnu.org>
2 9
3 * lib/makefile.w32-in ($(BLD)/sig2str.$(O)): New dependency. 10 * lib/makefile.w32-in ($(BLD)/sig2str.$(O)): New dependency.
diff --git a/admin/ChangeLog b/admin/ChangeLog
index 81d85f8f24c..9c6413aa14f 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,5 +1,8 @@
12012-12-08 Paul Eggert <eggert@cs.ucla.edu> 12012-12-08 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
4 * merge-gnulib (GNULIB_MODULES): Add putenv, unsetenv.
5
3 Simplify get_lim_data. 6 Simplify get_lim_data.
4 * CPP-DEFINES (ULIMIT_BREAK_VALUE): Remove. 7 * CPP-DEFINES (ULIMIT_BREAK_VALUE): Remove.
5 8
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 75e7ec6b000..1f60bb2973e 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -31,10 +31,10 @@ GNULIB_MODULES='
31 dtoastr dtotimespec dup2 environ execinfo faccessat 31 dtoastr dtotimespec dup2 environ execinfo faccessat
32 fcntl-h filemode getloadavg getopt-gnu gettime gettimeofday 32 fcntl-h filemode getloadavg getopt-gnu gettime gettimeofday
33 ignore-value intprops largefile lstat 33 ignore-value intprops largefile lstat
34 manywarnings mktime pselect pthread_sigmask readlink 34 manywarnings mktime pselect pthread_sigmask putenv readlink
35 sig2str socklen stat-time stdalign stdarg stdbool stdio 35 sig2str socklen stat-time stdalign stdarg stdbool stdio
36 strftime strtoimax strtoumax symlink sys_stat 36 strftime strtoimax strtoumax symlink sys_stat
37 sys_time time timer-time timespec-add timespec-sub utimens 37 sys_time time timer-time timespec-add timespec-sub unsetenv utimens
38 warnings 38 warnings
39' 39'
40 40
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 1335c80dae5..420520fbce7 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=at-internal --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=openat-h --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub utimens warnings 24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=at-internal --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=openat-h --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask putenv readlink sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -439,6 +439,15 @@ EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
439 439
440## end gnulib module pthread_sigmask 440## end gnulib module pthread_sigmask
441 441
442## begin gnulib module putenv
443
444
445EXTRA_DIST += putenv.c
446
447EXTRA_libgnu_a_SOURCES += putenv.c
448
449## end gnulib module putenv
450
442## begin gnulib module readlink 451## begin gnulib module readlink
443 452
444 453
@@ -1409,6 +1418,15 @@ EXTRA_DIST += unistd.in.h
1409 1418
1410## end gnulib module unistd 1419## end gnulib module unistd
1411 1420
1421## begin gnulib module unsetenv
1422
1423
1424EXTRA_DIST += unsetenv.c
1425
1426EXTRA_libgnu_a_SOURCES += unsetenv.c
1427
1428## end gnulib module unsetenv
1429
1412## begin gnulib module utimens 1430## begin gnulib module utimens
1413 1431
1414libgnu_a_SOURCES += utimens.c 1432libgnu_a_SOURCES += utimens.c
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 @@
1/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2012 Free Software
2 Foundation, Inc.
3
4 NOTE: The canonical source of this file is maintained with the GNU C
5 Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
6
7 This program is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or any
10 later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include <config.h>
21
22/* Specification. */
23#include <stdlib.h>
24
25#include <stddef.h>
26
27/* Include errno.h *after* sys/types.h to work around header problems
28 on AIX 3.2.5. */
29#include <errno.h>
30#ifndef __set_errno
31# define __set_errno(ev) ((errno) = (ev))
32#endif
33
34#include <string.h>
35#include <unistd.h>
36
37#if _LIBC
38# if HAVE_GNU_LD
39# define environ __environ
40# else
41extern char **environ;
42# endif
43#endif
44
45#if _LIBC
46/* This lock protects against simultaneous modifications of 'environ'. */
47# include <bits/libc-lock.h>
48__libc_lock_define_initialized (static, envlock)
49# define LOCK __libc_lock_lock (envlock)
50# define UNLOCK __libc_lock_unlock (envlock)
51#else
52# define LOCK
53# define UNLOCK
54#endif
55
56static int
57_unsetenv (const char *name)
58{
59 size_t len;
60 char **ep;
61
62 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
63 {
64 __set_errno (EINVAL);
65 return -1;
66 }
67
68 len = strlen (name);
69
70 LOCK;
71
72 ep = environ;
73 while (*ep != NULL)
74 if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
75 {
76 /* Found it. Remove this pointer by moving later ones back. */
77 char **dp = ep;
78
79 do
80 dp[0] = dp[1];
81 while (*dp++);
82 /* Continue the loop in case NAME appears again. */
83 }
84 else
85 ++ep;
86
87 UNLOCK;
88
89 return 0;
90}
91
92
93/* Put STRING, which is of the form "NAME=VALUE", in the environment.
94 If STRING contains no '=', then remove STRING from the environment. */
95int
96putenv (char *string)
97{
98 const char *const name_end = strchr (string, '=');
99 register size_t size;
100 register char **ep;
101
102 if (name_end == NULL)
103 {
104 /* Remove the variable from the environment. */
105 return _unsetenv (string);
106 }
107
108 size = 0;
109 for (ep = environ; *ep != NULL; ++ep)
110 if (!strncmp (*ep, string, name_end - string) &&
111 (*ep)[name_end - string] == '=')
112 break;
113 else
114 ++size;
115
116 if (*ep == NULL)
117 {
118 static char **last_environ = NULL;
119 char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
120 if (new_environ == NULL)
121 return -1;
122 (void) memcpy ((void *) new_environ, (void *) environ,
123 size * sizeof (char *));
124 new_environ[size] = (char *) string;
125 new_environ[size + 1] = NULL;
126 free (last_environ);
127 last_environ = new_environ;
128 environ = new_environ;
129 }
130 else
131 *ep = string;
132
133 return 0;
134}
diff --git a/lib/unsetenv.c b/lib/unsetenv.c
new file mode 100644
index 00000000000..ddbe9a4d293
--- /dev/null
+++ b/lib/unsetenv.c
@@ -0,0 +1,127 @@
1/* Copyright (C) 1992, 1995-2002, 2005-2012 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <config.h>
18
19/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
20 optimizes away the name == NULL test below. */
21#define _GL_ARG_NONNULL(params)
22
23/* Specification. */
24#include <stdlib.h>
25
26#include <errno.h>
27#if !_LIBC
28# define __set_errno(ev) ((errno) = (ev))
29#endif
30
31#include <string.h>
32#include <unistd.h>
33
34#if !_LIBC
35# define __environ environ
36#endif
37
38#if _LIBC
39/* This lock protects against simultaneous modifications of 'environ'. */
40# include <bits/libc-lock.h>
41__libc_lock_define_initialized (static, envlock)
42# define LOCK __libc_lock_lock (envlock)
43# define UNLOCK __libc_lock_unlock (envlock)
44#else
45# define LOCK
46# define UNLOCK
47#endif
48
49/* In the GNU C library we must keep the namespace clean. */
50#ifdef _LIBC
51# define unsetenv __unsetenv
52#endif
53
54#if _LIBC || !HAVE_UNSETENV
55
56int
57unsetenv (const char *name)
58{
59 size_t len;
60 char **ep;
61
62 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
63 {
64 __set_errno (EINVAL);
65 return -1;
66 }
67
68 len = strlen (name);
69
70 LOCK;
71
72 ep = __environ;
73 while (*ep != NULL)
74 if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
75 {
76 /* Found it. Remove this pointer by moving later ones back. */
77 char **dp = ep;
78
79 do
80 dp[0] = dp[1];
81 while (*dp++);
82 /* Continue the loop in case NAME appears again. */
83 }
84 else
85 ++ep;
86
87 UNLOCK;
88
89 return 0;
90}
91
92#ifdef _LIBC
93# undef unsetenv
94weak_alias (__unsetenv, unsetenv)
95#endif
96
97#else /* HAVE_UNSETENV */
98
99# undef unsetenv
100# if !HAVE_DECL_UNSETENV
101# if VOID_UNSETENV
102extern void unsetenv (const char *);
103# else
104extern int unsetenv (const char *);
105# endif
106# endif
107
108/* Call the underlying unsetenv, in case there is hidden bookkeeping
109 that needs updating beyond just modifying environ. */
110int
111rpl_unsetenv (const char *name)
112{
113 int result = 0;
114 if (!name || !*name || strchr (name, '='))
115 {
116 errno = EINVAL;
117 return -1;
118 }
119 while (getenv (name))
120# if !VOID_UNSETENV
121 result =
122# endif
123 unsetenv (name);
124 return result;
125}
126
127#endif /* HAVE_UNSETENV */
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index ebfbdf933f6..c836801649f 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -85,6 +85,7 @@ AC_DEFUN([gl_EARLY],
85 # Code from module pathmax: 85 # Code from module pathmax:
86 # Code from module pselect: 86 # Code from module pselect:
87 # Code from module pthread_sigmask: 87 # Code from module pthread_sigmask:
88 # Code from module putenv:
88 # Code from module readlink: 89 # Code from module readlink:
89 # Code from module root-uid: 90 # Code from module root-uid:
90 # Code from module sig2str: 91 # Code from module sig2str:
@@ -126,6 +127,7 @@ AC_DEFUN([gl_EARLY],
126 # Code from module timespec-sub: 127 # Code from module timespec-sub:
127 # Code from module u64: 128 # Code from module u64:
128 # Code from module unistd: 129 # Code from module unistd:
130 # Code from module unsetenv:
129 # Code from module utimens: 131 # Code from module utimens:
130 # Code from module verify: 132 # Code from module verify:
131 # Code from module warnings: 133 # Code from module warnings:
@@ -240,6 +242,11 @@ AC_DEFUN([gl_INIT],
240 gl_PREREQ_PTHREAD_SIGMASK 242 gl_PREREQ_PTHREAD_SIGMASK
241 fi 243 fi
242 gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask]) 244 gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask])
245 gl_FUNC_PUTENV
246 if test $REPLACE_PUTENV = 1; then
247 AC_LIBOBJ([putenv])
248 fi
249 gl_STDLIB_MODULE_INDICATOR([putenv])
243 gl_FUNC_READLINK 250 gl_FUNC_READLINK
244 if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then 251 if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
245 AC_LIBOBJ([readlink]) 252 AC_LIBOBJ([readlink])
@@ -297,6 +304,12 @@ AC_DEFUN([gl_INIT],
297 gl_TIMER_TIME 304 gl_TIMER_TIME
298 gl_TIMESPEC 305 gl_TIMESPEC
299 gl_UNISTD_H 306 gl_UNISTD_H
307 gl_FUNC_UNSETENV
308 if test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1; then
309 AC_LIBOBJ([unsetenv])
310 gl_PREREQ_UNSETENV
311 fi
312 gl_STDLIB_MODULE_INDICATOR([unsetenv])
300 gl_UTIMENS 313 gl_UTIMENS
301 gl_gnulib_enabled_dosname=false 314 gl_gnulib_enabled_dosname=false
302 gl_gnulib_enabled_euidaccess=false 315 gl_gnulib_enabled_euidaccess=false
@@ -679,6 +692,7 @@ AC_DEFUN([gl_FILE_LIST], [
679 lib/pathmax.h 692 lib/pathmax.h
680 lib/pselect.c 693 lib/pselect.c
681 lib/pthread_sigmask.c 694 lib/pthread_sigmask.c
695 lib/putenv.c
682 lib/readlink.c 696 lib/readlink.c
683 lib/root-uid.h 697 lib/root-uid.h
684 lib/sha1.c 698 lib/sha1.c
@@ -723,6 +737,7 @@ AC_DEFUN([gl_FILE_LIST], [
723 lib/u64.h 737 lib/u64.h
724 lib/unistd.c 738 lib/unistd.c
725 lib/unistd.in.h 739 lib/unistd.in.h
740 lib/unsetenv.c
726 lib/utimens.c 741 lib/utimens.c
727 lib/utimens.h 742 lib/utimens.h
728 lib/verify.h 743 lib/verify.h
@@ -764,7 +779,9 @@ AC_DEFUN([gl_FILE_LIST], [
764 m4/pathmax.m4 779 m4/pathmax.m4
765 m4/pselect.m4 780 m4/pselect.m4
766 m4/pthread_sigmask.m4 781 m4/pthread_sigmask.m4
782 m4/putenv.m4
767 m4/readlink.m4 783 m4/readlink.m4
784 m4/setenv.m4
768 m4/sha1.m4 785 m4/sha1.m4
769 m4/sha256.m4 786 m4/sha256.m4
770 m4/sha512.m4 787 m4/sha512.m4
diff --git a/m4/putenv.m4 b/m4/putenv.m4
new file mode 100644
index 00000000000..b971b1204d6
--- /dev/null
+++ b/m4/putenv.m4
@@ -0,0 +1,50 @@
1# putenv.m4 serial 19
2dnl Copyright (C) 2002-2012 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7dnl From Jim Meyering.
8dnl
9dnl Check whether putenv ("FOO") removes FOO from the environment.
10dnl The putenv in libc on at least SunOS 4.1.4 does *not* do that.
11
12AC_DEFUN([gl_FUNC_PUTENV],
13[
14 AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
15 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
16 AC_CACHE_CHECK([for putenv compatible with GNU and SVID],
17 [gl_cv_func_svid_putenv],
18 [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],[[
19 /* Put it in env. */
20 if (putenv ("CONFTEST_putenv=val"))
21 return 1;
22
23 /* Try to remove it. */
24 if (putenv ("CONFTEST_putenv"))
25 return 2;
26
27 /* Make sure it was deleted. */
28 if (getenv ("CONFTEST_putenv") != 0)
29 return 3;
30
31 return 0;
32 ]])],
33 gl_cv_func_svid_putenv=yes,
34 gl_cv_func_svid_putenv=no,
35 dnl When crosscompiling, assume putenv is broken.
36 [case "$host_os" in
37 # Guess yes on glibc systems.
38 *-gnu*) gl_cv_func_svid_putenv="guessing yes" ;;
39 # If we don't know, assume the worst.
40 *) gl_cv_func_svid_putenv="guessing no" ;;
41 esac
42 ])
43 ])
44 case "$gl_cv_func_svid_putenv" in
45 *yes) ;;
46 *)
47 REPLACE_PUTENV=1
48 ;;
49 esac
50])
diff --git a/m4/setenv.m4 b/m4/setenv.m4
new file mode 100644
index 00000000000..e1931e7eb28
--- /dev/null
+++ b/m4/setenv.m4
@@ -0,0 +1,160 @@
1# setenv.m4 serial 26
2dnl Copyright (C) 2001-2004, 2006-2012 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_FUNC_SETENV],
8[
9 AC_REQUIRE([gl_FUNC_SETENV_SEPARATE])
10 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
11 if test $ac_cv_func_setenv = no; then
12 HAVE_SETENV=0
13 else
14 AC_CACHE_CHECK([whether setenv validates arguments],
15 [gl_cv_func_setenv_works],
16 [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <string.h>
20 ]], [[
21 int result = 0;
22 {
23 if (setenv ("", "", 0) != -1)
24 result |= 1;
25 else if (errno != EINVAL)
26 result |= 2;
27 }
28 {
29 if (setenv ("a", "=", 1) != 0)
30 result |= 4;
31 else if (strcmp (getenv ("a"), "=") != 0)
32 result |= 8;
33 }
34 return result;
35 ]])],
36 [gl_cv_func_setenv_works=yes], [gl_cv_func_setenv_works=no],
37 [case "$host_os" in
38 # Guess yes on glibc systems.
39 *-gnu*) gl_cv_func_setenv_works="guessing yes" ;;
40 # If we don't know, assume the worst.
41 *) gl_cv_func_setenv_works="guessing no" ;;
42 esac
43 ])])
44 case "$gl_cv_func_setenv_works" in
45 *yes) ;;
46 *)
47 REPLACE_SETENV=1
48 ;;
49 esac
50 fi
51])
52
53# Like gl_FUNC_SETENV, except prepare for separate compilation
54# (no REPLACE_SETENV, no AC_LIBOBJ).
55AC_DEFUN([gl_FUNC_SETENV_SEPARATE],
56[
57 AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
58 AC_CHECK_DECLS_ONCE([setenv])
59 if test $ac_cv_have_decl_setenv = no; then
60 HAVE_DECL_SETENV=0
61 fi
62 AC_CHECK_FUNCS_ONCE([setenv])
63 gl_PREREQ_SETENV
64])
65
66AC_DEFUN([gl_FUNC_UNSETENV],
67[
68 AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
69 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
70 AC_CHECK_DECLS_ONCE([unsetenv])
71 if test $ac_cv_have_decl_unsetenv = no; then
72 HAVE_DECL_UNSETENV=0
73 fi
74 AC_CHECK_FUNCS([unsetenv])
75 if test $ac_cv_func_unsetenv = no; then
76 HAVE_UNSETENV=0
77 else
78 HAVE_UNSETENV=1
79 dnl Some BSDs return void, failing to do error checking.
80 AC_CACHE_CHECK([for unsetenv() return type], [gt_cv_func_unsetenv_ret],
81 [AC_COMPILE_IFELSE(
82 [AC_LANG_PROGRAM(
83 [[
84#undef _BSD
85#define _BSD 1 /* unhide unsetenv declaration in OSF/1 5.1 <stdlib.h> */
86#include <stdlib.h>
87extern
88#ifdef __cplusplus
89"C"
90#endif
91int unsetenv (const char *name);
92 ]],
93 [[]])],
94 [gt_cv_func_unsetenv_ret='int'],
95 [gt_cv_func_unsetenv_ret='void'])])
96 if test $gt_cv_func_unsetenv_ret = 'void'; then
97 AC_DEFINE([VOID_UNSETENV], [1], [Define to 1 if unsetenv returns void
98 instead of int.])
99 REPLACE_UNSETENV=1
100 fi
101
102 dnl Solaris 10 unsetenv does not remove all copies of a name.
103 dnl Haiku alpha 2 unsetenv gets confused by assignment to environ.
104 dnl OpenBSD 4.7 unsetenv("") does not fail.
105 AC_CACHE_CHECK([whether unsetenv obeys POSIX],
106 [gl_cv_func_unsetenv_works],
107 [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
108 #include <stdlib.h>
109 #include <errno.h>
110 extern char **environ;
111 ]], [[
112 char entry1[] = "a=1";
113 char entry2[] = "b=2";
114 char *env[] = { entry1, entry2, NULL };
115 if (putenv ((char *) "a=1")) return 1;
116 if (putenv (entry2)) return 2;
117 entry2[0] = 'a';
118 unsetenv ("a");
119 if (getenv ("a")) return 3;
120 if (!unsetenv ("") || errno != EINVAL) return 4;
121 entry2[0] = 'b';
122 environ = env;
123 if (!getenv ("a")) return 5;
124 entry2[0] = 'a';
125 unsetenv ("a");
126 if (getenv ("a")) return 6;
127 ]])],
128 [gl_cv_func_unsetenv_works=yes], [gl_cv_func_unsetenv_works=no],
129 [case "$host_os" in
130 # Guess yes on glibc systems.
131 *-gnu*) gl_cv_func_unsetenv_works="guessing yes" ;;
132 # If we don't know, assume the worst.
133 *) gl_cv_func_unsetenv_works="guessing no" ;;
134 esac
135 ])])
136 case "$gl_cv_func_unsetenv_works" in
137 *yes) ;;
138 *)
139 REPLACE_UNSETENV=1
140 ;;
141 esac
142 fi
143])
144
145# Prerequisites of lib/setenv.c.
146AC_DEFUN([gl_PREREQ_SETENV],
147[
148 AC_REQUIRE([AC_FUNC_ALLOCA])
149 AC_REQUIRE([gl_ENVIRON])
150 AC_CHECK_HEADERS_ONCE([unistd.h])
151 AC_CHECK_HEADERS([search.h])
152 AC_CHECK_FUNCS([tsearch])
153])
154
155# Prerequisites of lib/unsetenv.c.
156AC_DEFUN([gl_PREREQ_UNSETENV],
157[
158 AC_REQUIRE([gl_ENVIRON])
159 AC_CHECK_HEADERS_ONCE([unistd.h])
160])
diff --git a/src/ChangeLog b/src/ChangeLog
index 54985d33b59..0be3eee6726 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,29 @@
12012-12-08 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
4 * alloc.c (xputenv): New function.
5 * dbusbind.c (Fdbus_init_bus):
6 * emacs.c (main):
7 * xterm.c (x_term_init):
8 Use xputenv instead of setenv or putenv, to detect memory exhaustion.
9 * editfns.c (initial_tz): Move static var decl up.
10 (tzvalbuf_in_environ): New static var.
11 (init_editfns): Initialize these two static vars.
12 (Fencode_time): Don't assume arbitrary limit on EMACS_INT width.
13 Save old TZ value on stack, if it's small.
14 (Fencode_time, set_time_zone_rule): Don't modify 'environ' directly;
15 instead, use xputenv+unsetenv to set and restore TZ.
16 (environbuf): Remove static var. All uses removed.
17 (Fset_time_zone_rule): Do not save TZ and environ;
18 no longer needed here.
19 (set_time_zone_rule_tz1, set_time_zone_rule_tz2) [LOCALTIME_CACHE]:
20 Move to inside set_time_zone_rule; they don't need file scope any more.
21 (set_time_zone_rule): Maintain the TZ=value string separately.
22 (syms_of_editfns): Don't initialize initial_tz;
23 init_editfns now does it.
24 * emacs.c (dump_tz) [HAVE_TZSET]: Now const.
25 * lisp.h (xputenv): New decl.
26
12012-12-08 Fabrice Popineau <fabrice.popineau@gmail.com> 272012-12-08 Fabrice Popineau <fabrice.popineau@gmail.com>
2 28
3 * w32fns.c (emacs_abort): Don't do arithmetics on void pointers. 29 * w32fns.c (emacs_abort): Don't do arithmetics on void pointers.
diff --git a/src/alloc.c b/src/alloc.c
index 0f105f87207..5a3ba465d81 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -820,6 +820,15 @@ xstrdup (const char *s)
820 return p; 820 return p;
821} 821}
822 822
823/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
824 argument is a const pointer. */
825
826void
827xputenv (char const *string)
828{
829 if (putenv ((char *) string) != 0)
830 memory_full (0);
831}
823 832
824/* Unwind for SAFE_ALLOCA */ 833/* Unwind for SAFE_ALLOCA */
825 834
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 80086946fc4..da8bbb1e5d7 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -1203,7 +1203,7 @@ this connection to those buses. */)
1203 xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses); 1203 xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses);
1204 1204
1205 /* We do not want to abort. */ 1205 /* We do not want to abort. */
1206 putenv ((char *) "DBUS_FATAL_WARNINGS=0"); 1206 xputenv ("DBUS_FATAL_WARNINGS=0");
1207 1207
1208 /* Cleanup. */ 1208 /* Cleanup. */
1209 dbus_error_free (&derror); 1209 dbus_error_free (&derror);
diff --git a/src/editfns.c b/src/editfns.c
index ffb9a38909b..7d179c8566a 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -78,6 +78,15 @@ Lisp_Object Qfield;
78 78
79static Lisp_Object Qboundary; 79static Lisp_Object Qboundary;
80 80
81/* The startup value of the TZ environment variable so it can be
82 restored if the user calls set-time-zone-rule with a nil
83 argument. If null, the TZ environment variable was unset. */
84static char const *initial_tz;
85
86/* True if the static variable tzvalbuf (defined in
87 set_time_zone_rule) is part of 'environ'. */
88static bool tzvalbuf_in_environ;
89
81 90
82void 91void
83init_editfns (void) 92init_editfns (void)
@@ -96,6 +105,9 @@ init_editfns (void)
96 return; 105 return;
97#endif /* not CANNOT_DUMP */ 106#endif /* not CANNOT_DUMP */
98 107
108 initial_tz = getenv ("TZ");
109 tzvalbuf_in_environ = 0;
110
99 pw = getpwuid (getuid ()); 111 pw = getpwuid (getuid ());
100#ifdef MSDOS 112#ifdef MSDOS
101 /* We let the real user name default to "root" because that's quite 113 /* We let the real user name default to "root" because that's quite
@@ -1900,9 +1912,11 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1900 } 1912 }
1901 else 1913 else
1902 { 1914 {
1903 char tzbuf[100]; 1915 static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
1916 char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
1917 char *old_tzstring;
1904 const char *tzstring; 1918 const char *tzstring;
1905 char **oldenv = environ, **newenv; 1919 USE_SAFE_ALLOCA;
1906 1920
1907 if (EQ (zone, Qt)) 1921 if (EQ (zone, Qt))
1908 tzstring = "UTC0"; 1922 tzstring = "UTC0";
@@ -1914,13 +1928,20 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1914 EMACS_INT zone_hr = abszone / (60*60); 1928 EMACS_INT zone_hr = abszone / (60*60);
1915 int zone_min = (abszone/60) % 60; 1929 int zone_min = (abszone/60) % 60;
1916 int zone_sec = abszone % 60; 1930 int zone_sec = abszone % 60;
1917 sprintf (tzbuf, "XXX%s%"pI"d:%02d:%02d", "-" + (XINT (zone) < 0), 1931 sprintf (tzbuf, tzbuf_format, "-" + (XINT (zone) < 0),
1918 zone_hr, zone_min, zone_sec); 1932 zone_hr, zone_min, zone_sec);
1919 tzstring = tzbuf; 1933 tzstring = tzbuf;
1920 } 1934 }
1921 else 1935 else
1922 error ("Invalid time zone specification"); 1936 error ("Invalid time zone specification");
1923 1937
1938 old_tzstring = getenv ("TZ");
1939 if (old_tzstring)
1940 {
1941 char *buf = SAFE_ALLOCA (strlen (old_tzstring) + 1);
1942 old_tzstring = strcpy (buf, old_tzstring);
1943 }
1944
1924 block_input (); 1945 block_input ();
1925 1946
1926 /* Set TZ before calling mktime; merely adjusting mktime's returned 1947 /* Set TZ before calling mktime; merely adjusting mktime's returned
@@ -1929,15 +1950,12 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1929 1950
1930 value = mktime (&tm); 1951 value = mktime (&tm);
1931 1952
1932 /* Restore TZ to previous value. */ 1953 set_time_zone_rule (old_tzstring);
1933 newenv = environ;
1934 environ = oldenv;
1935#ifdef LOCALTIME_CACHE 1954#ifdef LOCALTIME_CACHE
1936 tzset (); 1955 tzset ();
1937#endif 1956#endif
1938 unblock_input (); 1957 unblock_input ();
1939 1958 SAFE_FREE ();
1940 xfree (newenv);
1941 } 1959 }
1942 1960
1943 if (value == (time_t) -1) 1961 if (value == (time_t) -1)
@@ -2067,16 +2085,6 @@ the data it can't find. */)
2067 return list2 (zone_offset, zone_name); 2085 return list2 (zone_offset, zone_name);
2068} 2086}
2069 2087
2070/* This holds the value of `environ' produced by the previous
2071 call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
2072 has never been called. */
2073static char **environbuf;
2074
2075/* This holds the startup value of the TZ environment variable so it
2076 can be restored if the user calls set-time-zone-rule with a nil
2077 argument. */
2078static char *initial_tz;
2079
2080DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0, 2088DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
2081 doc: /* Set the local time zone using TZ, a string specifying a time zone rule. 2089 doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
2082If TZ is nil, use implementation-defined default time zone information. 2090If TZ is nil, use implementation-defined default time zone information.
@@ -2089,18 +2097,10 @@ only the former. */)
2089 (Lisp_Object tz) 2097 (Lisp_Object tz)
2090{ 2098{
2091 const char *tzstring; 2099 const char *tzstring;
2092 char **old_environbuf;
2093 2100
2094 if (! (NILP (tz) || EQ (tz, Qt))) 2101 if (! (NILP (tz) || EQ (tz, Qt)))
2095 CHECK_STRING (tz); 2102 CHECK_STRING (tz);
2096 2103
2097 block_input ();
2098
2099 /* When called for the first time, save the original TZ. */
2100 old_environbuf = environbuf;
2101 if (!old_environbuf)
2102 initial_tz = (char *) getenv ("TZ");
2103
2104 if (NILP (tz)) 2104 if (NILP (tz))
2105 tzstring = initial_tz; 2105 tzstring = initial_tz;
2106 else if (EQ (tz, Qt)) 2106 else if (EQ (tz, Qt))
@@ -2108,106 +2108,97 @@ only the former. */)
2108 else 2108 else
2109 tzstring = SSDATA (tz); 2109 tzstring = SSDATA (tz);
2110 2110
2111 block_input ();
2111 set_time_zone_rule (tzstring); 2112 set_time_zone_rule (tzstring);
2112 environbuf = environ;
2113
2114 unblock_input (); 2113 unblock_input ();
2115 2114
2116 xfree (old_environbuf);
2117 return Qnil; 2115 return Qnil;
2118} 2116}
2119 2117
2120#ifdef LOCALTIME_CACHE
2121
2122/* These two values are known to load tz files in buggy implementations,
2123 i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
2124 Their values shouldn't matter in non-buggy implementations.
2125 We don't use string literals for these strings,
2126 since if a string in the environment is in readonly
2127 storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
2128 See Sun bugs 1113095 and 1114114, ``Timezone routines
2129 improperly modify environment''. */
2130
2131static char set_time_zone_rule_tz1[] = "TZ=GMT+0";
2132static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
2133
2134#endif
2135
2136/* Set the local time zone rule to TZSTRING. 2118/* Set the local time zone rule to TZSTRING.
2137 This allocates memory into `environ', which it is the caller's 2119
2138 responsibility to free. */ 2120 This function is not thread-safe, partly because putenv, unsetenv
2121 and tzset are not, and partly because of the static storage it
2122 updates. Other threads that invoke localtime etc. may be adversely
2123 affected while this function is executing. */
2139 2124
2140void 2125void
2141set_time_zone_rule (const char *tzstring) 2126set_time_zone_rule (const char *tzstring)
2142{ 2127{
2143 ptrdiff_t envptrs; 2128 /* A buffer holding a string of the form "TZ=value", intended
2144 char **from, **to, **newenv; 2129 to be part of the environment. */
2130 static char *tzvalbuf;
2131 static ptrdiff_t tzvalbufsize;
2145 2132
2146 /* Make the ENVIRON vector longer with room for TZSTRING. */ 2133 int tzeqlen = sizeof "TZ=" - 1;
2147 for (from = environ; *from; from++) 2134
2148 continue; 2135#ifdef LOCALTIME_CACHE
2149 envptrs = from - environ + 2; 2136 /* These two values are known to load tz files in buggy implementations,
2150 newenv = to = xmalloc (envptrs * sizeof *newenv 2137 i.e., Solaris 1 executables running under either Solaris 1 or Solaris 2.
2151 + (tzstring ? strlen (tzstring) + 4 : 0)); 2138 Their values shouldn't matter in non-buggy implementations.
2139 We don't use string literals for these strings,
2140 since if a string in the environment is in readonly
2141 storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
2142 See Sun bugs 1113095 and 1114114, ``Timezone routines
2143 improperly modify environment''. */
2144
2145 static char set_time_zone_rule_tz[][sizeof "TZ=GMT+0"]
2146 = { "TZ=GMT+0", "TZ=GMT+1" };
2147
2148 /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
2149 "US/Pacific" that loads a tz file, then changes to a value like
2150 "XXX0" that does not load a tz file, and then changes back to
2151 its original value, the last change is (incorrectly) ignored.
2152 Also, if TZ changes twice in succession to values that do
2153 not load a tz file, tzset can dump core (see Sun bug#1225179).
2154 The following code works around these bugs. */
2152 2155
2153 /* Add TZSTRING to the end of environ, as a value for TZ. */
2154 if (tzstring) 2156 if (tzstring)
2155 { 2157 {
2156 char *t = (char *) (to + envptrs); 2158 /* Temporarily set TZ to a value that loads a tz file
2157 strcpy (t, "TZ="); 2159 and that differs from tzstring. */
2158 strcat (t, tzstring); 2160 bool eq0 = strcmp (tzstring, set_time_zone_rule_tz[0] + tzeqlen) == 0;
2159 *to++ = t; 2161 xputenv (set_time_zone_rule_tz[eq0]);
2160 } 2162 }
2163 else
2164 {
2165 /* The implied tzstring is unknown, so temporarily set TZ to
2166 two different values that each load a tz file. */
2167 xputenv (set_time_zone_rule_tz[0]);
2168 tzset ();
2169 xputenv (set_time_zone_rule_tz[1]);
2170 }
2171 tzset ();
2172#endif
2161 2173
2162 /* Copy the old environ vector elements into NEWENV, 2174 if (!tzstring)
2163 but don't copy the TZ variable. 2175 {
2164 So we have only one definition of TZ, which came from TZSTRING. */ 2176 unsetenv ("TZ");
2165 for (from = environ; *from; from++) 2177 tzvalbuf_in_environ = 0;
2166 if (strncmp (*from, "TZ=", 3) != 0) 2178 }
2167 *to++ = *from; 2179 else
2168 *to = 0; 2180 {
2169 2181 ptrdiff_t tzstringlen = strlen (tzstring);
2170 environ = newenv;
2171 2182
2172 /* If we do have a TZSTRING, NEWENV points to the vector slot where 2183 if (tzvalbufsize <= tzeqlen + tzstringlen)
2173 the TZ variable is stored. If we do not have a TZSTRING, 2184 {
2174 TO points to the vector slot which has the terminating null. */ 2185 unsetenv ("TZ");
2186 tzvalbuf_in_environ = 0;
2187 tzvalbuf = xpalloc (tzvalbuf, &tzvalbufsize,
2188 tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1);
2189 memcpy (tzvalbuf, "TZ=", tzeqlen);
2190 }
2175 2191
2176#ifdef LOCALTIME_CACHE 2192 strcpy (tzvalbuf + tzeqlen, tzstring);
2177 {
2178 /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
2179 "US/Pacific" that loads a tz file, then changes to a value like
2180 "XXX0" that does not load a tz file, and then changes back to
2181 its original value, the last change is (incorrectly) ignored.
2182 Also, if TZ changes twice in succession to values that do
2183 not load a tz file, tzset can dump core (see Sun bug#1225179).
2184 The following code works around these bugs. */
2185
2186 if (tzstring)
2187 {
2188 /* Temporarily set TZ to a value that loads a tz file
2189 and that differs from tzstring. */
2190 char *tz = *newenv;
2191 *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
2192 ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
2193 tzset ();
2194 *newenv = tz;
2195 }
2196 else
2197 {
2198 /* The implied tzstring is unknown, so temporarily set TZ to
2199 two different values that each load a tz file. */
2200 *to = set_time_zone_rule_tz1;
2201 to[1] = 0;
2202 tzset ();
2203 *to = set_time_zone_rule_tz2;
2204 tzset ();
2205 *to = 0;
2206 }
2207 2193
2208 /* Now TZ has the desired value, and tzset can be invoked safely. */ 2194 if (!tzvalbuf_in_environ)
2209 } 2195 {
2196 xputenv (tzvalbuf);
2197 tzvalbuf_in_environ = 1;
2198 }
2199 }
2210 2200
2201#ifdef LOCALTIME_CACHE
2211 tzset (); 2202 tzset ();
2212#endif 2203#endif
2213} 2204}
@@ -4800,9 +4791,6 @@ Transposing beyond buffer boundaries is an error. */)
4800void 4791void
4801syms_of_editfns (void) 4792syms_of_editfns (void)
4802{ 4793{
4803 environbuf = 0;
4804 initial_tz = 0;
4805
4806 DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions"); 4794 DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
4807 4795
4808 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion, 4796 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
diff --git a/src/emacs.c b/src/emacs.c
index b2b193e3a4f..fbaf0355000 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -535,7 +535,7 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
535#ifdef HAVE_TZSET 535#ifdef HAVE_TZSET
536/* A valid but unlikely value for the TZ environment value. 536/* A valid but unlikely value for the TZ environment value.
537 It is OK (though a bit slower) if the user actually chooses this value. */ 537 It is OK (though a bit slower) if the user actually chooses this value. */
538static char dump_tz[] = "UtC0"; 538static char const dump_tz[] = "UtC0";
539#endif 539#endif
540 540
541#ifndef ORDINARY_LINK 541#ifndef ORDINARY_LINK
@@ -717,7 +717,7 @@ main (int argc, char **argv)
717 717
718#ifdef G_SLICE_ALWAYS_MALLOC 718#ifdef G_SLICE_ALWAYS_MALLOC
719 /* This is used by the Cygwin build. */ 719 /* This is used by the Cygwin build. */
720 setenv ("G_SLICE", "always-malloc", 1); 720 xputenv ("G_SLICE=always-malloc");
721#endif 721#endif
722 722
723#ifdef GNU_LINUX 723#ifdef GNU_LINUX
@@ -803,9 +803,8 @@ main (int argc, char **argv)
803#ifdef HAVE_PERSONALITY_LINUX32 803#ifdef HAVE_PERSONALITY_LINUX32
804 if (dumping && ! getenv ("EMACS_HEAP_EXEC")) 804 if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
805 { 805 {
806 static char heapexec[] = "EMACS_HEAP_EXEC=true";
807 /* Set this so we only do this once. */ 806 /* Set this so we only do this once. */
808 putenv (heapexec); 807 xputenv ("EMACS_HEAP_EXEC=true");
809 808
810 /* A flag to turn off address randomization which is introduced 809 /* A flag to turn off address randomization which is introduced
811 in linux kernel shipped with fedora core 4 */ 810 in linux kernel shipped with fedora core 4 */
@@ -1309,7 +1308,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1309 don't pollute Vglobal_environment. */ 1308 don't pollute Vglobal_environment. */
1310 /* Setting LANG here will defeat the startup locale processing... */ 1309 /* Setting LANG here will defeat the startup locale processing... */
1311#ifdef AIX 1310#ifdef AIX
1312 putenv ("LANG=C"); 1311 xputenv ("LANG=C");
1313#endif 1312#endif
1314 1313
1315 init_buffer (); /* Init default directory of main buffer. */ 1314 init_buffer (); /* Init default directory of main buffer. */
diff --git a/src/lisp.h b/src/lisp.h
index 172a32e92a9..91fc3dfa1c6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3594,6 +3594,7 @@ extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t);
3594extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); 3594extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t);
3595 3595
3596extern char *xstrdup (const char *); 3596extern char *xstrdup (const char *);
3597extern void xputenv (const char *);
3597 3598
3598extern char *egetenv (const char *); 3599extern char *egetenv (const char *);
3599 3600
diff --git a/src/xterm.c b/src/xterm.c
index 8acd1d7843e..e9e99574663 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9908,10 +9908,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
9908 9908
9909 /* Emacs can only handle core input events, so make sure 9909 /* Emacs can only handle core input events, so make sure
9910 Gtk doesn't use Xinput or Xinput2 extensions. */ 9910 Gtk doesn't use Xinput or Xinput2 extensions. */
9911 { 9911 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
9912 static char fix_events[] = "GDK_CORE_DEVICE_EVENTS=1";
9913 putenv (fix_events);
9914 }
9915 9912
9916 /* Work around GLib bug that outputs a faulty warning. See 9913 /* Work around GLib bug that outputs a faulty warning. See
9917 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */ 9914 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */