Added unsetenv and setenv from gnulib

This commit is contained in:
Ton Voon 2010-06-24 10:02:31 +01:00
parent f789a37b05
commit 342f3b403e
12 changed files with 1039 additions and 2 deletions

View file

@ -9,7 +9,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=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex strsep timegm vasprintf vsnprintf
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
AUTOMAKE_OPTIONS = 1.5 gnits
@ -678,6 +678,14 @@ EXTRA_libgnu_a_SOURCES += malloc.c
## end gnulib module malloc-posix
## begin gnulib module malloca
libgnu_a_SOURCES += malloca.c
EXTRA_DIST += malloca.h malloca.valgrind
## end gnulib module malloca
## begin gnulib module math
BUILT_SOURCES += math.h
@ -928,6 +936,15 @@ EXTRA_libgnu_a_SOURCES += safe-write.c
## end gnulib module safe-write
## begin gnulib module setenv
EXTRA_DIST += setenv.c
EXTRA_libgnu_a_SOURCES += setenv.c
## end gnulib module setenv
## begin gnulib module size_max
libgnu_a_SOURCES += size_max.h
@ -1683,6 +1700,15 @@ EXTRA_libgnu_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c
## end gnulib module unistd-safer
## begin gnulib module unsetenv
EXTRA_DIST += unsetenv.c
EXTRA_libgnu_a_SOURCES += unsetenv.c
## end gnulib module unsetenv
## begin gnulib module vasnprintf

32
gl/m4/eealloc.m4 Normal file
View file

@ -0,0 +1,32 @@
# eealloc.m4 serial 2
dnl Copyright (C) 2003, 2009, 2010 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_EEALLOC],
[
AC_REQUIRE([gl_EEMALLOC])
AC_REQUIRE([gl_EEREALLOC])
AC_REQUIRE([AC_C_INLINE])
])
AC_DEFUN([gl_EEMALLOC],
[
_AC_FUNC_MALLOC_IF(
[gl_cv_func_malloc_0_nonnull=1],
[gl_cv_func_malloc_0_nonnull=0])
AC_DEFINE_UNQUOTED([MALLOC_0_IS_NONNULL], [$gl_cv_func_malloc_0_nonnull],
[If malloc(0) is != NULL, define this to 1. Otherwise define this
to 0.])
])
AC_DEFUN([gl_EEREALLOC],
[
_AC_FUNC_REALLOC_IF(
[gl_cv_func_realloc_0_nonnull=1],
[gl_cv_func_realloc_0_nonnull=0])
AC_DEFINE_UNQUOTED([REALLOC_0_IS_NONNULL], [$gl_cv_func_realloc_0_nonnull],
[If realloc(NULL,0) is != NULL, define this to 1. Otherwise define this
to 0.])
])

36
gl/m4/environ.m4 Normal file
View file

