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