143f32c10Smrg/*
243f32c10Smrg * Provide setenv() and unsetenv() on platforms that don't have them.
343f32c10Smrg * From FreeBSD's libc.
443f32c10Smrg */
543f32c10Smrg
643f32c10Smrg/*
743f32c10Smrg * Copyright (c) 1987, 1993
843f32c10Smrg *      The Regents of the University of California.  All rights reserved.
943f32c10Smrg *
1043f32c10Smrg * Redistribution and use in source and binary forms, with or without
1143f32c10Smrg * modification, are permitted provided that the following conditions
1243f32c10Smrg * are met:
1343f32c10Smrg * 1. Redistributions of source code must retain the above copyright
1443f32c10Smrg *    notice, this list of conditions and the following disclaimer.
1543f32c10Smrg * 2. Redistributions in binary form must reproduce the above copyright
1643f32c10Smrg *    notice, this list of conditions and the following disclaimer in the
1743f32c10Smrg *    documentation and/or other materials provided with the distribution.
1843f32c10Smrg * 3. All advertising materials mentioning features or use of this software
1943f32c10Smrg *    must display the following acknowledgement:
2043f32c10Smrg *      This product includes software developed by the University of
2143f32c10Smrg *      California, Berkeley and its contributors.
2243f32c10Smrg * 4. Neither the name of the University nor the names of its contributors
2343f32c10Smrg *    may be used to endorse or promote products derived from this software
2443f32c10Smrg *    without specific prior written permission.
2543f32c10Smrg *
2643f32c10Smrg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2743f32c10Smrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2843f32c10Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2943f32c10Smrg * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3043f32c10Smrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3143f32c10Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3243f32c10Smrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3343f32c10Smrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3443f32c10Smrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3543f32c10Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3643f32c10Smrg * SUCH DAMAGE.
3743f32c10Smrg */
3843f32c10Smrg
3943f32c10Smrg/* $XFree86: xc/programs/xedit/lisp/env.c,v 1.1 2002/03/05 03:52:34 dawes Exp $ */
4043f32c10Smrg
4143f32c10Smrg
4243f32c10Smrg#include <stdlib.h>
4343f32c10Smrg#include <stddef.h>
4443f32c10Smrg#include <string.h>
4543f32c10Smrg
4643f32c10Smrgextern char **environ;
4743f32c10Smrg
4843f32c10Smrgextern int setenv(const char *name, const char *value, int overwrite);
4943f32c10Smrgextern void unsetenv(const char *name);
5043f32c10Smrg
5143f32c10Smrgstatic char *
5243f32c10Smrgfindenv(const char *name, int *offset)
5343f32c10Smrg{
5443f32c10Smrg    int len, i;
5543f32c10Smrg    const char *np;
5643f32c10Smrg    char **p, *cp;
5743f32c10Smrg
5843f32c10Smrg    if (name == NULL || environ == NULL)
5943f32c10Smrg	return NULL;
6043f32c10Smrg
6143f32c10Smrg    for (np = name; *np && *np != '='; ++np)
6243f32c10Smrg	continue;
6343f32c10Smrg    len = np - name;
6443f32c10Smrg    for (p = environ; (cp = *p) != NULL; ++p) {
6543f32c10Smrg	for (np = name, i = len; i && *cp; i--)
6643f32c10Smrg	    if (*cp++ != *np++)
6743f32c10Smrg		break;
6843f32c10Smrg	if (i == 0 && *cp++ == '=') {
6943f32c10Smrg	    *offset = p - environ;
7043f32c10Smrg	    return cp;
7143f32c10Smrg	}
7243f32c10Smrg    }
7343f32c10Smrg    return NULL;
7443f32c10Smrg}
7543f32c10Smrg
7643f32c10Smrg/*
7743f32c10Smrg * setenv --
7843f32c10Smrg *      Set the value of the environmental variable "name" to be
7943f32c10Smrg *      "value".  If overwrite is set, replace any current value.
8043f32c10Smrg */
8143f32c10Smrg
8243f32c10Smrgint
8343f32c10Smrgsetenv(const char *name, const char *value, int overwrite)
8443f32c10Smrg{
8543f32c10Smrg    static char **alloced;			/* if allocated space before */
8643f32c10Smrg    char *c;
8743f32c10Smrg    int l_value, offset;
8843f32c10Smrg
8943f32c10Smrg    if (*value == '=')				/* no '=' in value */
9043f32c10Smrg	++value;
9143f32c10Smrg    l_value = strlen(value);
9243f32c10Smrg    if ((c = findenv(name, &offset))) {		/* find if already exists */
9343f32c10Smrg	if (!overwrite)
9443f32c10Smrg	    return 0;
9543f32c10Smrg	if (strlen(c) >= l_value) {		/* old larger; copy over */
9643f32c10Smrg	    while ((*c++ = *value++))
9743f32c10Smrg		;
9843f32c10Smrg	    return 0;
9943f32c10Smrg	}
10043f32c10Smrg    } else {					/* create new slot */
10143f32c10Smrg	int cnt;
10243f32c10Smrg	char **p;
10343f32c10Smrg
10443f32c10Smrg	for (p = environ, cnt = 0; *p; ++p, ++cnt)
10543f32c10Smrg	    ;
10643f32c10Smrg	if (alloced == environ) {		/* just increase size */
10743f32c10Smrg	    p = (char **)realloc((char *)environ,
10843f32c10Smrg				 sizeof(char *) * (cnt + 2));
10943f32c10Smrg	    if (!p)
11043f32c10Smrg		return -1;
11143f32c10Smrg	    alloced = environ = p;
11243f32c10Smrg	} else {				/* get new space */
11343f32c10Smrg						/* copy old entries into it */
11443f32c10Smrg	    p = malloc(sizeof(char *) * (cnt + 2));
11543f32c10Smrg	    if (!p)
11643f32c10Smrg		return -1;
11743f32c10Smrg	    memcpy(p, environ, cnt * sizeof(char *));
11843f32c10Smrg	    alloced = environ = p;
11943f32c10Smrg	}
12043f32c10Smrg	environ[cnt + 1] = NULL;
12143f32c10Smrg	offset = cnt;
12243f32c10Smrg    }
12343f32c10Smrg    for (c = (char *)name; *c && *c != '='; ++c)	/* no '=' in name */
12443f32c10Smrg	;
12543f32c10Smrg    if (!(environ[offset] =				/* name + '=' + value */
12643f32c10Smrg			malloc((int)(c - name) + l_value + 2)))
12743f32c10Smrg	return -1;
12843f32c10Smrg    for (c = environ[offset]; (*c = *name++) && *c != '='; ++c)
12943f32c10Smrg	;
13043f32c10Smrg    for (*c++ = '='; (*c++ = *value++); )
13143f32c10Smrg	;
13243f32c10Smrg    return 0;
13343f32c10Smrg}
13443f32c10Smrg
13543f32c10Smrg/*
13643f32c10Smrg * unsetenv(name) --
13743f32c10Smrg *      Delete environmental variable "name".
13843f32c10Smrg */
13943f32c10Smrg
14043f32c10Smrgvoid
14143f32c10Smrgunsetenv(const char *name)
14243f32c10Smrg{
14343f32c10Smrg    char **p;
14443f32c10Smrg    int offset;
14543f32c10Smrg
14643f32c10Smrg    while (findenv(name, &offset))		/* if set multiple times */
14743f32c10Smrg	for (p = &environ[offset];; ++p)
14843f32c10Smrg	    if (!(*p = *(p + 1)))
14943f32c10Smrg		break;
15043f32c10Smrg}
15143f32c10Smrg
152