@ -0,0 +1,36 @@
# environ.m4 serial 4
dnl Copyright (C) 2001-2004, 2006-2010 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_ONCE([gl_ENVIRON],
[
AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
dnl Persuade glibc <unistd.h> to declare environ.
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
gt_CHECK_VAR_DECL([#include <unistd.h>], environ)
if test $gt_cv_var_environ_declaration != yes; then
HAVE_DECL_ENVIRON=0
fi
])
# Check if a variable is properly declared.
# gt_CHECK_VAR_DECL(includes,variable)
AC_DEFUN([gt_CHECK_VAR_DECL],
[
define([gt_cv_var], [gt_cv_var_]$2[_declaration])
AC_MSG_CHECKING([if $2 is properly declared])
AC_CACHE_VAL([gt_cv_var], [
AC_TRY_COMPILE([$1
extern struct { int foo; } $2;],
[$2.foo = 1;],
gt_cv_var=no,
gt_cv_var=yes)])
AC_MSG_RESULT([$gt_cv_var])
if test $gt_cv_var = yes; then
AC_DEFINE([HAVE_]m4_translit($2, [a-z], [A-Z])[_DECL], 1,
[Define if you have the declaration of $2.])
fi
undefine([gt_cv_var])
])

View file

@ -15,7 +15,7 @@
# Specification in the form of a command-line invocation:
# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex strsep timegm vasprintf vsnprintf
# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex setenv strsep timegm unsetenv vasprintf vsnprintf
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([])
@ -32,8 +32,10 @@ gl_MODULES([
gettext
mountlist
regex
setenv
strsep
timegm
unsetenv
vasprintf
vsnprintf
])

View file

@ -41,6 +41,7 @@ AC_DEFUN([gl_EARLY],
# Code from module dirname-lgpl:
# Code from module double-slash-root:
# Code from module dup2:
# Code from module environ:
# Code from module errno:
# Code from module error:
# Code from module exitfail:
@ -74,6 +75,7 @@ AC_DEFUN([gl_EARLY],
# Code from module locale:
# Code from module malloc:
# Code from module malloc-posix:
# Code from module malloca:
# Code from module math:
# Code from module mbrtowc:
# Code from module mbsinit:
@ -89,6 +91,7 @@ AC_DEFUN([gl_EARLY],
# Code from module safe-read:
# Code from module safe-write:
# Code from module servent:
# Code from module setenv:
# Code from module size_max:
# Code from module snprintf:
# Code from module sockets:
@ -115,6 +118,7 @@ AC_DEFUN([gl_EARLY],
# Code from module timegm:
# Code from module unistd:
# Code from module unistd-safer:
# Code from module unsetenv:
# Code from module vasnprintf:
# Code from module vasprintf:
# Code from module verify:
@ -178,6 +182,9 @@ AC_DEFUN([gl_INIT],
# Code from module dup2:
gl_FUNC_DUP2
gl_UNISTD_MODULE_INDICATOR([dup2])
# Code from module environ:
gl_ENVIRON
gl_UNISTD_MODULE_INDICATOR([environ])
# Code from module errno:
gl_HEADER_ERRNO_H
# Code from module error:
@ -252,6 +259,8 @@ AC_DEFUN([gl_INIT],
# Code from module malloc-posix:
gl_FUNC_MALLOC_POSIX
gl_STDLIB_MODULE_INDICATOR([malloc-posix])
# Code from module malloca:
gl_MALLOCA
# Code from module math:
gl_MATH_H
# Code from module mbrtowc:
@ -289,6 +298,9 @@ AC_DEFUN([gl_INIT],
gl_SAFE_WRITE
# Code from module servent:
gl_SERVENT
# Code from module setenv:
gl_FUNC_SETENV
gl_STDLIB_MODULE_INDICATOR([setenv])
# Code from module size_max:
gl_SIZE_MAX
# Code from module snprintf:
@ -352,6 +364,9 @@ AC_DEFUN([gl_INIT],
gl_UNISTD_H
# Code from module unistd-safer:
gl_UNISTD_SAFER
# Code from module unsetenv:
gl_FUNC_UNSETENV
gl_STDLIB_MODULE_INDICATOR([unsetenv])
# Code from module vasnprintf:
gl_FUNC_VASNPRINTF
# Code from module vasprintf:
@ -586,6 +601,9 @@ AC_DEFUN([gl_FILE_LIST], [
lib/localcharset.h
lib/locale.in.h
lib/malloc.c
lib/malloca.c
lib/malloca.h
lib/malloca.valgrind
lib/math.in.h
lib/mbrtowc.c
lib/mbsinit.c
@ -617,6 +635,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/safe-read.h
lib/safe-write.c
lib/safe-write.h
lib/setenv.c
lib/sha1.c
lib/sha1.h
lib/size_max.h
@ -648,6 +667,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/unistd--.h
lib/unistd-safer.h
lib/unistd.in.h
lib/unsetenv.c
lib/vasnprintf.c
lib/vasnprintf.h
lib/vasprintf.c
@ -677,6 +697,8 @@ AC_DEFUN([gl_FILE_LIST], [
m4/dos.m4
m4/double-slash-root.m4
m4/dup2.m4
m4/eealloc.m4
m4/environ.m4
m4/errno_h.m4
m4/error.m4
m4/extensions.m4
@ -724,6 +746,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/longlong.m4
m4/ls-mntd-fs.m4
m4/malloc.m4
m4/malloca.m4
m4/math_h.m4
m4/mbrtowc.m4
m4/mbsinit.m4
@ -748,6 +771,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/safe-read.m4
m4/safe-write.m4
m4/servent.m4
m4/setenv.m4
m4/sha1.m4
m4/size_max.m4
m4/snprintf.m4

15
gl/m4/malloca.m4 Normal file
View file

@ -0,0 +1,15 @@
# malloca.m4 serial 1
dnl Copyright (C) 2003-2004, 2006-2007, 2009-2010 Free Software Foundation,
dnl 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_MALLOCA],
[
dnl Use the autoconf tests for alloca(), but not the AC_SUBSTed variables
dnl @ALLOCA@ and @LTALLOCA@.
dnl gl_FUNC_ALLOCA dnl Already brought in by the module dependencies.
AC_REQUIRE([gl_EEMALLOC])
AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
])

111
gl/m4/setenv.m4 Normal file
View file

@ -0,0 +1,111 @@
# setenv.m4 serial 16
dnl Copyright (C) 2001-2004, 2006-2010 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])
if test $HAVE_SETENV$REPLACE_SETENV != 10; then
AC_LIBOBJ([setenv])
fi
])
# Like gl_FUNC_SETENV, except prepare for separate compilation (no AC_LIBOBJ).
AC_DEFUN([gl_FUNC_SETENV_SEPARATE],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_CHECK_FUNCS_ONCE([setenv])
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>
]], [[
if (setenv ("", "", 0) != -1) return 1;
if (errno != EINVAL) return 2;
if (setenv ("a", "=", 1) != 0) return 3;
if (strcmp (getenv ("a"), "=") != 0) return 4;
]])],
[gl_cv_func_setenv_works=yes], [gl_cv_func_setenv_works=no],
[gl_cv_func_setenv_works="guessing no"])])
if test "$gl_cv_func_setenv_works" != yes; then
REPLACE_SETENV=1
AC_LIBOBJ([setenv])
fi
fi
gl_PREREQ_SETENV
])
AC_DEFUN([gl_FUNC_UNSETENV],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_CHECK_FUNCS([unsetenv])
if test $ac_cv_func_unsetenv = no; then
HAVE_UNSETENV=0
AC_LIBOBJ([unsetenv])
gl_PREREQ_UNSETENV
else
dnl Some BSDs return void, failing to do error checking.
AC_CACHE_CHECK([for unsetenv() return type], [gt_cv_func_unsetenv_ret],
[AC_TRY_COMPILE([#include <stdlib.h>
extern
#ifdef __cplusplus
"C"
#endif
#if defined(__STDC__) || defined(__cplusplus)
int unsetenv (const char *name);
#else
int unsetenv();
#endif
], , 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
AC_LIBOBJ([unsetenv])
fi
dnl Solaris 10 unsetenv does not remove all copies of a name.
AC_CACHE_CHECK([whether unsetenv works on duplicates],
[gl_cv_func_unsetenv_works],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
]], [[
char entry[] = "b=2";
if (putenv ((char *) "a=1")) return 1;
if (putenv (entry)) return 2;
entry[0] = 'a';
unsetenv ("a");
if (getenv ("a")) return 3;
]])],
[gl_cv_func_unsetenv_works=yes], [gl_cv_func_unsetenv_works=no],
[gl_cv_func_unsetenv_works="guessing no"])])
if test "$gl_cv_func_unsetenv_works" != yes; then
REPLACE_UNSETENV=1
AC_LIBOBJ([unsetenv])
fi
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])
])

