119304Speter/*
219304Speter * Copyright (c) 1987, 1993
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter *
519304Speter * Redistribution and use in source and binary forms, with or without
619304Speter * modification, are permitted provided that the following conditions
719304Speter * are met:
819304Speter * 1. Redistributions of source code must retain the above copyright
919304Speter *    notice, this list of conditions and the following disclaimer.
1019304Speter * 2. Redistributions in binary form must reproduce the above copyright
1119304Speter *    notice, this list of conditions and the following disclaimer in the
1219304Speter *    documentation and/or other materials provided with the distribution.
1319304Speter * 3. All advertising materials mentioning features or use of this software
1419304Speter *    must display the following acknowledgement:
1519304Speter *	This product includes software developed by the University of
1619304Speter *	California, Berkeley and its contributors.
1719304Speter * 4. Neither the name of the University nor the names of its contributors
1819304Speter *    may be used to endorse or promote products derived from this software
1919304Speter *    without specific prior written permission.
2019304Speter *
2119304Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2219304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2319304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2419304Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2519304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2619304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2719304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2819304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2919304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3019304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3119304Speter * SUCH DAMAGE.
3219304Speter */
3319304Speter
3419304Speter#include "config.h"
3519304Speter
3619304Speter#if defined(LIBC_SCCS) && !defined(lint)
3719304Speterstatic const char sccsid[] = "@(#)getenv.c	8.1 (Berkeley) 6/4/93";
3819304Speterstatic const char sccsid[] = "@(#)setenv.c	8.1 (Berkeley) 6/4/93";
3919304Speter#endif /* LIBC_SCCS and not lint */
4019304Speter
4119304Speter#include <stdlib.h>
4219304Speter#include <string.h>
4319304Speter
4419304Speter/*
4519304Speter * __findenv --
4619304Speter *	Returns pointer to value associated with name, if any, else NULL.
4719304Speter *	Sets offset to be the offset of the name/value combination in the
4819304Speter *	environmental array, for use by setenv(3) and unsetenv(3).
4919304Speter *	Explicitly removes '=' in argument name.
5019304Speter *
5119304Speter *	This routine *should* be a static; don't use it.
5219304Speter */
5319304Speterstatic char *
5419304Speter__findenv(name, offset)
5519304Speter	register char *name;
5619304Speter	int *offset;
5719304Speter{
5819304Speter	extern char **environ;
5919304Speter	register int len;
6019304Speter	register char *np;
6119304Speter	register char **p, *c;
6219304Speter
6319304Speter	if (name == NULL || environ == NULL)
6419304Speter		return (NULL);
6519304Speter	for (np = name; *np && *np != '='; ++np)
6619304Speter		continue;
6719304Speter	len = np - name;
6819304Speter	for (p = environ; (c = *p) != NULL; ++p)
6919304Speter		if (strncmp(c, name, len) == 0 && c[len] == '=') {
7019304Speter			*offset = p - environ;
7119304Speter			return (c + len + 1);
7219304Speter		}
7319304Speter	return (NULL);
7419304Speter}
7519304Speter
7619304Speter#ifndef HAVE_SETENV
7719304Speter/*
7819304Speter * setenv --
7919304Speter *	Set the value of the environmental variable "name" to be
8019304Speter *	"value".  If rewrite is set, replace any current value.
8119304Speter *
8219304Speter * PUBLIC: #ifndef HAVE_SETENV
8319304Speter * PUBLIC: int setenv __P((const char *, const char *, int));
8419304Speter * PUBLIC: #endif
8519304Speter */
8619304Spetersetenv(name, value, rewrite)
8719304Speter	register char *name;
8819304Speter	register char *value;
8919304Speter	int rewrite;
9019304Speter{
9119304Speter	extern char **environ;
9219304Speter	static int alloced;			/* if allocated space before */
9319304Speter	register char *c;
9419304Speter	int l_value, offset;
9519304Speter
9619304Speter	if (*value == '=')			/* no `=' in value */
9719304Speter		++value;
9819304Speter	l_value = strlen(value);
9919304Speter	if ((c = __findenv(name, &offset))) {	/* find if already exists */
10019304Speter		if (!rewrite)
10119304Speter			return (0);
10219304Speter		if (strlen(c) >= l_value) {	/* old larger; copy over */
10319304Speter			while (*c++ = *value++);
10419304Speter			return (0);
10519304Speter		}
10619304Speter	} else {					/* create new slot */
10719304Speter		register int cnt;
10819304Speter		register char **p;
10919304Speter
11019304Speter		for (p = environ, cnt = 0; *p; ++p, ++cnt);
11119304Speter		if (alloced) {			/* just increase size */
11219304Speter			environ = (char **)realloc((char *)environ,
11319304Speter			    (size_t)(sizeof(char *) * (cnt + 2)));
11419304Speter			if (!environ)
11519304Speter				return (-1);
11619304Speter		}
11719304Speter		else {				/* get new space */
11819304Speter			alloced = 1;		/* copy old entries into it */
11919304Speter			p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
12019304Speter			if (!p)
12119304Speter				return (-1);
12219304Speter			memmove(p, environ, cnt * sizeof(char *));
12319304Speter			environ = p;
12419304Speter		}
12519304Speter		environ[cnt + 1] = NULL;
12619304Speter		offset = cnt;
12719304Speter	}
12819304Speter	for (c = (char *)name; *c && *c != '='; ++c);	/* no `=' in name */
12919304Speter	if (!(environ[offset] =			/* name + `=' + value */
13019304Speter	    malloc((size_t)((int)(c - name) + l_value + 2))))
13119304Speter		return (-1);
13219304Speter	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
13319304Speter	for (*c++ = '='; *c++ = *value++;);
13419304Speter	return (0);
13519304Speter}
13619304Speter#endif
13719304Speter
13819304Speter#ifndef HAVE_UNSETENV
13919304Speter/*
14019304Speter * unsetenv(name) --
14119304Speter *	Delete environmental variable "name".
14219304Speter *
14319304Speter * PUBLIC: #ifndef HAVE_UNSETENV
14419304Speter * PUBLIC: void unsetenv __P((const char *));
14519304Speter * PUBLIC: #endif
14619304Speter */
14719304Spetervoid
14819304Speterunsetenv(name)
14919304Speter	char *name;
15019304Speter{
15119304Speter	extern char **environ;
15219304Speter	register char **p;
15319304Speter	int offset;
15419304Speter
15519304Speter	while (__findenv(name, &offset))	/* if set multiple times */
15619304Speter		for (p = &environ[offset];; ++p)
15719304Speter			if (!(*p = *(p + 1)))
15819304Speter				break;
15919304Speter}
16019304Speter#endif
161