1 /* $OpenBSD: setenv.c,v 1.16 2015/09/13 08:31:47 guenther Exp $ */
2 /*
3 * Copyright (c) 1987 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 extern char **environ;
36 static char **lastenv; /* last value of environ */
37
38 /*
39 * putenv --
40 * Add a name=value string directly to the environmental, replacing
41 * any current value.
42 */
43 int
putenv(char * str)44 putenv(char *str)
45 {
46 char **P, *cp;
47 size_t cnt;
48 int offset = 0;
49
50 for (cp = str; *cp && *cp != '='; ++cp)
51 ;
52 if (*cp != '=') {
53 errno = EINVAL;
54 return (-1); /* missing `=' in string */
55 }
56
57 if (__findenv(str, (int)(cp - str), &offset) != NULL) {
58 environ[offset++] = str;
59 /* could be set multiple times */
60 while (__findenv(str, (int)(cp - str), &offset)) {
61 for (P = &environ[offset];; ++P)
62 if (!(*P = *(P + 1)))
63 break;
64 }
65 return (0);
66 }
67
68 /* create new slot for string */
69 for (P = environ; *P != NULL; P++)
70 ;
71 cnt = P - environ;
72 P = reallocarray(lastenv, cnt + 2, sizeof(char *));
73 if (!P)
74 return (-1);
75 if (lastenv != environ)
76 memcpy(P, environ, cnt * sizeof(char *));
77 lastenv = environ = P;
78 environ[cnt] = str;
79 environ[cnt + 1] = NULL;
80 return (0);
81 }
82 DEF_WEAK(putenv);
83
84 /*
85 * setenv --
86 * Set the value of the environmental variable "name" to be
87 * "value". If rewrite is set, replace any current value.
88 */
89 int
setenv(const char * name,const char * value,int rewrite)90 setenv(const char *name, const char *value, int rewrite)
91 {
92 char *C, **P;
93 const char *np;
94 int l_value, offset = 0;
95
96 if (!name || !*name) {
97 errno = EINVAL;
98 return (-1);
99 }
100 for (np = name; *np && *np != '='; ++np)
101 ;
102 if (*np) {
103 errno = EINVAL;
104 return (-1); /* has `=' in name */
105 }
106
107 l_value = strlen(value);
108 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
109 int tmpoff = offset + 1;
110 if (!rewrite)
111 return (0);
112 #if 0 /* XXX - existing entry may not be writable */
113 if (strlen(C) >= l_value) { /* old larger; copy over */
114 while ((*C++ = *value++))
115 ;
116 return (0);
117 }
118 #endif
119 /* could be set multiple times */
120 while (__findenv(name, (int)(np - name), &tmpoff)) {
121 for (P = &environ[tmpoff];; ++P)
122 if (!(*P = *(P + 1)))
123 break;
124 }
125 } else { /* create new slot */
126 size_t cnt;
127
128 for (P = environ; *P != NULL; P++)
129 ;
130 cnt = P - environ;
131 P = reallocarray(lastenv, cnt + 2, sizeof(char *));
132 if (!P)
133 return (-1);
134 if (lastenv != environ)
135 memcpy(P, environ, cnt * sizeof(char *));
136 lastenv = environ = P;
137 offset = cnt;
138 environ[cnt + 1] = NULL;
139 }
140 if (!(environ[offset] = /* name + `=' + value */
141 malloc((size_t)((int)(np - name) + l_value + 2))))
142 return (-1);
143 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
144 ;
145 for (*C++ = '='; (*C++ = *value++); )
146 ;
147 return (0);
148 }
149 DEF_WEAK(setenv);
150
151 /*
152 * unsetenv(name) --
153 * Delete environmental variable "name".
154 */
155 int
unsetenv(const char * name)156 unsetenv(const char *name)
157 {
158 char **P;
159 const char *np;
160 int offset = 0;
161
162 if (!name || !*name) {
163 errno = EINVAL;
164 return (-1);
165 }
166 for (np = name; *np && *np != '='; ++np)
167 ;
168 if (*np) {
169 errno = EINVAL;
170 return (-1); /* has `=' in name */
171 }
172
173 /* could be set multiple times */
174 while (__findenv(name, (int)(np - name), &offset)) {
175 for (P = &environ[offset];; ++P)
176 if (!(*P = *(P + 1)))
177 break;
178 }
179 return (0);
180 }
181 DEF_WEAK(unsetenv);
182