module; #include #include #include #include export module ttwhy.terminal:signal_handling; namespace ttwhy::terminal { //! Asynchronously handle POSIX process and job-control signals for a terminal application. //! //! Intercepts SIGINT and SIGTERM to print an exit notification and terminate gracefully. //! Intercepts SIGTSTP to restore terminal canonical and echo flags before raising SIGSTOP, //! and intercepts SIGCONT to restore the terminal attributes when execution resumes. //! //! @tparam Stream The output stream type used for writing diagnostic messages. //! @tparam TerminalAttributes The terminal attributes manager type. //! @param stream The stream to write diagnostic messages to. //! @param attributes The scoped attributes managing terminal canonical mode and echo. //! @return An awaitable task that yields an error code upon termination. export template auto handle_signals(Stream & stream, TerminalAttributes & attributes) -> asio::awaitable { auto executor = co_await asio::this_coro::executor; auto signals = asio::signal_set{executor, SIGINT, SIGTERM}; signals.add(SIGTSTP); signals.add(SIGCONT); while (true) { auto [error, signal] = co_await signals.async_wait(asio::as_tuple(asio::use_awaitable)); if (error) { co_return error; } switch (signal) { case SIGINT: case SIGTERM: { auto message = std::format("Received signal {}, exiting ...\n", signal); co_await asio::async_write(stream, asio::buffer(message), asio::use_awaitable); co_return asio::error_code{}; } case SIGTSTP: { attributes.canonical_mode(true).echo(true); ::raise(SIGSTOP); break; } case SIGCONT: { attributes.canonical_mode(false).echo(false); break; } } } } } // namespace ttwhy::terminal