140
gl/malloca.c Normal file
View file

@ -0,0 +1,140 @@
/* Safe automatic memory allocation.
Copyright (C) 2003, 2006-2007, 2009-2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
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, 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, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <config.h>
/* Specification. */
#include "malloca.h"
/* Use the system functions, not the gnulib overrides in this file. */
#undef malloc
/* The speed critical point in this file is freea() applied to an alloca()
result: it must be fast, to match the speed of alloca(). The speed of
mmalloca() and freea() in the other case are not critical, because they
are only invoked for big memory sizes. */
#if HAVE_ALLOCA
/* Store the mmalloca() results in a hash table. This is needed to reliably
distinguish a mmalloca() result and an alloca() result.
Although it is possible that the same pointer is returned by alloca() and
by mmalloca() at different times in the same application, it does not lead
to a bug in freea(), because:
- Before a pointer returned by alloca() can point into malloc()ed memory,
the function must return, and once this has happened the programmer must
not call freea() on it anyway.
- Before a pointer returned by mmalloca() can point into the stack, it
must be freed. The only function that can free it is freea(), and
when freea() frees it, it also removes it from the hash table. */
#define MAGIC_NUMBER 0x1415fb4a
#define MAGIC_SIZE sizeof (int)
/* This is how the header info would look like without any alignment
considerations. */
struct preliminary_header { void *next; char room[MAGIC_SIZE]; };
/* But the header's size must be a multiple of sa_alignment_max. */
#define HEADER_SIZE \
(((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max)
struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; };
/* Verify that HEADER_SIZE == sizeof (struct header). */
typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1];
/* We make the hash table quite big, so that during lookups the probability
of empty hash buckets is quite high. There is no need to make the hash
table resizable, because when the hash table gets filled so much that the
lookup becomes slow, it means that the application has memory leaks. */
#define HASH_TABLE_SIZE 257
static void * mmalloca_results[HASH_TABLE_SIZE];
#endif
void *
mmalloca (size_t n)
{
#if HAVE_ALLOCA
/* Allocate one more word, that serves as an indicator for malloc()ed
memory, so that freea() of an alloca() result is fast. */
size_t nplus = n + HEADER_SIZE;
if (nplus >= n)
{
char *p = (char *) malloc (nplus);
if (p != NULL)
{
size_t slot;
p += HEADER_SIZE;
/* Put a magic number into the indicator word. */
((int *) p)[-1] = MAGIC_NUMBER;
/* Enter p into the hash table. */
slot = (unsigned long) p % HASH_TABLE_SIZE;
((struct header *) (p - HEADER_SIZE))->next = mmalloca_results[slot];
mmalloca_results[slot] = p;
return p;
}
}
/* Out of memory. */
return NULL;
#else
# if !MALLOC_0_IS_NONNULL
if (n == 0)
n = 1;
# endif
return malloc (n);
#endif
}
#if HAVE_ALLOCA
void
freea (void *p)
{
/* mmalloca() may have returned NULL. */
if (p != NULL)
{
/* Attempt to quickly distinguish the mmalloca() result - which has
a magic indicator word - and the alloca() result - which has an
uninitialized indicator word. It is for this test that sa_increment
additional bytes are allocated in the alloca() case. */
if (((int *) p)[-1] == MAGIC_NUMBER)
{
/* Looks like a mmalloca() result. To see whether it really is one,
perform a lookup in the hash table. */
size_t slot = (unsigned long) p % HASH_TABLE_SIZE;
void **chain = &mmalloca_results[slot];
for (; *chain != NULL;)
{
if (*chain == p)
{
/* Found it. Remove it from the hash table and free it. */
char *p_begin = (char *) p - HEADER_SIZE;
*chain = ((struct header *) p_begin)->next;
free (p_begin);
return;
}
chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next;
}
}
/* At this point, we know it was not a mmalloca() result. */
}
}
#endif

