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