This function forks a child which calls child_main(). First, * however, it has to establish communication paths to and from the * newborn child. It creates two socket pairs -- one for writing to * the child (from the parent) and one for reading from the child * (writing to the parent). Since that's four socket ends, each * process has to close the two ends it doesn't need. The remaining
| 107 | * sockets. In the parent, the function arguments f_in and f_out are |
| 108 | * set to refer to these sockets. */ |
| 109 | pid_t local_child(int argc, char **argv, int *f_in, int *f_out, |
| 110 | int (*child_main)(int, char*[])) |
| 111 | { |
| 112 | pid_t pid; |
| 113 | int to_child_pipe[2]; |
| 114 | int from_child_pipe[2]; |
| 115 | |
| 116 | /* The parent process is always the sender for a local rsync. */ |
| 117 | assert(am_sender); |
| 118 | |
| 119 | if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) { |
| 120 | rsyserr(FERROR, errno, "pipe"); |
| 121 | exit_cleanup(RERR_IPC); |
| 122 | } |
| 123 | |
| 124 | pid = do_fork(); |
| 125 | if (pid == -1) { |
| 126 | rsyserr(FERROR, errno, "fork"); |
| 127 | exit_cleanup(RERR_IPC); |
| 128 | } |
| 129 | |
| 130 | if (pid == 0) { |
| 131 | am_sender = 0; |
| 132 | am_server = 1; |
| 133 | filesfrom_fd = -1; |
| 134 | munge_symlinks = 0; /* Each side needs its own option. */ |
| 135 | chmod_modes = NULL; /* Let the sending side handle this. */ |
| 136 | |
| 137 | /* Let the client side handle this. */ |
| 138 | if (logfile_name) { |
| 139 | logfile_name = NULL; |
| 140 | logfile_close(); |
| 141 | } |
| 142 | |
| 143 | if (remote_option_cnt) { |
| 144 | int rc = remote_option_cnt + 1; |
| 145 | const char **rv = remote_options; |
| 146 | if (!parse_arguments(&rc, &rv)) { |
| 147 | option_error(); |
| 148 | exit_cleanup(RERR_SYNTAX); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 |
| 153 | || close(to_child_pipe[1]) < 0 |
| 154 | || close(from_child_pipe[0]) < 0 |
| 155 | || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) { |
| 156 | rsyserr(FERROR, errno, "Failed to dup/close"); |
| 157 | exit_cleanup(RERR_IPC); |
| 158 | } |
| 159 | if (to_child_pipe[0] != STDIN_FILENO) |
| 160 | close(to_child_pipe[0]); |
| 161 | if (from_child_pipe[1] != STDOUT_FILENO) |
| 162 | close(from_child_pipe[1]); |
| 163 | #ifdef ICONV_CONST |
| 164 | setup_iconv(); |
| 165 | #endif |
| 166 | child_main(argc, argv); |
no test coverage detected