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 /lib | |
| 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
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/gnulib.mk | 20 | ||||
| -rw-r--r-- | lib/putenv.c | 134 | ||||
| -rw-r--r-- | lib/unsetenv.c | 127 |
3 files changed, 280 insertions, 1 deletions
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 */ | ||