Get output of `posix_spawn`

Here's a minimal example of modifying file descriptors of a spawned process, saved as foo.c:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <spawn.h>

int main(int argc, char* argv[], char *env[])
    int ret;
    pid_t child_pid;
    posix_spawn_file_actions_t child_fd_actions;
    if (ret = posix_spawn_file_actions_init (&child_fd_actions))
        perror ("posix_spawn_file_actions_init"), exit(ret);
    if (ret = posix_spawn_file_actions_addopen (&child_fd_actions, 1, "/tmp/foo-log", 
            O_WRONLY | O_CREAT | O_TRUNC, 0644))
        perror ("posix_spawn_file_actions_addopen"), exit(ret);
    if (ret = posix_spawn_file_actions_adddup2 (&child_fd_actions, 1, 2))
        perror ("posix_spawn_file_actions_adddup2"), exit(ret);

    if (ret = posix_spawnp (&child_pid, "date", &child_fd_actions, NULL, argv, env))
        perror ("posix_spawn"), exit(ret);

What does it do?

  • The third parameter of posix_spwan is a pointer of type posix_spawn_file_actions_t (one you have given as NULL). posix_spawn will open, close or duplicate file descriptors inherited from the calling process as specified by the posix_spawn_file_actions_t object.
  • So we start with a posix_spawn_file_actions_t object (chiild_fd_actions), and initialize it with posix_spawn_file_actions_init().
  • Now, the posix_spawn_file_actions_{addopen,addclose,addup2} functions can be used to open, close or duplicate file descriptors (after the open(3), close(3) and dup2(3) functions) respectively.
  • So we posix_spawn_file_actions_addopen a file at /tmp/foo-log to file descriptor 1 (aka stdout).
  • Then we posix_spawn_file_actions_adddup2 fd 2 (aka stderr) to fd 1.
  • Note that nothing has been opened or duped yet. The last two functions simply changed the child_fd_actions object to note that these actions are to be taken.
  • And finally we use posix_spawn with the child_fd_actions object.

Testing it out:

$ make foo
cc     foo.c   -o foo
$ ./foo
$ cat /tmp/foo-log 
Sun Jan  3 03:48:17 IST 2016
$ ./foo +'%F %R'  
$ cat /tmp/foo-log
2016-01-03 03:48
$  ./foo -d 'foo'  
$ cat /tmp/foo-log
./foo: invalid date ‘foo’

As you can see, both stdout and stderr of the spawned process went to /tmp/foo-log.