Merge commit 'crater/master'
[dragonfly.git] / contrib / tcp_wrappers / environ.c
blobe7f846ddd6b7a9251896793e16a42605f14460bd
1 /*
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.
7 */
9 #ifndef lint
10 static char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46";
11 #endif
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();
21 extern int strncmp();
22 extern void free();
24 #ifdef no_memcpy
25 #define memcpy(d,s,l) bcopy(s,d,l)
26 #else
27 extern char *memcpy();
28 #endif
30 /* Local stuff. */
32 static int addenv(); /* append entry to environment */
34 static int allocated = 0; /* environ is, or is not, allocated */
36 #define DO_CLOBBER 1
38 /* namelength - determine length of name in "name=whatever" */
40 static int namelength(name)
41 char *name;
43 char *equal;
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)
52 char *name;
53 int len;
55 char **envp;
57 for (envp = environ; envp && *envp; envp++)
58 if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
59 return (envp);
60 return (0);
63 /* getenv - given name, locate value */
65 char *getenv(name)
66 char *name;
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 */
76 int putenv(nameval)
77 char *nameval;
79 char *equal = strchr(nameval, '=');
80 char *value = (equal ? equal : "");
82 return (setenv(nameval, value, DO_CLOBBER));
85 /* unsetenv - remove variable from environment */
87 void unsetenv(name)
88 char *name;
90 char **envp;
92 if ((envp = findenv(name, namelength(name))) != 0)
93 while (envp[0] = envp[1])
94 envp++;
97 /* setenv - update or append environment (name,value) pair */
99 int setenv(name, value, clobber)
100 char *name;
101 char *value;
102 int clobber;
104 char *destination;
105 char **envp;
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)
114 return (0);
115 if (*value == '=')
116 value++;
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)
127 return (-1);
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)
137 char *old;
138 int old_len;
140 char *new = malloc(new_len);
142 if (new != 0)
143 memcpy(new, old, old_len);
144 return (new);
147 /* addenv - append environment entry */
149 static int addenv(nameval)
150 char *nameval;
152 char **envp;
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++)
158 /* void */ ;
159 n_used = envp - environ;
160 l_used = n_used * sizeof(*envp);
161 l_need = l_used + 2 * sizeof(*envp);
163 envp = allocated ?
164 (char **) realloc((char *) environ, l_need) :
165 (char **) cmalloc(l_need, (char *) environ, l_used);
166 if (envp == 0) {
167 return (-1);
168 } else {
169 allocated = 1;
170 environ = envp;
171 environ[n_used++] = nameval; /* add new entry */
172 environ[n_used] = 0; /* terminate list */
173 return (0);
177 #ifdef TEST
180 * Stand-alone program for test purposes.
183 /* printenv - display environment */
185 static void printenv()
187 char **envp;
189 for (envp = environ; envp && *envp; envp++)
190 printf("%s\n", *envp);
193 int main(argc, argv)
194 int argc;
195 char **argv;
197 char *cp;
198 int changed = 0;
200 if (argc < 2) {
201 printf("usage: %s name[=value]...\n", argv[0]);
202 return (1);
204 while (--argc && *++argv) {
205 if (argv[0][0] == '-') { /* unsetenv() test */
206 unsetenv(argv[0] + 1);
207 changed = 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])) {
213 perror("putenv");
214 return (1);
216 changed = 1;
219 if (changed)
220 printenv();
221 return (0);
224 #endif /* TEST */