[cmake-developers] [PATCH v2] Improve encoding handling on Windows

Dāvis Mosāns davispuh at gmail.com
Sat Jul 2 20:29:41 EDT 2016


On Windows getenv (and putenv) uses ANSI codepage so it needs to
be encoded to internally used encoding (eg. UTF-8). Here we use
_wgetenv (and _wputenv) instead and encode that.

Also typically Windows applications (eg. MSVC compiler) use current
console's codepage for output to pipes so we need to encode that
to internally used encoding (KWSYS_ENCODING_DEFAULT_CODEPAGE).

Next, when we're outputing to console need to use wide functions.

This change allows that compilers such as MSVC on Windows can be
installed in non-ASCII path and will work correctly for all
console's codepages which supports that path's characters.
---
 Source/CPack/cmCPackGenerator.cxx           |  8 +--
 Source/CTest/cmCTestCoverageHandler.cxx     | 12 ++--
 Source/CTest/cmCTestCurl.cxx                | 21 +++----
 Source/CTest/cmCTestMultiProcessHandler.cxx |  8 +--
 Source/cmBuildCommand.cxx                   | 23 +++----
 Source/cmCLocaleEnvironmentScope.cxx        |  4 +-
 Source/cmCTest.cxx                          | 11 ++--
 Source/cmCommandArgumentParserHelper.cxx    |  8 +--
 Source/cmConditionEvaluator.cxx             |  2 +-
 Source/cmExportCommand.cxx                  |  5 +-
 Source/cmExtraEclipseCDT4Generator.cxx      |  9 +--
 Source/cmFileCommand.cxx                    | 12 ++--
 Source/cmFindPackageCommand.cxx             |  4 +-
 Source/cmGlobalVisualStudio7Generator.cxx   |  6 +-
 Source/cmMakefile.cxx                       |  5 +-
 Source/cmNinjaTargetGenerator.cxx           |  2 +-
 Source/cmQtAutoGenerators.cxx               |  2 +-
 Source/cmSetCommand.cxx                     |  6 +-
 Source/cmState.cxx                          |  5 +-
 Source/cmSystemTools.cxx                    | 11 +++-
 Source/cmTimestamp.cxx                      |  7 +--
 Source/cmake.cxx                            | 16 ++---
 Source/cmakemain.cxx                        | 38 ++++++++++-
 Source/cmcmd.cxx                            | 12 ++--
 Source/kwsys/CMakeLists.txt                 |  2 +
 Source/kwsys/Directory.cxx                  |  2 +-
 Source/kwsys/FStream.hxx.in                 | 19 +++++-
 Source/kwsys/ProcessWin32.c                 | 25 +++++++-
 Source/kwsys/SystemInformation.cxx          | 20 +++---
 Source/kwsys/SystemTools.cxx                | 98 +++++++++++++++++++----------
 Source/kwsys/SystemTools.hxx.in             |  4 +-
 Source/kwsys/testSystemTools.cxx            |  9 +--
 32 files changed, 260 insertions(+), 156 deletions(-)

diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index df8bb0f..76609e1 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -1074,11 +1074,11 @@ const char* cmCPackGenerator::GetInstallPath()
     return this->InstallPath.c_str();
   }
 #if defined(_WIN32) && !defined(__CYGWIN__)
