Skip to content

Commit

Permalink
feat: add StdoutRedirector
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Aug 11, 2024
1 parent b4b8fdf commit 72320b2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
1 change: 1 addition & 0 deletions src-client/ll/core/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

79 changes: 79 additions & 0 deletions src/ll/api/io/StdoutRedirector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "ll/api/io/StdoutRedirector.h"

#include "ll/api/utils/RandomUtils.h"
#include "ll/api/utils/StringUtils.h"

#include "Windows.h"

#include "fcntl.h"
#include "io.h"

namespace ll::io {

static void createWinPipe(HANDLE& hRead, HANDLE& hWrite) {
std::wstring pipeName = LR"(\\.\pipe\stdoutredirector-levilamina-)";
pipeName += string_utils::str2wstr(string_utils::intToHexStr(random_utils::rand<uint64>()));
SECURITY_ATTRIBUTES attributes = {sizeof(SECURITY_ATTRIBUTES), 0, false};
hRead = ::CreateNamedPipe(
pipeName.c_str(),
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
1,
0,
1024 * 1024,
0,
&attributes
);
SECURITY_ATTRIBUTES attributes2 = {sizeof(SECURITY_ATTRIBUTES), 0, true};
hWrite = ::CreateFile(pipeName.c_str(), GENERIC_WRITE, 0, &attributes2, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

::ConnectNamedPipe(hRead, NULL);
}

StdoutRedirector::StdoutRedirector(ProcessChannel channels) : m_channels(channels) {
createWinPipe(hRead, hWrite);
if (m_channels & StandardOutput) {
setvbuf(stdout, NULL, _IONBF, 0);
::SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
}
if (m_channels & StandardError) {
setvbuf(stderr, NULL, _IONBF, 0);
::SetStdHandle(STD_ERROR_HANDLE, hWrite);
}

int fd = _open_osfhandle((intptr_t)hWrite, _O_WRONLY | _O_U8TEXT);
if (m_channels & StandardOutput) _dup2(fd, 1);
if (m_channels & StandardError) _dup2(fd, 2);
_close(fd);
}

StdoutRedirector::~StdoutRedirector() {
::DisconnectNamedPipe(hRead);
if (m_channels & StandardOutput) {
FILE* s;
freopen_s(&s, "CONOUT$", "w+t", stdout);
}
if (m_channels & StandardError) {
FILE* s;
freopen_s(&s, "CONOUT$", "w+t", stderr);
}
}

std::string StdoutRedirector::read() {
std::string result;
BOOL fSuccess;
do {
// Read from the pipe.

char buf[4096];
DWORD cbRead{0};

fSuccess = ReadFile(hRead, buf, sizeof(buf), &cbRead, NULL);

result.append(buf, cbRead);

if (!fSuccess && GetLastError() != ERROR_MORE_DATA) break;
} while (!fSuccess); // repeat loop if ERROR_MORE_DATA
return result;
}
} // namespace ll::io
24 changes: 24 additions & 0 deletions src/ll/api/io/StdoutRedirector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <string>

#include "ll/api/base/Macro.h"

namespace ll::io {

class StdoutRedirector {
public:
enum ProcessChannel { StandardOutput = 1, StandardError = 2 };

LLNDAPI explicit StdoutRedirector(ProcessChannel channels = (ProcessChannel)(StandardOutput | StandardError));

LLAPI ~StdoutRedirector();

LLNDAPI std::string read();

ProcessChannel m_channels;

void* hRead;
void* hWrite;
};
} // namespace ll::io
3 changes: 1 addition & 2 deletions src/ll/api/utils/RandomUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ namespace ll::inline utils::random_utils {

template <std::integral T>
inline T rand(T upBound = 0) {
static pcg_extras::seed_seq_from<std::random_device> rd{};
static pcg64 random{rd};
static pcg64 random{pcg_extras::seed_seq_from<std::random_device>{}};

constexpr auto digits = std::numeric_limits<T>::digits;
if (upBound != 0) {
Expand Down

0 comments on commit 72320b2

Please sign in to comment.