I need to create a function that, among other things, spawns a child process. I would like to pass this function an additional list of file descriptors, so that depending on the needs of the user it would be possible to redirect the input / output of the child process.
I saw dozens of people talking about how to do this using dup2 something like this:
if( pid < 0 ) // error forking. { //... } else if( pid != 0 ) // Parent process. { ret = waitpid( pid, &status, 0 ); return WEXITSTATUS( status ); } else // Child process. { dup2( fd, STDIN_FILENO ); // Clone passed file discriptor. close( fd ); // Close the passed one, since we have already cloned. execvp( arglist[ 0 ], arglist ); }
Good. All this on the Internet. My question is how (or what is the best way) to redirect to /dev/null ?
Should I force the user open( /dev/null) and pass it as fd or is there a better way?
EDIT:
This is not as beautiful as I wanted, but I could not find a better way, so I ended up passing the array of file names to where the user could redirect STDIN, STDOUT and STDERR respectively:
static int do_exec( arglist_t arglist, const char *fio[ 3 ] ) { DEBUG__( OSU_DEBUG_LEVEL_1, "fio = %p\n", fio ); if ( fio ) { if ( fio[ STDIN_FILENO ] ) { int fd = open( fio[ STDIN_FILENO ], O_RDONLY ); if ( -1 < fd ) { dup2( fd, STDIN_FILENO ); close( fd ); } } if ( fio[ STDOUT_FILENO ] ) { int fd = open( fio[ STDOUT_FILENO ], O_WRONLY | O_CREAT | O_APPEND ); if ( -1 < fd ) { dup2( fd, STDOUT_FILENO ); close( fd ); } } if ( fio[ STDERR_FILENO ] ) { int fd = open( fio[ STDERR_FILENO ], O_WRONLY | O_CREAT | O_APPEND ); if ( -1 < fd ) { dup2( fd, STDERR_FILENO ); close( fd ); } } } return execvp( arglist[ 0 ], arglist ); }
- I have not fully tested it yet, so it may have some errors.
Really thanks to @Zack and @gbulmer.