Cbeam
Loading...
Searching...
No Matches
stdout_redirector.hpp
Go to the documentation of this file.
1/*
2Copyright (c) 2025 acrion innovations GmbH
3Authors: Stefan Zipproth, s.zipproth@acrion.ch
4
5This file is part of Cbeam, see https://github.com/acrion/cbeam and https://cbeam.org
6
7Cbeam is offered under a commercial and under the AGPL license.
8For commercial licensing, contact us at https://acrion.ch/sales. For AGPL licensing, see below.
9
10AGPL licensing:
11
12Cbeam is free software: you can redistribute it and/or modify
13it under the terms of the GNU Affero General Public License as published by
14the Free Software Foundation, either version 3 of the License, or
15(at your option) any later version.
16
17Cbeam is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU Affero General Public License for more details.
21
22You should have received a copy of the GNU Affero General Public License
23along with Cbeam. If not, see <https://www.gnu.org/licenses/>.
24*/
25
26#pragma once
27
28#include <cbeam/error/runtime_error.hpp> // for cbeam::error:runtime_error
29#include <cbeam/logging/log_manager.hpp> // for CBEAM_LOG_DEBUG
30
31#include <cassert> // for assert
32#include <cstdio> // for freopen, fclose, stdout
33
34#include <filesystem> // for std::filesystem::path
35#include <mutex> // for std::mutex, std::lock_guard
36#include <string> // for std::operator+
37
38#ifdef _WIN32
40 #include <io.h>
41#endif
42
43namespace cbeam::filesystem
44{
51 {
52 public:
55 explicit stdout_redirector(const std::filesystem::path& file_path)
56 {
57 std::lock_guard<std::mutex> lock(_mtx);
58 if (freopen(file_path.string().c_str(), "w", stdout) == nullptr)
59 {
60 throw cbeam::error::runtime_error("cbeam::filesystem::stdout_redirector: Could not redirect stdout to file " + file_path.string());
61 }
62 }
63
69 virtual ~stdout_redirector() noexcept
70 {
71 try
72 {
73 std::lock_guard<std::mutex> lock(_mtx);
74 auto redirected_stdout = stdout;
75 fflush(stdout);
76 bool done = false;
77#ifdef _WIN32
78 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
79 if (hStdout != INVALID_HANDLE_VALUE)
80 {
81 int fdStdout = _open_osfhandle((intptr_t)hStdout, _O_TEXT);
82 if (fdStdout != -1)
83 {
84 FILE* fpStdout = _fdopen(fdStdout, "w");
85 if (fpStdout)
86 {
87 *stdout = *fpStdout;
88 std::setvbuf(stdout, NULL, _IONBF, 0);
89 }
90 else
91 {
92 CBEAM_LOG("cbeam::filesystem::stdout_redirector: Could not set stdout to default (failed to reopen stdout as FILE*)");
93 }
94 }
95 else
96 {
97 CBEAM_LOG("cbeam::filesystem::stdout_redirector: Could not set stdout to default (failed to open osfhandle as file descriptor)");
98 }
99 }
100 else
101 {
102 CBEAM_LOG("cbeam::filesystem::stdout_redirector: Could not set stdout to default (invalid standard output handle)");
103 }
104#else
105 done = freopen("/dev/tty", "w", stdout) != nullptr;
106
107 if (!done)
108 {
109 CBEAM_LOG("cbeam::filesystem::stdout_redirector: Could not set stdout to default");
110 }
111#endif
112 if (done && redirected_stdout != stdout)
113 {
114 assert(fclose(redirected_stdout) == 0);
115 }
116 }
117 catch (const std::system_error& ex)
118 {
119 CBEAM_LOG("cbeam::filesystem::stdout_redirector: Could not lock the mutex. This indicates a serious (unexpected) bug that must be fixed during development phase.");
120 assert(false);
121 }
122 }
123
124 private:
125 std::mutex _mtx;
126 };
127}
A Cbeam-specific runtime error that also acts like std::runtime_error.
Definition runtime_error.hpp:46
stdout_redirector(const std::filesystem::path &file_path)
Constructor that redirects stdout to the specified file.
Definition stdout_redirector.hpp:55
virtual ~stdout_redirector() noexcept
Destructor that resets stdout to the system's default state.
Definition stdout_redirector.hpp:69
#define CBEAM_LOG(s)
Logs a message using cbeam::logging::log_manager.
Definition log_manager.hpp:124
Facilitates file I/O, path normalization, and directory operations in a cross-platform manner....
Definition io.hpp:36
Header file to manage inclusion of windows.h with specific settings.