diff options
| author | Paul Eggert | 2012-12-08 09:19:51 -0800 |
|---|---|---|
| committer | Paul Eggert | 2012-12-08 09:19:51 -0800 |
| commit | 5745a7df2b4abe06d032820f6ec7ddbac9ad5028 (patch) | |
| tree | 5deecfc1b7b7c789abf9df72c177380d2cbef905 | |
| parent | c56efa40745336c8067f047fe8f736821ddb3791 (diff) | |
| download | emacs-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-- | ChangeLog | 7 | ||||
| -rw-r--r-- | admin/ChangeLog | 3 | ||||
| -rwxr-xr-x | admin/merge-gnulib | 4 | ||||
| -rw-r--r-- | lib/gnulib.mk | 20 | ||||
| -rw-r--r-- | lib/putenv.c | 134 | ||||
| -rw-r--r-- | lib/unsetenv.c | 127 | ||||
| -rw-r--r-- | m4/gnulib-comp.m4 | 17 | ||||
| -rw-r--r-- | m4/putenv.m4 | 50 | ||||
| -rw-r--r-- | m4/setenv.m4 | 160 | ||||
| -rw-r--r-- | src/ChangeLog | 26 | ||||
| -rw-r--r-- | src/alloc.c | 9 | ||||
| -rw-r--r-- | src/dbusbind.c | 2 | ||||
| -rw-r--r-- | src/editfns.c | 204 | ||||
| -rw-r--r-- | src/emacs.c | 9 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/xterm.c | 5 |
16 files changed, 657 insertions, 121 deletions
| @@ -1,3 +1,10 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-12-08 Eli Zaretskii <eliz@gnu.org> | 8 | 2012-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 @@ | |||
| 1 | 2012-12-08 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2012-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 | ||
| 27 | MOSTLYCLEANFILES += core *.stackdump | 27 | MOSTLYCLEANFILES += 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 | |||
| 445 | EXTRA_DIST += putenv.c | ||
| 446 | |||
| 447 | EXTRA_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 | |||
| 1424 | EXTRA_DIST += unsetenv.c | ||
| 1425 | |||
| 1426 | EXTRA_libgnu_a_SOURCES += unsetenv.c | ||
| 1427 | |||
| 1428 | ## end gnulib module unsetenv | ||
| 1429 | |||
| 1412 | ## begin gnulib module utimens | 1430 | ## begin gnulib module utimens |
| 1413 | 1431 | ||
| 1414 | libgnu_a_SOURCES += utimens.c | 1432 | libgnu_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 | ||
| 41 | extern 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 | |||
| 56 | static 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. */ | ||
| 95 | int | ||
| 96 | putenv (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 | |||
| 56 | 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 | #ifdef _LIBC | ||
| 93 | # undef unsetenv | ||
| 94 | weak_alias (__unsetenv, unsetenv) | ||
| 95 | #endif | ||
| 96 | |||
| 97 | #else /* HAVE_UNSETENV */ | ||
| 98 | |||
| 99 | # undef unsetenv | ||
| 100 | # if !HAVE_DECL_UNSETENV | ||
| 101 | # if VOID_UNSETENV | ||
| 102 | extern void unsetenv (const char *); | ||
| 103 | # else | ||
| 104 | extern 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. */ | ||
| 110 | int | ||
| 111 | rpl_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 | ||
| 2 | dnl Copyright (C) 2002-2012 Free Software Foundation, Inc. | ||
| 3 | dnl This file is free software; the Free Software Foundation | ||
| 4 | dnl gives unlimited permission to copy and/or distribute it, | ||
| 5 | dnl with or without modifications, as long as this notice is preserved. | ||
| 6 | |||
| 7 | dnl From Jim Meyering. | ||
| 8 | dnl | ||
| 9 | dnl Check whether putenv ("FOO") removes FOO from the environment. | ||
| 10 | dnl The putenv in libc on at least SunOS 4.1.4 does *not* do that. | ||
| 11 | |||
| 12 | AC_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 | ||
| 2 | dnl Copyright (C) 2001-2004, 2006-2012 Free Software Foundation, Inc. | ||
| 3 | dnl This file is free software; the Free Software Foundation | ||
| 4 | dnl gives unlimited permission to copy and/or distribute it, | ||
| 5 | dnl with or without modifications, as long as this notice is preserved. | ||
| 6 | |||
| 7 | AC_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). | ||
| 55 | AC_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 | |||
| 66 | AC_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> | ||
| 87 | extern | ||
| 88 | #ifdef __cplusplus | ||
| 89 | "C" | ||
| 90 | #endif | ||
| 91 | int 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. | ||
| 146 | AC_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. | ||
| 156 | AC_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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-12-08 Fabrice Popineau <fabrice.popineau@gmail.com> | 27 | 2012-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 | |||
| 826 | void | ||
| 827 | xputenv (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 | ||
| 79 | static Lisp_Object Qboundary; | 79 | static 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. */ | ||
| 84 | static char const *initial_tz; | ||
| 85 | |||
| 86 | /* True if the static variable tzvalbuf (defined in | ||
| 87 | set_time_zone_rule) is part of 'environ'. */ | ||
| 88 | static bool tzvalbuf_in_environ; | ||
| 89 | |||
| 81 | 90 | ||
| 82 | void | 91 | void |
| 83 | init_editfns (void) | 92 | init_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. */ | ||
| 2073 | static 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. */ | ||
| 2078 | static char *initial_tz; | ||
| 2079 | |||
| 2080 | DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0, | 2088 | DEFUN ("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. |
| 2082 | If TZ is nil, use implementation-defined default time zone information. | 2090 | If 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 | |||
| 2131 | static char set_time_zone_rule_tz1[] = "TZ=GMT+0"; | ||
| 2132 | static 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 | ||
| 2140 | void | 2125 | void |
| 2141 | set_time_zone_rule (const char *tzstring) | 2126 | set_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. */) | |||
| 4800 | void | 4791 | void |
| 4801 | syms_of_editfns (void) | 4792 | syms_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. */ |
| 538 | static char dump_tz[] = "UtC0"; | 538 | static 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); | |||
| 3594 | extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); | 3594 | extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); |
| 3595 | 3595 | ||
| 3596 | extern char *xstrdup (const char *); | 3596 | extern char *xstrdup (const char *); |
| 3597 | extern void xputenv (const char *); | ||
| 3597 | 3598 | ||
| 3598 | extern char *egetenv (const char *); | 3599 | extern 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. */ |