Redirect the output of the processed process to NULL

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.

+4
source share
2 answers

You could use this as your API convention, which is passed to -1 for fd, to use /dev/null , and do

 // ... same as you have ... else // Child process { if (stdin_fd == -1) stdin_fd = open("/dev/null", O_RDONLY); if (stdin_fd == -1) _exit(127); dup2(stdin_fd, STDIN_FILENO); close(stdin_fd); // similarly for stdout and stderr execvp(arglist[0], arglist); _exit(127); } 

(Psst: every time you put spaces inside your parentheses, God kills the kitten.)

+4
source

The child process must know which fd to use as oldfd for dup2 and which fd to dup2 on.

For example, why would fd be dup2 on STDIN_FILENO?

The child needs information for open fd, and fd is dup2'd.

To summarize, to cover cases where file names are processed, not just fd, you will have a way to say "/ dev / null", since this is the real file name.

So, I have a list of structures struct { int oldfd; char* filename; int newfd; } struct { int oldfd; char* filename; int newfd; } struct { int oldfd; char* filename; int newfd; } , and the job is regular, and / dev / null is not a special case. When oldfd is -1, open the file name newfd instead of dup2'ing on it.

+1
source

Source: https://habr.com/ru/post/1403531/


All Articles