mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
125 lines
2.1 KiB
C++
125 lines
2.1 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#include "cmStdIoInit.h"
|
|
|
|
#include <cerrno>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#ifdef _WIN32
|
|
# include <windows.h>
|
|
|
|
# include <io.h> // for _close, _dup2, _get_osfhandle
|
|
|
|
# include "cm_fileno.hxx"
|
|
#else
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
#include "cmStdIoStream.h"
|
|
|
|
namespace cm {
|
|
namespace StdIo {
|
|
|
|
namespace {
|
|
|
|
#ifdef _WIN32
|
|
void InitStdPipe(int stdFd, DWORD nStdHandle, FILE* stream,
|
|
wchar_t const* mode)
|
|
{
|
|
if (cm_fileno(stream) >= 0) {
|
|
return;
|
|
}
|
|
_close(stdFd);
|
|
_wfreopen(L"NUL", mode, stream);
|
|
int fd = cm_fileno(stream);
|
|
if (fd < 0) {
|
|
perror("failed to open NUL for missing stdio pipe");
|
|
abort();
|
|
}
|
|
if (fd != stdFd) {
|
|
_dup2(fd, stdFd);
|
|
}
|
|
SetStdHandle(nStdHandle, reinterpret_cast<HANDLE>(_get_osfhandle(fd)));
|
|
}
|
|
#else
|
|
void InitStdPipe(int fd)
|
|
{
|
|
if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) {
|
|
return;
|
|
}
|
|
|
|
int f = open("/dev/null", fd == STDIN_FILENO ? O_RDONLY : O_WRONLY);
|
|
if (f == -1) {
|
|
perror("failed to open /dev/null for missing stdio pipe");
|
|
abort();
|
|
}
|
|
if (f != fd) {
|
|
dup2(f, fd);
|
|
close(f);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
struct InitStdPipes
|
|
{
|
|
InitStdPipes()
|
|
{
|
|
#ifdef _WIN32
|
|
InitStdPipe(0, STD_INPUT_HANDLE, stdin, L"rb");
|
|
InitStdPipe(1, STD_OUTPUT_HANDLE, stdout, L"wb");
|
|
InitStdPipe(2, STD_ERROR_HANDLE, stderr, L"wb");
|
|
#else
|
|
InitStdPipe(STDIN_FILENO);
|
|
InitStdPipe(STDOUT_FILENO);
|
|
InitStdPipe(STDERR_FILENO);
|
|
#endif
|
|
}
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
class Globals
|
|
{
|
|
public:
|
|
std::ios::Init InitIos;
|
|
InitStdPipes InitPipes;
|
|
IStream StdIn{ std::cin, stdin };
|
|
OStream StdOut{ std::cout, stdout };
|
|
OStream StdErr{ std::cerr, stderr };
|
|
|
|
static Globals& Get();
|
|
};
|
|
|
|
Globals& Globals::Get()
|
|
{
|
|
static Globals globals;
|
|
return globals;
|
|
}
|
|
|
|
Init::Init()
|
|
{
|
|
Globals::Get();
|
|
}
|
|
|
|
IStream& In()
|
|
{
|
|
return Globals::Get().StdIn;
|
|
}
|
|
|
|
OStream& Out()
|
|
{
|
|
return Globals::Get().StdOut;
|
|
}
|
|
|
|
OStream& Err()
|
|
{
|
|
return Globals::Get().StdErr;
|
|
}
|
|
|
|
}
|
|
}
|