From 60068693f0f9bb07349e6e551cacdce561560064 Mon Sep 17 00:00:00 2001 From: liduo Date: Fri, 27 Jun 2025 14:40:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=BF=E6=8D=A2popen=E4=B8=BA=E6=9B=B4?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liduo --- include/restool_errors.h | 1 + src/restool_errors.cpp | 133 +++++++++++++++++++++++++++++++++------ 2 files changed, 116 insertions(+), 18 deletions(-) diff --git a/include/restool_errors.h b/include/restool_errors.h index 3bcb79d..b218903 100644 --- a/include/restool_errors.h +++ b/include/restool_errors.h @@ -29,6 +29,7 @@ namespace Restool { constexpr uint32_t RESTOOL_SUCCESS = 0; constexpr uint32_t RESTOOL_ERROR = -1; constexpr uint16_t BUFFER_SIZE = 4096; +constexpr uint16_t BUFFER_SIZE_SMALL = 128; const std::string ERROR_MORE_INFO_FILE = "restool_faq.json"; // 11200xxx unknown error constexpr uint32_t ERR_CODE_UNDEFINED_ERROR = 11200000; diff --git a/src/restool_errors.cpp b/src/restool_errors.cpp index e3e63d8..35d7e78 100644 --- a/src/restool_errors.cpp +++ b/src/restool_errors.cpp @@ -15,6 +15,13 @@ #include #include +#ifdef __WIN32 +#include +#else +#include +#include +#include +#endif #include "resource_util.h" #include "restool_errors.h" @@ -525,33 +532,132 @@ const std::map ERRORS_MAP = { #ifdef __WIN32 constexpr int WIN_LOCALE_CN = 2052; #endif +const std::string LOCALE_CMD_WIN = "wmic os get locale"; +const std::string LOCALE_CMD_LINUX = "locale"; +const std::string LOCALE_CMD_MAC = "defaults read -globalDomain AppleLocale"; const std::string LOCALE_CN = "zh_CN"; std::map faqInfos; MoreInfo defaultMoreInfo = {}; Language osLanguage = Language::EN; +bool IsValidCmd(const std::string &cmd) +{ + if (cmd == LOCALE_CMD_WIN || cmd == LOCALE_CMD_LINUX || cmd == LOCALE_CMD_MAC) { + return true; + } + return false; +} + +#ifdef __WIN32 std::string ExecuteCommand(const std::string &cmd) { + if (!IsValidCmd(cmd)) { + return ""; + } + SECURITY_ATTRIBUTES saAttr; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + HANDLE hReadPipe; + HANDLE hWritePipe; + if (!CreatePipe(&hReadPipe, &hWritePipe, &saAttr, 0)) { + return "CreatePipe failed"; + } + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdError = hWritePipe; + si.hStdOutput = hWritePipe; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.dwFlags |= STARTF_USESTDHANDLES; + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcess(NULL, const_cast(cmd.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + return "CreateProcess failed"; + } + // close the write end of the pipe in the parent process + CloseHandle(hWritePipe); std::string result; - FILE *pipe = popen(cmd.c_str(), "r"); - if (!pipe) { + DWORD bytesRead; + CHAR buffer[BUFFER_SIZE_SMALL]; + while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead != 0) { + buffer[bytesRead] = '\0'; + result += buffer; + } + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(hReadPipe); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return result; +} +#else +std::vector split(const std::string &s, const char &delimiter) +{ + std::vector tokens; + std::string token; + std::stringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } + return tokens; +} + +std::string ExecuteCommand(const std::string &cmd) +{ + std::string result; + if (!IsValidCmd(cmd)) { return result; } - char buffer[BUFFER_SIZE]; - while (!feof(pipe)) { - if (fgets(buffer, BUFFER_SIZE, pipe) != NULL) { + int pipefd[2]; + pid_t pid; + if (pipe(pipefd) == -1) { + perror("open pipe failed"); + return result; + } + pid = fork(); + if (pid == -1) { + perror("fork failed"); + return result; + } + if (pid == 0) { + // child process + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); + close(pipefd[1]); + std::vector cmds = split(cmd, ' '); + char *argv[cmds.size() + 1]; + size_t i = 0; + for (i = 0; i < cmds.size(); ++i) { + argv[i] = cmds[i].data(); + } + argv[i] = nullptr; + execvp(argv[0], argv); + // if execvp returns, there was an error. + perror("execle failed"); + exit(EXIT_FAILURE); + } else { + // parent process + // close unused write end + close(pipefd[1]); + char buffer[BUFFER_SIZE_SMALL]; + ssize_t readBytes; + while ((readBytes = read(pipefd[0], buffer, sizeof(buffer) - 1)) > 0) { + buffer[readBytes] = '\0'; result += buffer; } + close(pipefd[0]); + wait(nullptr); } - pclose(pipe); return result; } +#endif #ifdef __WIN32 Language GetWinLanguage() { - std::string result = ExecuteCommand("wmic os get locale"); + std::string result = ExecuteCommand(LOCALE_CMD_WIN); size_t pos = 0; std::string locale = "Locale"; if ((pos = result.find(locale)) != std::string::npos) { @@ -574,18 +680,9 @@ Language GetWinLanguage() #endif #ifdef __LINUX__ -std::vector split(const std::string &s, const char &delimiter) -{ - std::vector tokens; - std::string token; - std::stringstream tokenStream(s); - while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } - return tokens; -} - Language GetLinuxLanguage() { - std::string result = ExecuteCommand("locale"); + std::string result = ExecuteCommand(LOCALE_CMD_LINUX); if (result.empty()) { return Language::CN; } @@ -609,7 +706,7 @@ Language GetLinuxLanguage() #ifdef __MAC__ Language GetMacLanguage() { - std::string result = ExecuteCommand("defaults read -globalDomain AppleLocale"); + std::string result = ExecuteCommand(LOCALE_CMD_MAC); if (result.empty()) { return Language::CN; } -- Gitee