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
This commit is contained in:
Paul Eggert 2012-12-08 09:19:51 -08:00
parent c56efa4074
commit 5745a7df2b
16 changed files with 661 additions and 125 deletions

View file

@ -1,3 +1,10 @@
2012-12-08 Paul Eggert <eggert@cs.ucla.edu>
Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
* 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.
2012-12-08 Eli Zaretskii <eliz@gnu.org>
* lib/makefile.w32-in ($(BLD)/sig2str.$(O)): New dependency.

View file

@ -1,5 +1,8 @@
2012-12-08 Paul Eggert <eggert@cs.ucla.edu>
Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
* merge-gnulib (GNULIB_MODULES): Add putenv, unsetenv.
Simplify get_lim_data.
* CPP-DEFINES (ULIMIT_BREAK_VALUE): Remove.

View file

@ -31,10 +31,10 @@ GNULIB_MODULES='
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
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 utimens
sys_time time timer-time timespec-add timespec-sub unsetenv utimens
warnings
'

View file

@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
# 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
# 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
MOSTLYCLEANFILES += core *.stackdump
@ -439,6 +439,15 @@ EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
## end gnulib module pthread_sigmask
## begin gnulib module putenv
EXTRA_DIST += putenv.c
EXTRA_libgnu_a_SOURCES += putenv.c
## end gnulib module putenv
## begin gnulib module readlink
@ -1409,6 +1418,15 @@ EXTRA_DIST += unistd.in.h
## end gnulib module unistd
## begin gnulib module unsetenv
EXTRA_DIST += unsetenv.c
EXTRA_libgnu_a_SOURCES += unsetenv.c
## end gnulib module unsetenv
## begin gnulib module utimens
libgnu_a_SOURCES += utimens.c

134
lib/putenv.c Normal file
View file

@ -0,0 +1,134 @@
/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2012 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <stdlib.h>
#include <stddef.h>
/* Include errno.h *after* sys/types.h to work around header problems
on AIX 3.2.5. */
#include <errno.h>
#ifndef __set_errno
# define __set_errno(ev) ((errno) = (ev))
#endif
#include <string.h>
#include <unistd.h>
#if _LIBC
# if HAVE_GNU_LD
# define environ __environ
# else
extern char **environ;
# endif
#endif
#if _LIBC
/* This lock protects against simultaneous modifications of 'environ'. */
# include <bits/libc-lock.h>
__libc_lock_define_initialized (static, envlock)
# define LOCK __libc_lock_lock (envlock)
# define UNLOCK __libc_lock_unlock (envlock)
#else
# define LOCK
# define UNLOCK
#endif
static int
_unsetenv (const char *name)
{
size_t len;
char **ep;
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
__set_errno (EINVAL);
return -1;
}
len = strlen (name);
LOCK;
ep = environ;
while (*ep != NULL)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
}
else
++ep;
UNLOCK;
return 0;
}
/* Put STRING, which is of the form "NAME=VALUE", in the environment.
If STRING contains no '=', then remove STRING from the environment. */
int
putenv (char *string)
{
const char *const name_end = strchr (string, '=');
register size_t size;
register char **ep;
if (name_end == NULL)
{
/* Remove the variable from the environment. */
return _unsetenv (string);
}
size = 0;
for (ep = environ; *ep != NULL; ++ep)
if (!strncmp (*ep, string, name_end - string) &&
(*ep)[name_end - string] == '=')
break;
else
++size;
if (*ep == NULL)
{
static char **last_environ = NULL;
char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
if (new_environ == NULL)
return -1;
(void) memcpy ((void *) new_environ, (void *) environ,
size * sizeof (char *));
new_environ[size] = (char *) string;
new_environ[size + 1] = NULL;
free (last_environ);
last_environ = new_environ;
environ = new_environ;
}
else
*ep = string;
return 0;
}

127
lib/unsetenv.c Normal file
View file

