]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/generic/setenv.c
update from main archive
[thirdparty/glibc.git] / sysdeps / generic / setenv.c
CommitLineData
299a95b9 1/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
28f540f4
RM
2This file is part of the GNU C Library.
3
4The GNU C Library is free software; you can redistribute it and/or
5modify it under the terms of the GNU Library General Public License as
6published by the Free Software Foundation; either version 2 of the
7License, or (at your option) any later version.
8
9The GNU C Library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12Library General Public License for more details.
13
14You should have received a copy of the GNU Library General Public
15License along with the GNU C Library; see the file COPYING.LIB. If
16not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17Cambridge, MA 02139, USA. */
18
196980f5
RM
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include <errno.h>
24
25#if _LIBC || HAVE_STDLIB_H
28f540f4 26#include <stdlib.h>
196980f5
RM
27#endif
28#if _LIBC || HAVE_STRING_H
28f540f4 29#include <string.h>
196980f5
RM
30#endif
31#if _LIBC || HAVE_UNISTD_H
28f540f4 32#include <unistd.h>
196980f5 33#endif
28f540f4 34
9e0f4072 35#if _LIBC - 0 == 0
28f540f4
RM
36#define __environ environ
37#endif
38
9e0f4072
RM
39#if _LIBC - 0
40/* This lock protects against simultaneous modifications of `environ'. */
41#include <libc-lock.h>
42__libc_lock_define_initialized (static, envlock)
43#define LOCK __libc_lock_lock (envlock)
44#define UNLOCK __libc_lock_unlock (envlock)
45#else
46#define LOCK
47#define UNLOCK
48#endif
49
28f540f4 50int
196980f5
RM
51setenv (name, value, replace)
52 const char *name;
53 const char *value;
54 int replace;
28f540f4
RM
55{
56 register char **ep;
57 register size_t size;
196980f5
RM
58 const size_t namelen = strlen (name);
59 const size_t vallen = strlen (value) + 1;
28f540f4 60
9e0f4072
RM
61 LOCK;
62
28f540f4
RM
63 size = 0;
64 for (ep = __environ; *ep != NULL; ++ep)
65 if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
66 break;
67 else
68 ++size;
196980f5 69
28f540f4
RM
70 if (*ep == NULL)
71 {
196980f5
RM
72 static char **last_environ;
73 char **new_environ;
74 if (__environ == last_environ)
75 /* We allocated this space; we can extend it. */
76 new_environ = (char **) realloc (last_environ,
77 (size + 2) * sizeof (char *));
78 else
79 new_environ = (char **) malloc ((size + 2) * sizeof (char *));
80
28f540f4 81 if (new_environ == NULL)
9e0f4072
RM
82 {
83 UNLOCK;
84 return -1;
85 }
28f540f4 86
196980f5 87 new_environ[size] = malloc (namelen + 1 + vallen);
28f540f4
RM
88 if (new_environ[size] == NULL)
89 {
196980f5 90 free ((char *) new_environ);
c4029823 91 __set_errno (ENOMEM);
9e0f4072 92 UNLOCK;
28f540f4
RM
93 return -1;
94 }
196980f5
RM
95
96 if (__environ != last_environ)
97 memcpy ((char *) new_environ, (char *) __environ,
98 size * sizeof (char *));
99
28f540f4
RM
100 memcpy (new_environ[size], name, namelen);
101 new_environ[size][namelen] = '=';
196980f5 102 memcpy (&new_environ[size][namelen + 1], value, vallen);
28f540f4
RM
103
104 new_environ[size + 1] = NULL;
105
196980f5 106 last_environ = __environ = new_environ;
28f540f4
RM
107 }
108 else if (replace)
109 {
110 size_t len = strlen (*ep);
196980f5 111 if (len + 1 < namelen + 1 + vallen)
28f540f4 112 {
196980f5 113 /* The existing string is too short; malloc a new one. */
28f540f4
RM
114 char *new = malloc (namelen + 1 + vallen);
115 if (new == NULL)
9e0f4072
RM
116 {
117 UNLOCK;
118 return -1;
119 }
28f540f4
RM
120 *ep = new;
121 }
122 memcpy (*ep, name, namelen);
123 (*ep)[namelen] = '=';
196980f5 124 memcpy (&(*ep)[namelen + 1], value, vallen);
28f540f4
RM
125 }
126
9e0f4072
RM
127 UNLOCK;
128
28f540f4
RM
129 return 0;
130}
196980f5
RM
131
132void
299a95b9
RM
133unsetenv (name)
134 const char *name;
196980f5
RM
135{
136 const size_t len = strlen (name);
137 char **ep;
138
9e0f4072
RM
139 LOCK;
140
196980f5
RM
141 for (ep = __environ; *ep; ++ep)
142 if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
143 {
144 /* Found it. Remove this pointer by moving later ones back. */
145 char **dp = ep;
146 do
147 dp[0] = dp[1];
148 while (*dp++);
149 /* Continue the loop in case NAME appears again. */
150 }
9e0f4072
RM
151
152 UNLOCK;
196980f5 153}