1 /* $NetBSD: setenv.c,v 1.1.1.1 2009/04/12 15:33:26 christos Exp $ */
2
3 #if defined(LIBC_SCCS) && !defined(lint)
4 static const char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
5 static const char rcsid[] = "Id: setenv.c,v 1.2 2005/04/27 04:56:11 sra Exp";
6 #endif /* LIBC_SCCS and not lint */
7
8 /*
9 * Copyright (c) 1987, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 /*
38 * Per the statement at http://opensource.org/licenses/bsd-license.php,
39 *
40 * The advertising clause in the license appearing on BSD Unix files was
41 * officially rescinded by the Director of the Office of Technology
42 * Licensing of the University of California on July 22 1999. He states
43 * that clause 3 is "hereby deleted in its entirety."
44 *
45 * I removed the advertising clause in the above copyright.
46 * The above web site points to
47 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change.
48 *
49 * Arnold Robbins
50 * 7 September 2016
51 */
52
53 /* #include "port_before.h" */
54
55 #include <stddef.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <errno.h>
59
60 /* #include "port_after.h" */
61
62 #define NEED_SETENV
63 #if !defined(NEED_SETENV)
64 int __bindcompat_setenv;
65 #else
66
67 /*
68 * Gawk changes:
69 * 1. Comment out "port_before.h" and "port_after.h" includes.
70 * 2. Define NEED_SETENV.
71 * 3. Add leading "int" to setenv() for C99 compilers. Which is worse,
72 * that it wasn't there in the first place, or that C99 now makes
73 * such functions void, breaking 40+ years of historical practice?
74 * 4. Change return type of unsetenv to "int" for standards
75 * conformance and check for name containing an "=" in
76 * which case it return an error. (See unsetenv(3), at least on Linux.)
77 */
78
79 extern char **environ;
80
81 static char *findenv(const char *name, int *offset);
82
83 /*%
84 * setenv --
85 * Set the value of the environmental variable "name" to be
86 * "value". If rewrite is set, replace any current value.
87 */
88 int
89 setenv(const char *name, const char *value, int rewrite)
90 {
91 extern char **environ;
92 static int alloced; /*%< if allocated space before */
93 char *c;
94 int l_value, offset;
95
96 if (*value == '=') /*%< no `=' in value */
97 ++value;
98 l_value = strlen(value);
99 if ((c = findenv(name, &offset))) { /*%< find if already exists */
100 if (!rewrite)
101 return (0);
102 if (strlen(c) >= l_value) { /*%< old larger; copy over */
103 while (*c++ = *value++);
104 return (0);
105 }
106 } else { /*%< create new slot */
107 int cnt;
108 char **p;
109
110 for (p = environ, cnt = 0; *p; ++p, ++cnt);
111 if (alloced) { /*%< just increase size */
112 environ = (char **)realloc((char *)environ,
113 (size_t)(sizeof(char *) * (cnt + 2)));
114 if (!environ)
115 return (-1);
116 }
117 else { /*%< get new space */
118 alloced = 1; /*%< copy old entries into it */
119 p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
120 if (!p)
121 return (-1);
122 memcpy(p, environ, cnt * sizeof(char *));
123 environ = p;
124 }
125 environ[cnt + 1] = NULL;
126 offset = cnt;
127 }
128 for (c = (char *)name; *c && *c != '='; ++c); /*%< no `=' in name */
129 if (!(environ[offset] = /*%< name + `=' + value */
130 malloc((size_t)((int)(c - name) + l_value + 2))))
131 return (-1);
132 for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
133 for (*c++ = '='; *c++ = *value++;);
134 return (0);
135 }
136
137 /*%
138 * unsetenv(name) --
139 * Delete environmental variable "name".
140 */
141 int
142 unsetenv(const char *name)
143 {
144 char **p;
145 int offset;
146
147 if (strchr(name, '=') != NULL) {
148 errno = EINVAL;
149 return -1;
150 }
151
152 while (findenv(name, &offset)) /*%< if set multiple times */
153 for (p = &environ[offset];; ++p)
154 if (!(*p = *(p + 1)))
155 break;
156
157 return 0;
158 }
159
160 /*%
161 * findenv --
162 * Returns pointer to value associated with name, if any, else NULL.
163 * Sets offset to be the offset of the name/value combination in the
164 * environmental array, for use by setenv(3) and unsetenv(3).
165 * Explicitly removes '=' in argument name.
166 *
167 * This routine *should* be a static; don't use it.
168 */
169 static char *
170 findenv(const char *name, int *offset)
171 {
172 const char *np;
173 char **p, *c;
174 int len;
175
176 if (name == NULL || environ == NULL)
177 return (NULL);
178 for (np = name; *np && *np != '='; ++np)
179 continue;
180 len = np - name;
181 for (p = environ; (c = *p) != NULL; ++p)
182 if (strncmp(c, name, len) == 0 && c[len] == '=') {
183 *offset = p - environ;
184 return (c + len + 1);
185 }
186 return (NULL);
187 }
188 #endif
189
190 /*! \file */