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@lists.isocpp.org> 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@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals