This method is not advisable. Do not use. If it breaks your system, you get to keep all the pieces.
Okay! Still with me? For an uncomplicated case with appropriate includes (fcntl, for open), redirecting standard out somewhere else is (in theory) possible:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
while (1) {
printf("blat\n");
sleep(1);
}
exit(EXIT_SUCCESS);
}
Compiled, and run:
$ cc -g blat.c -o blat
$ ./blat &
Now in some other terminal (this may run afoul security policies for various obvious reasons given what a debugger can do to a live process) using the PID issued for the background job:
$ gdb -q -p 3727
...
(gdb) call close(1)
$1 = 0
After reading close(2) we determine that's a success, standard input has been closed. Let's open a new file...
(gdb) call open("/home/userrunningblat/blat.out", O_CREAT|O_WRONLY, 0666)
No symbol "O_CREAT" in current context.
Well shoot. What is the magic number lacking those symbols? In a third terminal, using our handy compile-and-execute-some-C-program:
$ cfu 'printf("%d\n", O_CREAT|O_WRONLY)'
65
Or you could go delve through the /usr/include directory and figure out the input formats and bitwise OR yourself, but that's super annoying. (Note also that these numbers can and do vary by OS.) Back to gdb!
(gdb) call open("/home/userrunningblat/blat.out", 65, 0666)
$2 = 1
(gdb) quit
$ tail -f blat.out
Which means since we earlier closed standard out (1) this open(2) call has reused that file descriptor number, so after we exit gdb the standard out should now be going to that file.
This method may not be possible for more complicated programs, may not be possible due to security restrictions, missing debugger info, may cause horrible breakage, etc.