2 * Many systems have putenv() but no setenv(). Other systems have setenv()
3 * but no putenv() (MIPS). Still other systems have neither (NeXT). This is a
4 * re-implementation that hopefully ends all problems.
6 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
10 static char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46";
13 /* System libraries. */
15 extern char **environ;
16 extern char *strchr();
17 extern char *strcpy();
18 extern char *strncpy();
19 extern char *malloc();
20 extern char *realloc();
25 #define memcpy(d,s,l) bcopy(s,d,l)
27 extern char *memcpy();
32 static int addenv(); /* append entry to environment */
34 static int allocated = 0; /* environ is, or is not, allocated */
38 /* namelength - determine length of name in "name=whatever" */
40 static int namelength(char *name)
44 equal = strchr(name, '=');
45 return ((equal == 0) ? strlen(name) : (equal - name));
48 /* findenv - given name, locate name=value */
50 static char **findenv(char *name, int len)
54 for (envp = environ; envp && *envp; envp++)
55 if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
60 /* getenv - given name, locate value */
62 char *getenv(char *name)
64 int len = namelength(name);
65 char **envp = findenv(name, len);
67 return (envp ? *envp + len + 1 : 0);
70 /* putenv - update or append environment (name,value) pair */
72 int putenv(char *nameval)
74 char *equal = strchr(nameval, '=');
75 char *value = (equal ? equal : "");
77 return (setenv(nameval, value, DO_CLOBBER));
80 /* unsetenv - remove variable from environment */
82 void unsetenv(char *name)
86 if ((envp = findenv(name, namelength(name))) != 0)
87 while (envp[0] = envp[1])
91 /* setenv - update or append environment (name,value) pair */
93 int setenv(char *name, char *value, int clobber)
97 int l_name; /* length of name part */
98 int l_nameval; /* length of name=value */
100 /* Permit name= and =value. */
102 l_name = namelength(name);
103 envp = findenv(name, l_name);
104 if (envp != 0 && clobber == 0)
108 l_nameval = l_name + strlen(value) + 1;
111 * Use available memory if the old value is long enough. Never free an
112 * old name=value entry because it may not be allocated.
115 destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
116 *envp : malloc(l_nameval + 1);
117 if (destination == 0)
119 strncpy(destination, name, l_name);
120 destination[l_name] = '=';
121 strcpy(destination + l_name + 1, value);
122 return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
125 /* cmalloc - malloc and copy block of memory */
127 static char *cmalloc(int new_len, char *old, int old_len)
129 char *new = malloc(new_len);
132 memcpy(new, old, old_len);
136 /* addenv - append environment entry */
138 static int addenv(char *nameval)
141 int n_used; /* number of environment entries */
142 int l_used; /* bytes used excl. terminator */
143 int l_need; /* bytes needed incl. terminator */
145 for (envp = environ; envp && *envp; envp++)
147 n_used = envp - environ;
148 l_used = n_used * sizeof(*envp);
149 l_need = l_used + 2 * sizeof(*envp);
152 (char **) realloc((char *) environ, l_need) :
153 (char **) cmalloc(l_need, (char *) environ, l_used);
159 environ[n_used++] = nameval; /* add new entry */
160 environ[n_used] = 0; /* terminate list */
168 * Stand-alone program for test purposes.
171 /* printenv - display environment */
173 static void printenv()
177 for (envp = environ; envp && *envp; envp++)
178 printf("%s\n", *envp);
181 int main(int argc, char **argv)
187 printf("usage: %s name[=value]...\n", argv[0]);
190 while (--argc && *++argv) {
191 if (argv[0][0] == '-') { /* unsetenv() test */
192 unsetenv(argv[0] + 1);
194 } else if (strchr(argv[0], '=') == 0) { /* getenv() test */
195 cp = getenv(argv[0]);
196 printf("%s: %s\n", argv[0], cp ? cp : "not found");
197 } else { /* putenv() test */
198 if (putenv(argv[0])) {