Add more test cases.
[rsync/rsync.git] / pipe.c
CommitLineData
b35d0d8e
MP
1#include "rsync.h"
2
3/**
4 * Create a child connected to use on stdin/stdout.
5 *
6 * This is derived from CVS code
7 *
8 * Note that in the child STDIN is set to blocking and STDOUT
9 * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
10 * and ssh relies on stdout being non-blocking
11 *
12 * If blocking_io is set then use blocking io on both fds. That can be
13 * used to cope with badly broken rsh implementations like the one on
14 * Solaris.
15 **/
16pid_t piped_child(char **command, int *f_in, int *f_out)
17{
18 pid_t pid;
19 int to_child_pipe[2];
20 int from_child_pipe[2];
21 extern int blocking_io;
22
23 if (verbose >= 2) {
24 print_child_argv(command);
25 }
26
27 if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
28 rprintf(FERROR, "pipe: %s\n", strerror(errno));
29 exit_cleanup(RERR_IPC);
30 }
31
32
33 pid = do_fork();
34 if (pid == -1) {
35 rprintf(FERROR, "fork: %s\n", strerror(errno));
36 exit_cleanup(RERR_IPC);
37 }
38
39 if (pid == 0) {
40 extern int orig_umask;
41 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
42 close(to_child_pipe[1]) < 0 ||
43 close(from_child_pipe[0]) < 0 ||
44 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
45 rprintf(FERROR, "Failed to dup/close : %s\n",
46 strerror(errno));
47 exit_cleanup(RERR_IPC);
48 }
49 if (to_child_pipe[0] != STDIN_FILENO)
50 close(to_child_pipe[0]);
51 if (from_child_pipe[1] != STDOUT_FILENO)
52 close(from_child_pipe[1]);
53 umask(orig_umask);
54 set_blocking(STDIN_FILENO);
55 if (blocking_io) {
56 set_blocking(STDOUT_FILENO);
57 }
58 execvp(command[0], command);
59 rprintf(FERROR, "Failed to exec %s : %s\n",
60 command[0], strerror(errno));
61 exit_cleanup(RERR_IPC);
62 }
63
64 if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
65 rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
66 exit_cleanup(RERR_IPC);
67 }
68
69 *f_in = from_child_pipe[0];
70 *f_out = to_child_pipe[1];
71
72 return pid;
73}
74
75pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
76 int (*child_main)(int, char **))
77{
78 pid_t pid;
79 int to_child_pipe[2];
80 int from_child_pipe[2];
81 extern int read_batch; /* dw */
82
83 if (fd_pair(to_child_pipe) < 0 ||
84 fd_pair(from_child_pipe) < 0) {
85 rprintf(FERROR,"pipe: %s\n",strerror(errno));
86 exit_cleanup(RERR_IPC);
87 }
88
89
90 pid = do_fork();
91 if (pid == -1) {
92 rprintf(FERROR,"fork: %s\n",strerror(errno));
93 exit_cleanup(RERR_IPC);
94 }
95
96 if (pid == 0) {
97 extern int am_sender;
98 extern int am_server;
99
100 am_sender = read_batch ? 0 : !am_sender;
101 am_server = 1;
102
103 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
104 close(to_child_pipe[1]) < 0 ||
105 close(from_child_pipe[0]) < 0 ||
106 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
107 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
108 exit_cleanup(RERR_IPC);
109 }
110 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
111 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
112 child_main(argc, argv);
113 }
114
115 if (close(from_child_pipe[1]) < 0 ||
116 close(to_child_pipe[0]) < 0) {
117 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
118 exit_cleanup(RERR_IPC);
119 }
120
121 *f_in = from_child_pipe[0];
122 *f_out = to_child_pipe[1];
123
124 return pid;
125}
126
127