1: /*
2: * Routines used to setup various kinds of inter-process pipes.
3: *
4: * Copyright (C) 1996-2000 Andrew Tridgell
5: * Copyright (C) 1996 Paul Mackerras
6: * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
7: * Copyright (C) 2004-2020 Wayne Davison
8: *
9: * This program is free software; you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation; either version 3 of the License, or
12: * (at your option) any later version.
13: *
14: * This program is distributed in the hope that it will be useful,
15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: * GNU General Public License for more details.
18: *
19: * You should have received a copy of the GNU General Public License along
20: * with this program; if not, visit the http://fsf.org website.
21: */
22:
23: #include "rsync.h"
24:
25: extern int am_sender;
26: extern int am_server;
27: extern int blocking_io;
28: extern int filesfrom_fd;
29: extern int munge_symlinks;
30: extern int always_checksum;
31: extern int use_db;
32: extern char *db_config;
33: extern char *logfile_name;
34: extern int remote_option_cnt;
35: extern const char **remote_options;
36: extern struct chmod_mode_struct *chmod_modes;
37:
38: int same_db = 0;
39:
40: /**
41: * Create a child connected to us via its stdin/stdout.
42: *
43: * This is derived from CVS code
44: *
45: * Note that in the child STDIN is set to blocking and STDOUT
46: * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
47: * and ssh relies on stdout being non-blocking
48: *
49: * If blocking_io is set then use blocking io on both fds. That can be
50: * used to cope with badly broken rsh implementations like the one on
51: * Solaris.
52: **/
53: pid_t piped_child(char **command, int *f_in, int *f_out)
54: {
55: pid_t pid;
56: int to_child_pipe[2];
57: int from_child_pipe[2];
58:
59: if (DEBUG_GTE(CMD, 1))
60: print_child_argv("opening connection using:", command);
61:
62: if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
63: rsyserr(FERROR, errno, "pipe");
64: exit_cleanup(RERR_IPC);
65: }
66:
67: pid = do_fork();
68: if (pid == -1) {
69: rsyserr(FERROR, errno, "fork");
70: exit_cleanup(RERR_IPC);
71: }
72:
73: if (pid == 0) {
74: if (dup2(to_child_pipe[0], STDIN_FILENO) < 0
75: || close(to_child_pipe[1]) < 0
76: || close(from_child_pipe[0]) < 0
77: || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
78: rsyserr(FERROR, errno, "Failed to dup/close");
79: exit_cleanup(RERR_IPC);
80: }
81: if (to_child_pipe[0] != STDIN_FILENO)
82: close(to_child_pipe[0]);
83: if (from_child_pipe[1] != STDOUT_FILENO)
84: close(from_child_pipe[1]);
85: set_blocking(STDIN_FILENO);
86: if (blocking_io > 0)
87: set_blocking(STDOUT_FILENO);
88: execvp(command[0], command);
89: rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
90: exit_cleanup(RERR_IPC);
91: }
92:
93: if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
94: rsyserr(FERROR, errno, "Failed to close");
95: exit_cleanup(RERR_IPC);
96: }
97:
98: *f_in = from_child_pipe[0];
99: *f_out = to_child_pipe[1];
100:
101: return pid;
102: }
103:
104: /* This function forks a child which calls child_main(). First,
105: * however, it has to establish communication paths to and from the
106: * newborn child. It creates two socket pairs -- one for writing to
107: * the child (from the parent) and one for reading from the child
108: * (writing to the parent). Since that's four socket ends, each
109: * process has to close the two ends it doesn't need. The remaining
110: * two socket ends are retained for reading and writing. In the
111: * child, the STDIN and STDOUT file descriptors refer to these
112: * sockets. In the parent, the function arguments f_in and f_out are
113: * set to refer to these sockets. */
114: pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
115: int (*child_main)(int, char*[]))
116: {
117: pid_t pid;
118: int to_child_pipe[2];
119: int from_child_pipe[2];
120:
121: /* The parent process is always the sender for a local rsync. */
122: assert(am_sender);
123:
124: if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
125: rsyserr(FERROR, errno, "pipe");
126: exit_cleanup(RERR_IPC);
127: }
128:
129: pid = do_fork();
130: if (pid == -1) {
131: rsyserr(FERROR, errno, "fork");
132: exit_cleanup(RERR_IPC);
133: }
134:
135: if (pid == 0) {
136: am_sender = 0;
137: am_server = 1;
138: filesfrom_fd = -1;
139: munge_symlinks = 0; /* Each side needs its own option. */
140: chmod_modes = NULL; /* Let the sending side handle this. */
141:
142: /* Let the client side handle this. */
143: if (logfile_name) {
144: logfile_name = NULL;
145: logfile_close();
146: }
147:
148: if (remote_option_cnt) {
149: const char *db_config_save = db_config;
150: int rc = remote_option_cnt + 1;
151: const char **rv = remote_options;
152: if (!parse_arguments(&rc, &rv)) {
153: option_error();
154: exit_cleanup(RERR_SYNTAX);
155: }
156: if (db_config == db_config_save)
157: same_db = db_config != NULL;
158: else if (!db_config || !db_config_save || strcmp(db_config, db_config_save) != 0) {
159: use_db = 0;
160: if (db_config)
161: db_read_config(FERROR, db_config);
162: }
163: } else if (use_db)
164: same_db = 1;
165:
166: if (dup2(to_child_pipe[0], STDIN_FILENO) < 0
167: || close(to_child_pipe[1]) < 0
168: || close(from_child_pipe[0]) < 0
169: || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
170: rsyserr(FERROR, errno, "Failed to dup/close");
171: exit_cleanup(RERR_IPC);
172: }
173: if (to_child_pipe[0] != STDIN_FILENO)
174: close(to_child_pipe[0]);
175: if (from_child_pipe[1] != STDOUT_FILENO)
176: close(from_child_pipe[1]);
177: #ifdef ICONV_CONST
178: setup_iconv();
179: #endif
180: child_main(argc, argv);
181: }
182:
183: if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
184: rsyserr(FERROR, errno, "Failed to close");
185: exit_cleanup(RERR_IPC);
186: }
187:
188: *f_in = from_child_pipe[0];
189: *f_out = to_child_pipe[1];
190:
191: return pid;
192: }
193:
194: pid_t run_filter(char *command[], int out, int *pipe_to_filter)
195: {
196: pid_t pid;
197: int pipefds[2];
198:
199: if (DEBUG_GTE(CMD, 1))
200: print_child_argv("opening connection using:", command);
201:
202: if (pipe(pipefds) < 0) {
203: rsyserr(FERROR, errno, "pipe");
204: exit_cleanup(RERR_IPC);
205: }
206:
207: pid = do_fork();
208: if (pid == -1) {
209: rsyserr(FERROR, errno, "fork");
210: exit_cleanup(RERR_IPC);
211: }
212:
213: if (pid == 0) {
214: if (dup2(pipefds[0], STDIN_FILENO) < 0
215: || close(pipefds[1]) < 0
216: || dup2(out, STDOUT_FILENO) < 0) {
217: rsyserr(FERROR, errno, "Failed dup/close");
218: exit_cleanup(RERR_IPC);
219: }
220: umask(orig_umask);
221: set_blocking(STDIN_FILENO);
222: if (blocking_io)
223: set_blocking(STDOUT_FILENO);
224: execvp(command[0], command);
225: rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
226: exit_cleanup(RERR_IPC);
227: }
228:
229: if (close(pipefds[0]) < 0) {
230: rsyserr(FERROR, errno, "Failed to close");
231: exit_cleanup(RERR_IPC);
232: }
233:
234: *pipe_to_filter = pipefds[1];
235:
236: return pid;
237: }
238:
239: pid_t run_filter_on_file(char *command[], int out, int in)
240: {
241: pid_t pid;
242:
243: if (DEBUG_GTE(CMD, 1))
244: print_child_argv("opening connection using:", command);
245:
246: pid = do_fork();
247: if (pid == -1) {
248: rsyserr(FERROR, errno, "fork");
249: exit_cleanup(RERR_IPC);
250: }
251:
252: if (pid == 0) {
253: if (dup2(in, STDIN_FILENO) < 0
254: || dup2(out, STDOUT_FILENO) < 0) {
255: rsyserr(FERROR, errno, "Failed to dup2");
256: exit_cleanup(RERR_IPC);
257: }
258: if (blocking_io)
259: set_blocking(STDOUT_FILENO);
260: execvp(command[0], command);
261: rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
262: exit_cleanup(RERR_IPC);
263: }
264:
265: return pid;
266: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>