diff options
Diffstat (limited to 'tools/regression/environ')
| -rw-r--r-- | tools/regression/environ/Makefile | 13 | ||||
| -rw-r--r-- | tools/regression/environ/Makefile.envctl | 15 | ||||
| -rw-r--r-- | tools/regression/environ/Makefile.retention | 15 | ||||
| -rw-r--r-- | tools/regression/environ/Makefile.timings | 15 | ||||
| -rw-r--r-- | tools/regression/environ/envctl.c | 215 | ||||
| -rw-r--r-- | tools/regression/environ/envtest.t | 248 | ||||
| -rw-r--r-- | tools/regression/environ/retention.c | 106 | ||||
| -rw-r--r-- | tools/regression/environ/timings.c | 197 | 
8 files changed, 824 insertions, 0 deletions
| diff --git a/tools/regression/environ/Makefile b/tools/regression/environ/Makefile new file mode 100644 index 000000000000..00796304b60d --- /dev/null +++ b/tools/regression/environ/Makefile @@ -0,0 +1,13 @@ +# +# +PROGS=	envctl retention timings + +all clean test: +.for target in ${.TARGET} +.for prog in ${PROGS} +	@${MAKE} -f Makefile.${prog} ${target} +.endfor +.if make(clean) +	rm -f *~ +.endif +.endfor diff --git a/tools/regression/environ/Makefile.envctl b/tools/regression/environ/Makefile.envctl new file mode 100644 index 000000000000..37fac012cd2e --- /dev/null +++ b/tools/regression/environ/Makefile.envctl @@ -0,0 +1,15 @@ +# +# +SRCS=	envctl.c +PROG=	envctl + +CFLAGS+=-Wall -I../../../include + +CLEANFILES=	${PROG}.core + +MAN= + +.include <bsd.prog.mk> + +test: ${PROG} +	@env -i sh envtest.t diff --git a/tools/regression/environ/Makefile.retention b/tools/regression/environ/Makefile.retention new file mode 100644 index 000000000000..90eb544c5afc --- /dev/null +++ b/tools/regression/environ/Makefile.retention @@ -0,0 +1,15 @@ +# +# +SRCS=	retention.c +PROG=	retention + +CFLAGS+=-Wall -I../../../include + +CLEANFILES=	*~ ${PROG}.core + +MAN= + +.include <bsd.prog.mk> + +test: ${PROG} +	@./${PROG} diff --git a/tools/regression/environ/Makefile.timings b/tools/regression/environ/Makefile.timings new file mode 100644 index 000000000000..4d48eb44d386 --- /dev/null +++ b/tools/regression/environ/Makefile.timings @@ -0,0 +1,15 @@ +# +# +SRCS=	timings.c +PROG=	timings + +CFLAGS+=-Wall -I../../../include + +CLEANFILES=	${PROG}.core + +MAN= + +.include <bsd.prog.mk> + +test: ${PROG} +	@./timings diff --git a/tools/regression/environ/envctl.c b/tools/regression/environ/envctl.c new file mode 100644 index 000000000000..06071f642cc1 --- /dev/null +++ b/tools/regression/environ/envctl.c @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 2007-2008 Sean C. Farley <scf@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer, + *    without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <errno.h> +#include <libgen.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +#include <sys/cdefs.h> +extern char **environ; + + +/* + * Print entire environ array. + */ +static void +dump_environ(void) +{ +	char **environPtr; + +	for (environPtr = environ; *environPtr != NULL; environPtr++) +		printf("%s\n", *environPtr); + +	return; +} + + +/* + * Print usage. + */ +static void +usage(const char *program) +{ +	fprintf(stderr, "Usage:  %s [-DGUchrt] [-c 1|2|3|4] [-bgu name] " +	    "[-p name=value]\n" +	    "\t[(-S|-s name) value overwrite]\n\n" +	    "Options:\n" +	    "  -D\t\t\t\tDump environ\n" +	    "  -G name\t\t\tgetenv(NULL)\n" +	    "  -S value overwrite\t\tsetenv(NULL, value, overwrite)\n" +	    "  -U\t\t\t\tunsetenv(NULL)\n" +	    "  -b name\t\t\tblank the 'name=$name' entry, corrupting it\n" +	    "  -c 1|2|3|4\t\t\tClear environ variable using method:\n" +	    "\t\t\t\t1 - set environ to NULL pointer\n" +	    "\t\t\t\t2 - set environ[0] to NULL pointer\n" +	    "\t\t\t\t3 - set environ to calloc()'d NULL-terminated array\n" +	    "\t\t\t\t4 - set environ to static NULL-terminated array\n" +	    "  -g name\t\t\tgetenv(name)\n" +	    "  -h\t\t\t\tHelp\n" +	    "  -p name=value\t\t\tputenv(name=value)\n" +	    "  -r\t\t\t\treplace environ with { \"FOO=bar\", NULL }\n" +	    "  -s name value overwrite\tsetenv(name, value, overwrite)\n" +	    "  -t\t\t\t\tOutput is suitable for testing (no newlines)\n" +	    "  -u name\t\t\tunsetenv(name)\n", +	    basename(program)); + +	return; +} + + +/* + * Print the return value of a call along with errno upon error else zero. + * Also, use the eol string based upon whether running in test mode or not. + */ +static void +print_rtrn_errno(int rtrnVal, const char *eol) +{ +	printf("%d %d%s", rtrnVal, rtrnVal != 0 ? errno : 0, eol); + +	return; +} + +static void +blank_env(const char *var) +{ +	char **newenviron; +	int n, varlen; + +	if (environ == NULL) +		return; + +	for (n = 0; environ[n] != NULL; n++) +		; +	newenviron = malloc(sizeof(char *) * (n + 1)); +	varlen = strlen(var); +	for (; n >= 0; n--) { +		newenviron[n] = environ[n]; +		if (newenviron[n] != NULL && +		    strncmp(newenviron[n], var, varlen) == 0 && +		    newenviron[n][varlen] == '=') +			newenviron[n] += strlen(newenviron[n]); +	} +	environ = newenviron; +} + +int +main(int argc, char **argv) +{ +	char arg; +	const char *eol = "\n"; +	const char *value; +	static char *emptyEnv[] = { NULL }; +	static char *staticEnv[] = { "FOO=bar", NULL }; + +	if (argc == 1) { +		usage(argv[0]); +		exit(EXIT_FAILURE); +	} + +	/* The entire program is basically executed from this loop. */ +	while ((arg = getopt(argc, argv, "DGS:Ub:c:g:hp:rs:tu:")) != -1) { +		switch (arg) { +		case 'b': +			blank_env(optarg); +			break; + +		case 'c': +			switch (atoi(optarg)) { +			case 1: +				environ = NULL; +				break; + +			case 2: +				environ[0] = NULL; +				break; + +			case 3: +				environ = calloc(1, sizeof(*environ)); +				break; + +			case 4: +				environ = emptyEnv; +				break; +			} +			break; + +		case 'D': +			dump_environ(); +			break; + +		case 'G': +		case 'g': +			value = getenv(arg == 'g' ? optarg : NULL); +			printf("%s%s", value == NULL ? "*NULL*" : value, eol); +			break; + +		case 'p': +			print_rtrn_errno(putenv(optarg), eol); +			break; + +		case 'r': +			environ = staticEnv; +			break; + +		case 'S': +			print_rtrn_errno(setenv(NULL, optarg, +			    atoi(argv[optind])), eol); +			optind += 1; +			break; + +		case 's': +			print_rtrn_errno(setenv(optarg, argv[optind], +			    atoi(argv[optind + 1])), eol); +			optind += 2; +			break; + +		case 't': +			eol = " "; +			break; + +		case 'U': +		case 'u': +			print_rtrn_errno(unsetenv(arg == 'u' ? optarg : NULL), +			    eol); +			break; + +		case 'h': +		default: +			usage(argv[0]); +			exit(EXIT_FAILURE); +		} +	} + +	/* Output a closing newline in test mode. */ +	if (eol[0] == ' ') +		printf("\n"); + +	return (EXIT_SUCCESS); +} diff --git a/tools/regression/environ/envtest.t b/tools/regression/environ/envtest.t new file mode 100644 index 000000000000..5532c2ee7860 --- /dev/null +++ b/tools/regression/environ/envtest.t @@ -0,0 +1,248 @@ +#!/bin/sh +# +# Copyright (c) 2007-2008 Sean C. Farley <scf@FreeBSD.org> +# All rights reserved. +#  +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +#    notice, this list of conditions and the following disclaimer, +#    without modification, immediately at the beginning of the file. +# 2. Redistributions in binary form must reproduce the above copyright +#    notice, this list of conditions and the following disclaimer in the +#    documentation and/or other materials provided with the distribution. +#  +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + + +# Initialization. +testndx=0 + + +# Testing function. +run_test() +{ +	lasttest="${@}" +	result=`./envctl -t "${@}"` + +	if [ ${?} -ne 0 ] +	then +		echo "Test program failed" >&2 +		exit 1 +	fi + +	return +} + + +# Perform test on results. +check_result() +{ +	testndx=$((testndx + 1)) + +	echo "${result}" | sed 's/[ \t]*$//' | grep -q "^${@}$" +	if [ ${?} -eq 0 ] +	then +		echo "ok ${testndx}" +	else +		echo "not ok ${testndx} - '${lasttest}'" +	fi + +	return +} + + +# +# Regression tests +# + +# How NULL will be returned by program. +readonly NULL="\*NULL\*" + +# Setup environment for tests. +readonly BAR="bar" +readonly NEWBAR="newbar" +export FOO=${BAR} + + +# Gets from environ. +run_test -g FOO +check_result "${FOO}" + +run_test -c 3 -g FOO +check_result "${NULL}" + +run_test -g FOOBAR +check_result "${NULL}" + +run_test -c 3 -g FOOBAR +check_result "${NULL}" + +run_test -G +check_result "${NULL}" + + +# Clear environ. +run_test -c 1 -g FOO +check_result "${NULL}" + +run_test -c 2 -g FOO +check_result "${NULL}" + +run_test -c 3 -g FOO +check_result "${NULL}" + +run_test -c 4 -g FOO +check_result "${NULL}" + + +# Clear environ and verify values do not return after a set. +run_test -c 1 -g FOO -s FOO2 ${NEWBAR} 1 -g FOO -g FOO2 +check_result "${NULL} 0 0 ${NULL} ${NEWBAR}" + +run_test -c 2 -g FOO -s FOO2 ${NEWBAR} 1 -g FOO -g FOO2 +check_result "${NULL} 0 0 ${NULL} ${NEWBAR}" + +run_test -c 3 -g FOO -s FOO2 ${NEWBAR} 1 -g FOO -g FOO2 +check_result "${NULL} 0 0 ${NULL} ${NEWBAR}" + +run_test -c 4 -g FOO -s FOO2 ${NEWBAR} 1 -g FOO -g FOO2 +check_result "${NULL} 0 0 ${NULL} ${NEWBAR}" + + +# Sets. +run_test -s FOO ${NEWBAR} 0 -g FOO +check_result "0 0 ${BAR}" + +run_test -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 ${NEWBAR}" + +run_test -c 3 -s FOO ${NEWBAR} 0 -g FOO +check_result "0 0 ${NEWBAR}" + +run_test -c 3 -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 ${NEWBAR}" + +run_test -s "FOO=" ${NEWBAR} 1 -g FOO +check_result "-1 22 ${BAR}" + +run_test -s "=FOO" ${NEWBAR} 1 +check_result "-1 22" + +run_test -s "=" ${NEWBAR} 1 +check_result "-1 22" + +run_test -s "" ${NEWBAR} 1 +check_result "-1 22" + +run_test -S ${NEWBAR} 1 +check_result "-1 22" + +run_test -s FOO ${NEWBAR} 1 -s FOO ${BAR} 1 -g FOO +check_result "0 0 0 0 ${BAR}" + +run_test -c 3 -s FOO ${NEWBAR} 1 -s FOO ${BAR} 1 -g FOO +check_result "0 0 0 0 ${BAR}" + +run_test -s FOO ${NEWBAR} 1 -s FOO ${BAR} 1 -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 0 0 0 0 ${NEWBAR}" + +run_test -s FOO ${NEWBAR} 1 -s FOO ${BAR} 1 -s FOO ${NEWBAR} 1 -s FOO ${BAR} 1\ +	-g FOO +check_result "0 0 0 0 0 0 0 0 ${BAR}" + +run_test -c 3 -s FOO ${BAR} 1 -g FOO -c 3 -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 ${BAR} 0 0 ${NEWBAR}" + + +# Unsets. +run_test -u FOO -g FOO +check_result "0 0 ${NULL}" + +run_test -c 3 -u FOO -g FOO +check_result "0 0 ${NULL}" + +run_test -U +check_result "-1 22" + +run_test -u "" +check_result "-1 22" + +run_test -u "=${BAR}" +check_result "-1 22" + +run_test -c 3 -s FOO ${NEWBAR} 1 -g FOO -u FOO -g FOO +check_result "0 0 ${NEWBAR} 0 0 ${NULL}" + +run_test -c 3 -u FOO -s FOO ${BAR} 1 -g FOO -u FOO -g FOO -c 3 -u FOO\ +	-s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 0 0 ${BAR} 0 0 ${NULL} 0 0 0 0 ${NEWBAR}" + + +# Puts. +run_test -p FOO=${NEWBAR} -g FOO +check_result "0 0 ${NEWBAR}" + +run_test -c 3 -p FOO=${NEWBAR} -g FOO +check_result "0 0 ${NEWBAR}" + +run_test -p FOO -g FOO +check_result "-1 22 ${BAR}" + +run_test -p FOO=${BAR} -p FOO=${NEWBAR} -g FOO +check_result "0 0 0 0 ${NEWBAR}" + +run_test -p FOO=${BAR} -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 0 0 ${NEWBAR}" + +run_test -s FOO ${NEWBAR} 1 -p FOO=${BAR} -g FOO +check_result "0 0 0 0 ${BAR}" + +run_test -p FOO=${BAR} -u FOO +check_result "0 0 0 0" + +run_test -p FOO=${BAR} -s FOO ${NEWBAR} 1 -u FOO +check_result "0 0 0 0 0 0" + +run_test -s FOO ${NEWBAR} 1 -p FOO=${BAR} -u FOO +check_result "0 0 0 0 0 0" + +run_test -s FOO ${NEWBAR} 1 -p FOO=${BAR} -c 3 -g FOO -p FOO=${NEWBAR} -g FOO +check_result "0 0 0 0 ${NULL} 0 0 ${NEWBAR}" + +run_test -c 3 -p FOO=${BAR} -g FOO -c 3 -p FOO=${NEWBAR} -g FOO +check_result "0 0 ${BAR} 0 0 ${NEWBAR}" + + +# environ replacements. +run_test -r -g FOO -s FOO ${BAR} 1 -g FOO -u FOO -g FOO +check_result "${BAR} 0 0 ${BAR} 0 0 ${NULL}" + +run_test -r -g FOO -u FOO -g FOO -s FOO ${BAR} 1 -g FOO +check_result "${BAR} 0 0 ${NULL} 0 0 ${BAR}" + + +# corruption (blanking) of environ members. +export BLANK_ME= +export AFTER_BLANK=blanked +run_test -b BLANK_ME -p MORE=vars -g FOO -g BLANK_ME -g AFTER_BLANK +check_result "0 0 ${FOO} ${NULL} ${AFTER_BLANK}" + +run_test -b BLANK_ME -u FOO -g FOO -g AFTER_BLANK +check_result "0 0 ${NULL} ${AFTER_BLANK}" + +export BLANK_ME2= +export AFTER_BLANKS=blankD +run_test -b BLANK_ME -b AFTER_BLANK -b BLANK_ME2 -g FOO -g AFTER_BLANKS +check_result "${FOO} ${AFTER_BLANKS}" diff --git a/tools/regression/environ/retention.c b/tools/regression/environ/retention.c new file mode 100644 index 000000000000..3edaf8ca1d0a --- /dev/null +++ b/tools/regression/environ/retention.c @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2007 Sean C. Farley <scf@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer, + *    without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#include <sys/cdefs.h> +extern char **environ; +const char *envName = "FOOBAR"; +const char *envValSmall = "Hi"; +const char *envValLarge = "Hi, again"; +const char *envValAny = "Any value"; + + +int +main(int argc, char **argv) +{ +	const char *env1 = NULL; +	const char *env2 = NULL; +	const char *env3 = NULL; +	const char *env4 = NULL; +	const char *env5 = NULL; +	int testNdx; + +	/* Clean slate. */ +	environ = NULL; +	testNdx = 0; + +	/* Initial value of variable. */ +	if (getenv(envName) != NULL) +		printf("not "); +	printf("ok %d - getenv(\"%s\")\n", ++testNdx, envName); + +	/* Set value of variable to smaller value and get value. */ +	if ((setenv(envName, envValSmall, 1) != 0) || +	    ((env1 = getenv(envName)) == NULL) || +	    (strcmp(env1, envValSmall) != 0)) +		printf("not "); +	printf("ok %d - setenv(\"%s\", \"%s\", 1)\n", ++testNdx, envName, +	    envValSmall); + +	/* Unset variable. */ +	if ((unsetenv(envName) == -1) || ((env2 = getenv(envName)) != NULL)) +		printf("not "); +	printf("ok %d - unsetenv(\"%s\")\n", ++testNdx, envName); + +	/* Set variable to bigger value and get value. */ +	if ((setenv(envName, envValLarge, 1) != 0) || +	    ((env3 = getenv(envName)) == NULL) || +	    (strcmp(env3, envValLarge) != 0)) +		printf("not "); +	printf("ok %d - setenv(\"%s\", \"%s\", 1)\n", ++testNdx, envName, +	    envValLarge); + +	/* Set variable to smaller value and get value. */ +	if ((setenv(envName, envValSmall, 1) != 0) || +	    ((env4 = getenv(envName)) == NULL) || +	    (strcmp(env4, envValSmall) != 0)) +		printf("not "); +	printf("ok %d - setenv(\"%s\", \"%s\", 1)\n", ++testNdx, envName, +	    envValSmall); + +	/* Set variable to any value without overwrite and get value. */ +	if ((setenv(envName, envValAny, 0) != 0) || +	    ((env5 = getenv(envName)) == NULL) || +	    (strcmp(env5, envValAny) == 0)) +		printf("not "); +	printf("ok %d - setenv(\"%s\", \"%s\", 0)\n", ++testNdx, envName, +	    envValAny); + +	/* +	 * Verify FreeBSD-ism about allowing a program to keep old pointers without +	 * risk of segfaulting. +	 */ +	if ((strcmp(env1, envValSmall) != 0) || +	    (strcmp(env3, envValSmall) != 0) || +	    (strcmp(env4, envValSmall) != 0)) +		printf("not "); +	printf("ok %d - old variables point to valid memory\n", ++testNdx); + +	exit(EXIT_SUCCESS); +} diff --git a/tools/regression/environ/timings.c b/tools/regression/environ/timings.c new file mode 100644 index 000000000000..ac7dfcaa658f --- /dev/null +++ b/tools/regression/environ/timings.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 2007 Sean C. Farley <scf@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +#include <sys/cdefs.h> +const char value1[] = "Large ------------------ value"; +const char value2[] = "Small -- value"; +char nameValuePair[] = "less=more"; +const char name[] = "PATH"; +const char name2[] = "SHELL"; +const int MaxIterations = 1000000; +const char Tabs[] = "\t\t\t"; + + +static int +report_time(const char *action, struct timeval *startTime, +    struct timeval *endTime) +{ +	int actionLen; +	int numTabs; + +	actionLen = strlen(action); +	numTabs = 3 - actionLen / 8; + +	return (printf("Time spent executing %s:%.*s%f\n", action, numTabs, Tabs, +	    (endTime->tv_sec - startTime->tv_sec) + +	    (double)(endTime->tv_usec - startTime->tv_usec) / 1000000)); +} + + +int +main(int argc, char **argv) +{ +	int iterations; +	struct rusage endUsage; +	struct rusage startUsage; + +	/* +	 * getenv() on the existing environment. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		if (getenv(name) == NULL) +			err(EXIT_FAILURE, "getenv(name)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); + + +	/* +	 * setenv() a variable with a large value. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		if (setenv(name, value1, 1) == -1) +			err(EXIT_FAILURE, "setenv(name, value1, 1)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("setenv(name, value1, 1)", &startUsage.ru_utime, +	    &endUsage.ru_utime); + + +	/* +	 * getenv() the new variable on the new environment. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		/* Set large value to variable. */ +		if (getenv(name) == NULL) +			err(EXIT_FAILURE, "getenv(name)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); + + +	/* +	 * getenv() a different variable on the new environment. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		/* Set large value to variable. */ +		if (getenv(name2) == NULL) +			err(EXIT_FAILURE, "getenv(name2)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("getenv(name2)", &startUsage.ru_utime, &endUsage.ru_utime); + + +	/* +	 * setenv() a variable with a small value. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		if (setenv(name, value2, 1) == -1) +			err(EXIT_FAILURE, "setenv(name, value2, 1)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("setenv(name, value2, 1)", &startUsage.ru_utime, +	    &endUsage.ru_utime); + + +	/* +	 * getenv() a different variable on the new environment. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		/* Set large value to variable. */ +		if (getenv(name2) == NULL) +			err(EXIT_FAILURE, "getenv(name)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); + + +	/* +	 * getenv() a different variable on the new environment. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		/* Set large value to variable. */ +		if (getenv(name2) == NULL) +			err(EXIT_FAILURE, "getenv(name2)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("getenv(name2)", &startUsage.ru_utime, &endUsage.ru_utime); + + +	/* +	 * putenv() a variable with a small value. +	 */ +	getrusage(RUSAGE_SELF, &startUsage); + +	/* Iterate over setting variable. */ +	for (iterations = 0; iterations < MaxIterations; iterations++) +		if (putenv(nameValuePair) == -1) +			err(EXIT_FAILURE, "putenv(nameValuePair)"); + +	getrusage(RUSAGE_SELF, &endUsage); + +	report_time("putenv(nameValuePair)", &startUsage.ru_utime, +	    &endUsage.ru_utime); + + +	exit(EXIT_SUCCESS); +} | 
