diff liboctave/system/lo-sysdep.cc @ 25916:3f2282954600

Support non-ASCII characters in environment variables on Windows (bug #53922). * lo-sysdep.[cc/h] (octave::sys::getenv_wrapper, octave::sys::putenv_wrapper): Add new functions to call Unicode versions of CRT functions on Windows. * oct-env.cc (putenv, do_getenv), sysdep.cc (Funsetenv): Use these new functions. * lo-utils.[cc/h] (octave_putenv): Remove function moved to lo-sysdep.
author Markus Mützel <markus.muetzel@gmx.de>
date Thu, 04 Oct 2018 19:08:42 +0200
parents 4de7535ece11
children d478d5d1c8e9
line wrap: on
line diff
--- a/liboctave/system/lo-sysdep.cc	Wed Oct 03 21:30:19 2018 +0200
+++ b/liboctave/system/lo-sysdep.cc	Thu Oct 04 19:08:42 2018 +0200
@@ -30,8 +30,10 @@
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-sysdep.h"
+#include "putenv-wrapper.h"
 #include "uniconv-wrappers.h"
 #include "unistd-wrappers.h"
+#include "unsetenv-wrapper.h"
 
 #if defined (OCTAVE_USE_WINDOWS_API)
 #  include <windows.h>
@@ -153,6 +155,62 @@
 #endif
     }
 
+    void
+    putenv_wrapper (const std::string& name, const std::string& value)
+    {
+      // This function was adapted from xputenv from Karl Berry's kpathsearch
+      // library.
+      // FIXME: make this do the right thing if we don't have a SMART_PUTENV.
+
+      int new_len = name.length () + value.length () + 2;
+
+      // FIXME: This leaks memory, but so would a call to setenv.
+      // Short of extreme measures to track memory, altering the environment
+      // always leaks memory, but the saving grace is that the leaks are small.
+
+      char *new_item = static_cast<char *> (std::malloc (new_len));
+
+      sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
+
+      // As far as I can see there's no way to distinguish between the
+      // various errors; putenv doesn't have errno values.
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+      wchar_t *wnew_item = u8_to_wchar (new_item);
+      std::free (static_cast<void *> (new_item));
+      if (_wputenv (wnew_item) < 0)
+        (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
+#else
+      if (octave_putenv_wrapper (new_item) < 0)
+        (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
+#endif
+    }
+
+    std::string
+    getenv_wrapper (const std::string& name)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+      wchar_t *env = _wgetenv (u8_to_wstring (name).c_str ());
+      return env ? u8_from_wstring (env) : "";
+#else
+      char *env = ::getenv (name.c_str ());
+      return env ? env : "";
+#endif
+    }
+
+    int
+    unsetenv_wrapper (const std::string& name)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+      putenv_wrapper (name, "");
+
+      std::wstring wname = u8_to_wstring (name);
+      return (SetEnvironmentVariableW (wname.c_str (), nullptr) ? 0 : -1);
+#else
+      return octave_unsetenv_wrapper (name.c_str ());
+#endif
+    }
+
     std::wstring
     u8_to_wstring (const std::string& utf8_string)
     {