xref: /onnv-gate/usr/src/cmd/tcpd/environ.c (revision 0:68f95e015346)
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