From 65e9f6210c1af2eb60ccc2ed63d5cd5e9cd7a12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 19 May 2020 08:14:56 +0200 Subject: [PATCH] CLI: Tweak execution of python addons --- lib/cppcheck.cpp | 88 +++++++++++++++++++++++------------------------- lib/settings.cpp | 1 - 2 files changed, 42 insertions(+), 47 deletions(-) mode change 100644 => 100755 lib/cppcheck.cpp mode change 100644 => 100755 lib/settings.cpp diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp old mode 100644 new mode 100755 index 20f462da1..a42b77756 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -158,76 +158,72 @@ namespace { static std::string cmdFileName(std::string f) { - //f = Path::toNativeSeparators(f); + f = Path::toNativeSeparators(f); if (f.find(" ") != std::string::npos) return "\"" + f + "\""; return f; } +static bool executeShellCommand(std::string exe, const std::string &args, std::string *output) +{ + output->clear(); + +#ifdef _WIN32 + // Extra quoutes are needed in windows if filename has space + if (exe.find(" ") != std::string::npos) + exe = "\"" + exe + "\""; + const std::string cmd = exe + " " + args + " 2>&1"; + std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); +#else + const std::string cmd = exe + " " + args + " 2>&1"; + std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); +#endif + if (!pipe) + return false; + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) + *output += buffer; + return true; +} + static std::string executeAddon(const AddonInfo &addonInfo, const std::string &defaultPythonExe, const std::string &dumpFile) { - std::string pythonExe; - // Can python be executed? - const int lastTest = 3; - for (int test = 1; test <= lastTest; ++test) { - if (test == 1 || test == lastTest) - pythonExe = cmdFileName((addonInfo.python != "") ? addonInfo.python : defaultPythonExe); - else - pythonExe = "python3"; - - const std::string cmd = pythonExe + " --version 2>&1"; - + if (!addonInfo.python.empty()) + pythonExe = cmdFileName(addonInfo.python); + else if (!defaultPythonExe.empty()) + pythonExe = cmdFileName(defaultPythonExe); + else { #ifdef _WIN32 - if (pythonExe.find(" ") != std::string::npos) { - // popen strips the first quote. Needs 2 sets to fully quote. - pythonExe = "\"" + pythonExe + "\""; - } - - std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); + const char *p[] = { "python3.exe", "python.exe" }; #else - std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); + const char *p[] = { "python3", "python" }; #endif - if (!pipe) { - if (test < lastTest) - continue; - throw InternalError(nullptr, "popen failed (command: '" + cmd + "')"); - } - char buffer[1024]; - std::string result; - while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) - result += buffer; - if (result.compare(0, 7, "Python ", 0, 7) != 0 || result.size() > 50) { - if (test < lastTest) - continue; - throw InternalError(nullptr, "Failed to execute '" + cmd + "' (" + result + ")"); + for (int i = 0; i < 2; ++i) { + std::string out; + if (executeShellCommand(p[i], "--version", &out) && out.compare(0, 7, "Python ") == 0 && std::isdigit(out[7])) { + pythonExe = p[i]; + break; + } } + if (pythonExe.empty()) + throw InternalError(nullptr, "Failed to auto detect python"); } - const std::string cmd = pythonExe + " " + cmdFileName(addonInfo.scriptFile) + " --cli" + addonInfo.args + " " + cmdFileName(dumpFile) + " 2>&1"; - -#ifdef _WIN32 - std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); -#else - std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); -#endif - if (!pipe) - throw InternalError(nullptr, "popen failed (command: '" + cmd + "')"); - char buffer[1024]; + const std::string args = cmdFileName(addonInfo.scriptFile) + " --cli" + addonInfo.args + " " + cmdFileName(dumpFile); std::string result; - while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) { - result += buffer; - } + if (!executeShellCommand(pythonExe, args, &result)) + throw InternalError(nullptr, "Failed to execute addon (command: '" + pythonExe + " " + args + "')"); // Validate output.. std::istringstream istr(result); std::string line; while (std::getline(istr, line)) { if (line.compare(0,9,"Checking ", 0, 9) != 0 && !line.empty() && line[0] != '{') - throw InternalError(nullptr, "Failed to execute '" + cmd + "'. " + result); + throw InternalError(nullptr, "Failed to execute '" + pythonExe + " " + args + "'. " + result); } // Valid results diff --git a/lib/settings.cpp b/lib/settings.cpp old mode 100644 new mode 100755 index 016e033cb..dd7760950 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -30,7 +30,6 @@ const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables"; Settings::Settings() : mEnabled(0), - addonPython("python"), bugHunting(false), checkAllConfigurations(true), checkConfiguration(false),