From 0204f293b518934660b6797f2cb38cb6bc5ffb2b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 8 Mar 2023 00:52:25 +0100 Subject: [PATCH] Generic environment set/clear functions, file function to get app exe path --- src/pya/pya/pya.cc | 9 +------ src/tl/tl/tlEnv.cc | 22 ++++++++++++++++ src/tl/tl/tlEnv.h | 12 +++++++++ src/tl/tl/tlFileUtils.cc | 20 +++++++++++---- src/tl/tl/tlFileUtils.h | 5 ++++ src/tl/unit_tests/tlEnvTests.cpp | 44 ++++++++++++++++++++++++++++++++ src/tl/unit_tests/unit_tests.pro | 1 + 7 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 src/tl/unit_tests/tlEnvTests.cpp diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index 39a400f2c..46f452fe3 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -40,10 +40,6 @@ #include "tlString.h" #include "tlInternational.h" -#if defined(HAVE_QT) -# include -#endif - // For the installation path #ifdef _WIN32 # include @@ -225,10 +221,7 @@ PythonInterpreter::PythonInterpreter (bool embedded) tl::SelfTimer timer (tl::verbosity () >= 21, "Initializing Python"); - std::string app_path; -#if defined(HAVE_QT) - app_path = tl::to_string (QCoreApplication::applicationFilePath ()); -#endif + std::string app_path = tl::get_exe_file (); #if PY_MAJOR_VERSION >= 3 diff --git a/src/tl/tl/tlEnv.cc b/src/tl/tl/tlEnv.cc index ffd779ddd..5d6a6a344 100644 --- a/src/tl/tl/tlEnv.cc +++ b/src/tl/tl/tlEnv.cc @@ -58,6 +58,28 @@ std::string get_env (const std::string &name, const std::string &def_value) #endif } +void set_env (const std::string &name, const std::string &value) +{ +#ifdef _WIN32 + std::wstring wstr = tl::to_wstring (name + "=" + value); + _wputenv (wstr.c_str ()); +#else + char *str = strdup ((name + "=" + value).c_str ()); + putenv (str); +#endif +} + +void unset_env (const std::string &name) +{ +#ifdef _WIN32 + std::wstring wstr = tl::to_wstring (name + "="); + _wputenv (wstr.c_str ()); +#else + char *str = strdup (name.c_str ()); // TODO: needed? + putenv (str); +#endif +} + bool has_env (const std::string &name) { #ifdef _WIN32 diff --git a/src/tl/tl/tlEnv.h b/src/tl/tl/tlEnv.h index 454b68bd8..bbe8c4c28 100644 --- a/src/tl/tl/tlEnv.h +++ b/src/tl/tl/tlEnv.h @@ -38,6 +38,18 @@ namespace tl */ std::string TL_PUBLIC get_env (const std::string &name, const std::string &def_value = std::string ()); +/** + * @brief Sets the value of the given environment variable + * + * On Windows, the variable is removed when the value is an empty string. + */ +void TL_PUBLIC set_env (const std::string &name, const std::string &value); + +/** + * @brief Unsets the given environment variable + */ +void TL_PUBLIC unset_env (const std::string &name); + /** * @brief Gets the value if the given environment variable is set */ diff --git a/src/tl/tl/tlFileUtils.cc b/src/tl/tl/tlFileUtils.cc index 8b002aa78..2541a63ea 100644 --- a/src/tl/tl/tlFileUtils.cc +++ b/src/tl/tl/tlFileUtils.cc @@ -862,7 +862,7 @@ get_inst_path_internal () wchar_t buffer[MAX_PATH]; int len; if ((len = GetModuleFileNameW (NULL, buffer, MAX_PATH)) > 0) { - return tl::absolute_path (tl::to_string (std::wstring (buffer))); + return tl::to_string (std::wstring (buffer)); } #elif __APPLE__ @@ -871,7 +871,7 @@ get_inst_path_internal () int ret = proc_pidpath (getpid (), buffer, sizeof (buffer)); if (ret > 0) { // TODO: does this correctly translate paths? (MacOS uses UTF-8 encoding with D-like normalization) - return tl::absolute_path (buffer); + return std::string (buffer); } #elif defined (__FreeBSD__) @@ -880,7 +880,7 @@ get_inst_path_internal () size_t len = PATH_MAX; const int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; if (sysctl(&mib[0], 4, &path, &len, NULL, 0) == 0) { - return tl::absolute_path(path); + return path; } return ""; @@ -888,7 +888,7 @@ get_inst_path_internal () std::string pf = tl::sprintf ("/proc/%d/exe", getpid ()); if (tl::file_exists (pf)) { - return tl::absolute_path (pf); + return pf; } #endif @@ -900,7 +900,17 @@ get_inst_path () { static std::string s_inst_path; if (s_inst_path.empty ()) { - s_inst_path = get_inst_path_internal (); + s_inst_path = tl::absolute_path (get_inst_path_internal ()); + } + return s_inst_path; +} + +std::string +get_exe_file () +{ + static std::string s_inst_path; + if (s_inst_path.empty ()) { + s_inst_path = tl::absolute_file_path (get_inst_path_internal ()); } return s_inst_path; } diff --git a/src/tl/tl/tlFileUtils.h b/src/tl/tl/tlFileUtils.h index 354ab786e..95727b9dd 100644 --- a/src/tl/tl/tlFileUtils.h +++ b/src/tl/tl/tlFileUtils.h @@ -199,6 +199,11 @@ std::vector TL_PUBLIC split_path (const std::string &p, bool keep_l */ std::string TL_PUBLIC get_inst_path (); +/** + * @brief Gets the path of the binary executing + */ +std::string TL_PUBLIC get_exe_file (); + /** * @brief Gets the absolute path of the module (DLL/.so) which contains the given address * "address" is supposed to be the address of a function inside the module. diff --git a/src/tl/unit_tests/tlEnvTests.cpp b/src/tl/unit_tests/tlEnvTests.cpp new file mode 100644 index 000000000..0e9f0fe0e --- /dev/null +++ b/src/tl/unit_tests/tlEnvTests.cpp @@ -0,0 +1,44 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2023 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "tlEnv.h" +#include "tlUnitTest.h" + +TEST(1) +{ + const char *env_name = "$$$DOESNOTEXIST"; + + EXPECT_EQ (tl::has_env (env_name), false); + EXPECT_EQ (tl::has_env ("HOME"), true); + + tl::set_env (env_name, "abc"); + EXPECT_EQ (tl::has_env (env_name), true); + EXPECT_EQ (tl::get_env (env_name), "abc"); + + tl::set_env (env_name, "uvw"); + EXPECT_EQ (tl::has_env (env_name), true); + EXPECT_EQ (tl::get_env (env_name), "uvw"); + + tl::unset_env (env_name); + EXPECT_EQ (tl::has_env (env_name), false); +} diff --git a/src/tl/unit_tests/unit_tests.pro b/src/tl/unit_tests/unit_tests.pro index c648dcb1b..de8099b72 100644 --- a/src/tl/unit_tests/unit_tests.pro +++ b/src/tl/unit_tests/unit_tests.pro @@ -16,6 +16,7 @@ SOURCES = \ tlDataMappingTests.cc \ tlDeferredExecutionTests.cc \ tlDeflateTests.cc \ + tlEnvTests.cpp \ tlEventsTests.cc \ tlExpressionTests.cc \ tlFileSystemWatcherTests.cc \