1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Many systems have putenv() but no setenv(). Other systems have setenv()
3*86d7f5d3SJohn Marino * but no putenv() (MIPS). Still other systems have neither (NeXT). This is a
4*86d7f5d3SJohn Marino * re-implementation that hopefully ends all problems.
5*86d7f5d3SJohn Marino *
6*86d7f5d3SJohn Marino * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
7*86d7f5d3SJohn Marino */
8*86d7f5d3SJohn Marino
9*86d7f5d3SJohn Marino #ifndef lint
10*86d7f5d3SJohn Marino static char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46";
11*86d7f5d3SJohn Marino #endif
12*86d7f5d3SJohn Marino
13*86d7f5d3SJohn Marino /* System libraries. */
14*86d7f5d3SJohn Marino
15*86d7f5d3SJohn Marino extern char **environ;
16*86d7f5d3SJohn Marino extern char *strchr();
17*86d7f5d3SJohn Marino extern char *strcpy();
18*86d7f5d3SJohn Marino extern char *strncpy();
19*86d7f5d3SJohn Marino extern char *malloc();
20*86d7f5d3SJohn Marino extern char *realloc();
21*86d7f5d3SJohn Marino extern int strncmp();
22*86d7f5d3SJohn Marino extern void free();
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino #ifdef no_memcpy
25*86d7f5d3SJohn Marino #define memcpy(d,s,l) bcopy(s,d,l)
26*86d7f5d3SJohn Marino #else
27*86d7f5d3SJohn Marino extern char *memcpy();
28*86d7f5d3SJohn Marino #endif
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /* Local stuff. */
31*86d7f5d3SJohn Marino
32*86d7f5d3SJohn Marino static int addenv(); /* append entry to environment */
33*86d7f5d3SJohn Marino
34*86d7f5d3SJohn Marino static int allocated = 0; /* environ is, or is not, allocated */
35*86d7f5d3SJohn Marino
36*86d7f5d3SJohn Marino #define DO_CLOBBER 1
37*86d7f5d3SJohn Marino
38*86d7f5d3SJohn Marino /* namelength - determine length of name in "name=whatever" */
39*86d7f5d3SJohn Marino
namelength(name)40*86d7f5d3SJohn Marino static int namelength(name)
41*86d7f5d3SJohn Marino char *name;
42*86d7f5d3SJohn Marino {
43*86d7f5d3SJohn Marino char *equal;
44*86d7f5d3SJohn Marino
45*86d7f5d3SJohn Marino equal = strchr(name, '=');
46*86d7f5d3SJohn Marino return ((equal == 0) ? strlen(name) : (equal - name));
47*86d7f5d3SJohn Marino }
48*86d7f5d3SJohn Marino
49*86d7f5d3SJohn Marino /* findenv - given name, locate name=value */
50*86d7f5d3SJohn Marino
findenv(name,len)51*86d7f5d3SJohn Marino static char **findenv(name, len)
52*86d7f5d3SJohn Marino char *name;
53*86d7f5d3SJohn Marino int len;
54*86d7f5d3SJohn Marino {
55*86d7f5d3SJohn Marino char **envp;
56*86d7f5d3SJohn Marino
57*86d7f5d3SJohn Marino for (envp = environ; envp && *envp; envp++)
58*86d7f5d3SJohn Marino if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
59*86d7f5d3SJohn Marino return (envp);
60*86d7f5d3SJohn Marino return (0);
61*86d7f5d3SJohn Marino }
62*86d7f5d3SJohn Marino
63*86d7f5d3SJohn Marino /* getenv - given name, locate value */
64*86d7f5d3SJohn Marino
getenv(name)65*86d7f5d3SJohn Marino char *getenv(name)
66*86d7f5d3SJohn Marino char *name;
67*86d7f5d3SJohn Marino {
68*86d7f5d3SJohn Marino int len = namelength(name);
69*86d7f5d3SJohn Marino char **envp = findenv(name, len);
70*86d7f5d3SJohn Marino
71*86d7f5d3SJohn Marino return (envp ? *envp + len + 1 : 0);
72*86d7f5d3SJohn Marino }
73*86d7f5d3SJohn Marino
74*86d7f5d3SJohn Marino /* putenv - update or append environment (name,value) pair */
75*86d7f5d3SJohn Marino
putenv(nameval)76*86d7f5d3SJohn Marino int putenv(nameval)
77*86d7f5d3SJohn Marino char *nameval;
78*86d7f5d3SJohn Marino {
79*86d7f5d3SJohn Marino char *equal = strchr(nameval, '=');
80*86d7f5d3SJohn Marino char *value = (equal ? equal : "");
81*86d7f5d3SJohn Marino
82*86d7f5d3SJohn Marino return (setenv(nameval, value, DO_CLOBBER));
83*86d7f5d3SJohn Marino }
84*86d7f5d3SJohn Marino
85*86d7f5d3SJohn Marino /* unsetenv - remove variable from environment */
86*86d7f5d3SJohn Marino
unsetenv(name)87*86d7f5d3SJohn Marino void unsetenv(name)
88*86d7f5d3SJohn Marino char *name;
89*86d7f5d3SJohn Marino {
90*86d7f5d3SJohn Marino char **envp;
91*86d7f5d3SJohn Marino
92*86d7f5d3SJohn Marino if ((envp = findenv(name, namelength(name))) != 0)
93*86d7f5d3SJohn Marino while (envp[0] = envp[1])
94*86d7f5d3SJohn Marino envp++;
95*86d7f5d3SJohn Marino }
96*86d7f5d3SJohn Marino
97*86d7f5d3SJohn Marino /* setenv - update or append environment (name,value) pair */
98*86d7f5d3SJohn Marino
setenv(name,value,clobber)99*86d7f5d3SJohn Marino int setenv(name, value, clobber)
100*86d7f5d3SJohn Marino char *name;
101*86d7f5d3SJohn Marino char *value;
102*86d7f5d3SJohn Marino int clobber;
103*86d7f5d3SJohn Marino {
104*86d7f5d3SJohn Marino char *destination;
105*86d7f5d3SJohn Marino char **envp;
106*86d7f5d3SJohn Marino int l_name; /* length of name part */
107*86d7f5d3SJohn Marino int l_nameval; /* length of name=value */
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino /* Permit name= and =value. */
110*86d7f5d3SJohn Marino
111*86d7f5d3SJohn Marino l_name = namelength(name);
112*86d7f5d3SJohn Marino envp = findenv(name, l_name);
113*86d7f5d3SJohn Marino if (envp != 0 && clobber == 0)
114*86d7f5d3SJohn Marino return (0);
115*86d7f5d3SJohn Marino if (*value == '=')
116*86d7f5d3SJohn Marino value++;
117*86d7f5d3SJohn Marino l_nameval = l_name + strlen(value) + 1;
118*86d7f5d3SJohn Marino
119*86d7f5d3SJohn Marino /*
120*86d7f5d3SJohn Marino * Use available memory if the old value is long enough. Never free an
121*86d7f5d3SJohn Marino * old name=value entry because it may not be allocated.
122*86d7f5d3SJohn Marino */
123*86d7f5d3SJohn Marino
124*86d7f5d3SJohn Marino destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
125*86d7f5d3SJohn Marino *envp : malloc(l_nameval + 1);
126*86d7f5d3SJohn Marino if (destination == 0)
127*86d7f5d3SJohn Marino return (-1);
128*86d7f5d3SJohn Marino strncpy(destination, name, l_name);
129*86d7f5d3SJohn Marino destination[l_name] = '=';
130*86d7f5d3SJohn Marino strcpy(destination + l_name + 1, value);
131*86d7f5d3SJohn Marino return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
132*86d7f5d3SJohn Marino }
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino /* cmalloc - malloc and copy block of memory */
135*86d7f5d3SJohn Marino
cmalloc(new_len,old,old_len)136*86d7f5d3SJohn Marino static char *cmalloc(new_len, old, old_len)
137*86d7f5d3SJohn Marino char *old;
138*86d7f5d3SJohn Marino int old_len;
139*86d7f5d3SJohn Marino {
140*86d7f5d3SJohn Marino char *new = malloc(new_len);
141*86d7f5d3SJohn Marino
142*86d7f5d3SJohn Marino if (new != 0)
143*86d7f5d3SJohn Marino memcpy(new, old, old_len);
144*86d7f5d3SJohn Marino return (new);
145*86d7f5d3SJohn Marino }
146*86d7f5d3SJohn Marino
147*86d7f5d3SJohn Marino /* addenv - append environment entry */
148*86d7f5d3SJohn Marino
addenv(nameval)149*86d7f5d3SJohn Marino static int addenv(nameval)
150*86d7f5d3SJohn Marino char *nameval;
151*86d7f5d3SJohn Marino {
152*86d7f5d3SJohn Marino char **envp;
153*86d7f5d3SJohn Marino int n_used; /* number of environment entries */
154*86d7f5d3SJohn Marino int l_used; /* bytes used excl. terminator */
155*86d7f5d3SJohn Marino int l_need; /* bytes needed incl. terminator */
156*86d7f5d3SJohn Marino
157*86d7f5d3SJohn Marino for (envp = environ; envp && *envp; envp++)
158*86d7f5d3SJohn Marino /* void */ ;
159*86d7f5d3SJohn Marino n_used = envp - environ;
160*86d7f5d3SJohn Marino l_used = n_used * sizeof(*envp);
161*86d7f5d3SJohn Marino l_need = l_used + 2 * sizeof(*envp);
162*86d7f5d3SJohn Marino
163*86d7f5d3SJohn Marino envp = allocated ?
164*86d7f5d3SJohn Marino (char **) realloc((char *) environ, l_need) :
165*86d7f5d3SJohn Marino (char **) cmalloc(l_need, (char *) environ, l_used);
166*86d7f5d3SJohn Marino if (envp == 0) {
167*86d7f5d3SJohn Marino return (-1);
168*86d7f5d3SJohn Marino } else {
169*86d7f5d3SJohn Marino allocated = 1;
170*86d7f5d3SJohn Marino environ = envp;
171*86d7f5d3SJohn Marino environ[n_used++] = nameval; /* add new entry */
172*86d7f5d3SJohn Marino environ[n_used] = 0; /* terminate list */
173*86d7f5d3SJohn Marino return (0);
174*86d7f5d3SJohn Marino }
175*86d7f5d3SJohn Marino }
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino #ifdef TEST
178*86d7f5d3SJohn Marino
179*86d7f5d3SJohn Marino /*
180*86d7f5d3SJohn Marino * Stand-alone program for test purposes.
181*86d7f5d3SJohn Marino */
182*86d7f5d3SJohn Marino
183*86d7f5d3SJohn Marino /* printenv - display environment */
184*86d7f5d3SJohn Marino
printenv()185*86d7f5d3SJohn Marino static void printenv()
186*86d7f5d3SJohn Marino {
187*86d7f5d3SJohn Marino char **envp;
188*86d7f5d3SJohn Marino
189*86d7f5d3SJohn Marino for (envp = environ; envp && *envp; envp++)
190*86d7f5d3SJohn Marino printf("%s\n", *envp);
191*86d7f5d3SJohn Marino }
192*86d7f5d3SJohn Marino
main(argc,argv)193*86d7f5d3SJohn Marino int main(argc, argv)
194*86d7f5d3SJohn Marino int argc;
195*86d7f5d3SJohn Marino char **argv;
196*86d7f5d3SJohn Marino {
197*86d7f5d3SJohn Marino char *cp;
198*86d7f5d3SJohn Marino int changed = 0;
199*86d7f5d3SJohn Marino
200*86d7f5d3SJohn Marino if (argc < 2) {
201*86d7f5d3SJohn Marino printf("usage: %s name[=value]...\n", argv[0]);
202*86d7f5d3SJohn Marino return (1);
203*86d7f5d3SJohn Marino }
204*86d7f5d3SJohn Marino while (--argc && *++argv) {
205*86d7f5d3SJohn Marino if (argv[0][0] == '-') { /* unsetenv() test */
206*86d7f5d3SJohn Marino unsetenv(argv[0] + 1);
207*86d7f5d3SJohn Marino changed = 1;
208*86d7f5d3SJohn Marino } else if (strchr(argv[0], '=') == 0) { /* getenv() test */
209*86d7f5d3SJohn Marino cp = getenv(argv[0]);
210*86d7f5d3SJohn Marino printf("%s: %s\n", argv[0], cp ? cp : "not found");
211*86d7f5d3SJohn Marino } else { /* putenv() test */
212*86d7f5d3SJohn Marino if (putenv(argv[0])) {
213*86d7f5d3SJohn Marino perror("putenv");
214*86d7f5d3SJohn Marino return (1);
215*86d7f5d3SJohn Marino }
216*86d7f5d3SJohn Marino changed = 1;
217*86d7f5d3SJohn Marino }
218*86d7f5d3SJohn Marino }
219*86d7f5d3SJohn Marino if (changed)
220*86d7f5d3SJohn Marino printenv();
221*86d7f5d3SJohn Marino return (0);
222*86d7f5d3SJohn Marino }
223*86d7f5d3SJohn Marino
224*86d7f5d3SJohn Marino #endif /* TEST */
225