6 * Many systems have putenv() but no setenv(). Other systems have setenv() but
7 * no putenv() (MIPS). Still other systems have neither (NeXT). This is a
8 * re-implementation that hopefully ends all problems.
10 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
14 #ifdef MISSING_SETENV_PUTENV
20 extern char **environ
;
22 static int addenv(char *); /* append entry to environment */
23 static int allocated
= 0; /* environ is, or is not, allocated */
27 /* namelength - determine length of name in "name=whatever" */
29 static ssize_t
namelength(const char *name
)
33 equal
= strchr(name
, '=');
34 return ((equal
== 0) ? strlen(name
) : (equal
- name
));
37 /* findenv - given name, locate name=value */
39 static char **findenv(const char *name
, ssize_t len
)
43 for (envp
= environ
; envp
&& *envp
; envp
++)
44 if (strncmp(name
, *envp
, len
) == 0 && (*envp
)[len
] == '=')
51 /* getenv - given name, locate value */
53 char *getenv(const char *name
)
55 ssize_t len
= namelength(name
);
56 char **envp
= findenv(name
, len
);
58 return (envp
? *envp
+ len
+ 1 : 0);
61 /* putenv - update or append environment (name,value) pair */
63 int putenv(const char *nameval
)
65 char *equal
= strchr(nameval
, '=');
66 char *value
= (equal
? equal
: "");
68 return (setenv(nameval
, value
, DO_CLOBBER
));
71 /* unsetenv - remove variable from environment */
73 void unsetenv(const char *name
)
77 while ((envp
= findenv(name
, namelength(name
))) != 0)
78 while (envp
[0] = envp
[1])
84 /* setenv - update or append environment (name,value) pair */
86 int setenv(const char *name
, const char *value
, int clobber
)
90 ssize_t l_name
; /* length of name part */
91 unsigned int l_nameval
; /* length of name=value */
93 /* Permit name= and =value. */
95 l_name
= namelength(name
);
96 envp
= findenv(name
, l_name
);
97 if (envp
!= 0 && clobber
== 0)
101 l_nameval
= l_name
+ strlen(value
) + 1;
104 * Use available memory if the old value is long enough. Never free an
105 * old name=value entry because it may not be allocated.
108 destination
= (envp
!= 0 && strlen(*envp
) >= l_nameval
) ?
109 *envp
: malloc(l_nameval
+ 1);
110 if (destination
== 0)
112 strncpy(destination
, name
, l_name
);
113 destination
[l_name
] = '=';
114 strcpy(destination
+ l_name
+ 1, value
);
115 return ((envp
== 0) ? addenv(destination
) : (*envp
= destination
, 0));
118 /* cmalloc - malloc and copy block of memory */
120 static char *cmalloc(ssize_t new_len
, char *old
, ssize_t old_len
)
122 char *new = malloc(new_len
);
125 memcpy(new, old
, old_len
);
129 /* addenv - append environment entry */
131 static int addenv(char *nameval
)
134 ssize_t n_used
; /* number of environment entries */
135 ssize_t l_used
; /* bytes used excl. terminator */
136 ssize_t l_need
; /* bytes needed incl. terminator */
138 for (envp
= environ
; envp
&& *envp
; envp
++)
140 n_used
= envp
- environ
;
141 l_used
= n_used
* sizeof(*envp
);
142 l_need
= l_used
+ 2 * sizeof(*envp
);
145 (char **) realloc((char *) environ
, l_need
) :
146 (char **) cmalloc(l_need
, (char *) environ
, l_used
);
152 environ
[n_used
++] = nameval
; /* add new entry */
153 environ
[n_used
] = 0; /* terminate list */