From de6629754d45d21ad5d81b2b95a631a8e3073add Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 17 Mar 2025 15:45:27 +0100 Subject: [PATCH] libutil: add generic redirections runProgram2 explicit stderr redirection makes mergeStderrToStdout unnecessary also. Change-Id: I63de929e6dc53f6c5ceb2d43c2ce288bfc04d872 --- src/libfetchers/git.cc | 5 +++-- src/libstore/build/derivation-goal.cc | 2 +- src/libstore/globals.cc | 3 ++- src/libstore/ssh.cc | 3 ++- src/libutil/processes.cc | 8 +++++--- src/libutil/processes.hh | 7 ++++++- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 29eaf8b78..74275d8e7 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -17,6 +17,7 @@ #include #include #include +#include using namespace std::string_literals; @@ -163,7 +164,7 @@ WorkdirInfo getWorkdirInfo(const Input & input, const Path & workdir) .program = "git", .args = { "-C", workdir, "--git-dir", gitDir, "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" }, .environment = env, - .mergeStderrToStdout = true + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); auto exitCode = WEXITSTATUS(result.first); auto errorMessage = result.second; @@ -625,7 +626,7 @@ struct GitInputScheme : InputScheme auto result = runProgram(RunOptions { .program = "git", .args = { "-C", repoDir, "--git-dir", gitDir, "cat-file", "commit", input.getRev()->gitRev() }, - .mergeStderrToStdout = true + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); if (WEXITSTATUS(result.first) == 128 && result.second.find("bad file") != std::string::npos) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 4180654ab..50f39ddbc 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -917,7 +917,7 @@ void runPostBuildHook( .program = settings.postBuildHook, .environment = hookEnvironment, .captureStdout = true, - .mergeStderrToStdout = true, + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); Finally const _wait([&] { proc.waitAndCheck(); }); diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 6cfa3ffac..a06743f4c 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -233,7 +233,8 @@ StringSet Settings::getDefaultExtraPlatforms() // x86_64 in aarch64 environments or vice versa since they can // always exec with their own binary preferences. if (std::string{SYSTEM} == "aarch64-darwin" && - runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0) + runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}}).first == 0) extraPlatforms.insert("x86_64-darwin"); #endif diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index 8386b0e0a..02ae81989 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -4,6 +4,7 @@ #include "finally.hh" #include "logging.hh" #include "strings.hh" +#include namespace nix { @@ -49,7 +50,7 @@ bool SSHMaster::isMasterRunning() { Strings args = {"-O", "check", host}; addCommonSSHOpts(args); - auto res = runProgram(RunOptions {.program = "ssh", .args = args, .mergeStderrToStdout = true}); + auto res = runProgram(RunOptions {.program = "ssh", .args = args, .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}}); return res.first == 0; } diff --git a/src/libutil/processes.cc b/src/libutil/processes.cc index 46cbb66da..6fb903d9a 100644 --- a/src/libutil/processes.cc +++ b/src/libutil/processes.cc @@ -329,9 +329,11 @@ RunningProgram runProgram2(const RunOptions & options) replaceEnv(*options.environment); if (options.captureStdout && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) throw SysError("dupping stdout"); - if (options.mergeStderrToStdout) - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) - throw SysError("cannot dup stdout into stderr"); + for (auto redirection : options.redirections) { + if (dup2(redirection.to, redirection.from) == -1) { + throw SysError("dupping fd %i to %i", redirection.from, redirection.to); + } + } if (options.chdir && chdir((*options.chdir).c_str()) == -1) throw SysError("chdir failed"); diff --git a/src/libutil/processes.hh b/src/libutil/processes.hh index 3566aa3cf..a48fea3b9 100644 --- a/src/libutil/processes.hh +++ b/src/libutil/processes.hh @@ -76,6 +76,11 @@ std::string runProgram(Path program, bool searchPath = false, struct RunOptions { + struct Redirection + { + int from, to; + }; + Path program; bool searchPath = true; Strings args; @@ -84,8 +89,8 @@ struct RunOptions std::optional chdir; std::optional> environment; bool captureStdout = false; - bool mergeStderrToStdout = false; bool isInteractive = false; + std::vector redirections; }; struct [[nodiscard("you must call RunningProgram::wait()")]] RunningProgram