namespace fs = util::filesystem;
#ifdef _WIN32
-static int win32execute(const char* path,
- const char* const* argv,
+static int win32execute(const char* const* argv,
int doreturn,
int fd_stdout,
int fd_stderr,
{
LOG("Executing {}", util::format_argv_for_logging(argv));
- return win32execute(argv[0],
- argv,
+ return win32execute(argv,
1,
fd_out.release(),
fd_err.release(),
void
execute_noreturn(const char* const* argv, const fs::path& temp_dir)
{
- win32execute(argv[0], argv, 0, -1, -1, util::pstr(temp_dir).c_str());
+ win32execute(argv, 0, -1, -1, util::pstr(temp_dir).c_str());
}
std::string
}
int
-win32execute(const char* path,
- const char* const* argv,
+win32execute(const char* const* argv,
int doreturn,
int fd_stdout,
int fd_stderr,
STARTUPINFO si;
memset(&si, 0x00, sizeof(si));
- std::string sh = win32getshell(path);
- if (!sh.empty()) {
- path = sh.c_str();
- }
-
si.cb = sizeof(STARTUPINFO);
if (fd_stdout != -1) {
si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
}
}
- std::string args = util::format_argv_as_win32_command_string(argv, sh);
- std::string full_path = util::add_exe_suffix(path);
- fs::path tmp_file_path;
+ std::string args = util::format_argv_as_win32_command_string(argv);
+ fs::path tmp_file_path;
DEFER([&] {
if (!tmp_file_path.empty()) {
util::remove(tmp_file_path);
if (args.length() > 8192) {
auto tmp_file = util::value_or_throw<core::Fatal>(
util::TemporaryFile::create(FMT("{}/cmd_args", temp_dir)));
- args = util::format_argv_as_win32_command_string(argv + 1, sh, true);
+ args = util::format_argv_as_win32_command_string(argv + 1, true);
util::write_fd(*tmp_file.fd, args.data(), args.length());
- args = FMT(R"("{}" "@{}")", full_path, tmp_file.path);
+ args = FMT(R"("{}" "@{}")", argv[0], tmp_file.path);
tmp_file_path = tmp_file.path;
LOG("Arguments from {}", tmp_file.path);
}
+
+ std::string sh = win32getshell(argv[0]);
+ if (!sh.empty()) {
+ args = FMT(R"("{}" {})", sh, args);
+ }
BOOL ret = CreateProcess(nullptr,
const_cast<char*>(args.c_str()),
nullptr,
if (ret == 0) {
DWORD error = GetLastError();
LOG("failed to execute {}: {} ({})",
- full_path,
+ argv[0],
util::win32_error_message(error),
error);
return -1;
TerminateProcess(pi.hProcess, 1);
DWORD error = GetLastError();
- LOG("failed to assign process to job object {}: {} ({})",
- full_path,
+ LOG("failed to assign process to job object for {}: {} ({})",
+ argv[0],
util::win32_error_message(error),
error);
return -1;
-// Copyright (C) 2009-2024 Joel Rosdahl and other contributors
+// Copyright (C) 2009-2025 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
using_cmd_exe = false;
}
Args args = Args::from_string(adjusted_command);
+ {
+ auto full_path =
+ find_executable_in_path(args[0], util::getenv_path_list("PATH")).string();
+ if (!full_path.empty()) {
+ args[0] = full_path;
+ }
+ }
#else
Args args = Args::from_string(command);
#endif
STARTUPINFO si;
memset(&si, 0x00, sizeof(si));
- auto path =
- find_executable_in_path(args[0], util::getenv_path_list("PATH")).string();
- if (path.empty()) {
- path = args[0];
- }
- std::string sh = win32getshell(path);
- if (!sh.empty()) {
- path = sh;
- }
-
si.cb = sizeof(STARTUPINFO);
HANDLE pipe_out[2];
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.dwFlags = STARTF_USESTDHANDLES;
- std::string win32args;
+ std::string commandline;
if (using_cmd_exe) {
- win32args = adjusted_command; // quoted
+ commandline = adjusted_command; // quoted
} else {
- win32args = util::format_argv_as_win32_command_string(argv, sh);
+ commandline = util::format_argv_as_win32_command_string(argv);
+ std::string sh = win32getshell(args[0]);
+ if (!sh.empty()) {
+ commandline = FMT(R"("{}" {})", sh, commandline);
+ }
}
- BOOL ret = CreateProcess(path.c_str(),
- const_cast<char*>(win32args.c_str()),
+ BOOL ret = CreateProcess(nullptr,
+ const_cast<char*>(commandline.c_str()),
nullptr,
nullptr,
1,
-// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2025 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
std::string
format_argv_as_win32_command_string(const char* const* argv,
- const std::string& prefix,
bool escape_backslashes)
{
std::string result;
- size_t i = 0;
- const char* arg = prefix.empty() ? argv[i++] : prefix.c_str();
- do {
+ for (size_t i = 0; argv[i]; ++i) {
+ const char* arg = argv[i];
int bs = 0;
result += '"';
for (size_t j = 0; arg[j]; ++j) {
--bs;
}
result += "\" ";
- } while ((arg = argv[i++]));
+ }
result.resize(result.length() - 1);
return result;
-// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2025 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
// is not at the end of `argv[i]` either.
std::string
format_argv_as_win32_command_string(const char* const* argv,
- const std::string& prefix,
bool escape_backslashes = false);
// Format `argv` as a simple string for logging purposes. That is, the result is
-// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2025 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
{
{
const char* const argv[] = {"a", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "") == R"("a")");
- }
- {
- const char* const argv[] = {"a", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "p") == R"("p" "a")");
+ CHECK(util::format_argv_as_win32_command_string(argv) == R"("a")");
}
{
const char* const argv[] = {"a", "b c", "\"d\"", "'e'", "\\\"h", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "")
+ CHECK(util::format_argv_as_win32_command_string(argv)
== R"("a" "b c" "\"d\"" "'e'" "\\\"h")");
}
{
const char* const argv[] = {"a\\b\\c", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "") == R"("a\b\c")");
+ CHECK(util::format_argv_as_win32_command_string(argv) == R"("a\b\c")");
}
{
const char* const argv[] = {"a\\b\\c", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "", true)
+ CHECK(util::format_argv_as_win32_command_string(argv, true)
== R"("a\\b\\c")");
}
{
const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "")
+ CHECK(util::format_argv_as_win32_command_string(argv)
== R"("a\b \\\"c\\\" \\")");
}
{
const char* const argv[] = {R"(a\b \"c\" \)", nullptr};
- CHECK(util::format_argv_as_win32_command_string(argv, "", true)
+ CHECK(util::format_argv_as_win32_command_string(argv, true)
== R"("a\\b \\\"c\\\" \\")");
}
}