Skip to content

Commit

Permalink
Put back the _putenv since it is used by Mono
Browse files Browse the repository at this point in the history
  • Loading branch information
janvorli committed Oct 13, 2022
1 parent 9ca2453 commit 647cc64
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/coreclr/pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -4443,6 +4443,7 @@ PALIMPORT DLLEXPORT int * __cdecl PAL_errno(int caller);
#endif // PAL_STDCPP_COMPAT

PALIMPORT DLLEXPORT char * __cdecl getenv(const char *);
PALIMPORT DLLEXPORT int __cdecl _putenv(const char *);

#define ERANGE 34

Expand Down
32 changes: 32 additions & 0 deletions src/coreclr/pal/src/misc/environ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,38 @@ EnvironInitialize(void)

/*++
Function : _putenv.
See MSDN for more details.
Note: The BSD implementation can cause
memory leaks. See man pages for more details.
--*/
int
__cdecl
_putenv( const char * envstring )
{
int ret = -1;

PERF_ENTRY(_putenv);
ENTRY( "_putenv( %p (%s) )\n", envstring ? envstring : "NULL", envstring ? envstring : "NULL") ;

if (envstring != nullptr)
{
ret = EnvironPutenv(envstring, TRUE) ? 0 : -1;
}
else
{
ERROR( "_putenv() called with NULL envstring!\n");
}

LOGEXIT( "_putenv returning %d\n", ret);
PERF_EXIT(_putenv);
return ret;
}

/*++
Function : PAL_getenv
See MSDN for more details.
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/pal/tests/palsuite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ add_executable_clr(paltests
c_runtime/_isnan/test1/test1.cpp
c_runtime/_isnanf/test1/test1.cpp
c_runtime/_itow/test1/test1.cpp
c_runtime/_putenv/test1/test1.cpp
c_runtime/_putenv/test2/test2.cpp
c_runtime/_putenv/test3/test3.cpp
c_runtime/_putenv/test4/test4.cpp
c_runtime/_rotl/test1/test1.cpp
c_runtime/_rotr/test1/test1.cpp
c_runtime/_snprintf_s/test1/test1.cpp
Expand Down
97 changes: 97 additions & 0 deletions src/coreclr/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/*=====================================================================
**
** Source: test1.c
**
** Purpose: Create an environment variable with _putenv and then use getenv
** to check it. Check that we get the expected errors with invalid input.
**
**
**===================================================================*/

#include <palsuite.h>

struct TestElement
{
char _putenvString[1024]; /* argument string sent to putenv */
char varName[1024]; /* variable component of argument string */
char varValue[1024]; /* value component of argument string */
BOOL bValidString; /* valid argument string identifier */
};

PALTEST(c_runtime__putenv_test1_paltest_putenv_test1, "c_runtime/_putenv/test1/paltest_putenv_test1")
{
struct TestElement TestCases[] =
{
{"PalTestingEnvironmentVariable=A value", "PalTestingEnvironmentVariable",
"A value", TRUE},
{"AnotherVariable=", "AnotherVariable", "", TRUE},
{"YetAnotherVariable", "", "", FALSE},
{"=ADifferentVariable", "", "ADifferentVariable", FALSE},
{"", "", "", FALSE}

};

int i;
char *variableValue;

if (0 != (PAL_Initialize(argc, argv)))
{
return FAIL;
}

for (i = 0; i < (sizeof(TestCases)/sizeof(struct TestElement)) ; i++)
{
if((_putenv(TestCases[i]._putenvString) == -1) &&
( TestCases[i].bValidString == TRUE))
{
Fail("ERROR: _putenv failed to set an environment "
"variable with a valid format.\n Call was"
"_putenv(%s)\n", TestCases[i]._putenvString);
}
/*
* For valid _putenvString values, check to see the variable was set
*/
if (TestCases[i].bValidString == TRUE)
{
variableValue = getenv(TestCases[i].varName);

if (variableValue == NULL)
{
if (*TestCases[i].varValue != '\0')
{
Fail("ERROR: getenv(%s) call returned NULL.\nThe call "
"should have returned \"%s\"\n", TestCases[i].varName
, TestCases[i].varValue);
}
}
else if ( strcmp(variableValue, TestCases[i].varValue) != 0)
{
Fail("ERROR: _putenv(%s)\nshould have set the variable "
"%s\n to \"%s\".\nA subsequent call to getenv(%s)\n"
"returned \"%s\" instead.\n", TestCases[i]._putenvString
, TestCases[i].varName, TestCases[i].varValue
, TestCases[i].varName, variableValue);
}
}
else
/*
* Check to see that putenv fails for malformed _putenvString values
*/
{
variableValue = getenv(TestCases[i].varName);

if (variableValue != NULL)
{
Fail("ERROR: getenv(%s) call should have returned NULL.\n"
"Instead it returned \"%s\".\n", TestCases[i].varName
, TestCases[i].varValue);
}
}
}

PAL_Terminate();
return PASS;
}
75 changes: 75 additions & 0 deletions src/coreclr/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/*=====================================================================
**
** Source: test2.c
**
** Purpose: Create an environment variable with _putenv and then use getenv
** to check it. This test resets an environment variable.
**
**
**===================================================================*/

