(root)/
gawk-5.2.2/
missing_d/
setenv.c
       1  /*	$NetBSD: setenv.c,v 1.1.1.1 2009/04/12 15:33:26 christos Exp $	*/
       2  
       3  #if defined(LIBC_SCCS) && !defined(lint)
       4  static const char sccsid[] = "@(#)setenv.c	8.1 (Berkeley) 6/4/93";
       5  static const char rcsid[] = "Id: setenv.c,v 1.2 2005/04/27 04:56:11 sra Exp";
       6  #endif /* LIBC_SCCS and not lint */
       7  
       8  /*
       9   * Copyright (c) 1987, 1993
      10   *	The Regents of the University of California.  All rights reserved.
      11   *
      12   * Redistribution and use in source and binary forms, with or without
      13   * modification, are permitted provided that the following conditions
      14   * are met:
      15   * 1. Redistributions of source code must retain the above copyright
      16   *    notice, this list of conditions and the following disclaimer.
      17   * 2. Redistributions in binary form must reproduce the above copyright
      18   *    notice, this list of conditions and the following disclaimer in the
      19   *    documentation and/or other materials provided with the distribution.
      20   * 3. Neither the name of the University nor the names of its contributors
      21   *    may be used to endorse or promote products derived from this software
      22   *    without specific prior written permission.
      23   *
      24   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      25   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      26   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      27   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      28   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      29   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      30   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      31   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      32   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      33   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34   * SUCH DAMAGE.
      35   */
      36  
      37  /*
      38   * Per the statement at http://opensource.org/licenses/bsd-license.php,
      39   *
      40   *	The advertising clause in the license appearing on BSD Unix files was
      41   *	officially rescinded by the Director of the Office of Technology
      42   *	Licensing of the University of California on July 22 1999. He states
      43   *	that clause 3 is "hereby deleted in its entirety."
      44   *
      45   * I removed the advertising clause in the above copyright.
      46   * The above web site points to
      47   * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change.
      48   *
      49   * Arnold Robbins
      50   * 7 September 2016
      51   */
      52  
      53  /* #include "port_before.h" */
      54  
      55  #include <stddef.h>
      56  #include <stdlib.h>
      57  #include <string.h>
      58  #include <errno.h>
      59  
      60  /* #include "port_after.h" */
      61  
      62  #define NEED_SETENV
      63  #if !defined(NEED_SETENV)
      64  int __bindcompat_setenv;
      65  #else
      66  
      67  /*
      68   * Gawk changes:
      69   * 1. Comment out "port_before.h" and "port_after.h" includes.
      70   * 2. Define NEED_SETENV.
      71   * 3. Add leading "int" to setenv() for C99 compilers. Which is worse,
      72   *    that it wasn't there in the first place, or that C99 now makes
      73   *    such functions void, breaking 40+ years of historical practice?
      74   * 4. Change return type of unsetenv to "int" for standards
      75   *    conformance and check for name containing an "=" in
      76   *    which case it return an error. (See unsetenv(3), at least on Linux.)
      77   */
      78  
      79  extern char **environ;
      80  
      81  static char *findenv(const char *name, int *offset);
      82  
      83  /*%
      84   * setenv --
      85   *	Set the value of the environmental variable "name" to be
      86   *	"value".  If rewrite is set, replace any current value.
      87   */
      88  int
      89  setenv(const char *name, const char *value, int rewrite)
      90  {
      91  	extern char **environ;
      92  	static int alloced;			/*%< if allocated space before */
      93  	char *c;
      94  	int l_value, offset;
      95  
      96  	if (*value == '=')			/*%< no `=' in value */
      97  		++value;
      98  	l_value = strlen(value);
      99  	if ((c = findenv(name, &offset))) {	/*%< find if already exists */
     100  		if (!rewrite)
     101  			return (0);
     102  		if (strlen(c) >= l_value) {	/*%< old larger; copy over */
     103  			while (*c++ = *value++);
     104  			return (0);
     105  		}
     106  	} else {					/*%< create new slot */
     107  		int cnt;
     108  		char **p;
     109  
     110  		for (p = environ, cnt = 0; *p; ++p, ++cnt);
     111  		if (alloced) {			/*%< just increase size */
     112  			environ = (char **)realloc((char *)environ,
     113  			    (size_t)(sizeof(char *) * (cnt + 2)));
     114  			if (!environ)
     115  				return (-1);
     116  		}
     117  		else {				/*%< get new space */
     118  			alloced = 1;		/*%< copy old entries into it */
     119  			p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
     120  			if (!p)
     121  				return (-1);
     122  			memcpy(p, environ, cnt * sizeof(char *));
     123  			environ = p;
     124  		}
     125  		environ[cnt + 1] = NULL;
     126  		offset = cnt;
     127  	}
     128  	for (c = (char *)name; *c && *c != '='; ++c);	/*%< no `=' in name */
     129  	if (!(environ[offset] =			/*%< name + `=' + value */
     130  	    malloc((size_t)((int)(c - name) + l_value + 2))))
     131  		return (-1);
     132  	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
     133  	for (*c++ = '='; *c++ = *value++;);
     134  	return (0);
     135  }
     136  
     137  /*%
     138   * unsetenv(name) --
     139   *	Delete environmental variable "name".
     140   */
     141  int
     142  unsetenv(const char *name)
     143  {
     144  	char **p;
     145  	int offset;
     146  
     147  	if (strchr(name, '=') != NULL) {
     148  		errno = EINVAL;
     149  		return -1;
     150  	}
     151  
     152  	while (findenv(name, &offset))	/*%< if set multiple times */
     153  		for (p = &environ[offset];; ++p)
     154  			if (!(*p = *(p + 1)))
     155  				break;
     156  
     157  	return 0;
     158  }
     159  
     160  /*%
     161   * findenv --
     162   *	Returns pointer to value associated with name, if any, else NULL.
     163   *	Sets offset to be the offset of the name/value combination in the
     164   *	environmental array, for use by setenv(3) and unsetenv(3).
     165   *	Explicitly removes '=' in argument name.
     166   *
     167   *	This routine *should* be a static; don't use it.
     168   */
     169  static char *
     170  findenv(const char *name, int *offset)
     171  {
     172  	const char *np;
     173  	char **p, *c;
     174  	int len;
     175  
     176  	if (name == NULL || environ == NULL)
     177  		return (NULL);
     178  	for (np = name; *np && *np != '='; ++np)
     179  		continue;
     180  	len = np - name;
     181  	for (p = environ; (c = *p) != NULL; ++p)
     182  		if (strncmp(c, name, len) == 0 && c[len] == '=') {
     183  			*offset = p - environ;
     184  			return (c + len + 1);
     185  		}
     186  	return (NULL);
     187  }
     188  #endif
     189  
     190  /*! \file */