Skip to content

Commit

Permalink
env: no environ anymore on windows msvc
Browse files Browse the repository at this point in the history
Fixes GH #1191
  • Loading branch information
Reini Urban committed Jan 25, 2015
1 parent abf3f12 commit 6a6f30e
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 34 deletions.
83 changes: 49 additions & 34 deletions src/platform/win32/env.c
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2014, Parrot Foundation.
* Copyright (C) 2004-2015, Parrot Foundation.
*/

/*
Expand All @@ -22,6 +22,10 @@ To keep both in sync we always update environment variables through the C
runtime. Getting an environment variable can be done either way,
whichever is more convenient.
But since Visual Studio 2005 direct access to the _environ symbol is now deprecated,
and linking to msvcrt will not work then.
"Polling _environ in a Unicode context is meaningless when /MD or /MDd linkage is used"
=head2 Functions
=over 4
Expand All @@ -34,6 +38,10 @@ whichever is more convenient.

#include <windows.h>

#ifdef _MSC_VER
# define HAVE_PUTENV_S
#endif

/* HEADERIZER HFILE: none */

/*
Expand All @@ -49,6 +57,39 @@ it does exist.
*/

static
void
win32_setenv(PARROT_INTERP, char * const name, char * const value)
{
{
int result;
#ifndef HAVE_PUTENV_S
char * const envstring = (char * const)mem_internal_allocate(
name_len /* name */
+ 1 /* '=' */
+ value_len /* value */
+ 1); /* string terminator */

/* Save a bit of time, by using the fact we already have the
lengths, avoiding strcat */
strcpy(envstring, name);
strcpy(envstring + name_len, "=");
strcpy(envstring + name_len + 1, value);

result = _putenv(envstring);
mem_sys_free(envstring);
#else
result = _putenv_s(name, value);
#endif

if (result) {
Parrot_x_force_error_exit(interp, 1,
"Unable to set environment variable %s=%s",
name, value);
}
}
}

void
Parrot_setenv(PARROT_INTERP, const STRING *str_name, const STRING *str_value)
{
Expand All @@ -57,38 +98,10 @@ Parrot_setenv(PARROT_INTERP, const STRING *str_name, const STRING *str_value)
assert(name != NULL);
assert(value != NULL);

{
const int name_len = strlen(name);
const int value_len = strlen(value);

{
char * const envstring = (char * const)mem_internal_allocate(
name_len /* name */
+ 1 /* '=' */
+ value_len /* value */
+ 1); /* string terminator */

/* Save a bit of time, by using the fact we already have the
lengths, avoiding strcat */
strcpy(envstring, name);
strcpy(envstring + name_len, "=");
strcpy(envstring + name_len + 1, value);

Parrot_str_free_cstring(name);
Parrot_str_free_cstring(value);

if (_putenv(envstring) == 0) {
/* success */
mem_sys_free(envstring);
}
else {
mem_sys_free(envstring);
Parrot_x_force_error_exit(interp, 1,
"Unable to set environment variable %s=%s",
name, value);
}
}
}
win32_setenv(interp, name, value);

Parrot_str_free_cstring(name);
Parrot_str_free_cstring(value);
}

/*
Expand Down Expand Up @@ -139,7 +152,9 @@ Parrot_unsetenv(PARROT_INTERP, const STRING *str_name)
string -- in other words, by specifying only varname=.
-- _putenv, _wputenv (CRT) documentation
*/
Parrot_setenv(interp, str_name, Parrot_str_new(interp, "", 0));
char * const name = Parrot_str_to_cstring(interp, str_name);
assert(name != NULL);
win32_setenv(interp, name, NULL);
}

/*
Expand Down
6 changes: 6 additions & 0 deletions src/pmc/env.pmc
Expand Up @@ -100,8 +100,10 @@ This method is questionable, as environ is not in ISO-C.
UNUSED(INTERP)
UNUSED(SELF)

#ifndef _MSC_VER
while (environ[rv] != NULL)
++rv;
#endif

return rv;
}
Expand Down Expand Up @@ -190,9 +192,13 @@ Used during iteration.
return CONST_STRING(INTERP, "");
}
else {
#ifndef _MSC_VER
STRING * const envp = Parrot_str_from_platform_cstring(interp, environ[pos]);
const INTVAL delim = STRING_index(interp, envp, CONST_STRING(INTERP, "="), 0);
return STRING_substr(INTERP, envp, 0, delim);
#else
return CONST_STRING(INTERP, "");
#endif
}
}

Expand Down

0 comments on commit 6a6f30e

Please sign in to comment.