1 /*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution.
11 * Neither the name of the University nor the names of its
12 * contributors may be used to endorse or promote products derived
13 * from this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18
19 #ifndef _REENT_ONLY
20
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <envlock.h>
26
27 /*
28 * setenv --
29 * Set the value of the environmental variable "name" to be
30 * "value". If rewrite is set, replace any current value.
31 */
32
33 extern char **environ;
34
35 /* Only deal with a pointer to environ, to work around subtle bugs with shared
36 libraries and/or small data systems where the user declares his own
37 'environ'. */
38 static char ***p_environ = &environ;
39
40 int
setenv(const char * name,const char * value,int rewrite)41 setenv (const char *name,
42 const char *value,
43 int rewrite)
44 {
45 static int alloced; /* if allocated space before */
46 register char *C;
47 size_t l_value;
48 int offset;
49
50 /* Name cannot be NULL, empty, or contain an equal sign. */
51 if (name == NULL || name[0] == '\0' || strchr(name, '='))
52 {
53 errno = EINVAL;
54 return -1;
55 }
56
57 ENV_LOCK;
58
59 l_value = strlen (value);
60 if ((C = _findenv (name, &offset)))
61 { /* find if already exists */
62 if (!rewrite)
63 {
64 ENV_UNLOCK;
65 return 0;
66 }
67 if (strlen (C) >= l_value)
68 { /* old larger; copy over */
69 strcpy(C, value);
70 ENV_UNLOCK;
71 return 0;
72 }
73 }
74 else
75 { /* create new slot */
76 register int cnt;
77 register char **P;
78
79 for (P = *p_environ, cnt = 0; *P; ++P, ++cnt);
80 if (alloced)
81 { /* just increase size */
82 *p_environ = (char **) realloc ((char *) environ,
83 (size_t) (sizeof (char *) * (cnt + 2)));
84 if (!*p_environ)
85 {
86 ENV_UNLOCK;
87 return -1;
88 }
89 }
90 else
91 { /* get new space */
92 alloced = 1; /* copy old entries into it */
93 P = (char **) malloc ((size_t) (sizeof (char *) * (cnt + 2)));
94 if (!P)
95 {
96 ENV_UNLOCK;
97 return (-1);
98 }
99 memcpy((char *) P,(char *) *p_environ, cnt * sizeof (char *));
100 *p_environ = P;
101 }
102 (*p_environ)[cnt + 1] = NULL;
103 offset = cnt;
104 }
105 for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
106 char *E = malloc ((size_t) ((int) (C - name) + l_value + 2));
107 if (!E)
108 {
109 ENV_UNLOCK;
110 return -1;
111 }
112 (*p_environ)[offset] = E;
113 for (C = E; (*C = *name++) && *C != '='; ++C);
114 for (*C++ = '='; (*C++ = *value++) != 0;);
115
116 ENV_UNLOCK;
117
118 return 0;
119 }
120
121 /*
122 * unsetenv(name) --
123 * Delete environmental variable "name".
124 */
125 int
unsetenv(const char * name)126 unsetenv (const char *name)
127 {
128 register char **P;
129 int offset;
130
131 /* Name cannot be NULL, empty, or contain an equal sign. */
132 if (name == NULL || name[0] == '\0' || strchr(name, '='))
133 {
134 errno = EINVAL;
135 return -1;
136 }
137
138 ENV_LOCK;
139
140 while (_findenv (name, &offset)) /* if set multiple times */
141 {
142 for (P = &(*p_environ)[offset];; ++P)
143 if (!(*P = *(P + 1)))
144 break;
145 }
146
147 ENV_UNLOCK;
148 return 0;
149 }
150
151 #endif /* !_REENT_ONLY */
152