summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gl/Makefile.am28
-rw-r--r--gl/m4/eealloc.m432
-rw-r--r--gl/m4/environ.m436
-rw-r--r--gl/m4/gnulib-cache.m44
-rw-r--r--gl/m4/gnulib-comp.m424
-rw-r--r--gl/m4/malloca.m415
-rw-r--r--gl/m4/setenv.m4111
-rw-r--r--gl/malloca.c140
-rw-r--r--gl/malloca.h134
-rw-r--r--gl/malloca.valgrind7
-rw-r--r--gl/setenv.c390
-rw-r--r--gl/unsetenv.c120
12 files changed, 1039 insertions, 2 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am
index 2f5f9c43..41a370b0 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -9,7 +9,7 @@
9# the same distribution terms as the rest of that program. 9# the same distribution terms as the rest of that program.
10# 10#
11# Generated by gnulib-tool. 11# Generated by gnulib-tool.
12# 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 12# 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
13 13
14AUTOMAKE_OPTIONS = 1.5 gnits 14AUTOMAKE_OPTIONS = 1.5 gnits
15 15
@@ -678,6 +678,14 @@ EXTRA_libgnu_a_SOURCES += malloc.c
678 678
679## end gnulib module malloc-posix 679## end gnulib module malloc-posix
680 680
681## begin gnulib module malloca
682
683libgnu_a_SOURCES += malloca.c
684
685EXTRA_DIST += malloca.h malloca.valgrind
686
687## end gnulib module malloca
688
681## begin gnulib module math 689## begin gnulib module math
682 690
683BUILT_SOURCES += math.h 691BUILT_SOURCES += math.h
@@ -928,6 +936,15 @@ EXTRA_libgnu_a_SOURCES += safe-write.c
928 936
929## end gnulib module safe-write 937## end gnulib module safe-write
930 938
939## begin gnulib module setenv
940
941
942EXTRA_DIST += setenv.c
943
944EXTRA_libgnu_a_SOURCES += setenv.c
945
946## end gnulib module setenv
947
931## begin gnulib module size_max 948## begin gnulib module size_max
932 949
933libgnu_a_SOURCES += size_max.h 950libgnu_a_SOURCES += size_max.h
@@ -1683,6 +1700,15 @@ EXTRA_libgnu_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c
1683 1700
1684## end gnulib module unistd-safer 1701## end gnulib module unistd-safer
1685 1702
1703## begin gnulib module unsetenv
1704
1705
1706EXTRA_DIST += unsetenv.c
1707
1708EXTRA_libgnu_a_SOURCES += unsetenv.c
1709
1710## end gnulib module unsetenv
1711
1686## begin gnulib module vasnprintf 1712## begin gnulib module vasnprintf
1687 1713
1688 1714
diff --git a/gl/m4/eealloc.m4 b/gl/m4/eealloc.m4
new file mode 100644
index 00000000..63dd9202
--- /dev/null
+++ b/gl/m4/eealloc.m4
@@ -0,0 +1,32 @@
1# eealloc.m4 serial 2
2dnl Copyright (C) 2003, 2009, 2010 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_EEALLOC],
8[
9 AC_REQUIRE([gl_EEMALLOC])
10 AC_REQUIRE([gl_EEREALLOC])
11 AC_REQUIRE([AC_C_INLINE])
12])
13
14AC_DEFUN([gl_EEMALLOC],
15[
16 _AC_FUNC_MALLOC_IF(
17 [gl_cv_func_malloc_0_nonnull=1],
18 [gl_cv_func_malloc_0_nonnull=0])
19 AC_DEFINE_UNQUOTED([MALLOC_0_IS_NONNULL], [$gl_cv_func_malloc_0_nonnull],
20 [If malloc(0) is != NULL, define this to 1. Otherwise define this
21 to 0.])
22])
23
24AC_DEFUN([gl_EEREALLOC],
25[
26 _AC_FUNC_REALLOC_IF(
27 [gl_cv_func_realloc_0_nonnull=1],
28 [gl_cv_func_realloc_0_nonnull=0])
29 AC_DEFINE_UNQUOTED([REALLOC_0_IS_NONNULL], [$gl_cv_func_realloc_0_nonnull],
30 [If realloc(NULL,0) is != NULL, define this to 1. Otherwise define this
31 to 0.])
32])
diff --git a/gl/m4/environ.m4 b/gl/m4/environ.m4
new file mode 100644
index 00000000..4c6849a3
--- /dev/null
+++ b/gl/m4/environ.m4
@@ -0,0 +1,36 @@
1# environ.m4 serial 4
2dnl Copyright (C) 2001-2004, 2006-2010 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN_ONCE([gl_ENVIRON],
8[
9 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
10 dnl Persuade glibc <unistd.h> to declare environ.
11 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
12 gt_CHECK_VAR_DECL([#include <unistd.h>], environ)
13 if test $gt_cv_var_environ_declaration != yes; then
14 HAVE_DECL_ENVIRON=0
15 fi
16])
17
18# Check if a variable is properly declared.
19# gt_CHECK_VAR_DECL(includes,variable)
20AC_DEFUN([gt_CHECK_VAR_DECL],
21[
22 define([gt_cv_var], [gt_cv_var_]$2[_declaration])
23 AC_MSG_CHECKING([if $2 is properly declared])
24 AC_CACHE_VAL([gt_cv_var], [
25 AC_TRY_COMPILE([$1
26 extern struct { int foo; } $2;],
27 [$2.foo = 1;],
28 gt_cv_var=no,
29 gt_cv_var=yes)])
30 AC_MSG_RESULT([$gt_cv_var])
31 if test $gt_cv_var = yes; then
32 AC_DEFINE([HAVE_]m4_translit($2, [a-z], [A-Z])[_DECL], 1,
33 [Define if you have the declaration of $2.])
34 fi
35 undefine([gt_cv_var])
36])
diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4
index f23cb519..22e61333 100644
--- a/gl/m4/gnulib-cache.m4
+++ b/gl/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
15 15
16 16
17# Specification in the form of a command-line invocation: 17# Specification in the form of a command-line invocation:
18# 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 18# 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
19 19
20# Specification in the form of a few gnulib-tool.m4 macro invocations: 20# Specification in the form of a few gnulib-tool.m4 macro invocations:
21gl_LOCAL_DIR([]) 21gl_LOCAL_DIR([])
@@ -32,8 +32,10 @@ gl_MODULES([
32 gettext 32 gettext
33 mountlist 33 mountlist
34 regex 34 regex
35 setenv
35 strsep 36 strsep
36 timegm 37 timegm
38 unsetenv
37 vasprintf 39 vasprintf
38 vsnprintf 40 vsnprintf
39]) 41])
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4
index 73e63654..fc3f3538 100644
--- a/gl/m4/gnulib-comp.m4
+++ b/gl/m4/gnulib-comp.m4
@@ -41,6 +41,7 @@ AC_DEFUN([gl_EARLY],
41 # Code from module dirname-lgpl: 41 # Code from module dirname-lgpl:
42 # Code from module double-slash-root: 42 # Code from module double-slash-root:
43 # Code from module dup2: 43 # Code from module dup2:
44 # Code from module environ:
44 # Code from module errno: 45 # Code from module errno:
45 # Code from module error: 46 # Code from module error:
46 # Code from module exitfail: 47 # Code from module exitfail:
@@ -74,6 +75,7 @@ AC_DEFUN([gl_EARLY],
74 # Code from module locale: 75 # Code from module locale:
75 # Code from module malloc: 76 # Code from module malloc:
76 # Code from module malloc-posix: 77 # Code from module malloc-posix:
78 # Code from module malloca:
77 # Code from module math: 79 # Code from module math:
78 # Code from module mbrtowc: 80 # Code from module mbrtowc:
79 # Code from module mbsinit: 81 # Code from module mbsinit:
@@ -89,6 +91,7 @@ AC_DEFUN([gl_EARLY],
89 # Code from module safe-read: 91 # Code from module safe-read:
90 # Code from module safe-write: 92 # Code from module safe-write:
91 # Code from module servent: 93 # Code from module servent:
94 # Code from module setenv:
92 # Code from module size_max: 95 # Code from module size_max:
93 # Code from module snprintf: 96 # Code from module snprintf:
94 # Code from module sockets: 97 # Code from module sockets:
@@ -115,6 +118,7 @@ AC_DEFUN([gl_EARLY],
115 # Code from module timegm: 118 # Code from module timegm:
116 # Code from module unistd: 119 # Code from module unistd:
117 # Code from module unistd-safer: 120 # Code from module unistd-safer:
121 # Code from module unsetenv:
118 # Code from module vasnprintf: 122 # Code from module vasnprintf:
119 # Code from module vasprintf: 123 # Code from module vasprintf:
120 # Code from module verify: 124 # Code from module verify:
@@ -178,6 +182,9 @@ AC_DEFUN([gl_INIT],
178 # Code from module dup2: 182 # Code from module dup2:
179 gl_FUNC_DUP2 183 gl_FUNC_DUP2
180 gl_UNISTD_MODULE_INDICATOR([dup2]) 184 gl_UNISTD_MODULE_INDICATOR([dup2])
185 # Code from module environ:
186 gl_ENVIRON
187 gl_UNISTD_MODULE_INDICATOR([environ])
181 # Code from module errno: 188 # Code from module errno:
182 gl_HEADER_ERRNO_H 189 gl_HEADER_ERRNO_H
183 # Code from module error: 190 # Code from module error:
@@ -252,6 +259,8 @@ AC_DEFUN([gl_INIT],
252 # Code from module malloc-posix: 259 # Code from module malloc-posix:
253 gl_FUNC_MALLOC_POSIX 260 gl_FUNC_MALLOC_POSIX
254 gl_STDLIB_MODULE_INDICATOR([malloc-posix]) 261 gl_STDLIB_MODULE_INDICATOR([malloc-posix])
262 # Code from module malloca:
263 gl_MALLOCA
255 # Code from module math: 264 # Code from module math:
256 gl_MATH_H 265 gl_MATH_H
257 # Code from module mbrtowc: 266 # Code from module mbrtowc:
@@ -289,6 +298,9 @@ AC_DEFUN([gl_INIT],
289 gl_SAFE_WRITE 298 gl_SAFE_WRITE
290 # Code from module servent: 299 # Code from module servent:
291 gl_SERVENT 300 gl_SERVENT
301 # Code from module setenv:
302 gl_FUNC_SETENV
303 gl_STDLIB_MODULE_INDICATOR([setenv])
292 # Code from module size_max: 304 # Code from module size_max:
293 gl_SIZE_MAX 305 gl_SIZE_MAX
294 # Code from module snprintf: 306 # Code from module snprintf:
@@ -352,6 +364,9 @@ AC_DEFUN([gl_INIT],
352 gl_UNISTD_H 364 gl_UNISTD_H
353 # Code from module unistd-safer: 365 # Code from module unistd-safer:
354 gl_UNISTD_SAFER 366 gl_UNISTD_SAFER
367 # Code from module unsetenv:
368 gl_FUNC_UNSETENV
369 gl_STDLIB_MODULE_INDICATOR([unsetenv])
355 # Code from module vasnprintf: 370 # Code from module vasnprintf:
356 gl_FUNC_VASNPRINTF 371 gl_FUNC_VASNPRINTF
357 # Code from module vasprintf: 372 # Code from module vasprintf:
@@ -586,6 +601,9 @@ AC_DEFUN([gl_FILE_LIST], [
586 lib/localcharset.h 601 lib/localcharset.h
587 lib/locale.in.h 602 lib/locale.in.h
588 lib/malloc.c 603 lib/malloc.c
604 lib/malloca.c
605 lib/malloca.h
606 lib/malloca.valgrind
589 lib/math.in.h 607 lib/math.in.h
590 lib/mbrtowc.c 608 lib/mbrtowc.c
591 lib/mbsinit.c 609 lib/mbsinit.c
@@ -617,6 +635,7 @@ AC_DEFUN([gl_FILE_LIST], [
617 lib/safe-read.h 635 lib/safe-read.h
618 lib/safe-write.c 636 lib/safe-write.c
619 lib/safe-write.h 637 lib/safe-write.h
638 lib/setenv.c
620 lib/sha1.c 639 lib/sha1.c
621 lib/sha1.h 640 lib/sha1.h
622 lib/size_max.h 641 lib/size_max.h
@@ -648,6 +667,7 @@ AC_DEFUN([gl_FILE_LIST], [
648 lib/unistd--.h 667 lib/unistd--.h
649 lib/unistd-safer.h 668 lib/unistd-safer.h
650 lib/unistd.in.h 669 lib/unistd.in.h
670 lib/unsetenv.c
651 lib/vasnprintf.c 671 lib/vasnprintf.c
652 lib/vasnprintf.h 672 lib/vasnprintf.h
653 lib/vasprintf.c 673 lib/vasprintf.c
@@ -677,6 +697,8 @@ AC_DEFUN([gl_FILE_LIST], [
677 m4/dos.m4 697 m4/dos.m4
678 m4/double-slash-root.m4 698 m4/double-slash-root.m4
679 m4/dup2.m4 699 m4/dup2.m4
700 m4/eealloc.m4
701 m4/environ.m4
680 m4/errno_h.m4 702 m4/errno_h.m4
681 m4/error.m4 703 m4/error.m4
682 m4/extensions.m4 704 m4/extensions.m4
@@ -724,6 +746,7 @@ AC_DEFUN([gl_FILE_LIST], [
724 m4/longlong.m4 746 m4/longlong.m4
725 m4/ls-mntd-fs.m4 747 m4/ls-mntd-fs.m4
726 m4/malloc.m4 748 m4/malloc.m4
749 m4/malloca.m4
727 m4/math_h.m4 750 m4/math_h.m4
728 m4/mbrtowc.m4 751 m4/mbrtowc.m4
729 m4/mbsinit.m4 752 m4/mbsinit.m4
@@ -748,6 +771,7 @@ AC_DEFUN([gl_FILE_LIST], [
748 m4/safe-read.m4 771 m4/safe-read.m4
749 m4/safe-write.m4 772 m4/safe-write.m4
750 m4/servent.m4 773 m4/servent.m4
774 m4/setenv.m4
751 m4/sha1.m4 775 m4/sha1.m4
752 m4/size_max.m4 776 m4/size_max.m4
753 m4/snprintf.m4 777 m4/snprintf.m4
diff --git a/gl/m4/malloca.m4 b/gl/m4/malloca.m4
new file mode 100644
index 00000000..e07c6d93
--- /dev/null
+++ b/gl/m4/malloca.m4
@@ -0,0 +1,15 @@
1# malloca.m4 serial 1
2dnl Copyright (C) 2003-2004, 2006-2007, 2009-2010 Free Software Foundation,
3dnl Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8AC_DEFUN([gl_MALLOCA],
9[
10 dnl Use the autoconf tests for alloca(), but not the AC_SUBSTed variables
11 dnl @ALLOCA@ and @LTALLOCA@.
12 dnl gl_FUNC_ALLOCA dnl Already brought in by the module dependencies.
13 AC_REQUIRE([gl_EEMALLOC])
14 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
15])
diff --git a/gl/m4/setenv.m4 b/gl/m4/setenv.m4
new file mode 100644
index 00000000..58f6d138
--- /dev/null
+++ b/gl/m4/setenv.m4
@@ -0,0 +1,111 @@
1# setenv.m4 serial 16
2dnl Copyright (C) 2001-2004, 2006-2010 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_FUNC_SETENV],
8[
9 AC_REQUIRE([gl_FUNC_SETENV_SEPARATE])
10 if test $HAVE_SETENV$REPLACE_SETENV != 10; then
11 AC_LIBOBJ([setenv])
12 fi
13])
14
15# Like gl_FUNC_SETENV, except prepare for separate compilation (no AC_LIBOBJ).
16AC_DEFUN([gl_FUNC_SETENV_SEPARATE],
17[
18 AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
19 AC_CHECK_FUNCS_ONCE([setenv])
20 if test $ac_cv_func_setenv = no; then
21 HAVE_SETENV=0
22 else
23 AC_CACHE_CHECK([whether setenv validates arguments],
24 [gl_cv_func_setenv_works],
25 [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <string.h>
29 ]], [[
30 if (setenv ("", "", 0) != -1) return 1;
31 if (errno != EINVAL) return 2;
32 if (setenv ("a", "=", 1) != 0) return 3;
33 if (strcmp (getenv ("a"), "=") != 0) return 4;
34 ]])],
35 [gl_cv_func_setenv_works=yes], [gl_cv_func_setenv_works=no],
36 [gl_cv_func_setenv_works="guessing no"])])
37 if test "$gl_cv_func_setenv_works" != yes; then
38 REPLACE_SETENV=1
39 AC_LIBOBJ([setenv])
40 fi
41 fi
42 gl_PREREQ_SETENV
43])
44
45AC_DEFUN([gl_FUNC_UNSETENV],
46[
47 AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
48 AC_CHECK_FUNCS([unsetenv])
49 if test $ac_cv_func_unsetenv = no; then
50 HAVE_UNSETENV=0
51 AC_LIBOBJ([unsetenv])
52 gl_PREREQ_UNSETENV
53 else
54 dnl Some BSDs return void, failing to do error checking.
55 AC_CACHE_CHECK([for unsetenv() return type], [gt_cv_func_unsetenv_ret],
56 [AC_TRY_COMPILE([#include <stdlib.h>
57extern
58#ifdef __cplusplus
59"C"
60#endif
61#if defined(__STDC__) || defined(__cplusplus)
62int unsetenv (const char *name);
63#else
64int unsetenv();
65#endif
66], , gt_cv_func_unsetenv_ret='int', gt_cv_func_unsetenv_ret='void')])
67 if test $gt_cv_func_unsetenv_ret = 'void'; then
68 AC_DEFINE([VOID_UNSETENV], [1], [Define to 1 if unsetenv returns void
69 instead of int.])
70 REPLACE_UNSETENV=1
71 AC_LIBOBJ([unsetenv])
72 fi
73
74 dnl Solaris 10 unsetenv does not remove all copies of a name.
75 AC_CACHE_CHECK([whether unsetenv works on duplicates],
76 [gl_cv_func_unsetenv_works],
77 [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
78 #include <stdlib.h>
79 ]], [[
80 char entry[] = "b=2";
81 if (putenv ((char *) "a=1")) return 1;
82 if (putenv (entry)) return 2;
83 entry[0] = 'a';
84 unsetenv ("a");
85 if (getenv ("a")) return 3;
86 ]])],
87 [gl_cv_func_unsetenv_works=yes], [gl_cv_func_unsetenv_works=no],
88 [gl_cv_func_unsetenv_works="guessing no"])])
89 if test "$gl_cv_func_unsetenv_works" != yes; then
90 REPLACE_UNSETENV=1
91 AC_LIBOBJ([unsetenv])
92 fi
93 fi
94])
95
96# Prerequisites of lib/setenv.c.
97AC_DEFUN([gl_PREREQ_SETENV],
98[
99 AC_REQUIRE([AC_FUNC_ALLOCA])
100 AC_REQUIRE([gl_ENVIRON])
101 AC_CHECK_HEADERS_ONCE([unistd.h])
102 AC_CHECK_HEADERS([search.h])
103 AC_CHECK_FUNCS([tsearch])
104])
105
106# Prerequisites of lib/unsetenv.c.
107AC_DEFUN([gl_PREREQ_UNSETENV],
108[
109 AC_REQUIRE([gl_ENVIRON])
110 AC_CHECK_HEADERS_ONCE([unistd.h])
111])
diff --git a/gl/malloca.c b/gl/malloca.c
new file mode 100644
index 00000000..21bbc1f5
--- /dev/null
+++ b/gl/malloca.c
@@ -0,0 +1,140 @@
1/* Safe automatic memory allocation.
2 Copyright (C) 2003, 2006-2007, 2009-2010 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <config.h>
20
21/* Specification. */
22#include "malloca.h"
23
24/* Use the system functions, not the gnulib overrides in this file. */
25#undef malloc
26
27/* The speed critical point in this file is freea() applied to an alloca()
28 result: it must be fast, to match the speed of alloca(). The speed of
29 mmalloca() and freea() in the other case are not critical, because they
30 are only invoked for big memory sizes. */
31
32#if HAVE_ALLOCA
33
34/* Store the mmalloca() results in a hash table. This is needed to reliably
35 distinguish a mmalloca() result and an alloca() result.
36
37 Although it is possible that the same pointer is returned by alloca() and
38 by mmalloca() at different times in the same application, it does not lead
39 to a bug in freea(), because:
40 - Before a pointer returned by alloca() can point into malloc()ed memory,
41 the function must return, and once this has happened the programmer must
42 not call freea() on it anyway.
43 - Before a pointer returned by mmalloca() can point into the stack, it
44 must be freed. The only function that can free it is freea(), and
45 when freea() frees it, it also removes it from the hash table. */
46
47#define MAGIC_NUMBER 0x1415fb4a
48#define MAGIC_SIZE sizeof (int)
49/* This is how the header info would look like without any alignment
50 considerations. */
51struct preliminary_header { void *next; char room[MAGIC_SIZE]; };
52/* But the header's size must be a multiple of sa_alignment_max. */
53#define HEADER_SIZE \
54 (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max)
55struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; };
56/* Verify that HEADER_SIZE == sizeof (struct header). */
57typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1];
58/* We make the hash table quite big, so that during lookups the probability
59 of empty hash buckets is quite high. There is no need to make the hash
60 table resizable, because when the hash table gets filled so much that the
61 lookup becomes slow, it means that the application has memory leaks. */
62#define HASH_TABLE_SIZE 257
63static void * mmalloca_results[HASH_TABLE_SIZE];
64
65#endif
66
67void *
68mmalloca (size_t n)
69{
70#if HAVE_ALLOCA
71 /* Allocate one more word, that serves as an indicator for malloc()ed
72 memory, so that freea() of an alloca() result is fast. */
73 size_t nplus = n + HEADER_SIZE;
74
75 if (nplus >= n)
76 {
77 char *p = (char *) malloc (nplus);
78
79 if (p != NULL)
80 {
81 size_t slot;
82
83 p += HEADER_SIZE;
84
85 /* Put a magic number into the indicator word. */
86 ((int *) p)[-1] = MAGIC_NUMBER;
87
88 /* Enter p into the hash table. */
89 slot = (unsigned long) p % HASH_TABLE_SIZE;
90 ((struct header *) (p - HEADER_SIZE))->next = mmalloca_results[slot];
91 mmalloca_results[slot] = p;
92
93 return p;
94 }
95 }
96 /* Out of memory. */
97 return NULL;
98#else
99# if !MALLOC_0_IS_NONNULL
100 if (n == 0)
101 n = 1;
102# endif
103 return malloc (n);
104#endif
105}
106
107#if HAVE_ALLOCA
108void
109freea (void *p)
110{
111 /* mmalloca() may have returned NULL. */
112 if (p != NULL)
113 {
114 /* Attempt to quickly distinguish the mmalloca() result - which has
115 a magic indicator word - and the alloca() result - which has an
116 uninitialized indicator word. It is for this test that sa_increment
117 additional bytes are allocated in the alloca() case. */
118 if (((int *) p)[-1] == MAGIC_NUMBER)
119 {
120 /* Looks like a mmalloca() result. To see whether it really is one,
121 perform a lookup in the hash table. */
122 size_t slot = (unsigned long) p % HASH_TABLE_SIZE;
123 void **chain = &mmalloca_results[slot];
124 for (; *chain != NULL;)
125 {
126 if (*chain == p)
127 {
128 /* Found it. Remove it from the hash table and free it. */
129 char *p_begin = (char *) p - HEADER_SIZE;
130 *chain = ((struct header *) p_begin)->next;
131 free (p_begin);
132 return;
133 }
134 chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next;
135 }
136 }
137 /* At this point, we know it was not a mmalloca() result. */
138 }
139}
140#endif
diff --git a/gl/malloca.h b/gl/malloca.h
new file mode 100644
index 00000000..0d5ded3c
--- /dev/null
+++ b/gl/malloca.h
@@ -0,0 +1,134 @@
1/* Safe automatic memory allocation.
2 Copyright (C) 2003-2007, 2009-2010 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _MALLOCA_H
20#define _MALLOCA_H
21
22#include <alloca.h>
23#include <stddef.h>
24#include <stdlib.h>
25
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31
32/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
33 alloca(N); otherwise it returns NULL. It either returns N bytes of
34 memory allocated on the stack, that lasts until the function returns,
35 or NULL.
36 Use of safe_alloca should be avoided:
37 - inside arguments of function calls - undefined behaviour,
38 - in inline functions - the allocation may actually last until the
39 calling function returns.
40*/
41#if HAVE_ALLOCA
42/* The OS usually guarantees only one guard page at the bottom of the stack,
43 and a page size can be as small as 4096 bytes. So we cannot safely
44 allocate anything larger than 4096 bytes. Also care for the possibility
45 of a few compiler-allocated temporary stack slots.
46 This must be a macro, not an inline function. */
47# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
48#else
49# define safe_alloca(N) ((void) (N), NULL)
50#endif
51
52/* malloca(N) is a safe variant of alloca(N). It allocates N bytes of
53 memory allocated on the stack, that must be freed using freea() before
54 the function returns. Upon failure, it returns NULL. */
55#if HAVE_ALLOCA
56# define malloca(N) \
57 ((N) < 4032 - sa_increment \
58 ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
59 : mmalloca (N))
60#else
61# define malloca(N) \
62 mmalloca (N)
63#endif
64extern void * mmalloca (size_t n);
65
66/* Free a block of memory allocated through malloca(). */
67#if HAVE_ALLOCA
68extern void freea (void *p);
69#else
70# define freea free
71#endif
72
73/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
74 It allocates an array of N objects, each with S bytes of memory,
75 on the stack. S must be positive and N must be nonnegative.
76 The array must be freed using freea() before the function returns. */
77#if 1
78/* Cf. the definition of xalloc_oversized. */
79# define nmalloca(n, s) \
80 ((n) > (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) \
81 ? NULL \
82 : malloca ((n) * (s)))
83#else
84extern void * nmalloca (size_t n, size_t s);
85#endif
86
87
88#ifdef __cplusplus
89}
90#endif
91
92
93/* ------------------- Auxiliary, non-public definitions ------------------- */
94
95/* Determine the alignment of a type at compile time. */
96#if defined __GNUC__
97# define sa_alignof __alignof__
98#elif defined __cplusplus
99 template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
100# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
101#elif defined __hpux
102 /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
103 values. */
104# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
105#elif defined _AIX
106 /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof
107 values. */
108# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
109#else
110# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
111#endif
112
113enum
114{
115/* The desired alignment of memory allocations is the maximum alignment
116 among all elementary types. */
117 sa_alignment_long = sa_alignof (long),
118 sa_alignment_double = sa_alignof (double),
119#if HAVE_LONG_LONG_INT
120 sa_alignment_longlong = sa_alignof (long long),
121#endif
122 sa_alignment_longdouble = sa_alignof (long double),
123 sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
124#if HAVE_LONG_LONG_INT
125 | (sa_alignment_longlong - 1)
126#endif
127 | (sa_alignment_longdouble - 1)
128 ) + 1,
129/* The increment that guarantees room for a magic word must be >= sizeof (int)
130 and a multiple of sa_alignment_max. */
131 sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
132};
133
134#endif /* _MALLOCA_H */
diff --git a/gl/malloca.valgrind b/gl/malloca.valgrind
new file mode 100644
index 00000000..52f0a50f
--- /dev/null
+++ b/gl/malloca.valgrind
@@ -0,0 +1,7 @@
1# Suppress a valgrind message about use of uninitialized memory in freea().
2# This use is OK because it provides only a speedup.
3{
4 freea
5 Memcheck:Cond
6 fun:freea
7}
diff --git a/gl/setenv.c b/gl/setenv.c
new file mode 100644
index 00000000..ba760d6f
--- /dev/null
+++ b/gl/setenv.c
@@ -0,0 +1,390 @@
1/* Copyright (C) 1992, 1995-2003, 2005-2010 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#if !_LIBC
18# include <config.h>
19#endif
20
21/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
22 optimizes away the name == NULL test below. */
23#define _GL_ARG_NONNULL(params)
24
25#include <alloca.h>
26
27/* Specification. */
28#include <stdlib.h>
29
30#include <errno.h>
31#ifndef __set_errno
32# define __set_errno(ev) ((errno) = (ev))
33#endif
34
35#include <string.h>
36#if _LIBC || HAVE_UNISTD_H
37# include <unistd.h>
38#endif
39
40#if !_LIBC
41# include "malloca.h"
42#endif
43
44#if _LIBC || !HAVE_SETENV
45
46#if !_LIBC
47# define __environ environ
48#endif
49
50#if _LIBC
51/* This lock protects against simultaneous modifications of `environ'. */
52# include <bits/libc-lock.h>
53__libc_lock_define_initialized (static, envlock)
54# define LOCK __libc_lock_lock (envlock)
55# define UNLOCK __libc_lock_unlock (envlock)
56#else
57# define LOCK
58# define UNLOCK
59#endif
60
61/* In the GNU C library we must keep the namespace clean. */
62#ifdef _LIBC
63# define setenv __setenv
64# define clearenv __clearenv
65# define tfind __tfind
66# define tsearch __tsearch
67#else
68/* Use the system functions, not the gnulib overrides in this file. */
69# undef malloc
70# undef realloc
71#endif
72
73/* In the GNU C library implementation we try to be more clever and
74 allow arbitrarily many changes of the environment given that the used
75 values are from a small set. Outside glibc this will eat up all
76 memory after a while. */
77#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
78 && defined __GNUC__)
79# define USE_TSEARCH 1
80# include <search.h>
81typedef int (*compar_fn_t) (const void *, const void *);
82
83/* This is a pointer to the root of the search tree with the known
84 values. */
85static void *known_values;
86
87# define KNOWN_VALUE(Str) \
88 ({ \
89 void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \
90 value != NULL ? *(char **) value : NULL; \
91 })
92# define STORE_VALUE(Str) \
93 tsearch (Str, &known_values, (compar_fn_t) strcmp)
94
95#else
96# undef USE_TSEARCH
97
98# define KNOWN_VALUE(Str) NULL
99# define STORE_VALUE(Str) do { } while (0)
100
101#endif
102
103
104/* If this variable is not a null pointer we allocated the current
105 environment. */
106static char **last_environ;
107
108
109/* This function is used by `setenv' and `putenv'. The difference between
110 the two functions is that for the former must create a new string which
111 is then placed in the environment, while the argument of `putenv'
112 must be used directly. This is all complicated by the fact that we try
113 to reuse values once generated for a `setenv' call since we can never
114 free the strings. */
115int
116__add_to_environ (const char *name, const char *value, const char *combined,
117 int replace)
118{
119 char **ep;
120 size_t size;
121 const size_t namelen = strlen (name);
122 const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
123
124 LOCK;
125
126 /* We have to get the pointer now that we have the lock and not earlier
127 since another thread might have created a new environment. */
128 ep = __environ;
129
130 size = 0;
131 if (ep != NULL)
132 {
133 for (; *ep != NULL; ++ep)
134 if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
135 break;
136 else
137 ++size;
138 }
139
140 if (ep == NULL || *ep == NULL)
141 {
142 char **new_environ;
143#ifdef USE_TSEARCH
144 char *new_value;
145#endif
146
147 /* We allocated this space; we can extend it. */
148 new_environ =
149 (char **) (last_environ == NULL
150 ? malloc ((size + 2) * sizeof (char *))
151 : realloc (last_environ, (size + 2) * sizeof (char *)));
152 if (new_environ == NULL)
153 {
154 /* It's easier to set errno to ENOMEM than to rely on the
155 'malloc-posix' and 'realloc-posix' gnulib modules. */
156 __set_errno (ENOMEM);
157 UNLOCK;
158 return -1;
159 }
160
161 /* If the whole entry is given add it. */
162 if (combined != NULL)
163 /* We must not add the string to the search tree since it belongs
164 to the user. */
165 new_environ[size] = (char *) combined;
166 else
167 {
168 /* See whether the value is already known. */
169#ifdef USE_TSEARCH
170# ifdef _LIBC
171 new_value = (char *) alloca (namelen + 1 + vallen);
172 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
173 value, vallen);
174# else
175 new_value = (char *) malloca (namelen + 1 + vallen);
176 if (new_value == NULL)
177 {
178 __set_errno (ENOMEM);
179 UNLOCK;
180 return -1;
181 }
182 memcpy (new_value, name, namelen);
183 new_value[namelen] = '=';
184 memcpy (&new_value[namelen + 1], value, vallen);
185# endif
186
187 new_environ[size] = KNOWN_VALUE (new_value);
188 if (new_environ[size] == NULL)
189#endif
190 {
191 new_environ[size] = (char *) malloc (namelen + 1 + vallen);
192 if (new_environ[size] == NULL)
193 {
194#if defined USE_TSEARCH && !defined _LIBC
195 freea (new_value);
196#endif
197 __set_errno (ENOMEM);
198 UNLOCK;
199 return -1;
200 }
201
202#ifdef USE_TSEARCH
203 memcpy (new_environ[size], new_value, namelen + 1 + vallen);
204#else
205 memcpy (new_environ[size], name, namelen);
206 new_environ[size][namelen] = '=';
207 memcpy (&new_environ[size][namelen + 1], value, vallen);
208#endif
209 /* And save the value now. We cannot do this when we remove
210 the string since then we cannot decide whether it is a
211 user string or not. */
212 STORE_VALUE (new_environ[size]);
213 }
214#if defined USE_TSEARCH && !defined _LIBC
215 freea (new_value);
216#endif
217 }
218
219 if (__environ != last_environ)
220 memcpy ((char *) new_environ, (char *) __environ,
221 size * sizeof (char *));
222
223 new_environ[size + 1] = NULL;
224
225 last_environ = __environ = new_environ;
226 }
227 else if (replace)
228 {
229 char *np;
230
231 /* Use the user string if given. */
232 if (combined != NULL)
233 np = (char *) combined;
234 else
235 {
236#ifdef USE_TSEARCH
237 char *new_value;
238# ifdef _LIBC
239 new_value = alloca (namelen + 1 + vallen);
240 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
241 value, vallen);
242# else
243 new_value = malloca (namelen + 1 + vallen);
244 if (new_value == NULL)
245 {
246 __set_errno (ENOMEM);
247 UNLOCK;
248 return -1;
249 }
250 memcpy (new_value, name, namelen);
251 new_value[namelen] = '=';
252 memcpy (&new_value[namelen + 1], value, vallen);
253# endif
254
255 np = KNOWN_VALUE (new_value);
256 if (np == NULL)
257#endif
258 {
259 np = (char *) malloc (namelen + 1 + vallen);
260 if (np == NULL)
261 {
262#if defined USE_TSEARCH && !defined _LIBC
263 freea (new_value);
264#endif
265 __set_errno (ENOMEM);
266 UNLOCK;
267 return -1;
268 }
269
270#ifdef USE_TSEARCH
271 memcpy (np, new_value, namelen + 1 + vallen);
272#else
273 memcpy (np, name, namelen);
274 np[namelen] = '=';
275 memcpy (&np[namelen + 1], value, vallen);
276#endif
277 /* And remember the value. */
278 STORE_VALUE (np);
279 }
280#if defined USE_TSEARCH && !defined _LIBC
281 freea (new_value);
282#endif
283 }
284
285 *ep = np;
286 }
287
288 UNLOCK;
289
290 return 0;
291}
292
293int
294setenv (const char *name, const char *value, int replace)
295{
296 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
297 {
298 __set_errno (EINVAL);
299 return -1;
300 }
301
302 return __add_to_environ (name, value, NULL, replace);
303}
304
305/* The `clearenv' was planned to be added to POSIX.1 but probably
306 never made it. Nevertheless the POSIX.9 standard (POSIX bindings
307 for Fortran 77) requires this function. */
308int
309clearenv (void)
310{
311 LOCK;
312
313 if (__environ == last_environ && __environ != NULL)
314 {
315 /* We allocated this environment so we can free it. */
316 free (__environ);
317 last_environ = NULL;
318 }
319
320 /* Clear the environment pointer removes the whole environment. */
321 __environ = NULL;
322
323 UNLOCK;
324
325 return 0;
326}
327
328#ifdef _LIBC
329static void
330free_mem (void)
331{
332 /* Remove all traces. */
333 clearenv ();
334
335 /* Now remove the search tree. */
336 __tdestroy (known_values, free);
337 known_values = NULL;
338}
339text_set_element (__libc_subfreeres, free_mem);
340
341
342# undef setenv
343# undef clearenv
344weak_alias (__setenv, setenv)
345weak_alias (__clearenv, clearenv)
346#endif
347
348#endif /* _LIBC || !HAVE_SETENV */
349
350/* The rest of this file is called into use when replacing an existing
351 but buggy setenv. Known bugs include failure to diagnose invalid
352 name, and consuming a leading '=' from value. */
353#if HAVE_SETENV
354
355# undef setenv
356# define STREQ(a, b) (strcmp (a, b) == 0)
357
358int
359rpl_setenv (const char *name, const char *value, int replace)
360{
361 int result;
362 if (!name || !*name || strchr (name, '='))
363 {
364 errno = EINVAL;
365 return -1;
366 }
367 /* Call the real setenv even if replace is 0, in case implementation
368 has underlying data to update, such as when environ changes. */
369 result = setenv (name, value, replace);
370 if (result == 0 && replace && *value == '=')
371 {
372 char *tmp = getenv (name);
373 if (!STREQ (tmp, value))
374 {
375 int saved_errno;
376 size_t len = strlen (value);
377 tmp = malloca (len + 2);
378 /* Since leading '=' is eaten, double it up. */
379 *tmp = '=';
380 memcpy (tmp + 1, value, len + 1);
381 result = setenv (name, tmp, replace);
382 saved_errno = errno;
383 freea (tmp);
384 errno = saved_errno;
385 }
386 }
387 return result;
388}
389
390#endif /* HAVE_SETENV */
diff --git a/gl/unsetenv.c b/gl/unsetenv.c
new file mode 100644
index 00000000..65a19cca
--- /dev/null
+++ b/gl/unsetenv.c
@@ -0,0 +1,120 @@
1/* Copyright (C) 1992, 1995-2002, 2005-2010 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <config.h>
18
19/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
20 optimizes away the name == NULL test below. */
21#define _GL_ARG_NONNULL(params)
22
23/* Specification. */
24#include <stdlib.h>
25
26#include <errno.h>
27#if !_LIBC
28# define __set_errno(ev) ((errno) = (ev))
29#endif
30
31#include <string.h>
32#include <unistd.h>
33
34#if !_LIBC
35# define __environ environ
36#endif
37
38#if _LIBC
39/* This lock protects against simultaneous modifications of `environ'. */
40# include <bits/libc-lock.h>
41__libc_lock_define_initialized (static, envlock)
42# define LOCK __libc_lock_lock (envlock)
43# define UNLOCK __libc_lock_unlock (envlock)
44#else
45# define LOCK
46# define UNLOCK
47#endif
48
49/* In the GNU C library we must keep the namespace clean. */
50#ifdef _LIBC
51# define unsetenv __unsetenv
52#endif
53
54#if _LIBC || !HAVE_UNSETENV
55
56int
57unsetenv (const char *name)
58{
59 size_t len;
60 char **ep;
61
62 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
63 {
64 __set_errno (EINVAL);
65 return -1;
66 }
67
68 len = strlen (name);
69
70 LOCK;
71
72 ep = __environ;
73 while (*ep != NULL)
74 if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
75 {
76 /* Found it. Remove this pointer by moving later ones back. */
77 char **dp = ep;
78
79 do
80 dp[0] = dp[1];
81 while (*dp++);
82 /* Continue the loop in case NAME appears again. */
83 }
84 else
85 ++ep;
86
87 UNLOCK;
88
89 return 0;
90}
91
92#ifdef _LIBC
93# undef unsetenv
94weak_alias (__unsetenv, unsetenv)
95#endif
96
97#else /* HAVE_UNSETENV */
98
99# undef unsetenv
100
101/* Call the underlying unsetenv, in case there is hidden bookkeeping
102 that needs updating beyond just modifying environ. */
103int
104rpl_unsetenv (const char *name)
105{
106 int result = 0;
107 if (!name || !*name || strchr (name, '='))
108 {
109 errno = EINVAL;
110 return -1;
111 }
112 while (getenv (name))
113# if !VOID_UNSETENV
114 result =
115# endif
116 unsetenv (name);
117 return result;
118}
119
120#endif /* HAVE_UNSETENV */