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(name
)
45 equal
= strchr(name
, '=');
46 return ((equal
== 0) ? strlen(name
) : (equal
- name
));
49 /* findenv - given name, locate name=value */
51 static char **findenv(name
, len
)
57 for (envp
= environ
; envp
&& *envp
; envp
++)
58 if (strncmp(name
, *envp
, len
) == 0 && (*envp
)[len
] == '=')
63 /* getenv - given name, locate value */
68 int len
= namelength(name
);
69 char **envp
= findenv(name
, len
);
71 return (envp
? *envp
+ len
+ 1 : 0);
74 /* putenv - update or append environment (name,value) pair */
79 char *equal
= strchr(nameval
, '=');
80 char *value
= (equal
? equal
: "");
82 return (setenv(nameval
, value
, DO_CLOBBER
));
85 /* unsetenv - remove variable from environment */
92 if ((envp
= findenv(name
, namelength(name
))) != 0)
93 while (envp
[0] = envp
[1])
97 /* setenv - update or append environment (name,value) pair */
99 int setenv(name
, value
, clobber
)
106 int l_name
; /* length of name part */
107 int l_nameval
; /* length of name=value */
109 /* Permit name= and =value. */
111 l_name
= namelength(name
);
112 envp
= findenv(name
, l_name
);
113 if (envp
!= 0 && clobber
== 0)
117 l_nameval
= l_name
+ strlen(value
) + 1;
120 * Use available memory if the old value is long enough. Never free an
121 * old name=value entry because it may not be allocated.
124 destination
= (envp
!= 0 && strlen(*envp
) >= l_nameval
) ?
125 *envp
: malloc(l_nameval
+ 1);
126 if (destination
== 0)
128 strncpy(destination
, name
, l_name
);
129 destination
[l_name
] = '=';
130 strcpy(destination
+ l_name
+ 1, value
);
131 return ((envp
== 0) ? addenv(destination
) : (*envp
= destination
, 0));
134 /* cmalloc - malloc and copy block of memory */
136 static char *cmalloc(new_len
, old
, old_len
)
140 char *new = malloc(new_len
);
143 memcpy(new, old
, old_len
);
147 /* addenv - append environment entry */
149 static int addenv(nameval
)
153 int n_used
; /* number of environment entries */
154 int l_used
; /* bytes used excl. terminator */
155 int l_need
; /* bytes needed incl. terminator */
157 for (envp
= environ
; envp
&& *envp
; envp
++)
159 n_used
= envp
- environ
;
160 l_used
= n_used
* sizeof(*envp
);
161 l_need
= l_used
+ 2 * sizeof(*envp
);
164 (char **) realloc((char *) environ
, l_need
) :
165 (char **) cmalloc(l_need
, (char *) environ
, l_used
);
171 environ
[n_used
++] = nameval
; /* add new entry */
172 environ
[n_used
] = 0; /* terminate list */
180 * Stand-alone program for test purposes.
183 /* printenv - display environment */
185 static void printenv()
189 for (envp
= environ
; envp
&& *envp
; envp
++)
190 printf("%s\n", *envp
);
201 printf("usage: %s name[=value]...\n", argv
[0]);
204 while (--argc
&& *++argv
) {
205 if (argv
[0][0] == '-') { /* unsetenv() test */
206 unsetenv(argv
[0] + 1);
208 } else if (strchr(argv
[0], '=') == 0) { /* getenv() test */
209 cp
= getenv(argv
[0]);
210 printf("%s: %s\n", argv
[0], cp
? cp
: "not found");
211 } else { /* putenv() test */
212 if (putenv(argv
[0])) {