I'm creating some pipes and handing it over to fork()/exec()'d child process as stdout and stderr FDs. But the child program doesn't output ANSI colours.
For e.g., the gcc
command can output diagnostics with colours. But when I create it as a child of my program and hand over the piped FDs it doesn't send generate colours.
With a bit of snooping around, I found it tests isatty(STDERR_FILENO)
and doesn't send ANSI colour codes when it returns false. Is there a way I can make my pipes be treated as TTYs in child process?
P.S. Also, please not I'm aware of unbuffer
shell command which was recommended for similar question. I am looking for C/POSIX API solution that's portable across unices. Not just Linux.
There are two answers to your question, the direct answer and the answer to your XY problem. First, the latter. Generally, programs that can output color/formatting suitable for a terminal, or plain text, choose their default based on isatty
, but let you pass an explicit option to enable or disable it. For GCC, this is -fdiagnostics-color=always
. This is almost surely what you should be using.
But to answer your original question, the way to do this is not to use a pipe but instead a pseudo-tty (pty). The POSIX interfaces to do this are posix_openpt
, grantpt
, unlockpt
, and ptsname
(to get the name of the device to open). But there's a much nicer non-standardized interface, openpty
, that does it all for you in one call, and an accompanying forkpty
that automatically forks and connects the child's stdin/out/err up to it. I would use one of these if available (they're available on glibc and musl on Linux systems, and on most/all BSD systems).