134
gl/malloca.h Normal file
View file

@ -0,0 +1,134 @@
/* Safe automatic memory allocation.
Copyright (C) 2003-2007, 2009-2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
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, 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, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _MALLOCA_H
#define _MALLOCA_H
#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
alloca(N); otherwise it returns NULL. It either returns N bytes of
memory allocated on the stack, that lasts until the function returns,
or NULL.
Use of safe_alloca should be avoided:
- inside arguments of function calls - undefined behaviour,
- in inline functions - the allocation may actually last until the
calling function returns.
*/
#if HAVE_ALLOCA
/* The OS usually guarantees only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
allocate anything larger than 4096 bytes. Also care for the possibility
of a few compiler-allocated temporary stack slots.
This must be a macro, not an inline function. */
# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
#else
# define safe_alloca(N) ((void) (N), NULL)
#endif
/* malloca(N) is a safe variant of alloca(N). It allocates N bytes of
memory allocated on the stack, that must be freed using freea() before
the function returns. Upon failure, it returns NULL. */
#if HAVE_ALLOCA
# define malloca(N) \
((N) < 4032 - sa_increment \
? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
: mmalloca (N))
#else
# define malloca(N) \
mmalloca (N)
#endif
extern void * mmalloca (size_t n);
/* Free a block of memory allocated through malloca(). */
#if HAVE_ALLOCA
extern void freea (void *p);
#else
# define freea free
#endif
/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
It allocates an array of N objects, each with S bytes of memory,
on the stack. S must be positive and N must be nonnegative.
The array must be freed using freea() before the function returns. */
#if 1
/* Cf. the definition of xalloc_oversized. */
# define nmalloca(n, s) \
((n) > (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) \
? NULL \
: malloca ((n) * (s)))
#else
extern void * nmalloca (size_t n, size_t s);
#endif
#ifdef __cplusplus
}
#endif
/* ------------------- Auxiliary, non-public definitions ------------------- */
/* Determine the alignment of a type at compile time. */
#if defined __GNUC__
# define sa_alignof __alignof__
#elif defined __cplusplus
template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
#elif defined __hpux
/* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
values. */
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
#elif defined _AIX
/* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof
values. */
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
#else
# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
#endif
enum
{
/* The desired alignment of memory allocations is the maximum alignment
among all elementary types. */
sa_alignment_long = sa_alignof (long),
sa_alignment_double = sa_alignof (double),
#if HAVE_LONG_LONG_INT
sa_alignment_longlong = sa_alignof (long long),
#endif
sa_alignment_longdouble = sa_alignof (long double),
sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
#if HAVE_LONG_LONG_INT
| (sa_alignment_longlong - 1)
#endif
| (sa_alignment_longdouble - 1)
) + 1,
/* The increment that guarantees room for a magic word must be >= sizeof (int)
and a multiple of sa_alignment_max. */
sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
};
#endif /* _MALLOCA_H */

