Significantly reduce the memory leak as noted in BUGS section for
setenv(3) by tracking the size of the memory allocated instead of using strlen() on the current value. Convert all calls to POSIX from historic BSD API: - unsetenv returns an int. - putenv takes a char * instead of const char *. - putenv no longer makes a copy of the input string. - errno is set appropriately for POSIX. Exceptions involve bad environ variable and internal initialization code. These both set errno to EFAULT. Several patches to base utilities to handle the POSIX changes from Andrey Chernov's previous commit. A few I re-wrote to use setenv() instead of putenv(). New regression module for tools/regression/environ to test these functions. It also can be used to test the performance. Bump __FreeBSD_version to 700050 due to API change. PR: kern/99826 Approved by: wes Approved by: re (kensmith)
This commit is contained in:
parent
f6c1ecca50
commit
2966d28c32
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171195
@ -131,14 +131,14 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
if (kflag)
|
||||
break;
|
||||
putenv("BLOCKSIZE=512");
|
||||
setenv("BLOCKSIZE", "512", 1);
|
||||
hflag = 0;
|
||||
break;
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'g':
|
||||
putenv("BLOCKSIZE=1g");
|
||||
setenv("BLOCKSIZE", "1g", 1);
|
||||
hflag = 0;
|
||||
break;
|
||||
case 'H':
|
||||
@ -152,7 +152,7 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'k':
|
||||
kflag++;
|
||||
putenv("BLOCKSIZE=1024");
|
||||
setenv("BLOCKSIZE", "1024", 1);
|
||||
hflag = 0;
|
||||
break;
|
||||
case 'l':
|
||||
@ -162,7 +162,7 @@ main(int argc, char *argv[])
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'm':
|
||||
putenv("BLOCKSIZE=1m");
|
||||
setenv("BLOCKSIZE", "1m", 1);
|
||||
hflag = 0;
|
||||
break;
|
||||
case 'n':
|
||||
|
16
bin/sh/var.c
16
bin/sh/var.c
@ -289,6 +289,7 @@ void
|
||||
setvareq(char *s, int flags)
|
||||
{
|
||||
struct var *vp, **vpp;
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
if (aflag)
|
||||
@ -319,7 +320,10 @@ setvareq(char *s, int flags)
|
||||
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
||||
chkmail(1);
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
p = strchr(s, '=');
|
||||
*p = '\0';
|
||||
(void) setenv(s, p + 1, 1);
|
||||
*p = '=';
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
@ -335,7 +339,10 @@ setvareq(char *s, int flags)
|
||||
INTOFF;
|
||||
*vpp = vp;
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
p = strchr(s, '=');
|
||||
*p = '\0';
|
||||
(void) setenv(s, p + 1, 1);
|
||||
*p = '=';
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
@ -596,7 +603,10 @@ exportcmd(int argc, char **argv)
|
||||
|
||||
vp->flags |= flag;
|
||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||
putenv(vp->text);
|
||||
p = strchr(vp->text, '=');
|
||||
*p = '\0';
|
||||
(void) setenv(vp->text, p + 1, 1);
|
||||
*p = '=';
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
goto found;
|
||||
|
@ -161,7 +161,7 @@ void _Exit(int) __dead2;
|
||||
int posix_memalign(void **, size_t, size_t); /* (ADV) */
|
||||
int rand_r(unsigned *); /* (TSF) */
|
||||
int setenv(const char *, const char *, int);
|
||||
void unsetenv(const char *);
|
||||
int unsetenv(const char *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -197,7 +197,7 @@ long mrand48(void);
|
||||
long nrand48(unsigned short[3]);
|
||||
int posix_openpt(int);
|
||||
char *ptsname(int);
|
||||
int putenv(const char *);
|
||||
int putenv(char *);
|
||||
long random(void);
|
||||
char *realpath(const char *, char resolved_path[]);
|
||||
unsigned short
|
||||
|
@ -8,10 +8,10 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
bsearch.c div.c exit.c getenv.c getopt.c getopt_long.c \
|
||||
getsubopt.c grantpt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \
|
||||
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \
|
||||
merge.c putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c \
|
||||
reallocf.c realpath.c remque.c setenv.c strfmon.c strtoimax.c \
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c strtoumax.c \
|
||||
strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
merge.c qsort.c qsort_r.c radixsort.c rand.c random.c \
|
||||
reallocf.c realpath.c remque.c strfmon.c strtoimax.c \
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
|
||||
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
|
||||
SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" @(#)getenv.3 8.2 (Berkeley) 12/11/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 12, 2006
|
||||
.Dd June 20, 2007
|
||||
.Dt GETENV 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -50,22 +50,13 @@
|
||||
.Ft int
|
||||
.Fn setenv "const char *name" "const char *value" "int overwrite"
|
||||
.Ft int
|
||||
.Fn putenv "const char *string"
|
||||
.Ft void
|
||||
.Fn putenv "char *string"
|
||||
.Ft int
|
||||
.Fn unsetenv "const char *name"
|
||||
.Sh DESCRIPTION
|
||||
These functions set, unset and fetch environment variables from the
|
||||
host
|
||||
.Em environment list .
|
||||
For compatibility with differing environment conventions,
|
||||
the given arguments
|
||||
.Fa name
|
||||
and
|
||||
.Fa value
|
||||
may be appended and prepended,
|
||||
respectively,
|
||||
with an equal sign
|
||||
.Dq Li \&= .
|
||||
.Pp
|
||||
The
|
||||
.Fn getenv
|
||||
@ -97,11 +88,18 @@ to the given
|
||||
.Pp
|
||||
The
|
||||
.Fn putenv
|
||||
function takes an argument of the form ``name=value'' and is
|
||||
equivalent to:
|
||||
.Bd -literal -offset indent
|
||||
setenv(name, value, 1);
|
||||
.Ed
|
||||
function takes an argument of the form ``name=value'' and
|
||||
puts it directly into the current environment,
|
||||
so altering the argument shall change the environment.
|
||||
If the variable
|
||||
.Fa name
|
||||
does not exist in the list,
|
||||
it is inserted with the given
|
||||
.Fa value .
|
||||
If the variable
|
||||
.Fa name
|
||||
does exist, it is reset to the given
|
||||
.Fa value .
|
||||
.Pp
|
||||
The
|
||||
.Fn unsetenv
|
||||
@ -121,15 +119,55 @@ is not in the current environment,
|
||||
.Dv NULL
|
||||
is returned.
|
||||
.Pp
|
||||
.Rv -std setenv putenv
|
||||
.Rv -std setenv putenv unsetenv
|
||||
.Sh ERRORS
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The function
|
||||
.Fn getenv ,
|
||||
.Fn setenv
|
||||
or
|
||||
.Fn unsetenv
|
||||
failed because the
|
||||
.Fa name
|
||||
is a
|
||||
.Dv NULL
|
||||
pointer, points to an empty string, or points to a string containing an
|
||||
.Dq Li \&=
|
||||
character.
|
||||
.Pp
|
||||
The function
|
||||
.Fn putenv
|
||||
failed because
|
||||
.Fa string
|
||||
is a
|
||||
.Dv NULL
|
||||
pointer,
|
||||
.Fa string is without an
|
||||
.Dq Li \&=
|
||||
character or
|
||||
.Dq Li \&=
|
||||
is the first character in
|
||||
.Fa string .
|
||||
This does not follow the
|
||||
.Tn POSIX
|
||||
specification.
|
||||
.It Bq Er ENOMEM
|
||||
The function
|
||||
.Fn setenv
|
||||
.Fn setenv ,
|
||||
.Fn unsetenv
|
||||
or
|
||||
.Fn putenv
|
||||
failed because they were unable to allocate memory for the environment.
|
||||
.It Bq Er EFAULT
|
||||
The functions
|
||||
.Fn setenv ,
|
||||
.Fn unsetenv
|
||||
or
|
||||
.Fn putenv
|
||||
failed to make a valid copy of the environment due to the environment being
|
||||
corrupt (i.e., a name without a value). A warning will be output to stderr with
|
||||
information about the issue.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
@ -141,6 +179,13 @@ The
|
||||
.Fn getenv
|
||||
function conforms to
|
||||
.St -isoC .
|
||||
The
|
||||
.Fn setenv ,
|
||||
.Fn putenv
|
||||
and
|
||||
.Fn unsetenv
|
||||
functions conforms to
|
||||
.St -p1003.1-2001 .
|
||||
.Sh HISTORY
|
||||
The functions
|
||||
.Fn setenv
|
||||
@ -152,19 +197,30 @@ The
|
||||
.Fn putenv
|
||||
function appeared in
|
||||
.Bx 4.3 Reno .
|
||||
.Pp
|
||||
Until
|
||||
.Fx 7.0 ,
|
||||
.Fn putenv
|
||||
would make a copy of
|
||||
.Fa string
|
||||
and insert it into the environment using
|
||||
.Fn setenv .
|
||||
This was changed to use
|
||||
.Fa string
|
||||
as the memory location of the ``name=value'' pair to follow the
|
||||
.Tn POSIX
|
||||
specification.
|
||||
.Sh BUGS
|
||||
Successive calls to
|
||||
.Fn setenv
|
||||
or
|
||||
.Fn putenv
|
||||
assigning a differently sized
|
||||
that assign a larger-sized
|
||||
.Fa value
|
||||
to the same
|
||||
than any previous value to the same
|
||||
.Fa name
|
||||
will result in a memory leak.
|
||||
The
|
||||
.Fx
|
||||
semantics for these functions
|
||||
semantics for this function
|
||||
(namely, that the contents of
|
||||
.Fa value
|
||||
are copied and that old values remain accessible indefinitely) make this
|
||||
|
@ -1,89 +1,568 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
* 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 <sys/types.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
inline char *__findenv(const char *, int *);
|
||||
|
||||
/*
|
||||
* __findenv --
|
||||
* Returns pointer to value associated with name, if any, else NULL.
|
||||
* Sets offset to be the offset of the name/value combination in the
|
||||
* environmental array, for use by setenv(3) and unsetenv(3).
|
||||
* Explicitly removes '=' in argument name.
|
||||
* Standard environ. environ variable is exposed to entire process.
|
||||
*
|
||||
* This routine *should* be a static; don't use it.
|
||||
* origEnviron: Upon cleanup on unloading of library or failure, this
|
||||
* allows environ to return to as it was before.
|
||||
* environSize: Number of variables environ can hold. Can only
|
||||
* increase.
|
||||
*/
|
||||
inline char *
|
||||
__findenv(name, offset)
|
||||
const char *name;
|
||||
int *offset;
|
||||
{
|
||||
extern char **environ;
|
||||
int len, i;
|
||||
const char *np;
|
||||
char **p, *cp;
|
||||
extern char **environ;
|
||||
static char **origEnviron;
|
||||
static int environSize = 0;
|
||||
|
||||
if (name == NULL || environ == NULL)
|
||||
return (NULL);
|
||||
for (np = name; *np && *np != '='; ++np)
|
||||
continue;
|
||||
len = np - name;
|
||||
for (p = environ; (cp = *p) != NULL; ++p) {
|
||||
for (np = name, i = len; i && *cp; i--)
|
||||
if (*cp++ != *np++)
|
||||
break;
|
||||
if (i == 0 && *cp++ == '=') {
|
||||
*offset = p - environ;
|
||||
return (cp);
|
||||
/*
|
||||
* Array of environment variables built from environ. Each element records:
|
||||
* name: Pointer to name=value string
|
||||
* name length: Length of name not counting '=' character
|
||||
* value: Pointer to value within same string as name
|
||||
* value size: Size (not length) of space for value not counting the
|
||||
* nul character
|
||||
* active state: true/false value to signify whether variable is active.
|
||||
* Useful since multiple variables with the same name can
|
||||
* co-exist. At most, one variable can be active at any
|
||||
* one time.
|
||||
* putenv: Created from putenv() call. This memory must not be
|
||||
* reused.
|
||||
*/
|
||||
static struct envVars {
|
||||
size_t nameLen;
|
||||
size_t valueSize;
|
||||
char *name;
|
||||
char *value;
|
||||
bool active;
|
||||
bool putenv;
|
||||
} *envVars = NULL;
|
||||
|
||||
/*
|
||||
* Environment array information.
|
||||
*
|
||||
* envActive: Number of active variables in array.
|
||||
* envVarsSize: Size of array.
|
||||
* envVarsTotal: Number of total variables in array (active or not).
|
||||
*/
|
||||
static int envActive = 0;
|
||||
static int envVarsSize = 0;
|
||||
static int envVarsTotal = 0;
|
||||
|
||||
|
||||
/* Deinitialization of new environment. */
|
||||
static void __attribute__ ((destructor)) __clean_env(void);
|
||||
|
||||
|
||||
/*
|
||||
* Inline strlen() for performance. Also, perform check for an equals sign.
|
||||
* Cheaper here than peforming a strchr() later.
|
||||
*/
|
||||
static inline size_t
|
||||
__strleneq(const char *str)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s != '\0'; ++s)
|
||||
if (*s == '=')
|
||||
return (0);
|
||||
|
||||
return (s - str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Comparison of an environment name=value to a name.
|
||||
*/
|
||||
static inline bool
|
||||
strncmpeq(const char *nameValue, const char *name, size_t nameLen)
|
||||
{
|
||||
if (strncmp(nameValue, name, nameLen) == 0 && nameValue[nameLen] == '=')
|
||||
return (true);
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Using environment, returns pointer to value associated with name, if any,
|
||||
* else NULL. If the onlyActive flag is set to true, only variables that are
|
||||
* active are returned else all are.
|
||||
*/
|
||||
static inline char *
|
||||
__findenv(const char *name, size_t nameLen, int *envNdx, bool onlyActive)
|
||||
{
|
||||
int ndx;
|
||||
|
||||
/*
|
||||
* Find environment variable from end of array (more likely to be
|
||||
* active). A variable created by putenv is always active or it is not
|
||||
* tracked in the array.
|
||||
*/
|
||||
for (ndx = *envNdx; ndx >= 0; ndx--)
|
||||
if (envVars[ndx].putenv) {
|
||||
if (strncmpeq(envVars[ndx].name, name, nameLen)) {
|
||||
*envNdx = ndx;
|
||||
return (envVars[ndx].name + nameLen +
|
||||
sizeof ("=") - 1);
|
||||
}
|
||||
} else if ((!onlyActive || envVars[ndx].active) &&
|
||||
(envVars[ndx].nameLen == nameLen &&
|
||||
strncmpeq(envVars[ndx].name, name, nameLen))) {
|
||||
*envNdx = ndx;
|
||||
return (envVars[ndx].value);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getenv --
|
||||
* Returns ptr to value associated with name, if any, else NULL.
|
||||
* Using environ, returns pointer to value associated with name, if any, else
|
||||
* NULL. Used on the original environ passed into the program.
|
||||
*/
|
||||
static char *
|
||||
__findenv_environ(const char *name, size_t nameLen)
|
||||
{
|
||||
int envNdx;
|
||||
|
||||
/* Check for non-existant environment. */
|
||||
if (environ == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Find variable within environ. */
|
||||
for (envNdx = 0; environ[envNdx] != NULL; envNdx++)
|
||||
if (strncmpeq(environ[envNdx], name, nameLen))
|
||||
return (&(environ[envNdx][nameLen + sizeof("=") - 1]));
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Using the environment, rebuild the environ array for use by other C library
|
||||
* calls that depend upon it.
|
||||
*/
|
||||
static int
|
||||
__rebuild_environ(int newEnvironSize)
|
||||
{
|
||||
char **tmpEnviron;
|
||||
int envNdx;
|
||||
int environNdx;
|
||||
int tmpEnvironSize;
|
||||
|
||||
/* Resize environ. */
|
||||
if (newEnvironSize > environSize) {
|
||||
tmpEnvironSize = newEnvironSize * 2;
|
||||
tmpEnviron = realloc(environ, sizeof (*environ) *
|
||||
(tmpEnvironSize + 1));
|
||||
if (tmpEnviron == NULL)
|
||||
return (-1);
|
||||
environSize = tmpEnvironSize;
|
||||
environ = tmpEnviron;
|
||||
}
|
||||
envActive = newEnvironSize;
|
||||
|
||||
/* Assign active variables to environ. */
|
||||
for (envNdx = envVarsTotal - 1, environNdx = 0; envNdx >= 0; envNdx--)
|
||||
if (envVars[envNdx].active)
|
||||
environ[environNdx++] = envVars[envNdx].name;
|
||||
environ[environNdx] = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Enlarge new environment.
|
||||
*/
|
||||
static inline bool
|
||||
__enlarge_env(void)
|
||||
{
|
||||
int newEnvVarsSize;
|
||||
struct envVars *tmpEnvVars;
|
||||
|
||||
envVarsTotal++;
|
||||
if (envVarsTotal > envVarsSize) {
|
||||
newEnvVarsSize = envVarsTotal * 2;
|
||||
tmpEnvVars = realloc(envVars, sizeof (*envVars) *
|
||||
newEnvVarsSize);
|
||||
if (tmpEnvVars == NULL) {
|
||||
envVarsTotal--;
|
||||
return (false);
|
||||
}
|
||||
envVarsSize = newEnvVarsSize;
|
||||
envVars = tmpEnvVars;
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Using environ, build an environment for use by standard C library calls.
|
||||
*/
|
||||
static int
|
||||
__build_env(void)
|
||||
{
|
||||
char **env;
|
||||
int activeNdx;
|
||||
int envNdx;
|
||||
int rtrnVal;
|
||||
int savedErrno;
|
||||
size_t nameLen;
|
||||
|
||||
/* Check for non-existant environment. */
|
||||
if (environ == NULL)
|
||||
return (0);
|
||||
if (environ[0] == NULL)
|
||||
goto SaveEnviron;
|
||||
|
||||
/* Count environment variables. */
|
||||
for (env = environ, envVarsTotal = 0; *env != NULL; env++)
|
||||
envVarsTotal++;
|
||||
envVarsSize = envVarsTotal * 2;
|
||||
|
||||
/* Create new environment. */
|
||||
envVars = calloc(1, sizeof (*envVars) * envVarsSize);
|
||||
if (envVars == NULL)
|
||||
goto Failure;
|
||||
|
||||
/* Copy environ values and keep track of them. */
|
||||
for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) {
|
||||
envVars[envNdx].putenv = false;
|
||||
envVars[envNdx].name =
|
||||
strdup(environ[envVarsTotal - envNdx - 1]);
|
||||
if (envVars[envNdx].name == NULL)
|
||||
goto Failure;
|
||||
envVars[envNdx].value = strchr(envVars[envNdx].name, '=');
|
||||
if (envVars[envNdx].value != NULL) {
|
||||
envVars[envNdx].value++;
|
||||
envVars[envNdx].valueSize =
|
||||
strlen(envVars[envNdx].value);
|
||||
} else {
|
||||
warnx("environment corrupt; missing value for %s",
|
||||
envVars[envNdx].name);
|
||||
errno = EFAULT;
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find most current version of variable to make active. This
|
||||
* will prevent multiple active variables from being created
|
||||
* during this initialization phase.
|
||||
*/
|
||||
nameLen = envVars[envNdx].value - envVars[envNdx].name - 1;
|
||||
envVars[envNdx].nameLen = nameLen;
|
||||
activeNdx = envVarsTotal - 1;
|
||||
if (__findenv(envVars[envNdx].name, nameLen, &activeNdx,
|
||||
false) == NULL) {
|
||||
warnx("environment corrupt; unable to find %.*s",
|
||||
nameLen, envVars[envNdx].name);
|
||||
errno = EFAULT;
|
||||
goto Failure;
|
||||
}
|
||||
envVars[activeNdx].active = true;
|
||||
}
|
||||
|
||||
/* Create a new environ. */
|
||||
SaveEnviron:
|
||||
origEnviron = environ;
|
||||
environ = NULL;
|
||||
if (envVarsTotal > 0) {
|
||||
rtrnVal = __rebuild_environ(envVarsTotal);
|
||||
if (rtrnVal == -1) {
|
||||
savedErrno = errno;
|
||||
__clean_env();
|
||||
errno = savedErrno;
|
||||
}
|
||||
} else
|
||||
rtrnVal = 0;
|
||||
|
||||
return (rtrnVal);
|
||||
|
||||
Failure:
|
||||
savedErrno = errno;
|
||||
__clean_env();
|
||||
errno = savedErrno;
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove variable added by putenv() from variable tracking array.
|
||||
*/
|
||||
static void
|
||||
__remove_putenv(int envNdx)
|
||||
{
|
||||
memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]),
|
||||
(envVarsTotal - envNdx) * sizeof (*envVars));
|
||||
envVarsTotal--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deallocate the environment built from environ as well as environ then set
|
||||
* both to NULL. Eases debugging of memory leaks.
|
||||
*/
|
||||
static void
|
||||
__clean_env(void)
|
||||
{
|
||||
int envNdx;
|
||||
|
||||
/* Deallocate environment and environ if created by *env(). */
|
||||
if (envVars != NULL) {
|
||||
for (envNdx = 0; envNdx < envVarsTotal; envNdx++)
|
||||
if (!envVars[envNdx].putenv)
|
||||
free(envVars[envNdx].name);
|
||||
free(envVars);
|
||||
envVars = NULL;
|
||||
|
||||
/* Restore original environ. */
|
||||
if (origEnviron != NULL) {
|
||||
free(environ);
|
||||
environ = origEnviron;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns the value of a variable or NULL if none are found.
|
||||
*/
|
||||
char *
|
||||
getenv(name)
|
||||
const char *name;
|
||||
getenv(const char *name)
|
||||
{
|
||||
int offset;
|
||||
int envNdx;
|
||||
size_t nameLen;
|
||||
|
||||
return (__findenv(name, &offset));
|
||||
/* Check for malformed name. */
|
||||
if (name == NULL || (nameLen = __strleneq(name)) == 0) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Find environment variable via environ or rebuilt environment. */
|
||||
if (envVars == NULL)
|
||||
return (__findenv_environ(name, nameLen));
|
||||
else {
|
||||
envNdx = envVarsTotal - 1;
|
||||
return (__findenv(name, nameLen, &envNdx, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the value of a variable. Older settings are labeled as inactive. If an
|
||||
* older setting has enough room to store the new value, it will be reused. No
|
||||
* previous variables are ever freed here to avoid causing a segmentation fault
|
||||
* in a user's code.
|
||||
*/
|
||||
int
|
||||
setenv(const char *name, const char *value, int overwrite)
|
||||
{
|
||||
bool reuse;
|
||||
char *env;
|
||||
int envNdx;
|
||||
int newEnvActive;
|
||||
size_t nameLen;
|
||||
size_t valueLen;
|
||||
|
||||
/* Check for malformed name. */
|
||||
if (name == NULL || (nameLen = __strleneq(name)) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Initialize environment. */
|
||||
if (envVars == NULL && __build_env() == -1)
|
||||
return (-1);
|
||||
|
||||
/* Find existing environment variable large enough to use. */
|
||||
envNdx = envVarsTotal - 1;
|
||||
newEnvActive = envActive;
|
||||
valueLen = strlen(value);
|
||||
reuse = false;
|
||||
if (__findenv(name, nameLen, &envNdx, false) != NULL) {
|
||||
/* Deactivate entry if overwrite is allowed. */
|
||||
if (envVars[envNdx].active) {
|
||||
if (overwrite == 0)
|
||||
return (0);
|
||||
envVars[envNdx].active = false;
|
||||
newEnvActive--;
|
||||
}
|
||||
|
||||
/* putenv() created variable cannot be reused. */
|
||||
if (envVars[envNdx].putenv)
|
||||
__remove_putenv(envNdx);
|
||||
|
||||
/* Entry is large enough to reuse. */
|
||||
else if (envVars[envNdx].valueSize >= valueLen)
|
||||
reuse = true;
|
||||
|
||||
}
|
||||
|
||||
/* Create new variable if none was found of sufficient size. */
|
||||
if (! reuse) {
|
||||
/* Enlarge environment. */
|
||||
envNdx = envVarsTotal;
|
||||
if (!__enlarge_env())
|
||||
return (-1);
|
||||
|
||||
/* Create environment entry. */
|
||||
envVars[envNdx].name = malloc(nameLen + sizeof ("=") +
|
||||
valueLen);
|
||||
if (envVars[envNdx].name == NULL) {
|
||||
envVarsTotal--;
|
||||
return (-1);
|
||||
}
|
||||
envVars[envNdx].nameLen = nameLen;
|
||||
envVars[envNdx].valueSize = valueLen;
|
||||
|
||||
/* Save name of name/value pair. */
|
||||
env = stpcpy(envVars[envNdx].name, name);
|
||||
if ((envVars[envNdx].name)[nameLen] != '=')
|
||||
env = stpcpy(env, "=");
|
||||
}
|
||||
else
|
||||
env = envVars[envNdx].value;
|
||||
|
||||
/* Save value of name/value pair. */
|
||||
strcpy(env, value);
|
||||
envVars[envNdx].value = env;
|
||||
envVars[envNdx].active = true;
|
||||
newEnvActive++;
|
||||
|
||||
/* No need to rebuild environ if the variable was reused. */
|
||||
if (reuse)
|
||||
return (0);
|
||||
else
|
||||
return (__rebuild_environ(newEnvActive));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Insert a "name=value" string into then environment. Special settings must be
|
||||
* made to keep setenv() from reusing this memory block and unsetenv() from
|
||||
* allowing it to be tracked.
|
||||
*/
|
||||
int
|
||||
putenv(char *string)
|
||||
{
|
||||
char *equals;
|
||||
int envNdx;
|
||||
int newEnvActive;
|
||||
size_t nameLen;
|
||||
|
||||
/* Check for malformed argument. */
|
||||
if (string == NULL || (equals = strchr(string, '=')) == NULL ||
|
||||
(nameLen = equals - string) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Initialize environment. */
|
||||
if (envVars == NULL && __build_env() == -1)
|
||||
return (-1);
|
||||
|
||||
/* Deactivate previous environment variable. */
|
||||
envNdx = envVarsTotal - 1;
|
||||
newEnvActive = envActive;
|
||||
if (__findenv(string, nameLen, &envNdx, true) != NULL) {
|
||||
/* Reuse previous putenv slot. */
|
||||
if (envVars[envNdx].putenv) {
|
||||
envVars[envNdx].name = string;
|
||||
return (__rebuild_environ(envActive));
|
||||
} else {
|
||||
newEnvActive--;
|
||||
envVars[envNdx].active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enlarge environment. */
|
||||
envNdx = envVarsTotal;
|
||||
if (!__enlarge_env())
|
||||
return (-1);
|
||||
|
||||
/* Create environment entry. */
|
||||
envVars[envNdx].name = string;
|
||||
envVars[envNdx].nameLen = -1;
|
||||
envVars[envNdx].value = NULL;
|
||||
envVars[envNdx].valueSize = -1;
|
||||
envVars[envNdx].putenv = true;
|
||||
envVars[envNdx].active = true;
|
||||
newEnvActive++;
|
||||
|
||||
return (__rebuild_environ(newEnvActive));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unset variable with the same name by flagging it as inactive. No variable is
|
||||
* ever freed.
|
||||
*/
|
||||
int
|
||||
unsetenv(const char *name)
|
||||
{
|
||||
int envNdx;
|
||||
size_t nameLen;
|
||||
|
||||
/* Check for malformed name. */
|
||||
if (name == NULL || (nameLen = __strleneq(name)) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Initialize environment. */
|
||||
if (envVars == NULL && __build_env() == -1)
|
||||
return (-1);
|
||||
|
||||
/* Deactivate specified variable. */
|
||||
envNdx = envVarsTotal - 1;
|
||||
if (__findenv(name, nameLen, &envNdx, true) != NULL) {
|
||||
envVars[envNdx].active = false;
|
||||
if (envVars[envNdx].putenv)
|
||||
__remove_putenv(envNdx);
|
||||
__rebuild_environ(envActive - 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)putenv.c 8.2 (Berkeley) 3/27/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
putenv(str)
|
||||
const char *str;
|
||||
{
|
||||
char *p, *equal;
|
||||
int rval;
|
||||
|
||||
if ((p = strdup(str)) == NULL)
|
||||
return (-1);
|
||||
if ((equal = index(p, '=')) == NULL) {
|
||||
(void)free(p);
|
||||
return (-1);
|
||||
}
|
||||
*equal = '\0';
|
||||
rval = setenv(p, equal + 1, 1);
|
||||
(void)free(p);
|
||||
return (rval);
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *__findenv(const char *, int *);
|
||||
|
||||
/*
|
||||
* setenv --
|
||||
* Set the value of the environmental variable "name" to be
|
||||
* "value". If rewrite is set, replace any current value.
|
||||
*/
|
||||
int
|
||||
setenv(name, value, rewrite)
|
||||
const char *name;
|
||||
const char *value;
|
||||
int rewrite;
|
||||
{
|
||||
extern char **environ;
|
||||
static char **alloced; /* if allocated space before */
|
||||
char *c;
|
||||
int l_value, offset;
|
||||
|
||||
if (*value == '=') /* no `=' in value */
|
||||
++value;
|
||||
l_value = strlen(value);
|
||||
if ((c = __findenv(name, &offset))) { /* find if already exists */
|
||||
if (!rewrite)
|
||||
return (0);
|
||||
if (strlen(c) >= l_value) { /* old larger; copy over */
|
||||
while ( (*c++ = *value++) );
|
||||
return (0);
|
||||
}
|
||||
} else { /* create new slot */
|
||||
int cnt;
|
||||
char **p;
|
||||
|
||||
for (p = environ, cnt = 0; *p; ++p, ++cnt);
|
||||
if (alloced == environ) { /* just increase size */
|
||||
p = (char **)realloc((char *)environ,
|
||||
(size_t)(sizeof(char *) * (cnt + 2)));
|
||||
if (!p)
|
||||
return (-1);
|
||||
alloced = environ = p;
|
||||
}
|
||||
else { /* get new space */
|
||||
/* copy old entries into it */
|
||||
p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
|
||||
if (!p)
|
||||
return (-1);
|
||||
bcopy(environ, p, cnt * sizeof(char *));
|
||||
alloced = environ = p;
|
||||
}
|
||||
environ[cnt + 1] = NULL;
|
||||
offset = cnt;
|
||||
}
|
||||
for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */
|
||||
if (!(environ[offset] = /* name + `=' + value */
|
||||
malloc((size_t)((int)(c - name) + l_value + 2))))
|
||||
return (-1);
|
||||
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
|
||||
for (*c++ = '='; (*c++ = *value++); );
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* unsetenv(name) --
|
||||
* Delete environmental variable "name".
|
||||
*/
|
||||
void
|
||||
unsetenv(name)
|
||||
const char *name;
|
||||
{
|
||||
extern char **environ;
|
||||
char **p;
|
||||
int offset;
|
||||
|
||||
while (__findenv(name, &offset)) /* if set multiple times */
|
||||
for (p = &environ[offset];; ++p)
|
||||
if (!(*p = *(p + 1)))
|
||||
break;
|
||||
}
|
@ -258,7 +258,7 @@ Spawn(const char *prog, const char *acname, const char *provider,
|
||||
struct ng_mesg *rep = (struct ng_mesg *)msgbuf;
|
||||
struct ngpppoe_sts *sts = (struct ngpppoe_sts *)(msgbuf + sizeof *rep);
|
||||
struct ngpppoe_init_data *data;
|
||||
char env[sizeof(HISMACADDR)+18], unknown[14], sessionid[5], *path;
|
||||
char env[18], unknown[14], sessionid[5], *path;
|
||||
unsigned char *macaddr;
|
||||
const char *msg;
|
||||
int ret, slen;
|
||||
@ -352,11 +352,11 @@ Spawn(const char *prog, const char *acname, const char *provider,
|
||||
/* Put the peer's MAC address in the environment */
|
||||
if (sz >= sizeof(struct ether_header)) {
|
||||
macaddr = ((struct ether_header *)request)->ether_shost;
|
||||
snprintf(env, sizeof(env), "%s=%x:%x:%x:%x:%x:%x", HISMACADDR,
|
||||
snprintf(env, sizeof(env), "%x:%x:%x:%x:%x:%x",
|
||||
macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4],
|
||||
macaddr[5]);
|
||||
if (putenv(env) != 0)
|
||||
syslog(LOG_INFO, "putenv: cannot set %s: %m", env);
|
||||
if (setenv(HISMACADDR, env, 1) != 0)
|
||||
syslog(LOG_INFO, "setenv: cannot set %s: %m", HISMACADDR);
|
||||
}
|
||||
|
||||
/* And send our request data to the waiting node */
|
||||
|
@ -57,7 +57,7 @@
|
||||
* is created, otherwise 1.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 700049 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 700050 /* Master, propagated to newvers */
|
||||
|
||||
#ifndef LOCORE
|
||||
#include <sys/types.h>
|
||||
|
14
tools/regression/environ/Makefile
Normal file
14
tools/regression/environ/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
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
|
16
tools/regression/environ/Makefile.envctl
Normal file
16
tools/regression/environ/Makefile.envctl
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
SRCS= envctl.c
|
||||
PROG= envctl
|
||||
|
||||
CFLAGS+=-Wall -I../../../include
|
||||
|
||||
CLEANFILES= ${PROG}.core
|
||||
|
||||
NO_MAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
test: ${PROG}
|
||||
@sh envtest.t
|
16
tools/regression/environ/Makefile.retention
Normal file
16
tools/regression/environ/Makefile.retention
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
SRCS= retention.c
|
||||
PROG= retention
|
||||
|
||||
CFLAGS+=-Wall -I../../../include
|
||||
|
||||
CLEANFILES= *~ ${PROG}.core
|
||||
|
||||
NO_MAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
test: ${PROG}
|
||||
@./${PROG}
|
16
tools/regression/environ/Makefile.timings
Normal file
16
tools/regression/environ/Makefile.timings
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
SRCS= timings.c
|
||||
PROG= timings
|
||||
|
||||
CFLAGS+=-Wall -I../../../include
|
||||
|
||||
CLEANFILES= ${PROG}.core
|
||||
|
||||
NO_MAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
test: ${PROG}
|
||||
@./timings
|
154
tools/regression/environ/envctl.c
Normal file
154
tools/regression/environ/envctl.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*-
|
||||
* 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 <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
extern char **environ;
|
||||
|
||||
|
||||
static void
|
||||
dump_environ(void)
|
||||
{
|
||||
char **environPtr;
|
||||
|
||||
for (environPtr = environ; *environPtr != NULL; *environPtr++)
|
||||
printf("%s\n", *environPtr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(const char *program)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-DGUcht] [-gu name] [-p name=value] "
|
||||
"[(-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"
|
||||
" -c\t\t\t\tClear environ variable\n"
|
||||
" -g name\t\t\tgetenv(name)\n"
|
||||
" -h\t\t\t\tHelp\n"
|
||||
" -p name=value\t\t\tputenv(name=value)\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;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *cleanEnv[] = { NULL };
|
||||
char arg;
|
||||
const char *eol = "\n";
|
||||
const char *value;
|
||||
|
||||
if (argc == 1) {
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while ((arg = getopt(argc, argv, "DGS:Ucg:hp:s:tu:")) != -1) {
|
||||
switch (arg) {
|
||||
case 'D':
|
||||
errno = 0;
|
||||
dump_environ();
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
environ = cleanEnv;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
value = getenv(NULL);
|
||||
printf("%s%s", value == NULL ? "" : value, eol);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
value = getenv(optarg);
|
||||
printf("%s%s", value == NULL ? "" : value, eol);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
errno = 0;
|
||||
printf("%d %d%s", putenv(optarg), errno, eol);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
errno = 0;
|
||||
printf("%d %d%s", setenv(NULL, optarg,
|
||||
atoi(argv[optind])), errno, eol);
|
||||
optind += 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
errno = 0;
|
||||
printf("%d %d%s", setenv(optarg, argv[optind],
|
||||
atoi(argv[optind + 1])), errno, eol);
|
||||
optind += 2;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
eol = " ";
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
printf("%d %d%s", unsetenv(NULL), errno, eol);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
printf("%d %d%s", unsetenv(optarg), errno, 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);
|
||||
}
|
182
tools/regression/environ/envtest.t
Normal file
182
tools/regression/environ/envtest.t
Normal file
@ -0,0 +1,182 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
|
||||
# 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
|
||||
#
|
||||
|
||||
# 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 -g FOO
|
||||
check_result ""
|
||||
|
||||
run_test -g FOOBAR
|
||||
check_result ""
|
||||
|
||||
run_test -c -g FOOBAR
|
||||
check_result ""
|
||||
|
||||
run_test -G
|
||||
check_result ""
|
||||
|
||||
|
||||
# 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 -s FOO ${NEWBAR} 0 -g FOO
|
||||
check_result "0 0 ${NEWBAR}"
|
||||
|
||||
run_test -c -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 -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}"
|
||||
|
||||
|
||||
# Unsets.
|
||||
run_test -u FOO -g FOO
|
||||
check_result "0 0"
|
||||
|
||||
run_test -c -u FOO -g FOO
|
||||
check_result "0 0"
|
||||
|
||||
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 -s FOO ${NEWBAR} 1 -g FOO -u FOO -g FOO
|
||||
check_result "0 0 ${NEWBAR} 0 0"
|
||||
|
||||
|
||||
# Puts.
|
||||
run_test -p FOO=${NEWBAR} -g FOO
|
||||
check_result "0 0 ${NEWBAR}"
|
||||
|
||||
run_test -c -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"
|
109
tools/regression/environ/retention.c
Normal file
109
tools/regression/environ/retention.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* 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>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
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);
|
||||
}
|
195
tools/regression/environ/timings.c
Normal file
195
tools/regression/environ/timings.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*-
|
||||
* 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/time.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
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 timeval endTime;
|
||||
struct timeval startTime;
|
||||
|
||||
/*
|
||||
* getenv() on the existing environment.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
if (getenv(name) == NULL)
|
||||
err(EXIT_FAILURE, "getenv(name)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("getenv(name)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* setenv() a variable with a large value.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* 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);
|
||||
|
||||
report_time("setenv(name, value1, 1)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* getenv() the new variable on the new environment.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
/* Set large value to variable. */
|
||||
if (getenv(name) == NULL)
|
||||
err(EXIT_FAILURE, "getenv(name)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("getenv(name)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* getenv() a different variable on the new environment.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
/* Set large value to variable. */
|
||||
if (getenv(name2) == NULL)
|
||||
err(EXIT_FAILURE, "getenv(name2)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("getenv(name2)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* setenv() a variable with a small value.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* 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);
|
||||
|
||||
report_time("setenv(name, value2, 1)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* getenv() a different variable on the new environment.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
/* Set large value to variable. */
|
||||
if (getenv(name2) == NULL)
|
||||
err(EXIT_FAILURE, "getenv(name)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("getenv(name)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* getenv() a different variable on the new environment.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
/* Set large value to variable. */
|
||||
if (getenv(name2) == NULL)
|
||||
err(EXIT_FAILURE, "getenv(name2)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("getenv(name2)", &startTime, &endTime);
|
||||
|
||||
|
||||
/*
|
||||
* putenv() a variable with a small value.
|
||||
*/
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
/* Iterate over setting variable. */
|
||||
for (iterations = 0; iterations < MaxIterations; iterations++)
|
||||
if (putenv(nameValuePair) == -1)
|
||||
err(EXIT_FAILURE, "putenv(nameValuePair)");
|
||||
|
||||
gettimeofday(&endTime, NULL);
|
||||
|
||||
report_time("putenv(nameValuePair)", &startTime, &endTime);
|
||||
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
@ -140,16 +140,16 @@ main(int argc, char *argv[])
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'h':
|
||||
putenv("BLOCKSIZE=512");
|
||||
setenv("BLOCKSIZE", "512", 1);
|
||||
hflag = 1;
|
||||
break;
|
||||
case 'k':
|
||||
hflag = 0;
|
||||
putenv("BLOCKSIZE=1024");
|
||||
setenv("BLOCKSIZE", "1024", 1);
|
||||
break;
|
||||
case 'm':
|
||||
hflag = 0;
|
||||
putenv("BLOCKSIZE=1048576");
|
||||
setenv("BLOCKSIZE", "1048576", 1);
|
||||
break;
|
||||
case 'n':
|
||||
nodumpflag = 1;
|
||||
|
7
usr.bin/env/env.c
vendored
7
usr.bin/env/env.c
vendored
@ -67,6 +67,7 @@ main(int argc, char **argv)
|
||||
char *altpath, **ep, *p, **parg;
|
||||
char *cleanenv[1];
|
||||
int ch, want_clear;
|
||||
int rtrn;
|
||||
|
||||
altpath = NULL;
|
||||
want_clear = 0;
|
||||
@ -105,7 +106,11 @@ main(int argc, char **argv)
|
||||
for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) {
|
||||
if (env_verbosity)
|
||||
fprintf(stderr, "#env setenv:\t%s\n", *argv);
|
||||
(void)setenv(*argv, ++p, 1);
|
||||
*p = '\0';
|
||||
rtrn = setenv(*argv, p + 1, 1);
|
||||
*p = '=';
|
||||
if (rtrn == -1)
|
||||
err(EXIT_FAILURE, "setenv %s", *argv);
|
||||
}
|
||||
if (*argv) {
|
||||
if (altpath)
|
||||
|
@ -244,6 +244,7 @@ main(int argc, char *argv[])
|
||||
int rcswhich, shelltype;
|
||||
int i, num_limits = 0;
|
||||
int ch, doeval = 0, doall = 0;
|
||||
int rtrn;
|
||||
login_cap_t * lc = NULL;
|
||||
enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY;
|
||||
enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN;
|
||||
@ -399,8 +400,13 @@ main(int argc, char *argv[])
|
||||
login_close(lc);
|
||||
|
||||
/* set leading environment variables, like eval(1) */
|
||||
while (*argv && (p = strchr(*argv, '=')))
|
||||
(void)setenv(*argv++, ++p, 1);
|
||||
while (*argv && (p = strchr(*argv, '='))) {
|
||||
*p = '\0';
|
||||
rtrn = setenv(*argv++, p + 1, 1);
|
||||
*p = '=';
|
||||
if (rtrn == -1)
|
||||
err(EXIT_FAILURE, "setenv %s", *argv);
|
||||
}
|
||||
|
||||
/* Set limits */
|
||||
for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
|
||||
|
@ -766,10 +766,11 @@ export(const char *s)
|
||||
"SHELL", "HOME", "LOGNAME", "MAIL", "CDPATH",
|
||||
"IFS", "PATH", NULL
|
||||
};
|
||||
char *p;
|
||||
const char **pp;
|
||||
size_t n;
|
||||
|
||||
if (strlen(s) > 1024 || strchr(s, '=') == NULL)
|
||||
if (strlen(s) > 1024 || (p = strchr(s, '=')) == NULL)
|
||||
return (0);
|
||||
if (strncmp(s, "LD_", 3) == 0)
|
||||
return (0);
|
||||
@ -778,7 +779,9 @@ export(const char *s)
|
||||
if (s[n] == '=' && strncmp(s, *pp, n) == 0)
|
||||
return (0);
|
||||
}
|
||||
(void)putenv(s);
|
||||
*p = '\0';
|
||||
(void)setenv(s, p + 1, 1);
|
||||
*p = '=';
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -564,10 +564,14 @@ static void
|
||||
export_pam_environment(void)
|
||||
{
|
||||
char **pp;
|
||||
char *p;
|
||||
|
||||
for (pp = environ_pam; *pp != NULL; pp++) {
|
||||
if (ok_to_export(*pp))
|
||||
putenv(*pp);
|
||||
if (ok_to_export(*pp)) {
|
||||
p = strchr(*pp, '=');
|
||||
*p = '\0';
|
||||
setenv(*pp, p + 1, 1);
|
||||
}
|
||||
free(*pp);
|
||||
}
|
||||
}
|
||||
|
@ -135,16 +135,16 @@ main(int argc, char *argv[])
|
||||
fileflag = 1;
|
||||
break;
|
||||
case 'g':
|
||||
putenv("BLOCKSIZE=1G");
|
||||
setenv("BLOCKSIZE", "1G", 1);
|
||||
break;
|
||||
case 'h':
|
||||
humanflag = 1;
|
||||
break;
|
||||
case 'k':
|
||||
putenv("BLOCKSIZE=1K");
|
||||
setenv("BLOCKSIZE", "1K", 1);
|
||||
break;
|
||||
case 'm':
|
||||
putenv("BLOCKSIZE=1M");
|
||||
setenv("BLOCKSIZE", "1M", 1);
|
||||
break;
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
|
@ -56,7 +56,7 @@ main(int argc, char **argv)
|
||||
/* XXX */
|
||||
char *p = getenv("TERM");
|
||||
if (p && strcmp(p, "cons25") == 0)
|
||||
putenv("TERM=cons25w");
|
||||
setenv("TERM", "cons25w", 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -296,6 +296,7 @@ free_variables(void)
|
||||
void
|
||||
pvariable_set(char *var)
|
||||
{
|
||||
char *p;
|
||||
char tmp[1024];
|
||||
|
||||
if (!var)
|
||||
@ -307,7 +308,9 @@ pvariable_set(char *var)
|
||||
if (index(var, '=') == NULL)
|
||||
msgFatal("Invalid variable format: %s", var);
|
||||
strlcat(tmp, var, 1024);
|
||||
putenv(tmp);
|
||||
p = strchr(tmp, '=');
|
||||
*p = '\0';
|
||||
setenv(tmp, p + 1, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
|
@ -74,7 +74,7 @@ main(int argc, char **argv)
|
||||
/* XXX */
|
||||
char *p = getenv("TERM");
|
||||
if (p && strcmp(p, "cons25") == 0)
|
||||
putenv("TERM=cons25w");
|
||||
setenv("TERM", "cons25w", 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -301,6 +301,7 @@ free_variables(void)
|
||||
void
|
||||
pvariable_set(char *var)
|
||||
{
|
||||
char *p;
|
||||
char tmp[1024];
|
||||
|
||||
if (!var)
|
||||
@ -312,7 +313,9 @@ pvariable_set(char *var)
|
||||
if (index(var, '=') == NULL)
|
||||
msgFatal("Invalid variable format: %s", var);
|
||||
strlcat(tmp, var, 1024);
|
||||
putenv(tmp);
|
||||
p = strchr(tmp, '=');
|
||||
*p = '\0';
|
||||
setenv(tmp, p + 1, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
|
Loading…
Reference in New Issue
Block a user