#include <palsuite.h>

const char *_putenvString0 = "AnUnusualVariable=AnUnusualValue";
const char *_putenvString1 = "AnUnusualVariable=";
const char *variable = "AnUnusualVariable";
const char *value = "AnUnusualValue";

PALTEST(c_runtime__putenv_test2_paltest_putenv_test2, "c_runtime/_putenv/test2/paltest_putenv_test2")
{

char *variableValue;

if (0 != (PAL_Initialize(argc, argv)))
{
return FAIL;
}

if(_putenv(_putenvString0) == -1)
{
Fail("ERROR: _putenv failed to set an environment "
"variable with a valid format.\n Call was"
"_putenv(%s)\n", _putenvString0);
}

variableValue = getenv(variable);

if (variableValue == NULL)
{
Fail("ERROR: getenv(%s) call returned NULL\nThe call "
"should have returned '%s'\n", variable, value);
}
else
{
if ( strcmp(variableValue, value) != 0 )
{
Fail("ERROR: _putenv(%s)\nshould have set the variable "
"'%s'\n to '%s'.\nA subsequent call to getenv(%s)\n"
"returned '%s' instead.\n", _putenvString0,
variable, value, variable, variableValue);
}
else
{
if(_putenv(_putenvString1) == -1)
{
Fail("ERROR: _putenv failed to set an environment "
"variable with a valid format.\n Call was"
"_putenv(%s)\n", _putenvString1);
}

variableValue = getenv(variable);

if (variableValue != NULL)
{
Fail("ERROR: getenv(%s) call did not return NULL.\nThe call "
"returned '%s'.\n", variable, value);
}
}
}

PAL_Terminate();
return PASS;
}
101 changes: 101 additions & 0 deletions src/coreclr/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/*=====================================================================
**
** Source: test3.c
**
** Purpose: Create environment variables that differ only in Case, and
** verify that the BSD operating system treats the variables
** differently.
**
**
**===================================================================*/

#include <palsuite.h>

PALTEST(c_runtime__putenv_test3_paltest_putenv_test3, "c_runtime/_putenv/test3/paltest_putenv_test3")
{
#if WIN32

return PASS;

#else

const char* FirstVariable = "PalTestingEnvironmentVariable=The value";
const char* SecondVariable = "PALTESTINGEnvironmentVariable=Different value";
const char* FirstVarName = "PalTestingEnvironmentVariable";
const char* FirstVarValue = "The value";
char* result;


if (0 != (PAL_Initialize(argc, argv)))
{
return FAIL;
}

/* Use _putenv to set an environment variable. This ensures that the
variable we're testing on is always present.
*/

if(_putenv(FirstVariable) != 0)
{
Fail("ERROR: _putenv failed to set an environment variable that "
"getenv will be using for testing.\n");
}


/* Call getenv -- ensure it doesn't return NULL and the string it returns
is the value we set above. Also make sure that each environment variable,
differing only by case, returns it's own value.
*/

result = getenv(FirstVarName);
if(result == NULL)
{
Fail("ERROR: The result of getenv on a valid Environment Variable "
"was NULL, which indicates the environment variable was not "
"found.\n");
}

if(strcmp(result, FirstVarValue) != 0)
{
Fail("ERROR: The value obtained by getenv() was not equal to the "
"correct value of the environment variable. The correct "
"value is '%s' and the function returned '%s'.\n",
FirstVarValue,
result);
}

/* Set the second environment variable, which only differs in Case */
if(_putenv(SecondVariable) != 0)
{
Fail("ERROR: _putenv failed to set an environment variable that "
"getenv will be using for testing.\n");
}

/* Verify that the environment variables
*/

result = getenv(FirstVarName);
if(result == NULL)
{
Fail("ERROR: The result of getenv on a valid Environment Variable "
"was NULL, which indicates the environment variable was not "
"found.\n");
}

if(strcmp(result, FirstVarValue) != 0)
{
Fail("ERROR: The value obtained by getenv() was not equal to the "
"correct value of the environment variable. The correct "
"value is '%s' and the function returned '%s'.\n",
FirstVarValue,
result);
}

PAL_Terminate();
return PASS;

#endif
}
Loading

0 comments on commit 647cc64

Please # to comment.