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