C++ Logo

std-proposals

Advanced search

Re: [std-proposals] A standard way to redirect all standard output

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 13 Mar 2023 12:35:58 -0400
I suspect that if you're already interposing on POSIX `write`, then you
don't need any of the rest of that stuff.
`printf` will use `write(1,...)` internally, and so will `std::cout`.
*Neither* approach will help if someone `dup`s stdout like
    write(dup(1), "hello world\n", 12);
but that sounds more like a question for StackOverflow than for
std-proposals.

HTH,
Arthur


On Mon, Mar 13, 2023 at 11:56 AM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:

> I'm currently combining two programs into one program, so that they
> both run as one process.
>
> I have to capture all the output from one of the programs, and I've
> had to do so in 3 ways:
> (1) Create a new 'streambuf' type to assign to cout, cerr, clog
> (2) Use the GNU-gcc function fopencookie to change the FILE* for stdout,
> stderr
> (3) Provide my own implementation of the POSIX function "write" which
> checks if the file descriptor is 1 or 2
>
> I was thinking it would be nice if the Standard Library allowed us to
> redirect all standard output (destined for stdout + stderr), if we
> were to define these two functions:
>
> void stdout_redirect(char const *buf, size_t const len);
> void stderr_redirect(char const *buf, size_t const len);
>
> This would effect all invocations of printf, puts, fprintf(stderr),
> fwrite(stdout), cout <<, cerr <<, clog <<.
>
> Finally the Standard would have a paragraph saying that this
> redirection should be implemented by the compiler vendor for all
> platform-specific functions that write to stdout and stderr (for
> example 'write(fd = 1)' on POSIX systems).
>
> Here's the code I had to write in my own program to achieve all of this:
>
> ssize_t writer(void*, char const *const buffer, size_t const size)
> {
> if ( (0u == size) || (nullptr == buffer) ) return 0;
>
> // For example send output to text box in GUI
>
> return size;
> }
>
> class streambuf_redirect : public std::streambuf {
>
> using std::streambuf::streambuf;
>
> virtual std::streamsize xsputn(char const *const s,
> std::streamsize const count)
> {
> return writer(nullptr,s,count);
> }
> };
>
> extern "C" ssize_t write(int const fd, void const *const buf, size_t
> const count) // This takes the place of the function provided by
> glibc
> {
> static ssize_t (*const p)(int,void const*,size_t) =
> reinterpret_cast<ssize_t(*)(int,void const*,size_t)>(
> ::dlsym(RTLD_NEXT, "write") );
>
> if ( (fd < 1) || (fd > 2) ) return p(fd,buf,count); // 1 =
> stdout, 2 = stderr
>
> return writer(nullptr, static_cast<char const*>(buf), count);
> }
>
> void RedirectAllOutput(void)
> {
> cookie_io_functions_t g_funcptrs = {}; // all nullptr
>
> g_funcptrs.write = writer;
>
> FILE *const fp = fopencookie(nullptr, "w", g_funcptrs);
>
> assert( nullptr != fp );
>
> setvbuf(fp, nullptr, _IOLBF, 0); // line buffered
>
> stdout = stderr = fp;
>
> static streambuf_redirect buf;
>
> std::cout.rdbuf( &buf );
> std::clog.rdbuf( &buf );
> std::cerr.rdbuf( &buf );
> }
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-03-13 16:36:11