From 8db32e8a1ed746af220e5b0a1e06c8e3843893f0 Mon Sep 17 00:00:00 2001 From: scf Date: Fri, 20 Jul 2007 23:30:13 +0000 Subject: Added environ-replacement detection. For programs that "clean" (i.e., su) or replace (i.e., zdump) the environment after a call to setenv(), putenv() or unsetenv() has been made, a few changes were made. - getenv() will return the value from the new environ array. - setenv() was split into two functions: __setenv() which is most of the previous setenv() without checks on the name and setenv() which contains the checks before calling __setenv(). - setenv(), putenv() and unsetenv() will unset all previous values and call __setenv() on all entries in the new environ array which in turn adds them to the end of the envVars array. Calling __setenv() instead of setenv() is done to avoid the temporary replacement of the '=' in a string with a NUL byte. Some strings may be read-only data. Added more regression checks for clearing the environment array. Replaced gettimeofday() with getrusage() in timing regression check for better accuracy. Fixed an off-by-one bug in __remove_putenv() in the use of memmove(). This went unnoticed due to the allocation of double the number of environ entries when building envVars. Fixed a few spelling mistakes in the comments. Reviewed by: ache Approved by: wes Approved by: re (kensmith) --- tools/regression/environ/envctl.c | 26 +++++++++++------ tools/regression/environ/envtest.t | 21 ++++++++++++++ tools/regression/environ/timings.c | 57 +++++++++++++++++++++----------------- 3 files changed, 70 insertions(+), 34 deletions(-) (limited to 'tools') diff --git a/tools/regression/environ/envctl.c b/tools/regression/environ/envctl.c index 2681741..e077e42 100644 --- a/tools/regression/environ/envctl.c +++ b/tools/regression/environ/envctl.c @@ -54,17 +54,19 @@ dump_environ(void) static void usage(const char *program) { - fprintf(stderr, "Usage: %s [-DGUcht] [-gu name] [-p name=value] " + fprintf(stderr, "Usage: %s [-CDGUchrt] [-gu name] [-p name=value] " "[(-S|-s name) value overwrite]\n\n" "Options:\n" + " -C\t\t\t\tClear environ variable with NULL pointer\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" - " -c\t\t\t\tClear environ variable\n" + " -c\t\t\t\tClear environ variable with calloc()'d memory\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", @@ -77,7 +79,7 @@ usage(const char *program) int main(int argc, char **argv) { - char *cleanEnv[] = { NULL }; + char *staticEnv[] = { "FOO=bar", NULL }; char arg; const char *eol = "\n"; const char *value; @@ -87,15 +89,19 @@ main(int argc, char **argv) exit(EXIT_FAILURE); } - while ((arg = getopt(argc, argv, "DGS:Ucg:hp:s:tu:")) != -1) { + while ((arg = getopt(argc, argv, "CDGS:Ucg:hp:rs:tu:")) != -1) { switch (arg) { - case 'D': - errno = 0; - dump_environ(); + case 'C': + environ = NULL; break; case 'c': - environ = cleanEnv; + environ = calloc(1, sizeof(*environ)); + break; + + case 'D': + errno = 0; + dump_environ(); break; case 'G': @@ -113,6 +119,10 @@ main(int argc, char **argv) printf("%d %d%s", putenv(optarg), errno, eol); break; + case 'r': + environ = staticEnv; + break; + case 'S': errno = 0; printf("%d %d%s", setenv(NULL, optarg, diff --git a/tools/regression/environ/envtest.t b/tools/regression/environ/envtest.t index e3aca95..2b2c548 100644 --- a/tools/regression/environ/envtest.t +++ b/tools/regression/environ/envtest.t @@ -132,6 +132,9 @@ 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 -s FOO ${BAR} 1 -g FOO -c -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 ${BAR} 0 0 ${NEWBAR}" + # Unsets. run_test -u FOO -g FOO @@ -152,6 +155,10 @@ check_result "-1 22" run_test -c -s FOO ${NEWBAR} 1 -g FOO -u FOO -g FOO check_result "0 0 ${NEWBAR} 0 0" +run_test -c -u FOO -s FOO ${BAR} 1 -g FOO -u FOO -g FOO -c -u FOO\ + -s FOO ${NEWBAR} 1 -g FOO +check_result "0 0 0 0 ${BAR} 0 0 0 0 0 0 ${NEWBAR}" + # Puts. run_test -p FOO=${NEWBAR} -g FOO @@ -180,3 +187,17 @@ 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 -g FOO -p FOO=${NEWBAR} -g FOO +check_result "0 0 0 0 0 0 ${NEWBAR}" + +run_test -c -p FOO=${BAR} -g FOO -c -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" + +run_test -r -g FOO -u FOO -g FOO -s FOO ${BAR} 1 -g FOO +check_result "${BAR} 0 0 0 0 ${BAR}" diff --git a/tools/regression/environ/timings.c b/tools/regression/environ/timings.c index 1bf3c91..7999fa1 100644 --- a/tools/regression/environ/timings.c +++ b/tools/regression/environ/timings.c @@ -23,7 +23,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include #include +#include #include #include #include @@ -64,43 +66,44 @@ int main(int argc, char **argv) { int iterations; - struct timeval endTime; - struct timeval startTime; + struct rusage endUsage; + struct rusage startUsage; /* * getenv() on the existing environment. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) if (getenv(name) == NULL) err(EXIT_FAILURE, "getenv(name)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("getenv(name)", &startTime, &endTime); + report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); /* * setenv() a variable with a large value. */ - gettimeofday(&startTime, NULL); + 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)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("setenv(name, value1, 1)", &startTime, &endTime); + report_time("setenv(name, value1, 1)", &startUsage.ru_utime, + &endUsage.ru_utime); /* * getenv() the new variable on the new environment. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) @@ -108,15 +111,15 @@ main(int argc, char **argv) if (getenv(name) == NULL) err(EXIT_FAILURE, "getenv(name)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("getenv(name)", &startTime, &endTime); + report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); /* * getenv() a different variable on the new environment. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) @@ -124,30 +127,31 @@ main(int argc, char **argv) if (getenv(name2) == NULL) err(EXIT_FAILURE, "getenv(name2)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("getenv(name2)", &startTime, &endTime); + report_time("getenv(name2)", &startUsage.ru_utime, &endUsage.ru_utime); /* * setenv() a variable with a small value. */ - gettimeofday(&startTime, NULL); + 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)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("setenv(name, value2, 1)", &startTime, &endTime); + report_time("setenv(name, value2, 1)", &startUsage.ru_utime, + &endUsage.ru_utime); /* * getenv() a different variable on the new environment. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) @@ -155,15 +159,15 @@ main(int argc, char **argv) if (getenv(name2) == NULL) err(EXIT_FAILURE, "getenv(name)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("getenv(name)", &startTime, &endTime); + report_time("getenv(name)", &startUsage.ru_utime, &endUsage.ru_utime); /* * getenv() a different variable on the new environment. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) @@ -171,24 +175,25 @@ main(int argc, char **argv) if (getenv(name2) == NULL) err(EXIT_FAILURE, "getenv(name2)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("getenv(name2)", &startTime, &endTime); + report_time("getenv(name2)", &startUsage.ru_utime, &endUsage.ru_utime); /* * putenv() a variable with a small value. */ - gettimeofday(&startTime, NULL); + getrusage(RUSAGE_SELF, &startUsage); /* Iterate over setting variable. */ for (iterations = 0; iterations < MaxIterations; iterations++) if (putenv(nameValuePair) == -1) err(EXIT_FAILURE, "putenv(nameValuePair)"); - gettimeofday(&endTime, NULL); + getrusage(RUSAGE_SELF, &endUsage); - report_time("putenv(nameValuePair)", &startTime, &endTime); + report_time("putenv(nameValuePair)", &startUsage.ru_utime, + &endUsage.ru_utime); exit(EXIT_SUCCESS); -- cgit v1.1