dnl CF_CHECK_GETENV version: 2 updated: 2021/01/02 17:09:14
dnl ---------------
dnl Check if repeated getenv calls return the same pointer, e.g., it does not
dnl discard the previous pointer when returning a new one.
AC_DEFUN([CF_CHECK_GETENV],
[
AC_REQUIRE([CF_CHECK_ENVIRON])
AC_CHECK_FUNC( getenv, ,, AC_MSG_ERROR(getenv not found) )
AC_CHECK_FUNCS( putenv setenv strdup )
AC_CACHE_CHECK(if getenv returns consistent values,cf_cv_consistent_getenv,[
AC_TRY_RUN([
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

#if defined(HAVE_ENVIRON) && defined(DECL_ENVIRON) && !defined(environ)
extern char **environ;	/* POSIX, but some systems are not... */
#endif

#if defined(HAVE_STRDUP)
#define str_alloc(s) strdup(s)
#else
#define str_alloc(s) strcpy(malloc(strlen(s) + 1, s))
#endif

static void set_value(const char *name, const char *value)
{
#if defined(HAVE_SETENV)
	setenv(name, value, 1);
#elif defined(HAVE_PUTENV)
	char buffer[1024];
	sprintf(buffer, "%s=%s", name, value);
	putenv(str_alloc(buffer));
#else
#error neither putenv/setenv found
#endif
}
int main(void)
{
	int pass;
	size_t numenv, limit, j;
	char **mynames;
	char **myvalues;
	char **mypointer;
	char *equals;
	for (numenv = 0; environ[numenv]; ++numenv) ;
	limit = numenv + 10;
	mynames = (char **) calloc(limit + 1, sizeof(char *));
	myvalues = (char **) calloc(limit + 1, sizeof(char *));
	mypointer = (char **) calloc(limit + 1, sizeof(char *));
#if defined(HAVE_ENVIRON)
	for (j = 0; environ[j]; ++j) {
		mynames[j] = str_alloc(environ[j]);
		equals = strchr(mynames[j], '=');
		if (equals != 0) {
			*equals++ = '\\0';
			myvalues[j] = str_alloc(equals);
		} else {
			myvalues[j] = str_alloc("");
		}
	}
#endif
	for (j = numenv; j < limit; ++j) {
		char name[80];
		char value[80];
		size_t found;
		size_t k = 0;
		do {
			size_t jk;
			found = 0;
			sprintf(name, "TERM%lu", (unsigned long) k);
			for (jk = 0; jk < j; ++jk) {
				if (!strcmp(name, mynames[jk])) {
					found = 1;
					++k;
					break;
				}
			}
		} while (found);
		sprintf(value, "%lu:%p", (unsigned long) k, &mynames[j]);
		set_value(name, value);
		mynames[j] = str_alloc(name);
		myvalues[j] = str_alloc(value);
	}
	for (pass = 0; pass < 3; ++pass) {
		for (j = 0; j < limit; ++j) {
			char *value = getenv(mynames[j]);
			if (pass) {
				if (value == 0) {
					fprintf(stderr, "getenv returned null for %s\\n", mynames[j]);
					${cf_cv_main_return:-return}(1);
				} else if (value != mypointer[j]) {
					fprintf(stderr, "getenv returned different pointer for %s\\n", mynames[j]);
					${cf_cv_main_return:-return}(1);
				} else if (strcmp(value, myvalues[j])) {
					fprintf(stderr, "getenv returned different value for %s\\n", mynames[j]);
					${cf_cv_main_return:-return}(1);
				}
			} else {
				size_t k;
				mypointer[j] = value;
				for (k = 0; k < j; ++k) {
					if (mypointer[j] == mypointer[k]) {
						fprintf(stderr, "getenv returned same pointer for %s and %s\\n", mynames[j], mynames[k]);
						${cf_cv_main_return:-return}(1);
					}
				}
			}
		}
	}
	${cf_cv_main_return:-return}(0);
}
],
[cf_cv_consistent_getenv=yes],
[cf_cv_consistent_getenv=no],
[cf_cv_consistent_getenv=unknown])
])

if test "x$cf_cv_consistent_getenv" = xno
then
	AC_DEFINE(HAVE_CONSISTENT_GETENV,1,[Define to 1 if getenv repeatably returns the same value for a given name])
fi
])dnl
