• Re: Capturing everything sent to stdout, stderr, cout, cerr, clog

    From even andersen@even.oscar.andersen@gmail.com to comp.lang.c++ on Thu Apr 20 13:49:52 2023
    From Newsgroup: comp.lang.c++

    s√łndag 12. mars 2023 kl. 13:42:06 UTC+1 skrev Frederick Virchanza Gotham:
    I mentioned a few weeks ago on this newsgroup about how I'm combining two programs into one.


    ...
    stdout = f;
    Not sure the above is legal.
    As far as I know this cannot be done in neither C nor C++, it can be done in posix
    (For reference, and since the question was asked, not really c++ though) (For instance https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html)
    You might want to work on the right hand side of the filedescriptor table, assuming:
    (FILE *) / iostream ---> <file descriptor> ---> (client side object) ---> | ---> (kernel side object)
    with this model you would look at:
    pipe(2)
    dup(2)
    dup2(2)
    (dup3(2))
    close(2)
    read(2)
    write(2)
    flockfile(3) / funlockfile(3)
    fflush(3)
    fdopen(3)
    This way you would:
    Keep stdout as is
    Keep fileno(stdout) as is
    Redirect what fileno(stdout) refers to
    stdout -> | fileno(stdout) | (some object)
    | fd_1 | ^
    | pipe_wr | >---V
    | pipe_rd | <---V
    stdout -> | fileno(stdout) | (rewired to refer to pipe_wr)
    | fd_1 | (refers to old stdout object)
    | pipe_wr | >---V
    | pipe_rd | <---V
    1) Duplicate fileno(stdout) to keep it around (create a new fd to the client side object) (dup)
    2) Create a pipe, with a read end and a write end (create two fds to a new client side object) (pipe)
    3) Change fileno(stdout) to refer to the write end of the pipe above (dup2) 4) Read from the read end of the pipe,
    -> this is where you capture what is written to stdout, and fileno(stdout) 5) Process what you read, and write it to the filedescriptor you duplicated in 1)
    The problem with this approach is that the object layout/processing layout is not specified for C or C++.
    Another weak point is that std::cout etc does not necessarily write to stdout/fileno(stdout)
    (Not really c++ though)
    And if you want it standardized, try this pipeline
    (buffered layer) -> (file descriptor layer) -> (client side object) -> (kernel side object)
    .. or write a library
    --- Synchronet 3.20a-Linux NewsLink 1.114