@ -0,0 +1,127 @@
/* Copyright (C) 1992, 1995-2002, 2005-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the name == NULL test below. */
#define _GL_ARG_NONNULL(params)
/* Specification. */
#include <stdlib.h>
#include <errno.h>
#if !_LIBC
# define __set_errno(ev) ((errno) = (ev))
#endif
#include <string.h>
#include <unistd.h>
#if !_LIBC
# define __environ environ
#endif
#if _LIBC
/* This lock protects against simultaneous modifications of 'environ'. */
# include <bits/libc-lock.h>
__libc_lock_define_initialized (static, envlock)
# define LOCK __libc_lock_lock (envlock)
# define UNLOCK __libc_lock_unlock (envlock)
#else
# define LOCK
# define UNLOCK
#endif
/* In the GNU C library we must keep the namespace clean. */
#ifdef _LIBC
# define unsetenv __unsetenv
#endif
#if _LIBC || !HAVE_UNSETENV
int
unsetenv (const char *name)
{
size_t len;
char **ep;
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
__set_errno (EINVAL);
return -1;
}
len = strlen (name);
LOCK;
ep = __environ;
while (*ep != NULL)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
}
else
++ep;
UNLOCK;
return 0;
}
#ifdef _LIBC
# undef unsetenv
weak_alias (__unsetenv, unsetenv)
#endif
#else /* HAVE_UNSETENV */
# undef unsetenv
# if !HAVE_DECL_UNSETENV
# if VOID_UNSETENV
extern void unsetenv (const char *);
# else
extern int unsetenv (const char *);
# endif
# endif
/* Call the underlying unsetenv, in case there is hidden bookkeeping
that needs updating beyond just modifying environ. */
int
rpl_unsetenv (const char *name)
{
int result = 0;
if (!name || !*name || strchr (name, '='))
{
errno = EINVAL;
return -1;
}
while (getenv (name))
# if !VOID_UNSETENV
result =
# endif
unsetenv (name);
return result;
}
#endif /* HAVE_UNSETENV */

View file

@ -85,6 +85,7 @@ AC_DEFUN([gl_EARLY],
# Code from module pathmax:
# Code from module pselect:
# Code from module pthread_sigmask:
# Code from module putenv:
# Code from module readlink:
# Code from module root-uid:
# Code from module sig2str:
@ -126,6 +127,7 @@ AC_DEFUN([gl_EARLY],
# Code from module timespec-sub:
# Code from module u64:
# Code from module unistd:
# Code from module unsetenv:
# Code from module utimens:
# Code from module verify:
# Code from module warnings:
@ -240,6 +242,11 @@ AC_DEFUN([gl_INIT],
gl_PREREQ_PTHREAD_SIGMASK
fi
gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask])
gl_FUNC_PUTENV
if test $REPLACE_PUTENV = 1; then
AC_LIBOBJ([putenv])
fi
gl_STDLIB_MODULE_INDICATOR([putenv])
gl_FUNC_READLINK
if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
AC_LIBOBJ([readlink])
@ -297,6 +304,12 @@ AC_DEFUN([gl_INIT],
gl_TIMER_TIME
gl_TIMESPEC
gl_UNISTD_H
gl_FUNC_UNSETENV
if test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1; then
AC_LIBOBJ([unsetenv])
gl_PREREQ_UNSETENV
fi
gl_STDLIB_MODULE_INDICATOR([unsetenv])
gl_UTIMENS
gl_gnulib_enabled_dosname=false
gl_gnulib_enabled_euidaccess=false
@ -679,6 +692,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/pathmax.h
lib/pselect.c
lib/pthread_sigmask.c
lib/putenv.c
lib/readlink.c
lib/root-uid.h
lib/sha1.c
@ -723,6 +737,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/u64.h
lib/unistd.c
lib/unistd.in.h
lib/unsetenv.c
lib/utimens.c
lib/utimens.h
lib/verify.h
@ -764,7 +779,9 @@ AC_DEFUN([gl_FILE_LIST], [
m4/pathmax.m4
m4/pselect.m4
m4/pthread_sigmask.m4
m4/putenv.m4
m4/readlink.m4
m4/setenv.m4
m4/sha1.m4
m4/sha256.m4
m4/sha512.m4

50
m4/putenv.m4 Normal file
View file

@ -0,0 +1,50 @@
# putenv.m4 serial 19
dnl Copyright (C) 2002-2012 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Jim Meyering.
dnl
dnl Check whether putenv ("FOO") removes FOO from the environment.
dnl The putenv in libc on at least SunOS 4.1.4 does *not* do that.
AC_DEFUN([gl_FUNC_PUTENV],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
AC_CACHE_CHECK([for putenv compatible with GNU and SVID],
[gl_cv_func_svid_putenv],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],[[
/* Put it in env. */
if (putenv ("CONFTEST_putenv=val"))
return 1;
/* Try to remove it. */
if (putenv ("CONFTEST_putenv"))
return 2;
/* Make sure it was deleted. */
if (getenv ("CONFTEST_putenv") != 0)
return 3;
return 0;
]])],
gl_cv_func_svid_putenv=yes,
gl_cv_func_svid_putenv=no,
dnl When crosscompiling, assume putenv is broken.
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu*) gl_cv_func_svid_putenv="guessing yes" ;;
# If we don't know, assume the worst.
*) gl_cv_func_svid_putenv="guessing no" ;;
esac
])
])
case "$gl_cv_func_svid_putenv" in
*yes) ;;
*)
REPLACE_PUTENV=1
;;
esac
])

160
m4/setenv.m4 Normal file
View file

@ -0,0 +1,160 @@
# setenv.m4 serial 26
dnl Copyright (C) 2001-2004, 2006-2012 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_SETENV],
[
AC_REQUIRE([gl_FUNC_SETENV_SEPARATE])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
if test $ac_cv_func_setenv = no; then
HAVE_SETENV=0
else
AC_CACHE_CHECK([whether setenv validates arguments],
[gl_cv_func_setenv_works],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <errno.h>
#include <string.h>
]], [[
int result = 0;
{
if (setenv ("", "", 0) != -1)
result |= 1;
else if (errno != EINVAL)
result |= 2;
}
{
if (setenv ("a", "=", 1) != 0)
result |= 4;
else if (strcmp (getenv ("a"), "=") != 0)
result |= 8;
}
return result;
]])],
[gl_cv_func_setenv_works=yes], [gl_cv_func_setenv_works=no],
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu*) gl_cv_func_setenv_works="guessing yes" ;;
# If we don't know, assume the worst.
*) gl_cv_func_setenv_works="guessing no" ;;
esac
])])
case "$gl_cv_func_setenv_works" in
*yes) ;;
*)
REPLACE_SETENV=1
;;
esac
fi
])
# Like gl_FUNC_SETENV, except prepare for separate compilation
# (no REPLACE_SETENV, no AC_LIBOBJ).
AC_DEFUN([gl_FUNC_SETENV_SEPARATE],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_CHECK_DECLS_ONCE([setenv])
if test $ac_cv_have_decl_setenv = no; then
HAVE_DECL_SETENV=0
fi
AC_CHECK_FUNCS_ONCE([setenv])
gl_PREREQ_SETENV
])
AC_DEFUN([gl_FUNC_UNSETENV],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
AC_CHECK_DECLS_ONCE([unsetenv])
if test $ac_cv_have_decl_unsetenv = no; then
HAVE_DECL_UNSETENV=0
fi
AC_CHECK_FUNCS([unsetenv])
if test $ac_cv_func_unsetenv = no; then
HAVE_UNSETENV=0
else
HAVE_UNSETENV=1
dnl Some BSDs return void, failing to do error checking.
AC_CACHE_CHECK([for unsetenv() return type], [gt_cv_func_unsetenv_ret],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[
#undef _BSD
#define _BSD 1 /* unhide unsetenv declaration in OSF/1 5.1 <stdlib.h> */
#include <stdlib.h>
extern
#ifdef __cplusplus
"C"
#endif
int unsetenv (const char *name);
]],
[[]])],
[gt_cv_func_unsetenv_ret='int'],
[gt_cv_func_unsetenv_ret='void'])])
if test $gt_cv_func_unsetenv_ret = 'void'; then
AC_DEFINE([VOID_UNSETENV], [1], [Define to 1 if unsetenv returns void
instead of int.])
REPLACE_UNSETENV=1
fi
dnl Solaris 10 unsetenv does not remove all copies of a name.
dnl Haiku alpha 2 unsetenv gets confused by assignment to environ.
dnl OpenBSD 4.7 unsetenv("") does not fail.
AC_CACHE_CHECK([whether unsetenv obeys POSIX],
[gl_cv_func_unsetenv_works],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <errno.h>
extern char **environ;
]], [[
char entry1[] = "a=1";
char entry2[] = "b=2";
char *env[] = { entry1, entry2, NULL };
if (putenv ((char *) "a=1")) return 1;
if (putenv (entry2)) return 2;
entry2[0] = 'a';
unsetenv ("a");
if (getenv ("a")) return 3;
if (!unsetenv ("") || errno != EINVAL) return 4;
entry2[0] = 'b';
environ = env;
if (!getenv ("a")) return 5;
entry2[0] = 'a';
unsetenv ("a");
if (getenv ("a")) return 6;
]])],
[gl_cv_func_unsetenv_works=yes], [gl_cv_func_unsetenv_works=no],
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu*) gl_cv_func_unsetenv_works="guessing yes" ;;
# If we don't know, assume the worst.
*) gl_cv_func_unsetenv_works="guessing no" ;;
esac
])])
case "$gl_cv_func_unsetenv_works" in
*yes) ;;
*)
REPLACE_UNSETENV=1
;;
esac
fi
])
# Prerequisites of lib/setenv.c.
AC_DEFUN([gl_PREREQ_SETENV],
[
AC_REQUIRE([AC_FUNC_ALLOCA])
AC_REQUIRE([gl_ENVIRON])
AC_CHECK_HEADERS_ONCE([unistd.h])
AC_CHECK_HEADERS([search.h])
AC_CHECK_FUNCS([tsearch])
])
# Prerequisites of lib/unsetenv.c.
AC_DEFUN([gl_PREREQ_UNSETENV],
[
AC_REQUIRE([gl_ENVIRON])
AC_CHECK_HEADERS_ONCE([unistd.h])
])

