1236769Sobrien/*
2236769Sobrien * Copyright (c) 1987 Regents of the University of California.
3236769Sobrien * All rights reserved.
4236769Sobrien *
5236769Sobrien * Redistribution and use in source and binary forms, with or without
6236769Sobrien * modification, are permitted provided that the following conditions
7236769Sobrien * are met:
8236769Sobrien * 1. Redistributions of source code must retain the above copyright
9236769Sobrien *    notice, this list of conditions and the following disclaimer.
10236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright
11236769Sobrien *    notice, this list of conditions and the following disclaimer in the
12236769Sobrien *    documentation and/or other materials provided with the distribution.
13236769Sobrien * 3. All advertising materials mentioning features or use of this software
14236769Sobrien *    must display the following acknowledgement:
15236769Sobrien *	This product includes software developed by the University of
16236769Sobrien *	California, Berkeley and its contributors.
17236769Sobrien * 4. Neither the name of the University nor the names of its contributors
18236769Sobrien *    may be used to endorse or promote products derived from this software
19236769Sobrien *    without specific prior written permission.
20236769Sobrien *
21236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24236769Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31236769Sobrien * SUCH DAMAGE.
32236769Sobrien */
33236769Sobrien
34236769Sobrien#ifdef HAVE_CONFIG_H
35236769Sobrien# include "config.h"
36236769Sobrien#endif
37236769Sobrien#ifndef HAVE_SETENV
38236769Sobrien
39236769Sobrien#if defined(LIBC_SCCS) && !defined(lint)
40236769Sobrien/*static char *sccsid = "from: @(#)setenv.c	5.6 (Berkeley) 6/4/91";*/
41236769Sobrienstatic char *rcsid = "$Id: setenv.c,v 1.5 1996/09/04 22:10:42 sjg Exp $";
42236769Sobrien#endif /* LIBC_SCCS and not lint */
43236769Sobrien
44236769Sobrien#include <stddef.h>
45236769Sobrien#include <stdlib.h>
46236769Sobrien#include <string.h>
47236769Sobrien
48236769Sobrien/*
49236769Sobrien * __findenv --
50236769Sobrien *	Returns pointer to value associated with name, if any, else NULL.
51236769Sobrien *	Sets offset to be the offset of the name/value combination in the
52236769Sobrien *	environmental array, for use by setenv(3) and unsetenv(3).
53236769Sobrien *	Explicitly removes '=' in argument name.
54236769Sobrien *
55236769Sobrien *	This routine *should* be a static; don't use it.
56236769Sobrien */
57236769Sobrienstatic char *
58236769Sobrien__findenv(name, offset)
59236769Sobrien	register char *name;
60236769Sobrien	int *offset;
61236769Sobrien{
62236769Sobrien	extern char **environ;
63236769Sobrien	register int len;
64236769Sobrien	register char **P, *C;
65236769Sobrien
66236769Sobrien	for (C = name, len = 0; *C && *C != '='; ++C, ++len);
67236769Sobrien	for (P = environ; *P; ++P)
68236769Sobrien		if (!strncmp(*P, name, len))
69236769Sobrien			if (*(C = *P + len) == '=') {
70236769Sobrien				*offset = P - environ;
71236769Sobrien				return(++C);
72236769Sobrien			}
73236769Sobrien	return(NULL);
74236769Sobrien}
75236769Sobrien
76236769Sobrien/*
77236769Sobrien * setenv --
78236769Sobrien *	Set the value of the environmental variable "name" to be
79236769Sobrien *	"value".  If rewrite is set, replace any current value.
80236769Sobrien */
81236769Sobriensetenv(name, value, rewrite)
82236769Sobrien	register const char *name;
83236769Sobrien	register const char *value;
84236769Sobrien	int rewrite;
85236769Sobrien{
86236769Sobrien	extern char **environ;
87236769Sobrien	static int alloced;			/* if allocated space before */
88236769Sobrien	register char *C;
89236769Sobrien	int l_value, offset;
90236769Sobrien	char *__findenv();
91236769Sobrien
92236769Sobrien	if (*value == '=')			/* no `=' in value */
93236769Sobrien		++value;
94236769Sobrien	l_value = strlen(value);
95236769Sobrien	if ((C = __findenv(name, &offset))) {	/* find if already exists */
96236769Sobrien		if (!rewrite)
97236769Sobrien			return (0);
98236769Sobrien		if (strlen(C) >= l_value) {	/* old larger; copy over */
99236769Sobrien			while (*C++ = *value++);
100236769Sobrien			return (0);
101236769Sobrien		}
102236769Sobrien	} else {					/* create new slot */
103236769Sobrien		register int	cnt;
104236769Sobrien		register char	**P;
105236769Sobrien
106236769Sobrien		for (P = environ, cnt = 0; *P; ++P, ++cnt);
107236769Sobrien		if (alloced) {			/* just increase size */
108236769Sobrien			environ = (char **)realloc((char *)environ,
109236769Sobrien			    (size_t)(sizeof(char *) * (cnt + 2)));
110236769Sobrien			if (!environ)
111236769Sobrien				return (-1);
112236769Sobrien		}
113236769Sobrien		else {				/* get new space */
114236769Sobrien			alloced = 1;		/* copy old entries into it */
115236769Sobrien			P = (char **)malloc((size_t)(sizeof(char *) *
116236769Sobrien			    (cnt + 2)));
117236769Sobrien			if (!P)
118236769Sobrien				return (-1);
119236769Sobrien			bcopy(environ, P, cnt * sizeof(char *));
120236769Sobrien			environ = P;
121236769Sobrien		}
122236769Sobrien		environ[cnt + 1] = NULL;
123236769Sobrien		offset = cnt;
124236769Sobrien	}
125236769Sobrien	for (C = (char *)name; *C && *C != '='; ++C);	/* no `=' in name */
126236769Sobrien	if (!(environ[offset] =			/* name + `=' + value */
127236769Sobrien	    malloc((size_t)((int)(C - name) + l_value + 2))))
128236769Sobrien		return (-1);
129236769Sobrien	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
130236769Sobrien		;
131236769Sobrien	for (*C++ = '='; *C++ = *value++; )
132236769Sobrien		;
133236769Sobrien	return (0);
134236769Sobrien}
135236769Sobrien
136236769Sobrien/*
137236769Sobrien * unsetenv(name) --
138236769Sobrien *	Delete environmental variable "name".
139236769Sobrien */
140236769Sobrienvoid
141236769Sobrienunsetenv(name)
142236769Sobrien	const char	*name;
143236769Sobrien{
144236769Sobrien	extern char **environ;
145236769Sobrien	register char **P;
146236769Sobrien	int offset;
147236769Sobrien	char *__findenv();
148236769Sobrien
149236769Sobrien	while (__findenv(name, &offset))		/* if set multiple times */
150236769Sobrien		for (P = &environ[offset];; ++P)
151236769Sobrien			if (!(*P = *(P + 1)))
152236769Sobrien				break;
153236769Sobrien}
154236769Sobrien#endif
155