Fix compilation warning by MinGW GCC.
[deliverable/binutils-gdb.git] / libiberty / setenv.c
CommitLineData
d4d868a2
RW
1/* Copyright (C) 1992, 1995, 1996, 1997, 2002, 2011 Free Software Foundation,
2 Inc.
e2eaf477
ILT
3 This file based on setenv.c in the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
979c05d3
NC
17 write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18 Boston, MA 02110-1301, USA. */
e2eaf477 19
39423523
DD
20
21/*
22
d4d868a2
RW
23@deftypefn Supplemental int setenv (const char *@var{name}, @
24 const char *@var{value}, int @var{overwrite})
39423523
DD
25@deftypefnx Supplemental void unsetenv (const char *@var{name})
26
27@code{setenv} adds @var{name} to the environment with value
28@var{value}. If the name was already present in the environment,
56056af5 29the new value will be stored only if @var{overwrite} is nonzero.
39423523
DD
30The companion @code{unsetenv} function removes @var{name} from the
31environment. This implementation is not safe for multithreaded code.
32
33@end deftypefn
34
35*/
36
e2eaf477
ILT
37#if HAVE_CONFIG_H
38# include <config.h>
39#endif
40
cc096b71
DD
41#define setenv libiberty_setenv
42#define unsetenv libiberty_unsetenv
43
e2eaf477
ILT
44#include "ansidecl.h"
45#include <sys/types.h> /* For `size_t' */
46#include <stdio.h> /* For `NULL' */
47
48#include <errno.h>
49#if !defined(errno) && !defined(HAVE_ERRNO_DECL)
50extern int errno;
51#endif
52#define __set_errno(ev) ((errno) = (ev))
53
54#if HAVE_STDLIB_H
55# include <stdlib.h>
56#endif
57#if HAVE_STRING_H
58# include <string.h>
59#endif
60#if HAVE_UNISTD_H
61# include <unistd.h>
62#endif
63
64#define __environ environ
65#ifndef HAVE_ENVIRON_DECL
72edb7c2
EZ
66/* MinGW defines environ to call a function. */
67#ifndef environ
e2eaf477
ILT
68extern char **environ;
69#endif
72edb7c2 70#endif
e2eaf477 71
cc096b71
DD
72#undef setenv
73#undef unsetenv
74
e2eaf477
ILT
75/* LOCK and UNLOCK are defined as no-ops. This makes the libiberty
76 * implementation MT-Unsafe. */
77#define LOCK
78#define UNLOCK
79
80/* Below this point, it's verbatim code from the glibc-2.0 implementation */
81
82/* If this variable is not a null pointer we allocated the current
83 environment. */
84static char **last_environ;
85
86
87int
1e45deed 88setenv (const char *name, const char *value, int replace)
e2eaf477 89{
74bcd529 90 register char **ep = 0;
e2eaf477
ILT
91 register size_t size;
92 const size_t namelen = strlen (name);
93 const size_t vallen = strlen (value) + 1;
94
95 LOCK;
96
97 size = 0;
98 if (__environ != NULL)
eb383413
L
99 {
100 for (ep = __environ; *ep != NULL; ++ep)
101 if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
102 break;
103 else
104 ++size;
105 }
e2eaf477
ILT
106
107 if (__environ == NULL || *ep == NULL)
108 {
109 char **new_environ;
110 if (__environ == last_environ && __environ != NULL)
111 /* We allocated this space; we can extend it. */
112 new_environ = (char **) realloc (last_environ,
113 (size + 2) * sizeof (char *));
114 else
115 new_environ = (char **) malloc ((size + 2) * sizeof (char *));
116
117 if (new_environ == NULL)
118 {
119 UNLOCK;
120 return -1;
121 }
122
abf6a75b 123 new_environ[size] = (char *) malloc (namelen + 1 + vallen);
e2eaf477
ILT
124 if (new_environ[size] == NULL)
125 {
126 free ((char *) new_environ);
127 __set_errno (ENOMEM);
128 UNLOCK;
129 return -1;
130 }
131
132 if (__environ != last_environ)
133 memcpy ((char *) new_environ, (char *) __environ,
134 size * sizeof (char *));
135
136 memcpy (new_environ[size], name, namelen);
137 new_environ[size][namelen] = '=';
138 memcpy (&new_environ[size][namelen + 1], value, vallen);
139
140 new_environ[size + 1] = NULL;
141
142 last_environ = __environ = new_environ;
143 }
144 else if (replace)
145 {
146 size_t len = strlen (*ep);
147 if (len + 1 < namelen + 1 + vallen)
148 {
149 /* The existing string is too short; malloc a new one. */
abf6a75b
DD
150 char *new_string = (char *) malloc (namelen + 1 + vallen);
151 if (new_string == NULL)
e2eaf477
ILT
152 {
153 UNLOCK;
154 return -1;
155 }
abf6a75b 156 *ep = new_string;
e2eaf477
ILT
157 }
158 memcpy (*ep, name, namelen);
159 (*ep)[namelen] = '=';
160 memcpy (&(*ep)[namelen + 1], value, vallen);
161 }
162
163 UNLOCK;
164
165 return 0;
166}
167
168void
1e45deed 169unsetenv (const char *name)
e2eaf477
ILT
170{
171 const size_t len = strlen (name);
172 char **ep;
173
174 LOCK;
175
176 for (ep = __environ; *ep; ++ep)
177 if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
178 {
179 /* Found it. Remove this pointer by moving later ones back. */
180 char **dp = ep;
181 do
182 dp[0] = dp[1];
183 while (*dp++);
184 /* Continue the loop in case NAME appears again. */
185 }
186
187 UNLOCK;
188}
This page took 0.531687 seconds and 4 git commands to generate.