View file

@ -1,3 +1,29 @@
2012-12-08 Paul Eggert <eggert@cs.ucla.edu>
Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
* alloc.c (xputenv): New function.
* dbusbind.c (Fdbus_init_bus):
* emacs.c (main):
* xterm.c (x_term_init):
Use xputenv instead of setenv or putenv, to detect memory exhaustion.
* 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.
* emacs.c (dump_tz) [HAVE_TZSET]: Now const.
* lisp.h (xputenv): New decl.
2012-12-08 Fabrice Popineau <fabrice.popineau@gmail.com>
* w32fns.c (emacs_abort): Don't do arithmetics on void pointers.

View file

@ -820,6 +820,15 @@ xstrdup (const char *s)
return p;
}
/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
argument is a const pointer. */
void
xputenv (char const *string)
{
if (putenv ((char *) string) != 0)
memory_full (0);
}
/* Unwind for SAFE_ALLOCA */

View file

@ -1203,7 +1203,7 @@ this connection to those buses. */)
xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses);
/* We do not want to abort. */
putenv ((char *) "DBUS_FATAL_WARNINGS=0");
xputenv ("DBUS_FATAL_WARNINGS=0");
/* Cleanup. */
dbus_error_free (&derror);

View file

@ -78,6 +78,15 @@ Lisp_Object Qfield;
static Lisp_Object Qboundary;
/* The startup value of the TZ environment variable so it can be
restored if the user calls set-time-zone-rule with a nil
argument. If null, the TZ environment variable was unset. */
static char const *initial_tz;
/* True if the static variable tzvalbuf (defined in
set_time_zone_rule) is part of 'environ'. */
static bool tzvalbuf_in_environ;
void
init_editfns (void)
@ -96,6 +105,9 @@ init_editfns (void)
return;
#endif /* not CANNOT_DUMP */
initial_tz = getenv ("TZ");
tzvalbuf_in_environ = 0;
pw = getpwuid (getuid ());
#ifdef MSDOS
/* 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) */)
}
else
{
char tzbuf[100];
static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
char *old_tzstring;
const char *tzstring;
char **oldenv = environ, **newenv;
USE_SAFE_ALLOCA;
if (EQ (zone, Qt))
tzstring = "UTC0";
@ -1914,13 +1928,20 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
EMACS_INT zone_hr = abszone / (60*60);
int zone_min = (abszone/60) % 60;
int zone_sec = abszone % 60;
sprintf (tzbuf, "XXX%s%"pI"d:%02d:%02d", "-" + (XINT (zone) < 0),
sprintf (tzbuf, tzbuf_format, "-" + (XINT (zone) < 0),
zone_hr, zone_min, zone_sec);
tzstring = tzbuf;
}
else
error ("Invalid time zone specification");
old_tzstring = getenv ("TZ");
if (old_tzstring)
{
char *buf = SAFE_ALLOCA (strlen (old_tzstring) + 1);
old_tzstring = strcpy (buf, old_tzstring);
}
block_input ();
/* 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) */)
value = mktime (&tm);
/* Restore TZ to previous value. */
newenv = environ;
environ = oldenv;
set_time_zone_rule (old_tzstring);
#ifdef LOCALTIME_CACHE
tzset ();
#endif
unblock_input ();
xfree (newenv);
SAFE_FREE ();
}
if (value == (time_t) -1)
@ -2067,16 +2085,6 @@ the data it can't find. */)
return list2 (zone_offset, zone_name);
}
/* This holds the value of `environ' produced by the previous
call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
has never been called. */
static char **environbuf;
/* This holds the startup value of the TZ environment variable so it
can be restored if the user calls set-time-zone-rule with a nil
argument. */
static char *initial_tz;
DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
If TZ is nil, use implementation-defined default time zone information.
@ -2089,18 +2097,10 @@ only the former. */)
(Lisp_Object tz)
{
const char *tzstring;
char **old_environbuf;
if (! (NILP (tz) || EQ (tz, Qt)))
CHECK_STRING (tz);
block_input ();
/* When called for the first time, save the original TZ. */
old_environbuf = environbuf;
if (!old_environbuf)
initial_tz = (char *) getenv ("TZ");
if (NILP (tz))
tzstring = initial_tz;
else if (EQ (tz, Qt))
@ -2108,106 +2108,97 @@ only the former. */)
else
tzstring = SSDATA (tz);
block_input ();
set_time_zone_rule (tzstring);
environbuf = environ;
unblock_input ();
xfree (old_environbuf);
return Qnil;
}
#ifdef LOCALTIME_CACHE
/* These two values are known to load tz files in buggy implementations,
i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
Their values shouldn't matter in non-buggy implementations.
We don't use string literals for these strings,
since if a string in the environment is in readonly
storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
See Sun bugs 1113095 and 1114114, ``Timezone routines
improperly modify environment''. */
static char set_time_zone_rule_tz1[] = "TZ=GMT+0";
static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
#endif
/* Set the local time zone rule to TZSTRING.
This allocates memory into `environ', which it is the caller's
responsibility to free. */
This function is not thread-safe, partly because putenv, unsetenv
and tzset are not, and partly because of the static storage it
updates. Other threads that invoke localtime etc. may be adversely
affected while this function is executing. */
void
set_time_zone_rule (const char *tzstring)
{
ptrdiff_t envptrs;
char **from, **to, **newenv;
/* A buffer holding a string of the form "TZ=value", intended
to be part of the environment. */
static char *tzvalbuf;
static ptrdiff_t tzvalbufsize;
/* Make the ENVIRON vector longer with room for TZSTRING. */
for (from = environ; *from; from++)
continue;
envptrs = from - environ + 2;
newenv = to = xmalloc (envptrs * sizeof *newenv
+ (tzstring ? strlen (tzstring) + 4 : 0));
/* Add TZSTRING to the end of environ, as a value for TZ. */
if (tzstring)
{
char *t = (char *) (to + envptrs);
strcpy (t, "TZ=");
strcat (t, tzstring);
*to++ = t;
}
/* Copy the old environ vector elements into NEWENV,
but don't copy the TZ variable.
So we have only one definition of TZ, which came from TZSTRING. */
for (from = environ; *from; from++)
if (strncmp (*from, "TZ=", 3) != 0)
*to++ = *from;
*to = 0;
environ = newenv;
/* If we do have a TZSTRING, NEWENV points to the vector slot where
the TZ variable is stored. If we do not have a TZSTRING,
TO points to the vector slot which has the terminating null. */
int tzeqlen = sizeof "TZ=" - 1;
#ifdef LOCALTIME_CACHE
{
/* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
"US/Pacific" that loads a tz file, then changes to a value like
"XXX0" that does not load a tz file, and then changes back to
its original value, the last change is (incorrectly) ignored.
Also, if TZ changes twice in succession to values that do
not load a tz file, tzset can dump core (see Sun bug#1225179).
The following code works around these bugs. */
/* These two values are known to load tz files in buggy implementations,
i.e., Solaris 1 executables running under either Solaris 1 or Solaris 2.
Their values shouldn't matter in non-buggy implementations.
We don't use string literals for these strings,
since if a string in the environment is in readonly
storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
See Sun bugs 1113095 and 1114114, ``Timezone routines
improperly modify environment''. */
if (tzstring)
{
/* Temporarily set TZ to a value that loads a tz file
and that differs from tzstring. */
char *tz = *newenv;
*newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
tzset ();
*newenv = tz;
}
else
{
/* The implied tzstring is unknown, so temporarily set TZ to
two different values that each load a tz file. */
*to = set_time_zone_rule_tz1;
to[1] = 0;
tzset ();
*to = set_time_zone_rule_tz2;
tzset ();
*to = 0;
}
static char set_time_zone_rule_tz[][sizeof "TZ=GMT+0"]
= { "TZ=GMT+0", "TZ=GMT+1" };
/* Now TZ has the desired value, and tzset can be invoked safely. */
}
/* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
"US/Pacific" that loads a tz file, then changes to a value like
"XXX0" that does not load a tz file, and then changes back to
its original value, the last change is (incorrectly) ignored.
Also, if TZ changes twice in succession to values that do
not load a tz file, tzset can dump core (see Sun bug#1225179).
The following code works around these bugs. */
if (tzstring)
{
/* Temporarily set TZ to a value that loads a tz file
and that differs from tzstring. */
bool eq0 = strcmp (tzstring, set_time_zone_rule_tz[0] + tzeqlen) == 0;
xputenv (set_time_zone_rule_tz[eq0]);
}
else
{
/* The implied tzstring is unknown, so temporarily set TZ to
two different values that each load a tz file. */
xputenv (set_time_zone_rule_tz[0]);
tzset ();
xputenv (set_time_zone_rule_tz[1]);
}
tzset ();
#endif
if (!tzstring)
{
unsetenv ("TZ");
tzvalbuf_in_environ = 0;
}
else
{
ptrdiff_t tzstringlen = strlen (tzstring);
if (tzvalbufsize <= tzeqlen + tzstringlen)
{
unsetenv ("TZ");
tzvalbuf_in_environ = 0;
tzvalbuf = xpalloc (tzvalbuf, &tzvalbufsize,
tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1);
memcpy (tzvalbuf, "TZ=", tzeqlen);
}
strcpy (tzvalbuf + tzeqlen, tzstring);
if (!tzvalbuf_in_environ)
{
xputenv (tzvalbuf);
tzvalbuf_in_environ = 1;
}
}
#ifdef LOCALTIME_CACHE
tzset ();
#endif
}
@ -4800,9 +4791,6 @@ Transposing beyond buffer boundaries is an error. */)
void
syms_of_editfns (void)
{
environbuf = 0;
initial_tz = 0;
DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,

View file

@ -535,7 +535,7 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
#ifdef HAVE_TZSET
/* A valid but unlikely value for the TZ environment value.
It is OK (though a bit slower) if the user actually chooses this value. */
static char dump_tz[] = "UtC0";
static char const dump_tz[] = "UtC0";
#endif
#ifndef ORDINARY_LINK
@ -717,7 +717,7 @@ main (int argc, char **argv)
#ifdef G_SLICE_ALWAYS_MALLOC
/* This is used by the Cygwin build. */
setenv ("G_SLICE", "always-malloc", 1);
xputenv ("G_SLICE=always-malloc");
#endif
#ifdef GNU_LINUX
@ -803,9 +803,8 @@ main (int argc, char **argv)
#ifdef HAVE_PERSONALITY_LINUX32
if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
{
static char heapexec[] = "EMACS_HEAP_EXEC=true";
/* Set this so we only do this once. */
putenv (heapexec);
xputenv ("EMACS_HEAP_EXEC=true");
/* A flag to turn off address randomization which is introduced
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
don't pollute Vglobal_environment. */
/* Setting LANG here will defeat the startup locale processing... */
#ifdef AIX
putenv ("LANG=C");
xputenv ("LANG=C");
#endif
init_buffer (); /* Init default directory of main buffer. */

View file

@ -3594,6 +3594,7 @@ extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t);
extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t);
extern char *xstrdup (const char *);
extern void xputenv (const char *);
extern char *egetenv (const char *);

View file

@ -9908,10 +9908,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* Emacs can only handle core input events, so make sure
Gtk doesn't use Xinput or Xinput2 extensions. */
{
static char fix_events[] = "GDK_CORE_DEVICE_EVENTS=1";
putenv (fix_events);
}
xputenv ("GDK_CORE_DEVICE_EVENTS=1");
/* Work around GLib bug that outputs a faulty warning. See
https://bugzilla.gnome.org/show_bug.cgi?id=563627. */