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   if (strchr(name, '='))
51     {
52 	    __errno_r(ptr) = 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   if (!((*p_environ)[offset] =	/* name + `=' + value */
106 	malloc ((size_t) ((int) (C - name) + l_value + 2))))
107     {
108       ENV_UNLOCK;
109       return -1;
110     }
111   for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C);
112   for (*C++ = '='; (*C++ = *value++) != 0;);
113 
114   ENV_UNLOCK;
115 
116   return 0;
117 }
118 
119 /*
120  * unsetenv(name) --
121  *	Delete environmental variable "name".
122  */
123 int
unsetenv(const char * name)124 unsetenv (const char *name)
125 {
126   register char **P;
127   int offset;
128 
129   /* Name cannot be NULL, empty, or contain an equal sign.  */
130   if (name == NULL || name[0] == '\0' || strchr(name, '='))
131     {
132       errno = EINVAL;
133       return -1;
134     }
135 
136   ENV_LOCK;
137 
138   while (_findenv (name, &offset))	/* if set multiple times */
139     {
140       for (P = &(*p_environ)[offset];; ++P)
141         if (!(*P = *(P + 1)))
142 	  break;
143     }
144 
145   ENV_UNLOCK;
146   return 0;
147 }
148 
149 #endif /* !_REENT_ONLY */
150