diff --git a/core/relinker/cli/src/Autorun.cpp b/core/relinker/cli/src/Autorun.cpp index 95f8214038..0647c38018 100644 --- a/core/relinker/cli/src/Autorun.cpp +++ b/core/relinker/cli/src/Autorun.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -71,8 +72,11 @@ int Autorun(const std::string& absPath, bool toWindows) { std::cout << "\nRaw exit code: " << rawCode << "; Unpacked: " << exitCode << '\n'; #endif - std::cout << "\nPress Enter to exit...\n"; - std::cin.ignore((std::numeric_limits::max)(), '\n'); + const char* noPause = std::getenv("ANYPS5_AUTORUN_NO_PAUSE"); + if (!noPause || std::string_view(noPause) != "1") { + std::cout << "\nPress Enter to exit...\n"; + std::cin.ignore((std::numeric_limits::max)(), '\n'); + } return exitCode; } diff --git a/core/relinker/cli/tests/AutorunExitTests.cpp b/core/relinker/cli/tests/AutorunExitTests.cpp index 798fb129db..9bf9f3b6c6 100644 --- a/core/relinker/cli/tests/AutorunExitTests.cpp +++ b/core/relinker/cli/tests/AutorunExitTests.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #ifndef _WIN32 @@ -19,6 +21,26 @@ namespace { +void SetNoPause(const char* value) { +#ifdef _WIN32 + if (_putenv_s("ANYPS5_AUTORUN_NO_PAUSE", value ? value : "") != 0) throw std::runtime_error("Cannot set autorun environment"); +#else + if ((value ? setenv("ANYPS5_AUTORUN_NO_PAUSE", value, 1) : unsetenv("ANYPS5_AUTORUN_NO_PAUSE")) != 0) + throw std::runtime_error("Cannot set autorun environment"); +#endif +} + +class EnvironmentGuard { +public: + EnvironmentGuard() { + if (const auto* value = std::getenv("ANYPS5_AUTORUN_NO_PAUSE")) saved = value; + SetNoPause(nullptr); + } + ~EnvironmentGuard() { SetNoPause(saved ? saved->c_str() : nullptr); } +private: + std::optional saved; +}; + std::filesystem::path ExecutablePath(const char* argument) { #ifdef _WIN32 static_cast(argument); @@ -55,6 +77,7 @@ int main(int, char* argv[]) { #endif }; #endif + const EnvironmentGuard environment; std::istringstream input("\n\n\n"); auto* savedInput = std::cin.rdbuf(input.rdbuf()); int result = 0; @@ -66,6 +89,28 @@ int main(int, char* argv[]) { std::filesystem::create_symlink(executable, child); const auto changed = changeTime(executable); #endif + for (const char* value : {"1", "0", "yes", "", "10", "1 "}) { + SetNoPause(value); + std::istringstream pending("\nremaining"); + auto* originalInput = std::cin.rdbuf(pending.rdbuf()); + std::ostringstream output; + auto* originalOutput = std::cout.rdbuf(output.rdbuf()); + int code; + try { + code = Cli::Autorun(child.string(), true); + } catch (...) { + std::cin.rdbuf(originalInput); + std::cout.rdbuf(originalOutput); + throw; + } + std::cin.rdbuf(originalInput); + std::cout.rdbuf(originalOutput); + const bool skipped = std::string(value) == "1"; + if (code != 42 || (pending.tellg() == 0) != skipped || + (output.str().find("Press Enter") == std::string::npos) != skipped) + throw std::runtime_error("Autorun pause option changed the exit code, input position or prompt"); + } + SetNoPause(nullptr); std::vector suffixes{""}; #ifndef _WIN32 suffixes.insert(suffixes.end(), {" $HOME", " $(printf substituted)", " `printf substituted`", diff --git a/docs/dev/ENVIRONMENT.md b/docs/dev/ENVIRONMENT.md index f517fb7a3c..eb5d6b34ff 100644 --- a/docs/dev/ENVIRONMENT.md +++ b/docs/dev/ENVIRONMENT.md @@ -22,6 +22,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | Name | Kind | Source | Default | Description | |------|------|--------|---------|-------------| +| `ANYPS5_AUTORUN_NO_PAUSE` | string | `core/relinker/cli/src/Autorun.cpp` | | exactly `1` skips the exit prompt and stdin read after autorun; unset, empty and other values keep the prompt | | `ANYPS5_GUEST_MODULE_ARGS` | string | `core/relinker/elfpatcher/tests/GuestModuleArgsHost.cpp` | | path of the file the module-argument fixture appends its events to | ### core/shader