diff options
Diffstat (limited to 'src/lib/libc/stdlib/setenv.c')
-rw-r--r-- | src/lib/libc/stdlib/setenv.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c new file mode 100644 index 0000000000..089ab92d38 --- /dev/null +++ b/src/lib/libc/stdlib/setenv.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert 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 | char *__findenv(const char *name, int len, int *offset); | ||
36 | |||
37 | extern char **environ; | ||
38 | static char **lastenv; /* last value of environ */ | ||
39 | |||
40 | /* | ||
41 | * putenv -- | ||
42 | * Add a name=value string directly to the environmental, replacing | ||
43 | * any current value. | ||
44 | */ | ||
45 | int | ||
46 | putenv(char *str) | ||
47 | { | ||
48 | char **P, *cp; | ||
49 | size_t cnt; | ||
50 | int offset = 0; | ||
51 | |||
52 | for (cp = str; *cp && *cp != '='; ++cp) | ||
53 | ; | ||
54 | if (*cp != '=') { | ||
55 | errno = EINVAL; | ||
56 | return (-1); /* missing `=' in string */ | ||
57 | } | ||
58 | |||
59 | if (__findenv(str, (int)(cp - str), &offset) != NULL) { | ||
60 | environ[offset++] = str; | ||
61 | /* could be set multiple times */ | ||
62 | while (__findenv(str, (int)(cp - str), &offset)) { | ||
63 | for (P = &environ[offset];; ++P) | ||
64 | if (!(*P = *(P + 1))) | ||
65 | break; | ||
66 | } | ||
67 | return (0); | ||
68 | } | ||
69 | |||
70 | /* create new slot for string */ | ||
71 | for (P = environ; *P != NULL; P++) | ||
72 | ; | ||
73 | cnt = P - environ; | ||
74 | P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); | ||
75 | if (!P) | ||
76 | return (-1); | ||
77 | if (lastenv != environ) | ||
78 | memcpy(P, environ, cnt * sizeof(char *)); | ||
79 | lastenv = environ = P; | ||
80 | environ[cnt] = str; | ||
81 | environ[cnt + 1] = NULL; | ||
82 | return (0); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * setenv -- | ||
87 | * Set the value of the environmental variable "name" to be | ||
88 | * "value". If rewrite is set, replace any current value. | ||
89 | */ | ||
90 | int | ||
91 | setenv(const char *name, const char *value, int rewrite) | ||
92 | { | ||
93 | char *C, **P; | ||
94 | const char *np; | ||
95 | int l_value, offset = 0; | ||
96 | |||
97 | for (np = name; *np && *np != '='; ++np) | ||
98 | ; | ||
99 | #ifdef notyet | ||
100 | if (*np) { | ||
101 | errno = EINVAL; | ||
102 | return (-1); /* has `=' in name */ | ||
103 | } | ||
104 | #endif | ||
105 | |||
106 | l_value = strlen(value); | ||
107 | if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { | ||
108 | int tmpoff = offset + 1; | ||
109 | if (!rewrite) | ||
110 | return (0); | ||
111 | #if 0 /* XXX - existing entry may not be writable */ | ||
112 | if (strlen(C) >= l_value) { /* old larger; copy over */ | ||
113 | while ((*C++ = *value++)) | ||
114 | ; | ||
115 | return (0); | ||
116 | } | ||
117 | #endif | ||
118 | /* could be set multiple times */ | ||
119 | while (__findenv(name, (int)(np - name), &tmpoff)) { | ||
120 | for (P = &environ[tmpoff];; ++P) | ||
121 | if (!(*P = *(P + 1))) | ||
122 | break; | ||
123 | } | ||
124 | } else { /* create new slot */ | ||
125 | size_t cnt; | ||
126 | |||
127 | for (P = environ; *P != NULL; P++) | ||
128 | ; | ||
129 | cnt = P - environ; | ||
130 | P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); | ||
131 | if (!P) | ||
132 | return (-1); | ||
133 | if (lastenv != environ) | ||
134 | memcpy(P, environ, cnt * sizeof(char *)); | ||
135 | lastenv = environ = P; | ||
136 | offset = cnt; | ||
137 | environ[cnt + 1] = NULL; | ||
138 | } | ||
139 | if (!(environ[offset] = /* name + `=' + value */ | ||
140 | malloc((size_t)((int)(np - name) + l_value + 2)))) | ||
141 | return (-1); | ||
142 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) | ||
143 | ; | ||
144 | for (*C++ = '='; (*C++ = *value++); ) | ||
145 | ; | ||
146 | return (0); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * unsetenv(name) -- | ||
151 | * Delete environmental variable "name". | ||
152 | */ | ||
153 | int | ||
154 | unsetenv(const char *name) | ||
155 | { | ||
156 | char **P; | ||
157 | const char *np; | ||
158 | int offset = 0; | ||
159 | |||
160 | if (!name || !*name) { | ||
161 | errno = EINVAL; | ||
162 | return (-1); | ||
163 | } | ||
164 | for (np = name; *np && *np != '='; ++np) | ||
165 | ; | ||
166 | if (*np) { | ||
167 | errno = EINVAL; | ||
168 | return (-1); /* has `=' in name */ | ||
169 | } | ||
170 | |||
171 | /* could be set multiple times */ | ||
172 | while (__findenv(name, (int)(np - name), &offset)) { | ||
173 | for (P = &environ[offset];; ++P) | ||
174 | if (!(*P = *(P + 1))) | ||
175 | break; | ||
176 | } | ||
177 | return (0); | ||
178 | } | ||