-  const char* prgfiles = cmsys::SystemTools::GetEnv("ProgramFiles");
-  const char* sysDrive = cmsys::SystemTools::GetEnv("SystemDrive");
-  if (prgfiles) {
+  std::string prgfiles;
+  std::string sysDrive;
+  if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
     this->InstallPath = prgfiles;
-  } else if (sysDrive) {
+  } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
     this->InstallPath = sysDrive;
     this->InstallPath += "/Program Files";
   } else {
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 7102533..9410a52 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -727,10 +727,7 @@ int cmCTestCoverageHandler::HandleCoberturaCoverage(
   // if it doesn't exist or is empty, assume the
   // binary directory is used.
   std::string coverageXMLFile;
-  const char* covDir = cmSystemTools::GetEnv("COBERTURADIR");
-  if (covDir && strlen(covDir) != 0) {
-    coverageXMLFile = std::string(covDir);
-  } else {
+  if (!cmSystemTools::GetEnv("COBERTURADIR", coverageXMLFile) || coverageXMLFile.empty()) {
     coverageXMLFile = this->CTest->GetBinaryDir();
   }
   // build the find file string with the directory from above
@@ -791,7 +788,8 @@ struct cmCTestCoverageHandlerLocale
 {
   cmCTestCoverageHandlerLocale()
   {
-    if (const char* l = cmSystemTools::GetEnv("LC_ALL")) {
+    std::string l;
+    if (cmSystemTools::GetEnv("LC_ALL", l)) {
       lc_all = l;
     }
     if (lc_all != "C") {
@@ -2121,8 +2119,8 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
 int cmCTestCoverageHandler::HandleBullseyeCoverage(
   cmCTestCoverageHandlerContainer* cont)
 {
-  const char* covfile = cmSystemTools::GetEnv("COVFILE");
-  if (!covfile || strlen(covfile) == 0) {
+  std::string covfile;
+  if (!cmSystemTools::GetEnv("COVFILE", covfile) || covfile.empty()) {
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        " COVFILE environment variable not found, not running "
                        " bullseye\n",
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index 6b8e5b5..19f32c8 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -219,16 +219,16 @@ bool cmCTestCurl::HttpRequest(std::string const& url,
 
 void cmCTestCurl::SetProxyType()
 {
-  if (cmSystemTools::GetEnv("HTTP_PROXY")) {
-    this->HTTPProxy = cmSystemTools::GetEnv("HTTP_PROXY");
-    if (cmSystemTools::GetEnv("HTTP_PROXY_PORT")) {
+  if (cmSystemTools::GetEnv("HTTP_PROXY", this->HTTPProxy)) {
+    std::string port;
+    if (cmSystemTools::GetEnv("HTTP_PROXY_PORT", port)) {
       this->HTTPProxy += ":";
-      this->HTTPProxy += cmSystemTools::GetEnv("HTTP_PROXY_PORT");
+      this->HTTPProxy += port;
     }
-    if (cmSystemTools::GetEnv("HTTP_PROXY_TYPE")) {
+    std::string type;
+    if (cmSystemTools::GetEnv("HTTP_PROXY_TYPE", type)) {
       // this is the default
       this->HTTPProxyType = CURLPROXY_HTTP;
-      std::string type = cmSystemTools::GetEnv("HTTP_PROXY_TYPE");
       // HTTP/SOCKS4/SOCKS5
       if (type == "HTTP") {
         this->HTTPProxyType = CURLPROXY_HTTP;
@@ -238,12 +238,11 @@ void cmCTestCurl::SetProxyType()
         this->HTTPProxyType = CURLPROXY_SOCKS5;
       }
     }
-    if (cmSystemTools::GetEnv("HTTP_PROXY_USER")) {
-      this->HTTPProxyAuth = cmSystemTools::GetEnv("HTTP_PROXY_USER");
-    }
-    if (cmSystemTools::GetEnv("HTTP_PROXY_PASSWD")) {
+    cmSystemTools::GetEnv("HTTP_PROXY_USER", this->HTTPProxyAuth);
+    std::string passwd;
+    if (cmSystemTools::GetEnv("HTTP_PROXY_PASSWD", passwd)) {
       this->HTTPProxyAuth += ":";
-      this->HTTPProxyAuth += cmSystemTools::GetEnv("HTTP_PROXY_PASSWD");
+      this->HTTPProxyAuth += passwd;
     }
   }
 }
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index ae97d32..ffd51c7 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -261,12 +261,12 @@ void cmCTestMultiProcessHandler::StartNextTests()
     allTestsFailedTestLoadCheck = true;
 
     // Check for a fake load average value used in testing.
-    if (const char* fake_load_value =
-          cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING")) {
+    std::string fake_load_value;
+    if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING", fake_load_value)) {
       usedFakeLoadForTesting = true;
-      if (!cmSystemTools::StringToULong(fake_load_value, &systemLoad)) {
+      if (!cmSystemTools::StringToULong(fake_load_value.c_str(), &systemLoad)) {
         cmSystemTools::Error("Failed to parse fake load value: ",
-                             fake_load_value);
+                             fake_load_value.c_str());
       }
     }
     // If it's not set, look up the true load average.
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index fb143a2..d29c31f 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -36,8 +36,8 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
   const char* variable = args[0].c_str();
 
   // Parse remaining arguments.
-  const char* configuration = CM_NULLPTR;
-  const char* project_name = CM_NULLPTR;
+  std::string configuration;
+  std::string project_name;
   std::string target;
   enum Doing
   {
@@ -56,10 +56,10 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
       doing = DoingTarget;
     } else if (doing == DoingConfiguration) {
       doing = DoingNone;
-      configuration = args[i].c_str();
+      configuration = args[i];
     } else if (doing == DoingProjectName) {
       doing = DoingNone;
-      project_name = args[i].c_str();
+      project_name = args[i];
     } else if (doing == DoingTarget) {
       doing = DoingNone;
       target = args[i];
@@ -76,14 +76,14 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
   // so we put this code here to end up with the same default configuration
   // as the original 2-arg build_command signature:
   //
-  if (!configuration || !*configuration) {
-    configuration = getenv("CMAKE_CONFIG_TYPE");
+  if (configuration.empty()) {
+    cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configuration);
   }
-  if (!configuration || !*configuration) {
+  if (configuration.empty()) {
     configuration = "Release";
   }
 
-  if (project_name && *project_name) {
+  if (!project_name.empty()) {
     this->Makefile->IssueMessage(
       cmake::AUTHOR_WARNING,
       "Ignoring PROJECT_NAME option because it has no effect.");
@@ -91,7 +91,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
 
   std::string makecommand =
     this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
-      target, configuration, "", this->Makefile->IgnoreErrorsCMP0061());
+      target, configuration.c_str(), "", this->Makefile->IgnoreErrorsCMP0061());
 
   this->Makefile->AddDefinition(variable, makecommand.c_str());
 
@@ -109,10 +109,7 @@ bool cmBuildCommand::TwoArgsSignature(std::vector<std::string> const& args)
   const char* cacheValue = this->Makefile->GetDefinition(define);
 
   std::string configType = "Release";
-  const char* cfg = getenv("CMAKE_CONFIG_TYPE");
-  if (cfg && *cfg) {
-    configType = cfg;
-  }
+  cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType);
 
   std::string makecommand =
     this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
diff --git a/Source/cmCLocaleEnvironmentScope.cxx b/Source/cmCLocaleEnvironmentScope.cxx
index a19dbae..5661cd9 100644
--- a/Source/cmCLocaleEnvironmentScope.cxx
+++ b/Source/cmCLocaleEnvironmentScope.cxx
@@ -31,8 +31,8 @@ cmCLocaleEnvironmentScope::cmCLocaleEnvironmentScope()
 
 std::string cmCLocaleEnvironmentScope::GetEnv(std::string const& key)
 {
-  const char* value = cmSystemTools::GetEnv(key);
-  return value ? value : std::string();
+  std::string value;
+  return cmSystemTools::GetEnv(key, value) ? value : std::string();
 }
 
 void cmCLocaleEnvironmentScope::SetEnv(std::string const& key,
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 9950a84..4eb4e3a 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -298,9 +298,9 @@ cmCTest::cmCTest()
   this->ComputedCompressMemCheckOutput = false;
   this->RepeatTests = 1; // default to run each test once
   this->RepeatUntilFail = false;
-  if (const char* outOnFail =
-        cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE")) {
-    this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(outOnFail);
+  std::string outOnFail;
+  if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", outOnFail)) {
+    this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(outOnFail.c_str());
   }
   this->InitStreams();
 
@@ -2125,8 +2125,9 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
   } // the close of the for argument loop
 
   if (!this->ParallelLevelSetInCli) {
-    if (const char* parallel = cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL")) {
-      int plevel = atoi(parallel);
+    std::string parallel;
+    if (cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL", parallel)) {
+      int plevel = atoi(parallel.c_str());
       this->SetParallelLevel(plevel);
     }
   }
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 294117c..42fb105 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -71,12 +71,12 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
     return this->EmptyVariable;
   }
   if (strcmp(key, "ENV") == 0) {
-    char* ptr = getenv(var);
-    if (ptr) {
+    std::string str;
+    if (cmSystemTools::GetEnv(var, str)) {
       if (this->EscapeQuotes) {
-        return this->AddString(cmSystemTools::EscapeQuotes(ptr));
+        return this->AddString(cmSystemTools::EscapeQuotes(str.c_str()));
       } else {
-        return ptr;
+        return this->AddString(str);
       }
     }
     return this->EmptyVariable;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 67b2571..e02221c 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -486,7 +486,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
         if (argP1len > 4 && argP1->GetValue().substr(0, 4) == "ENV{" &&
             argP1->GetValue().operator[](argP1len - 1) == '}') {
           std::string env = argP1->GetValue().substr(4, argP1len - 5);
-          bdef = cmSystemTools::GetEnv(env.c_str()) ? true : false;
+          bdef = cmSystemTools::HasEnv(env.c_str());
         } else {
           bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
         }
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 3cb575e..fc62492 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -327,11 +327,10 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
   fname += "/cmake/packages/";
   fname += package;
 #else
-  const char* home = cmSystemTools::GetEnv("HOME");
-  if (!home) {
+  std::string fname;
+  if (!cmSystemTools::GetEnv("HOME", fname)) {
     return;
   }
-  std::string fname = home;
   cmSystemTools::ConvertToUnixSlashes(fname);
   fname += "/.cmake/packages/";
   fname += package;
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 16cb082..af09cd6 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -208,7 +208,8 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
   // get the variables from the environment and from the cache and then
   // figure out which one to use:
 
-  const char* envVarValue = getenv(envVar);
+  std::string envVarValue;
+  bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
 
   std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
   cacheEntryName += envVar;
@@ -217,17 +218,17 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
 
   // now we have both, decide which one to use
   std::string valueToUse;
-  if (envVarValue == CM_NULLPTR && cacheValue == CM_NULLPTR) {
+  if (!envVarSet && cacheValue == CM_NULLPTR) {
     // nothing known, do nothing
     valueToUse = "";
-  } else if (envVarValue != CM_NULLPTR && cacheValue == CM_NULLPTR) {
+  } else if (envVarSet && cacheValue == CM_NULLPTR) {
     // The variable is in the env, but not in the cache. Use it and put it
     // in the cache
     valueToUse = envVarValue;
     mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
                            cacheEntryName.c_str(), cmState::STRING, true);
     mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
-  } else if (envVarValue == CM_NULLPTR && cacheValue != CM_NULLPTR) {
+  } else if (!envVarSet && cacheValue != CM_NULLPTR) {
     // It is already in the cache, but not in the env, so use it from the cache
     valueToUse = cacheValue;
   } else {
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 5a1238b..def137e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1609,8 +1609,11 @@ struct cmFileInstaller : public cmFileCopier
     // Installation does not use source permissions by default.
     this->UseSourcePermissions = false;
     // Check whether to copy files always or only if they have changed.
-    this->Always =
-      cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
+     std::string install_always;
+     if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) {
+      this->Always =
+        cmSystemTools::IsOn(install_always.c_str());
+     }
     // Get the current manifest.
     this->Manifest =
       this->Makefile->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
@@ -1869,9 +1872,8 @@ bool cmFileInstaller::HandleInstallDestination()
     return false;
   }
 
-  const char* destdir = cmSystemTools::GetEnv("DESTDIR");
-  if (destdir && *destdir) {
-    std::string sdestdir = destdir;
+  std::string sdestdir;
+  if (cmSystemTools::GetEnv("DESTDIR", sdestdir) && !sdestdir.empty()) {
     cmSystemTools::ConvertToUnixSlashes(sdestdir);
     char ch1 = destination[0];
     char ch2 = destination[1];
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index d5fd75d..260079b 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1077,8 +1077,8 @@ void cmFindPackageCommand::FillPrefixesUserRegistry()
                                  this->LabeledPaths[PathLabel::UserRegistry]);
   }
 #else
-  if (const char* home = cmSystemTools::GetEnv("HOME")) {
-    std::string dir = home;
+  std::string dir;
+  if (cmSystemTools::GetEnv("HOME", dir)) {
     dir += "/.cmake/packages/";
     dir += this->Name;
     this->LoadPackageRegistryDir(dir,
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 262909f..0a83b3a 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -122,9 +122,9 @@ void cmGlobalVisualStudio7Generator::EnableLanguage(
   // does not use the environment it is run in, and this allows
   // for running commands and using dll's that the IDE environment
   // does not know about.
-  const char* extraPath = cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH");
-  if (extraPath) {
-    mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath,
+  std::string extraPath;
+  if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) {
+    mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath.c_str(),
                            "Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
                            cmState::STATIC);
   }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 0d550dd..ab7de57 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2572,6 +2572,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
           std::string const& lookup = result.substr(var.loc);
           const char* value = CM_NULLPTR;
           std::string varresult;
+          std::string svalue;
           static const std::string lineVar = "CMAKE_CURRENT_LIST_LINE";
           switch (var.domain) {
             case NORMAL:
@@ -2584,7 +2585,9 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
               }
               break;
             case ENVIRONMENT:
-              value = cmSystemTools::GetEnv(lookup.c_str());
+              if (cmSystemTools::GetEnv(lookup, svalue)) {
+                value = svalue.c_str();
+              }
               break;
             case CACHE:
               value = state->GetCacheEntryValue(lookup);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1d3e608..855a243 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -741,5 +741,5 @@ bool cmNinjaTargetGenerator::ForceResponseFile()
 {
   static std::string const forceRspFile = "CMAKE_NINJA_FORCE_RESPONSE_FILE";
   return (this->GetMakefile()->IsDefinitionSet(forceRspFile) ||
-          cmSystemTools::GetEnv(forceRspFile) != CM_NULLPTR);
+          cmSystemTools::HasEnv(forceRspFile));
 }
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 4b40c08..b821fda 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -88,7 +88,7 @@ static std::string extractSubDir(const std::string& absPath,
 }
 
 cmQtAutoGenerators::cmQtAutoGenerators()
-  : Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != CM_NULLPTR)
+  : Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
   , ColorOutput(true)
   , RunMocFailed(false)
   , RunUicFailed(false)
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 1484368..bbea89f 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -31,7 +31,11 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
     putEnvArg += "=";
 
     // what is the current value if any
-    const char* currValue = getenv(varName);
+    std::string scurrValue;
+    const char* currValue = 0;
+    if (cmSystemTools::GetEnv(varName, scurrValue)) {
+      currValue = scurrValue.c_str();
+    }
     delete[] varName;
 
     // will it be set to something, then set it
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index f2fe134..0470508 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -1286,8 +1286,9 @@ void cmState::Snapshot::SetDefaultDefinitions()
   this->SetDefinition("CMAKE_HOST_UNIX", "1");
 #endif
 #if defined(__CYGWIN__)
-  if (cmSystemTools::IsOn(
-        cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32"))) {
+  std::string legacy;
+  if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
+      cmSystemTools::IsOn(legacy.c_str())) {
     this->SetDefinition("WIN32", "1");
     this->SetDefinition("CMAKE_HOST_WIN32", "1");
   }
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 2d463f3..5656c30 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -333,7 +333,12 @@ void cmSystemTools::Message(const char* m1, const char* title)
                          s_MessageCallbackClientData);
     return;
   } else {
+#if defined(_WIN32)
+    std::wstring wm1 = cmsys::Encoding::ToWide(m1);
+    std::wcerr << wm1 << std::endl << std::flush;
+#else
     std::cerr << m1 << std::endl << std::flush;
+#endif
   }
 }
 
@@ -2069,9 +2074,9 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message,
   // However, we can test for some situations when the answer is most
   // likely no.
   int assumeTTY = cmsysTerminal_Color_AssumeTTY;
-  if (cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
-      cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
-      cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE")) {
+  if (cmSystemTools::HasEnv("DART_TEST_FROM_DART") ||
+      cmSystemTools::HasEnv("DASHBOARD_TEST_FROM_CTEST") ||
+      cmSystemTools::HasEnv("CTEST_INTERACTIVE_DEBUG_MODE")) {
     // Avoid printing color escapes during dashboard builds.
     assumeTTY = 0;
   }
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index c3c1d17..61b74db 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -93,10 +93,9 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
 #else
   // From Linux timegm() manpage.
 
-  std::string tz_old = "TZ=";
-  if (const char* tz = cmSystemTools::GetEnv("TZ")) {
-    tz_old += tz;
-  }
+  std::string tz_old = "";
+  cmSystemTools::GetEnv("TZ", tz_old);
+  tz_old = "TZ=" + tz_old;
 
   // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
   // It seems that "TZ=" does NOT work, at least under Windows
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index c597605..1fe881c 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -955,16 +955,10 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg)
   cmSystemTools::SetForceUnixPaths(this->GlobalGenerator->GetForceUnixPaths());
 
   // Save the environment variables CXX and CC
-  const char* cxx = getenv("CXX");
-  const char* cc = getenv("CC");
-  if (cxx) {
-    this->CXXEnvironment = cxx;
-  } else {
+  if (!cmSystemTools::GetEnv("CXX", this->CXXEnvironment)) {
     this->CXXEnvironment = "";
   }
-  if (cc) {
-    this->CCEnvironment = cc;
-  } else {
+  if (!cmSystemTools::GetEnv("CC", this->CCEnvironment)) {
     this->CCEnvironment = "";
   }
 }
@@ -1429,7 +1423,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
   // should fail (if "-i" is an option).  We cannot simply test
   // whether "-i" is given and remove it because some make programs
   // encode the MAKEFLAGS variable in a strange way.
-  if (getenv("MAKEFLAGS")) {
+  if (cmSystemTools::HasEnv("MAKEFLAGS")) {
     cmSystemTools::PutEnv("MAKEFLAGS=");
   }
 
@@ -1708,8 +1702,8 @@ int cmake::CheckBuildSystem()
   // the make system's VERBOSE environment variable to enable verbose
   // output. This can be skipped by setting CMAKE_NO_VERBOSE (which is set
   // by the Eclipse and KDevelop generators).
-  bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != CM_NULLPTR) &&
-                  (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == CM_NULLPTR));
+  bool verbose = ((cmSystemTools::HasEnv("VERBOSE")) &&
+                  (!cmSystemTools::HasEnv("CMAKE_NO_VERBOSE")));
 
   // This method will check the integrity of the build system if the
   // option was given on the command line.  It reads the given file to
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 521a5bf..efc6d52 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -127,7 +127,13 @@ static std::string cmakemainGetStack(void* clientdata)
 static void cmakemainMessageCallback(const char* m, const char*, bool&,
                                      void* clientdata)
 {
+#if defined(_WIN32)
+  std::wstring wm = cmsys::Encoding::ToWide(m);
+  std::wstring wstack = cmsys::Encoding::ToWide(cmakemainGetStack(clientdata).c_str());
+  std::wcerr << wm << wstack << std::endl << std::flush;
+#else
   std::cerr << m << cmakemainGetStack(clientdata) << std::endl << std::flush;
+#endif
 }
 
 static void cmakemainProgressCallback(const char* m, float prog,
@@ -144,15 +150,41 @@ static void cmakemainProgressCallback(const char* m, float prog,
   }
 
   if ((prog < 0) || (!dir.empty())) {
+#if defined(_WIN32)
+    std::wstring wm = cmsys::Encoding::ToWide(m);
+    std::wstring wdir = cmsys::Encoding::ToWide(dir.c_str());
+    std::wstring wstack = cmsys::Encoding::ToWide(cmakemainGetStack(clientdata).c_str());
+    std::wcout << L"-- " << wm << wdir << wstack << std::endl << std::flush;
+#else
     std::cout << "-- " << m << dir << cmakemainGetStack(clientdata)
-              << std::endl;
+              << std::endl << std::flush;
+#endif
   }
-
-  std::cout.flush();
 }
 
 int main(int ac, char const* const* av)
 {
+#if defined(_WIN32)
+  // Kinda hack, with MSVC (and MinGW) for some reason std::wcout
+  // (and all other std::w*) fails once it encounters non-ASCII
+  // string unless locale is set.
+  // Note that even with this, seems it can't output characters
+  // which aren't present in ANSI codepage no matter what encoding
+  // is used for console.
+  // Currently Microsoft's C++ library doesn't support UTF-8/UTF-16
+  // locales so we can only set and output in users's ANSI codepage.
+  // Also once any character outside of ANSI codepage is tried to
+  // be outputed then after there anymore won't be output from
+  // any of std::w* functions.
+  // We need to explictly set English locale because with other
+  // locales number parsing can differ.
+  // Can't use ".ACP" as it would be ANSI codepage for locale
+  // we're setting not the one user uses so we manually set user's
+  // codepage.
+  std::wstring locale = L"English_United States.";
+  locale += std::to_wstring(GetACP());
+  _wsetlocale(LC_ALL, locale.c_str());
+#endif
   cmsys::Encoding::CommandLineArguments args =
     cmsys::Encoding::CommandLineArguments::Main(ac, av);
   ac = args.argc();
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 010a3b2..d97d72d 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -701,8 +701,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
       // verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE
       // (which is set by the Eclipse and KDevelop generators).
       bool verbose =
-        ((cmSystemTools::GetEnv("VERBOSE") != CM_NULLPTR) &&
-         (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == CM_NULLPTR));
+        ((cmSystemTools::HasEnv("VERBOSE")) &&
+         (!cmSystemTools::HasEnv("CMAKE_NO_VERBOSE")));
 
       // Create a cmake object instance to process dependencies.
       cmake cm;
@@ -900,9 +900,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         // 1/10th of a second after the untar.  If CMAKE_UNTAR_DELAY
         // is set in the env, its value will be used instead of 100.
         int delay = 100;
-        const char* delayVar = cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY");
-        if (delayVar) {
-          delay = atoi(delayVar);
+        std::string delayVar;
+        if (cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY", delayVar)) {
+          delay = atoi(delayVar.c_str());
         }
         if (delay) {
           cmSystemTools::Delay(delay);
@@ -1254,7 +1254,7 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type)
   if (args.size() < 2) {
     return -1;
   }
-  bool verbose = cmSystemTools::GetEnv("VERBOSE") != CM_NULLPTR;
+  bool verbose = cmSystemTools::HasEnv("VERBOSE");
   std::vector<std::string> expandedArgs;
   for (std::vector<std::string>::iterator i = args.begin(); i != args.end();
        ++i) {
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 8b15394..cab7f38 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -709,6 +709,8 @@ IF(KWSYS_USE_Process)
   IF(NOT UNIX)
     # Use the Windows implementation.
     SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
+    SET_PROPERTY(SOURCE ProcessWin32.c APPEND PROPERTY COMPILE_DEFINITIONS
+      KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
   ELSE()
     # Use the UNIX implementation.
     SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index c549792..659c559 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -86,7 +86,7 @@ void Directory::Clear()
 
 // First microsoft compilers
 
-#if defined(_MSC_VER) || defined(__WATCOMC__)
+#if defined(_WIN32) || defined(__WATCOMC__)
 #include <windows.h>
 #include <io.h>
 #include <ctype.h>
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 681e4d8..842148d 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -17,7 +17,7 @@
 
 namespace @KWSYS_NAMESPACE@
 {
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(_WIN32)
 # if defined(_NOEXCEPT)
 #  define @KWSYS_NAMESPACE at _FStream_NOEXCEPT _NOEXCEPT
 # else
@@ -30,8 +30,23 @@ namespace @KWSYS_NAMESPACE@
       typedef std::basic_filebuf<CharType,Traits> my_base_type;
       basic_filebuf *open(char const *s,std::ios_base::openmode mode)
       {
+        std::wstring wstr = Encoding::ToWide(s);
+        const wchar_t *ws = wstr.c_str();
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+        const wchar_t *ss = ws;
+#else
+        const char *ss = 0;
+        size_t length = std::wcstombs(0, ws, 0);
+        if (length != size_t(-1)) {
+          std::vector<char> str(length + 1);
+          ss = str.data();
+          std::wcstombs((char *)ss, ws, str.size());
+        } else {
+          ss = s;
+        }
+#endif
         return static_cast<basic_filebuf*>(
-          my_base_type::open(Encoding::ToWide(s).c_str(), mode)
+          my_base_type::open(ss, mode)
           );
       }
   };
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 2b93e69..da21cca 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -181,7 +181,7 @@ struct kwsysProcessPipeData_s
   /* ------------- Data managed per call to Execute ------------- */
 
   /* Buffer for data read in this pipe's thread.  */
-  char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
+  char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE*2];
 
   /* The length of the data stored in the buffer.  */
   DWORD DataLength;
@@ -319,6 +319,9 @@ struct kwsysProcess_s
   /* Own handles for the child's ends of the pipes in the parent process.
      Used temporarily during process creation.  */
   HANDLE PipeChildStd[3];
+
+  /* Console's active codepage */
+  UINT codepage;
 };
 
 /*--------------------------------------------------------------------------*/
@@ -1626,6 +1629,21 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
       KWSYSPE_DEBUG((stderr, "read closed %d\n", td->Index));
       }
 
+    if (td->DataLength > 0) {
+      if (cp->codepage != KWSYS_ENCODING_DEFAULT_CODEPAGE) {
+        int wlength = MultiByteToWideChar(cp->codepage, 0, td->DataBuffer, td->DataLength, NULL, 0);
+        wchar_t* wdata = malloc(wlength * sizeof(wchar_t));
+        int r = MultiByteToWideChar(cp->codepage, 0, td->DataBuffer, td->DataLength, wdata, wlength);
+        if (r > 0) {
+          r = WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, wdata, wlength, td->DataBuffer, KWSYSPE_PIPE_BUFFER_SIZE * 2, NULL, NULL);
+          if (r > 0) {
+            td->DataLength = r;
+          }
+        }
+        free(wdata);
+      }
+    }
+
     KWSYSPE_DEBUG((stderr, "read %d\n", td->Index));
 
     /* Wait for our turn to be handled by the main thread.  */
@@ -1761,6 +1779,11 @@ int kwsysProcessInitialize(kwsysProcess* cp)
     }
   }
 
+  cp->codepage = GetConsoleCP();
+  if (!cp->codepage) {
+    cp->codepage = GetACP();
+  }
+
   return 1;
 }
 
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 81fb2f9..1af7bdb 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -219,6 +219,8 @@ typedef struct rlimit ResourceLimitType;
 # define USE_CPUID 0
 #endif
 
+#include <cmsys/SystemTools.hxx>
+
 #if USE_CPUID
 
 #define CPUID_AWARE_COMPILER
@@ -3476,10 +3478,10 @@ SystemInformationImplementation::GetHostMemoryAvailable(const char *hostLimitEnv
   // apply a limit across a set of processes. Units are in KiB.
   if (hostLimitEnvVarName)
     {
-    const char *hostLimitEnvVarValue=getenv(hostLimitEnvVarName);
-    if (hostLimitEnvVarValue)
+    std::string hostLimitEnvVarValue;
+    if (SystemTools::GetEnv(hostLimitEnvVarName, hostLimitEnvVarValue))
       {
-      SystemInformation::LongLong hostLimit=atoLongLong(hostLimitEnvVarValue);
+      SystemInformation::LongLong hostLimit=atoLongLong(hostLimitEnvVarValue.c_str());
       if (hostLimit>0)
         {
         memTotal=min(hostLimit,memTotal);
@@ -3506,10 +3508,10 @@ SystemInformationImplementation::GetProcMemoryAvailable(
   // are not employed. Units are in KiB.
   if (procLimitEnvVarName)
     {
-    const char *procLimitEnvVarValue=getenv(procLimitEnvVarName);
-    if (procLimitEnvVarValue)
+    std::string procLimitEnvVarValue;
+    if (SystemTools::GetEnv(procLimitEnvVarName, procLimitEnvVarValue))
       {
-      SystemInformation::LongLong procLimit=atoLongLong(procLimitEnvVarValue);
+      SystemInformation::LongLong procLimit=atoLongLong(procLimitEnvVarValue.c_str());
       if (procLimit>0)
         {
         memAvail=min(procLimit,memAvail);
@@ -5408,11 +5410,7 @@ bool SystemInformationImplementation::QueryOSInformation()
     }
   this->Hostname = name;
 
-  const char* arch = getenv("PROCESSOR_ARCHITECTURE");
-  if(arch)
-    {
-    this->OSPlatform = arch;
-    }
+  SystemTools::GetEnv("PROCESSOR_ARCHITECTURE", this->OSPlatform);
 
 #else
 
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index c6e668d..c4a3311 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -421,14 +421,12 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
     {
     env = "PATH";
     }
-  const char* cpathEnv = SystemTools::GetEnv(env);
-  if ( !cpathEnv )
+  std::string pathEnv;
+  if ( !SystemTools::GetEnv(env, pathEnv) )
     {
     return;
     }
 
-  std::string pathEnv = cpathEnv;
-
   // A hack to make the below algorithm work.
   if(!pathEnv.empty() && *pathEnv.rbegin() != pathSep)
     {
@@ -456,22 +454,45 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
     }
 }
 
-const char* SystemTools::GetEnv(const char* key)
+bool SystemTools::GetEnv(const char* key, std::string& result)
 {
-  return getenv(key);
+#if defined(_WIN32)
+  std::wstring wkey = Encoding::ToWide(key);
+  wchar_t* wv = _wgetenv(wkey.c_str());
+  if (wv) {
+    result = Encoding::ToNarrow(wv);
+    return true;
+  }
+  return false;
+#else
+  const char* v = getenv(key);
+  if(v)
+    {
+    result = v;
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+#endif
 }
 
-const char* SystemTools::GetEnv(const std::string& key)
+bool SystemTools::GetEnv(const std::string& key, std::string& result)
 {
-  return SystemTools::GetEnv(key.c_str());
+  return SystemTools::GetEnv(key.c_str(), result);
 }
 
-bool SystemTools::GetEnv(const char* key, std::string& result)
+bool SystemTools::HasEnv(const char* key)
 {
+#if defined(_WIN32)
+  std::wstring wkey = Encoding::ToWide(key);
+  wchar_t* v = _wgetenv(wkey.c_str());
+#else
   const char* v = getenv(key);
+#endif
   if(v)
     {
-    result = v;
     return true;
     }
   else
@@ -480,9 +501,9 @@ bool SystemTools::GetEnv(const char* key, std::string& result)
     }
 }
 
-bool SystemTools::GetEnv(const std::string& key, std::string& result)
+bool SystemTools::HasEnv(const std::string& key)
 {
-  return SystemTools::GetEnv(key.c_str(), result);
+  return SystemTools::HasEnv(key.c_str());
 }
 
 //----------------------------------------------------------------------------
@@ -533,13 +554,25 @@ static int kwsysUnPutEnv(const std::string& env)
 # ifdef KWSYS_PUTENV_EMPTY
   buf[len] = '=';
   buf[len+1] = 0;
-  if(putenv(buf) < 0)
+#if defined(_WIN32)
+  std::wstring wbuf = Encoding::ToWide(buf);
+  int r = _wputenv(wbuf.c_str());
+#else
+  int r = putenv(buf);
+#endif
+  if(r < 0)
     {
     err = errno;
     }
 # else
   buf[len] = 0;
-  if(putenv(buf) < 0 && errno != EINVAL)
+#if defined(_WIN32)
+  std::wstring wbuf = Encoding::ToWide(buf);
+  int r = _wputenv(wbuf.c_str());
+#else
+  int r = putenv(buf);
+#endif
+  if(r < 0 && errno != EINVAL)
     {
     err = errno;
     }
@@ -679,7 +712,12 @@ public:
     static_cast<void>(oldEnv);
     char* newEnv = strdup(env);
     this->insert(newEnv);
+#if defined(_WIN32)
+    std::wstring wEnv = Encoding::ToWide(newEnv);
+    return _wputenv(wEnv.c_str()) == 0;
+#else
     return putenv(newEnv) == 0;
+#endif
     }
   bool UnPut(const char* env)
     {
@@ -2044,8 +2082,8 @@ void SystemTools::ConvertToUnixSlashes(std::string& path)
     pathCString = path.c_str();
     if(pathCString[0] == '~' && (pathCString[1] == '/' || pathCString[1] == '\0'))
       {
-      const char* homeEnv = SystemTools::GetEnv("HOME");
-      if (homeEnv)
+      std::string homeEnv;
+      if (SystemTools::GetEnv("HOME", homeEnv))
         {
         path.replace(0,1,homeEnv);
         }
@@ -4061,16 +4099,9 @@ void SystemTools::SplitPath(const std::string& p,
     if(root.size() == 1)
       {
 #if defined(_WIN32) && !defined(__CYGWIN__)
-      if(const char* userp = getenv("USERPROFILE"))
-        {
-        homedir = userp;
-        }
-      else
+      if (!SystemTools::GetEnv("USERPROFILE", homedir))
 #endif
-      if(const char* h = getenv("HOME"))
-        {
-        homedir = h;
-        }
+      SystemTools::GetEnv("HOME", homedir);
       }
 #ifdef HAVE_GETPWNAM
     else if(passwd* pw = getpwnam(root.c_str()+1))
@@ -4811,7 +4842,7 @@ int SystemTools::GetTerminalWidth()
   int width = -1;
 #ifdef HAVE_TTY_INFO
   struct winsize ws;
-  char *columns; /* Unix98 environment variable */
+  std::string columns; /* Unix98 environment variable */
   if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
     {
     width = ws.ws_col;
@@ -4820,12 +4851,11 @@ int SystemTools::GetTerminalWidth()
     {
     width = -1;
     }
-  columns = getenv("COLUMNS");
-  if(columns && *columns)
+  if(SystemTools::GetEnv("COLUMNS", columns))
     {
     long t;
     char *endptr;
-    t = strtol(columns, &endptr, 0);
+    t = strtol(columns.c_str(), &endptr, 0);
     if(endptr && !*endptr && (t>0) && (t<1000))
       {
       width = static_cast<int>(t);
@@ -5435,7 +5465,8 @@ void SystemTools::ClassInitialize()
 
   // If the current working directory is a logical path then keep the
   // logical name.
-  if(const char* pwd = getenv("PWD"))
+  std::string pwd_str;
+  if(SystemTools::GetEnv("PWD", pwd_str))
     {
     char buf[2048];
     if(const char* cwd = Getcwd(buf, 2048))
@@ -5447,10 +5478,9 @@ void SystemTools::ClassInitialize()
       std::string pwd_changed;
 
       // Test progressively shorter logical-to-physical mappings.
-      std::string pwd_str = pwd;
       std::string cwd_str = cwd;
       std::string pwd_path;
-      Realpath(pwd, pwd_path);
+      Realpath(pwd_str.c_str(), pwd_path);
       while(cwd_str == pwd_path && cwd_str != pwd_str)
         {
         // The current pair of paths is a working logical mapping.
@@ -5505,8 +5535,8 @@ static int SystemToolsDebugReport(int, char* message, int*)
 
 void SystemTools::EnableMSVCDebugHook()
 {
-  if (getenv("DART_TEST_FROM_DART") ||
-      getenv("DASHBOARD_TEST_FROM_CTEST"))
+  if (SystemTools::HasEnv("DART_TEST_FROM_DART") ||
+      SystemTools::HasEnv("DASHBOARD_TEST_FROM_CTEST"))
     {
     _CrtSetReportHook(SystemToolsDebugReport);
     }
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index bba5a5c..643f0ca 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -839,10 +839,10 @@ public:
   /**
    * Read an environment variable
    */
-  static const char* GetEnv(const char* key);
-  static const char* GetEnv(const std::string& key);
   static bool GetEnv(const char* key, std::string& result);
   static bool GetEnv(const std::string& key, std::string& result);
+  static bool HasEnv(const char* key);
+  static bool HasEnv(const std::string& key);
 
   /** Put a string into the environment
       of the form var=value */
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 4d97688..0fcc561 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -848,9 +848,9 @@ static bool CheckPutEnv(const std::string& env, const char* name, const char* va
                     << "\") failed!" << std::endl;
     return false;
     }
-  const char* v = kwsys::SystemTools::GetEnv(name);
-  v = v? v : "(null)";
-  if(strcmp(v, value) != 0)
+  std::string v = "(null)";
+  kwsys::SystemTools::GetEnv(name, v);
+  if(strcmp(v.c_str(), value) != 0)
     {
     std::cerr << "GetEnv(\"" << name << "\") returned \""
                     << v << "\", not \"" << value << "\"!" << std::endl;
@@ -867,7 +867,8 @@ static bool CheckUnPutEnv(const char* env, const char* name)
                     << std::endl;
     return false;
     }
-  if(const char* v = kwsys::SystemTools::GetEnv(name))
+  std::string v;
+  if(kwsys::SystemTools::GetEnv(name, v))
     {
     std::cerr << "GetEnv(\"" << name << "\") returned \""
                     << v << "\", not (null)!" << std::endl;
-- 
2.9.0



More information about the cmake-developers mailing list