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 #define _DEFAULT_SOURCE
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <envlock.h>
25
26 /*
27 * setenv --
28 * Set the value of the environmental variable "name" to be
29 * "value". If rewrite is set, replace any current value.
30 */
31
32 extern char **environ;
33
34 /* Only deal with a pointer to environ, to work around subtle bugs with shared
35 libraries and/or small data systems where the user declares his own
36 'environ'. */
37 static char ***p_environ = &environ;
38
39 int
setenv(const char * name,const char * value,int rewrite)40 setenv (const char *name,
41 const char *value,
42 int rewrite)
43 {
44 static int alloced; /* if allocated space before */
45 register char *C;
46 size_t l_value;
47 int offset;
48
49 /* Name cannot be NULL, empty, or contain an equal sign. */
50 if (name == NULL || name[0] == '\0' || strchr(name, '='))
51 {
52 errno = EINVAL;
53 return -1;
54 }
55
56 ENV_LOCK;
57
58 l_value = strlen (value);
59 if ((C = _findenv (name, &offset)))
60 { /* find if already exists */
61 if (!rewrite)
62 {
63 ENV_UNLOCK;
64 return 0;
65 }
66 if (strlen (C) >= l_value)
67 { /* old larger; copy over */
68 strcpy(C, value);
69 ENV_UNLOCK;
70 return 0;
71 }
72 }
73 else
74 { /* create new slot */
75 register int cnt;
76 register char **P;
77
78 for (P = *p_environ, cnt = 0; *P; ++P, ++cnt);
79 if (alloced)
80 { /* just increase size */
81 *p_environ = (char **) realloc ((char *) environ,
82 (size_t) (sizeof (char *) * (cnt + 2)));
83 if (!*p_environ)
84 {
85 ENV_UNLOCK;
86 return -1;
87 }
88 }
89 else
90 { /* get new space */
91 alloced = 1; /* copy old entries into it */
92 P = (char **) malloc ((size_t) (sizeof (char *) * (cnt + 2)));
93 if (!P)
94 {
95 ENV_UNLOCK;
96 return (-1);
97 }
98 memcpy((char *) P,(char *) *p_environ, cnt * sizeof (char *));
99 *p_environ = P;
100 }
101 (*p_environ)[cnt + 1] = NULL;
102 offset = cnt;
103 }
104 for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
105 char *E = malloc ((size_t) ((int) (C - name) + l_value + 2));
106 if (!E)
107 {
108 ENV_UNLOCK;
109 return -1;
110 }
111 (*p_environ)[offset] = E;
112 for (C = E; (*C = *name++) && *C != '='; ++C);
113 for (*C++ = '='; (*C++ = *value++) != 0;);
114
115 ENV_UNLOCK;
116
117 return 0;
118 }
119
120 /*
121 * unsetenv(name) --
122 * Delete environmental variable "name".
123 */
124 int
unsetenv(const char * name)125 unsetenv (const char *name)
126 {
127 register char **P;
128 int offset;
129
130 /* Name cannot be NULL, empty, or contain an equal sign. */
131 if (name == NULL || name[0] == '\0' || strchr(name, '='))
132 {
133 errno = EINVAL;
134 return -1;
135 }
136
137 ENV_LOCK;
138
139 while (_findenv (name, &offset)) /* if set multiple times */
140 {
141 for (P = &(*p_environ)[offset];; ++P)
142 if (!(*P = *(P + 1)))
143 break;
144 }
145
146 ENV_UNLOCK;
147 return 0;
148 }
149