Annotation of embedaddon/rsync/pipe.c, revision 1.1.1.4
1.1 misho 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>
1.1.1.4 ! misho 7: * Copyright (C) 2004-2020 Wayne Davison
1.1 misho 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;
1.1.1.2 misho 29: extern int munge_symlinks;
1.1.1.4 ! misho 30: extern int always_checksum;
! 31: extern int use_db;
! 32: extern char *db_config;
1.1 misho 33: extern char *logfile_name;
1.1.1.2 misho 34: extern int remote_option_cnt;
35: extern const char **remote_options;
1.1 misho 36: extern struct chmod_mode_struct *chmod_modes;
37:
1.1.1.4 ! misho 38: int same_db = 0;
! 39:
1.1 misho 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:
1.1.1.2 misho 59: if (DEBUG_GTE(CMD, 1))
1.1 misho 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) {
1.1.1.4 ! misho 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) {
1.1 misho 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:
1.1.1.4 ! misho 124: if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
1.1 misho 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;
1.1.1.2 misho 139: munge_symlinks = 0; /* Each side needs its own option. */
1.1 misho 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:
1.1.1.2 misho 148: if (remote_option_cnt) {
1.1.1.4 ! misho 149: const char *db_config_save = db_config;
1.1.1.2 misho 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: }
1.1.1.4 ! misho 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;
1.1.1.2 misho 165:
1.1.1.4 ! misho 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) {
1.1 misho 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:
1.1.1.4 ! misho 183: if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
1.1 misho 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: }
1.1.1.4 ! misho 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>