I have a parent process which forks out a child to perform execv().
I need the output given by execv() to stdout to be displayed onscreen as also copied to a log file.
How do I write the same output to both stdout & a file, without using pipes or tees?
If you don't want to use a tee, before you write the data, write it to a file, then send it to stdout.
You should write a logging function that does this for you to make it cleaner.
You can do this entirely within your program, but you will still need to use anonymous pipes as created by the pipe()
system call.
Basically, you will need a subprocess that performs the equivalent of tee
, which is quite easy:
int child_pipe[2];
pid_t pid_exec_child, pid_output_child;
pipe(child_pipe);
pid_exec_child = fork();
if (pid_exec_child == 0)
{
dup2(child_pipe[1], STDOUT_FILENO);
close(child_pipe[0]);
close(child_pipe[1]);
execve(/* ... */);
_exit(127);
}
close(child_pipe[1]);
pid_output_child = fork();
if (pid_output_child == 0)
{
/* This child just loops around, reading from the other child and writing everything
* to both stdout and the log file. */
int logfd = open("logfile", O_WRONLY);
char buffer[4096];
ssize_t nread;
while ((nread = read(child_pipe[0], buffer, sizeof buffer) != 0)
{
size_t nwritten_total;
ssize_t nwritten;
if (nread < 0)
{
if (errno == EINTR)
continue;
perror("read");
_exit(1);
}
/* Copy data to stdout */
nwritten_total = 0;
while (nwritten_total < nread)
{
nwritten = write(STDOUT_FILENO, buffer + nwritten_total, nread - nwritten_total);
if (nwritten < 0)
{
if (errno == EINTR)
continue;
perror("write(stdout)");
_exit(2);
}
nwritten_total += nwritten;
}
/* Copy data to logfile */
nwritten_total = 0;
while (nwritten_total < nread)
{
nwritten = write(logfd, buffer + nwritten_total, nread - nwritten_total);
if (nwritten < 0)
{
if (errno == EINTR)
continue;
perror("write(logfile)");
_exit(3);
}
nwritten_total += nwritten;
}
}
_exit(0);
}
close(child_pipe[0]);
/* Parent continues here */
Of course, it is probably easier to just exec tee
in that second child instead...
(Note that the child processes use _exit()
, since they have inherited the standard I/O state from the parent).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With