7
gl/malloca.valgrind Normal file
View file

@ -0,0 +1,7 @@
# Suppress a valgrind message about use of uninitialized memory in freea().
# This use is OK because it provides only a speedup.
{
freea
Memcheck:Cond
fun:freea
}

390
gl/setenv.c Normal file
View file

@ -0,0 +1,390 @@
/* Copyright (C) 1992, 1995-2003, 2005-2010 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/>. */
#if !_LIBC
# include <config.h>
#endif
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the name == NULL test below. */
#define _GL_ARG_NONNULL(params)
#include <alloca.h>
/* Specification. */
#include <stdlib.h>
#include <errno.h>
#ifndef __set_errno
# define __set_errno(ev) ((errno) = (ev))
#endif
#include <string.h>
#if _LIBC || HAVE_UNISTD_H
# include <unistd.h>
#endif
#if !_LIBC
# include "malloca.h"
#endif
#if _LIBC || !HAVE_SETENV
#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 setenv __setenv
# define clearenv __clearenv
# define tfind __tfind
# define tsearch __tsearch
#else
/* Use the system functions, not the gnulib overrides in this file. */
# undef malloc
# undef realloc
#endif
/* In the GNU C library implementation we try to be more clever and
allow arbitrarily many changes of the environment given that the used
values are from a small set. Outside glibc this will eat up all
memory after a while. */
#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
&& defined __GNUC__)
# define USE_TSEARCH 1
# include <search.h>
typedef int (*compar_fn_t) (const void *, const void *);
/* This is a pointer to the root of the search tree with the known
values. */
static void *known_values;
# define KNOWN_VALUE(Str) \
({ \
void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \
value != NULL ? *(char **) value : NULL; \
})
# define STORE_VALUE(Str) \
tsearch (Str, &known_values, (compar_fn_t) strcmp)
#else
# undef USE_TSEARCH
# define KNOWN_VALUE(Str) NULL
# define STORE_VALUE(Str) do { } while (0)
#endif
/* If this variable is not a null pointer we allocated the current
environment. */
static char **last_environ;
/* This function is used by `setenv' and `putenv'. The difference between
the two functions is that for the former must create a new string which
is then placed in the environment, while the argument of `putenv'
must be used directly. This is all complicated by the fact that we try
to reuse values once generated for a `setenv' call since we can never
free the strings. */
int
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
char **ep;
size_t size;
const size_t namelen = strlen (name);
const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
LOCK;
/* We have to get the pointer now that we have the lock and not earlier
since another thread might have created a new environment. */
ep = __environ;
size = 0;
if (ep != NULL)
{
for (; *ep != NULL; ++ep)
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
break;
else
++size;
}
if (ep == NULL || *ep == NULL)
{
char **new_environ;
#ifdef USE_TSEARCH
char *new_value;
#endif
/* We allocated this space; we can extend it. */
new_environ =
(char **) (last_environ == NULL
? malloc ((size + 2) * sizeof (char *))
: realloc (last_environ, (size + 2) * sizeof (char *)));
if (new_environ == NULL)
{
/* It's easier to set errno to ENOMEM than to rely on the
'malloc-posix' and 'realloc-posix' gnulib modules. */
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
/* If the whole entry is given add it. */
if (combined != NULL)
/* We must not add the string to the search tree since it belongs
to the user. */
new_environ[size] = (char *) combined;
else
{
/* See whether the value is already known. */
#ifdef USE_TSEARCH
# ifdef _LIBC
new_value = (char *) alloca (namelen + 1 + vallen);
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen);
# else
new_value = (char *) malloca (namelen + 1 + vallen);
if (new_value == NULL)
{
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
# endif
new_environ[size] = KNOWN_VALUE (new_value);
if (new_environ[size] == NULL)
#endif
{
new_environ[size] = (char *) malloc (namelen + 1 + vallen);
if (new_environ[size] == NULL)
{
#if defined USE_TSEARCH && !defined _LIBC
freea (new_value);
#endif
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
#ifdef USE_TSEARCH
memcpy (new_environ[size], new_value, namelen + 1 + vallen);
#else
memcpy (new_environ[size], name, namelen);
new_environ[size][namelen] = '=';
memcpy (&new_environ[size][namelen + 1], value, vallen);
#endif
/* And save the value now. We cannot do this when we remove
the string since then we cannot decide whether it is a
user string or not. */
STORE_VALUE (new_environ[size]);
}
#if defined USE_TSEARCH && !defined _LIBC
freea (new_value);
#endif
}
if (__environ != last_environ)
memcpy ((char *) new_environ, (char *) __environ,
size * sizeof (char *));
new_environ[size + 1] = NULL;
last_environ = __environ = new_environ;
}
else if (replace)
{
char *np;
/* Use the user string if given. */
if (combined != NULL)
np = (char *) combined;
else
{
#ifdef USE_TSEARCH
char *new_value;
# ifdef _LIBC
new_value = alloca (namelen + 1 + vallen);
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen);
# else
new_value = malloca (namelen + 1 + vallen);
if (new_value == NULL)
{
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
# endif
np = KNOWN_VALUE (new_value);
if (np == NULL)
#endif
{
np = (char *) malloc (namelen + 1 + vallen);
if (np == NULL)
{
#if defined USE_TSEARCH && !defined _LIBC
freea (new_value);
#endif
__set_errno (ENOMEM);
UNLOCK;
return -1;
}
#ifdef USE_TSEARCH
memcpy (np, new_value, namelen + 1 + vallen);
#else
memcpy (np, name, namelen);
np[namelen] = '=';
memcpy (&np[namelen + 1], value, vallen);
#endif
/* And remember the value. */
STORE_VALUE (np);
}
#if defined USE_TSEARCH && !defined _LIBC
freea (new_value);
#endif
}
*ep = np;
}
UNLOCK;
return 0;
}
int
setenv (const char *name, const char *value, int replace)
{
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
__set_errno (EINVAL);
return -1;
}
return __add_to_environ (name, value, NULL, replace);
}
/* The `clearenv' was planned to be added to POSIX.1 but probably
never made it. Nevertheless the POSIX.9 standard (POSIX bindings
for Fortran 77) requires this function. */
int
clearenv (void)
{
LOCK;
if (__environ == last_environ && __environ != NULL)
{
/* We allocated this environment so we can free it. */
free (__environ);
last_environ = NULL;
}
/* Clear the environment pointer removes the whole environment. */
__environ = NULL;
UNLOCK;
return 0;
}
#ifdef _LIBC
static void
free_mem (void)
{
/* Remove all traces. */
clearenv ();
/* Now remove the search tree. */
__tdestroy (known_values, free);
known_values = NULL;
}
text_set_element (__libc_subfreeres, free_mem);
# undef setenv
# undef clearenv
weak_alias (__setenv, setenv)
weak_alias (__clearenv, clearenv)
#endif
#endif /* _LIBC || !HAVE_SETENV */
/* The rest of this file is called into use when replacing an existing
but buggy setenv. Known bugs include failure to diagnose invalid
name, and consuming a leading '=' from value. */
#if HAVE_SETENV
# undef setenv
# define STREQ(a, b) (strcmp (a, b) == 0)
int
rpl_setenv (const char *name, const char *value, int replace)
{
int result;
if (!name || !*name || strchr (name, '='))
{
errno = EINVAL;
return -1;
}
/* Call the real setenv even if replace is 0, in case implementation
has underlying data to update, such as when environ changes. */
result = setenv (name, value, replace);
if (result == 0 && replace && *value == '=')
{
char *tmp = getenv (name);
if (!STREQ (tmp, value))
{
int saved_errno;
size_t len = strlen (value);
tmp = malloca (len + 2);
/* Since leading '=' is eaten, double it up. */
*tmp = '=';
memcpy (tmp + 1, value, len + 1);
result = setenv (name, tmp, replace);
saved_errno = errno;
freea (tmp);
errno = saved_errno;
}
}
return result;
}
#endif /* HAVE_SETENV */

120
gl/unsetenv.c Normal file
View file

@ -0,0 +1,120 @@
/* Copyright (C) 1992, 1995-2002, 2005-2010 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
/* 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 */