Split code out into separate files and remove some global variables to
[rsync.git] / pipe.c
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  **/
16 pid_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
75 pid_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