* Execute a shell command and read the output from it. Returns true if command terminated successfully. */ cppcheck-suppress passedByValueCallback - used as callback so we need to preserve the signature NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
| 683 | // cppcheck-suppress passedByValueCallback - used as callback so we need to preserve the signature |
| 684 | // NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature |
| 685 | int CppCheckExecutor::executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output_) |
| 686 | { |
| 687 | output_.clear(); |
| 688 | |
| 689 | #ifdef _WIN32 |
| 690 | // Extra quoutes are needed in windows if filename has space |
| 691 | if (exe.find(" ") != std::string::npos) |
| 692 | exe = "\"" + exe + "\""; |
| 693 | #endif |
| 694 | |
| 695 | std::string joinedArgs; |
| 696 | for (const std::string &arg : args) { |
| 697 | if (!joinedArgs.empty()) |
| 698 | joinedArgs += " "; |
| 699 | if (arg.find(' ') != std::string::npos) |
| 700 | joinedArgs += '"' + arg + '"'; |
| 701 | else |
| 702 | joinedArgs += arg; |
| 703 | } |
| 704 | |
| 705 | std::string cmd = exe + " " + joinedArgs + " " + redirect; |
| 706 | |
| 707 | #ifdef _WIN32 |
| 708 | cmd = "\"" + cmd + "\""; |
| 709 | FILE* p = _popen(cmd.c_str(), "r"); |
| 710 | #else |
| 711 | FILE *p = popen(cmd.c_str(), "r"); |
| 712 | #endif |
| 713 | //std::cout << "invoking command '" << cmd << "'" << std::endl; |
| 714 | if (!p) { |
| 715 | // TODO: how to provide to caller? |
| 716 | //const int err = errno; |
| 717 | //std::cout << "popen() errno " << std::to_string(err) << std::endl; |
| 718 | return -1; |
| 719 | } |
| 720 | char buffer[1024]; |
| 721 | while (fgets(buffer, sizeof(buffer), p) != nullptr) |
| 722 | output_ += buffer; |
| 723 | |
| 724 | #ifdef _WIN32 |
| 725 | const int res = _pclose(p); |
| 726 | #elif defined(__APPLE__) && defined(__MACH__) |
| 727 | // the W* macros cast to int* on macOS |
| 728 | int res = pclose(p); |
| 729 | #else |
| 730 | const int res = pclose(p); |
| 731 | #endif |
| 732 | if (res == -1) { // error occurred |
| 733 | // TODO: how to provide to caller? |
| 734 | //const int err = errno; |
| 735 | //std::cout << "pclose() errno " << std::to_string(err) << std::endl; |
| 736 | return res; |
| 737 | } |
| 738 | #if !defined(_WIN32) && !defined(__MINGW32__) |
| 739 | if (WIFEXITED(res)) { |
| 740 | return WEXITSTATUS(res); |
| 741 | } |
| 742 | if (WIFSIGNALED(res)) { |