Decided on a better option name --itemize-changes (-i).
[rsync/rsync.git] / main.c
CommitLineData
0ba48136 1/* -*- c-file-style: "linux" -*-
d9c7edf6 2
50135767 3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
c627d613 4 Copyright (C) Paul Mackerras 1996
e5a2b854 5 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
d9c7edf6 6
c627d613
AT
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
d9c7edf6 11
c627d613
AT
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
d9c7edf6 16
c627d613
AT
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rsync.h"
23
f0fca04e 24time_t starttime = 0;
a800434a 25
b35d0d8e 26extern struct stats stats;
32eda096 27extern int am_root;
d9c7edf6
WD
28extern int am_server;
29extern int am_sender;
b695f242 30extern int am_generator;
d9c7edf6 31extern int am_daemon;
7a6421fa 32extern int verbose;
b78296cb 33extern int itemize_changes;
32eda096 34extern int blocking_io;
48a1ff0d 35extern int delete_before;
32eda096
WD
36extern int daemon_over_rsh;
37extern int do_stats;
38extern int dry_run;
39extern int list_only;
32eda096
WD
40extern int log_got_error;
41extern int module_id;
42extern int orig_umask;
bb6721dc 43extern int copy_links;
83926d3c 44extern int keep_dirlinks;
32eda096 45extern int preserve_hard_links;
d04e9c51 46extern int protocol_version;
32eda096 47extern int recurse;
06b96ffa 48extern int fuzzy_basis;
32eda096
WD
49extern int relative_paths;
50extern int rsync_port;
b1df18d7 51extern int whole_file;
32eda096
WD
52extern int read_batch;
53extern int write_batch;
b9f592fb 54extern int batch_fd;
c0d8e84c 55extern int batch_gen_fd;
32eda096
WD
56extern int filesfrom_fd;
57extern pid_t cleanup_child_pid;
58extern char *files_from;
59extern char *remote_filesfrom_file;
7162c65d 60extern char *partial_dir;
c3fad2e2 61extern char *basis_dir[];
32eda096
WD
62extern char *rsync_path;
63extern char *shell_cmd;
9b3318b0 64extern char *batch_name;
57dee64e
WD
65
66int local_server = 0;
c627d613 67
91c5833b
WD
68/* There's probably never more than at most 2 outstanding child processes,
69 * but set it higher, just in case. */
ee7118a8
DD
70#define MAXCHILDPROCS 5
71
72struct pid_status {
73 pid_t pid;
74 int status;
75} pid_stat_table[MAXCHILDPROCS];
76
e5a2b854 77static void show_malloc_stats(void);
82980a23
AT
78
79/****************************************************************************
80wait for a process to exit, calling io_flush while waiting
81****************************************************************************/
82void wait_process(pid_t pid, int *status)
83{
ee7118a8
DD
84 pid_t waited_pid;
85 int cnt;
86
87 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
a24c6870 88 msleep(20);
f1e3656e 89 io_flush(FULL_FLUSH);
82980a23 90 }
d9c7edf6 91
6fb812f7 92 if (waited_pid == -1 && errno == ECHILD) {
ee7118a8
DD
93 /* status of requested child no longer available.
94 * check to see if it was processed by the sigchld_handler.
95 */
96 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
97 if (pid == pid_stat_table[cnt].pid) {
98 *status = pid_stat_table[cnt].status;
99 pid_stat_table[cnt].pid = 0;
100 break;
101 }
102 }
103 }
104
d9c7edf6
WD
105 /* TODO: If the child exited on a signal, then log an
106 * appropriate error message. Perhaps we should also accept a
107 * message describing the purpose of the child. Also indicate
108 * this to the caller so that thhey know something went
109 * wrong. */
82980a23
AT
110 *status = WEXITSTATUS(*status);
111}
112
b9f592fb
WD
113/* This function gets called from all 3 processes. We want the client side
114 * to actually output the text, but the sender is the only process that has
115 * all the stats we need. So, if we're a client sender, we do the report.
116 * If we're a server sender, we write the stats on the supplied fd. If
117 * we're the client receiver we read the stats from the supplied fd and do
118 * the report. All processes might also generate a set of debug stats, if
119 * the verbose level is high enough (this is the only thing that the
120 * generator process and the server receiver ever do here). */
c627d613
AT
121static void report(int f)
122{
b9f592fb
WD
123 /* Cache two stats because the read/write code can change it. */
124 int64 total_read = stats.total_read;
125 int64 total_written = stats.total_written;
7a6421fa 126 time_t t = time(NULL);
7a6421fa 127
7bb7058e 128 if (do_stats && verbose > 1) {
5c15e29f 129 /* These come out from every process */
7bb7058e 130 show_malloc_stats();
86943126 131 show_flist_stats();
5c15e29f
MP
132 }
133
e5fbaa71
S
134 if (am_generator)
135 return;
136
248fbb8c 137 if (am_daemon) {
a9766ef1 138 log_exit(0, __FILE__, __LINE__);
83926d3c
WD
139 if (f == -1 || !am_sender)
140 return;
248fbb8c
AT
141 }
142
e19452a9 143 if (am_server) {
3e491682 144 if (am_sender) {
b9f592fb
WD
145 write_longint(f, total_read);
146 write_longint(f, total_written);
147 write_longint(f, stats.total_size);
f0f7e760
WD
148 if (protocol_version >= 29) {
149 write_longint(f, stats.flist_buildtime);
150 write_longint(f, stats.flist_xfertime);
151 }
e19452a9 152 }
7a6421fa
AT
153 return;
154 }
e19452a9
DD
155
156 /* this is the client */
d9c7edf6 157
3e491682 158 if (!am_sender) {
58c5c245
WD
159 /* Read the first two in opposite order because the meaning of
160 * read/write swaps when switching from sender to receiver. */
b9f592fb
WD
161 total_written = read_longint(f);
162 total_read = read_longint(f);
a800434a 163 stats.total_size = read_longint(f);
f0f7e760
WD
164 if (protocol_version >= 29) {
165 stats.flist_buildtime = read_longint(f);
166 stats.flist_xfertime = read_longint(f);
167 }
b9f592fb
WD
168 } else if (write_batch) {
169 /* The --read-batch process is going to be a client
170 * receiver, so we need to give it the stats. */
171 write_longint(batch_fd, total_read);
172 write_longint(batch_fd, total_written);
173 write_longint(batch_fd, stats.total_size);
f0f7e760
WD
174 if (protocol_version >= 29) {
175 write_longint(batch_fd, stats.flist_buildtime);
176 write_longint(batch_fd, stats.flist_xfertime);
177 }
a800434a
AT
178 }
179
180 if (do_stats) {
1f658d42 181 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
d9c7edf6
WD
182 rprintf(FINFO,"Number of files transferred: %d\n",
183 stats.num_transferred_files);
184 rprintf(FINFO,"Total file size: %.0f bytes\n",
185 (double)stats.total_size);
186 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
187 (double)stats.total_transferred_size);
188 rprintf(FINFO,"Literal data: %.0f bytes\n",
189 (double)stats.literal_data);
190 rprintf(FINFO,"Matched data: %.0f bytes\n",
191 (double)stats.matched_data);
1f658d42 192 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
f0f7e760
WD
193 if (stats.flist_buildtime) {
194 rprintf(FINFO,
195 "File list generation time: %.3f seconds\n",
196 (double)stats.flist_buildtime / 1000);
197 rprintf(FINFO,
198 "File list transfer time: %.3f seconds\n",
199 (double)stats.flist_xfertime / 1000);
200 }
4de2a174 201 rprintf(FINFO,"Total bytes sent: %.0f\n",
b9f592fb 202 (double)total_written);
4de2a174 203 rprintf(FINFO,"Total bytes received: %.0f\n",
b9f592fb 204 (double)total_read);
7a6421fa 205 }
d9c7edf6 206
e19452a9 207 if (verbose || do_stats) {
b9f592fb 208 rprintf(FINFO,
4de2a174 209 "\nsent %.0f bytes received %.0f bytes %.2f bytes/sec\n",
b9f592fb
WD
210 (double)total_written, (double)total_read,
211 (total_written + total_read)/(0.5 + (t - starttime)));
212 rprintf(FINFO, "total size is %.0f speedup is %.2f\n",
d9c7edf6 213 (double)stats.total_size,
b9f592fb 214 (double)stats.total_size / (total_written+total_read));
e19452a9 215 }
fc8a6b97
AT
216
217 fflush(stdout);
218 fflush(stderr);
c627d613
AT
219}
220
221
e5a2b854
MP
222/**
223 * If our C library can get malloc statistics, then show them to FINFO
224 **/
225static void show_malloc_stats(void)
226{
4f5b0756 227#ifdef HAVE_MALLINFO
e5a2b854
MP
228 struct mallinfo mi;
229
230 mi = mallinfo();
231
ce672562 232 rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
f846a9bf
WD
233 getpid(), am_server ? "server " : "",
234 am_daemon ? "daemon " : "", who_am_i());
235 rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
236 (long)mi.arena);
237 rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n",
238 (long)mi.ordblks);
239 rprintf(FINFO, " smblks: %10ld\n",
240 (long)mi.smblks);
241 rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n",
242 (long)mi.hblks);
243 rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n",
244 (long)mi.hblkhd);
245 rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n",
246 (long)mi.arena + mi.hblkhd);
247 rprintf(FINFO, " usmblks: %10ld\n",
248 (long)mi.usmblks);
249 rprintf(FINFO, " fsmblks: %10ld\n",
250 (long)mi.fsmblks);
251 rprintf(FINFO, " uordblks: %10ld (bytes used)\n",
252 (long)mi.uordblks);
253 rprintf(FINFO, " fordblks: %10ld (bytes free)\n",
254 (long)mi.fordblks);
255 rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n",
256 (long)mi.keepcost);
e5a2b854
MP
257#endif /* HAVE_MALLINFO */
258}
259
260
0882faa2 261/* Start the remote shell. cmd may be NULL to use the default. */
6c2e5b56
WD
262static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
263 int *f_in, int *f_out)
c627d613 264{
6c2e5b56 265 int i, argc = 0;
887e553f 266 char *args[MAX_ARGS];
19b27a48 267 pid_t ret;
6c2e5b56 268 char *tok, *dir = NULL;
bb4aa89c 269 int dash_l_set = 0;
366345fe 270
088aac85 271 if (!read_batch && !local_server) {
9af87151 272 char *rsh_env = getenv(RSYNC_RSH_ENV);
366345fe 273 if (!cmd)
9af87151 274 cmd = rsh_env;
366345fe
AT
275 if (!cmd)
276 cmd = RSYNC_RSH;
277 cmd = strdup(cmd);
d9c7edf6 278 if (!cmd)
366345fe
AT
279 goto oom;
280
887e553f 281 for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
e7a392c7
WD
282 /* Comparison leaves rooms for server_options(). */
283 if (argc >= MAX_ARGS - 100) {
284 rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
887e553f
WD
285 exit_cleanup(RERR_SYNTAX);
286 }
366345fe 287 args[argc++] = tok;
887e553f 288 }
c627d613 289
d9c7edf6 290 /* check to see if we've already been given '-l user' in
9af87151 291 * the remote-shell command */
bb4aa89c
WD
292 for (i = 0; i < argc-1; i++) {
293 if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
294 dash_l_set = 1;
295 }
296
4f5b0756 297#ifdef HAVE_REMSH
366345fe
AT
298 /* remsh (on HPUX) takes the arguments the other way around */
299 args[argc++] = machine;
bb4aa89c 300 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
301 args[argc++] = "-l";
302 args[argc++] = user;
303 }
7b8356d0 304#else
bb4aa89c 305 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
306 args[argc++] = "-l";
307 args[argc++] = user;
308 }
309 args[argc++] = machine;
7b8356d0 310#endif
c627d613 311
366345fe 312 args[argc++] = rsync_path;
c627d613 313
9af87151 314 if (blocking_io < 0) {
90e22f4b
WD
315 char *cp;
316 if ((cp = strrchr(cmd, '/')) != NULL)
317 cp++;
318 else
319 cp = cmd;
320 if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
321 blocking_io = 1;
66b71163 322 }
e384bfbd 323
93689aa5 324 server_options(args,&argc);
e7a392c7
WD
325
326 if (argc >= MAX_ARGS - 2) {
327 rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
328 exit_cleanup(RERR_SYNTAX);
329 }
366345fe 330 }
c627d613 331
366345fe 332 args[argc++] = ".";
76076c4b 333
d9c7edf6 334 if (!daemon_over_rsh && path && *path)
366345fe 335 args[argc++] = path;
c627d613 336
366345fe 337 args[argc] = NULL;
c627d613 338
366345fe 339 if (verbose > 3) {
9486289c 340 rprintf(FINFO,"cmd=");
e7a392c7 341 for (i = 0; i < argc; i++)
71903f60 342 rprintf(FINFO, "%s ", safe_fname(args[i]));
9486289c 343 rprintf(FINFO,"\n");
366345fe
AT
344 }
345
c0d8e84c
WD
346 if (read_batch) {
347 int from_gen_pipe[2];
348 if (fd_pair(from_gen_pipe) < 0) {
349 rsyserr(FERROR, errno, "pipe");
350 exit_cleanup(RERR_IPC);
351 }
352 batch_gen_fd = from_gen_pipe[0];
353 *f_out = from_gen_pipe[1];
354 *f_in = batch_fd;
355 ret = -1; /* no child pid */
356 } else if (local_server) {
b1df18d7
WD
357 /* If the user didn't request --[no-]whole-file, force
358 * it on, but only if we're not batch processing. */
c0d8e84c 359 if (whole_file < 0 && !write_batch)
b1df18d7 360 whole_file = 1;
25d34a5c 361 ret = local_child(argc, args, f_in, f_out, child_main);
c0d8e84c 362 } else
366345fe 363 ret = piped_child(args,f_in,f_out);
c627d613 364
3a69fad0
WD
365 if (dir)
366 free(dir);
82306bf6 367
366345fe 368 return ret;
c627d613
AT
369
370oom:
366345fe
AT
371 out_of_memory("do_cmd");
372 return 0; /* not reached */
c627d613
AT
373}
374
375
c627d613
AT
376static char *get_local_name(struct file_list *flist,char *name)
377{
7a6421fa 378 STRUCT_STAT st;
87cc45e1 379 int e;
c627d613 380
c95da96a 381 if (verbose > 2)
d9c7edf6 382 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
383 flist->count, NS(name));
384
d9c7edf6 385 if (!name)
1f0610ef 386 return NULL;
c95da96a 387
1ff5450d
AT
388 if (do_stat(name,&st) == 0) {
389 if (S_ISDIR(st.st_mode)) {
59187666 390 if (!push_dir(name)) {
982e05bb
WD
391 rsyserr(FERROR, errno, "push_dir#1 %s failed",
392 full_fname(name));
65417579 393 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
394 }
395 return NULL;
396 }
397 if (flist->count > 1) {
398 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 399 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
400 }
401 return name;
402 }
403
87cc45e1 404 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
1ff5450d
AT
405 return name;
406
1ff5450d 407 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
982e05bb 408 rsyserr(FERROR, errno, "mkdir %s failed", full_fname(name));
65417579 409 exit_cleanup(RERR_FILEIO);
e5a96f0f
WD
410 }
411 if (verbose > 0)
71903f60 412 rprintf(FINFO, "created directory %s\n", safe_fname(name));
e5a96f0f
WD
413
414 if (dry_run) {
415 dry_run++;
416 return NULL;
1ff5450d
AT
417 }
418
59187666 419 if (!push_dir(name)) {
982e05bb
WD
420 rsyserr(FERROR, errno, "push_dir#2 %s failed",
421 full_fname(name));
65417579 422 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
423 }
424
425 return NULL;
c627d613
AT
426}
427
428
9486289c 429static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 430{
7a6421fa
AT
431 int i;
432 struct file_list *flist;
433 char *dir = argv[0];
c627d613 434
45e08edb
WD
435 if (verbose > 2) {
436 rprintf(FINFO, "server_sender starting pid=%ld\n",
437 (long)getpid());
438 }
d9c7edf6 439
2adbcdc7 440 if (am_daemon && lp_write_only(module_id)) {
7a92ded3
WD
441 rprintf(FERROR, "ERROR: module is write only\n");
442 exit_cleanup(RERR_SYNTAX);
443 return;
444 }
445
59187666 446 if (!relative_paths && !push_dir(dir)) {
982e05bb
WD
447 rsyserr(FERROR, errno, "push_dir#3 %s failed",
448 full_fname(dir));
65417579 449 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
450 }
451 argc--;
452 argv++;
d9c7edf6 453
7a6421fa
AT
454 if (strcmp(dir,".")) {
455 int l = strlen(dir);
d9c7edf6 456 if (strcmp(dir,"/") == 0)
7a6421fa 457 l = 0;
e7a392c7 458 for (i = 0; i < argc; i++)
7a6421fa
AT
459 argv[i] += l+1;
460 }
c627d613 461
48a1ff0d 462 if (argc == 0 && (recurse || list_only)) {
e1f67417 463 argc = 1;
7a6421fa
AT
464 argv--;
465 argv[0] = ".";
466 }
d9c7edf6 467
7a6421fa 468 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
469 if (!flist || flist->count == 0) {
470 exit_cleanup(0);
471 }
472
da3478b2
WD
473 io_start_buffering_in();
474 io_start_buffering_out();
475
7a6421fa 476 send_files(flist,f_out,f_in);
f1e3656e 477 io_flush(FULL_FLUSH);
7a6421fa 478 report(f_out);
d04e9c51 479 if (protocol_version >= 24) {
d9c7edf6 480 /* final goodbye message */
64c3523a
WD
481 read_int(f_in);
482 }
f1e3656e 483 io_flush(FULL_FLUSH);
7a6421fa 484 exit_cleanup(0);
c627d613
AT
485}
486
487
dc5ddbcc
AT
488static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
489{
d186eb1a 490 int pid;
e1f67417 491 int status = 0;
41cfde6b 492 int error_pipe[2], name_pipe[2];
06b96ffa
WD
493 BOOL need_name_pipe = (basis_dir[0] || partial_dir || fuzzy_basis)
494 && !dry_run;
dc5ddbcc 495
bb6721dc
WD
496 /* The receiving side mustn't obey this, or an existing symlink that
497 * points to an identical file won't be replaced by the referent. */
498 copy_links = 0;
499
d186eb1a
AT
500 if (preserve_hard_links)
501 init_hard_links(flist);
dc5ddbcc 502
864146de
WD
503 if (delete_before && !local_name && flist->count > 0) {
504 /* Moved here from recv_files() to prevent a race condition */
505 delete_files(flist);
6957ae33
AT
506 }
507
41cfde6b
WD
508 if (fd_pair(error_pipe) < 0
509 || (need_name_pipe && fd_pair(name_pipe) < 0)) {
ab759cd2 510 rsyserr(FERROR, errno, "pipe failed in do_recv");
c8f2f857 511 exit_cleanup(RERR_IPC);
554e0a8d 512 }
d9c7edf6 513
f1e3656e 514 io_flush(NORMAL_FLUSH);
c6e7fcb4 515
ba449e44 516 if ((pid = do_fork()) == -1) {
c8f2f857 517 rsyserr(FERROR, errno, "fork failed in do_recv");
ba449e44
WD
518 exit_cleanup(RERR_IPC);
519 }
520
521 if (pid == 0) {
554e0a8d 522 close(error_pipe[0]);
41cfde6b
WD
523 if (need_name_pipe) {
524 close(name_pipe[1]);
525 set_blocking(name_pipe[0]);
526 } else
527 name_pipe[0] = -1;
3a69fad0
WD
528 if (f_in != f_out)
529 close(f_out);
e08c9610 530
554e0a8d 531 /* we can't let two processes write to the socket at one time */
9eeb3b9c 532 close_multiplexing_out();
554e0a8d
AT
533
534 /* set place to send errors */
f1e3656e 535 set_msg_fd_out(error_pipe[1]);
554e0a8d 536
41cfde6b 537 recv_files(f_in, flist, local_name, name_pipe[0]);
f1e3656e 538 io_flush(FULL_FLUSH);
ba5e128d 539 report(f_in);
e08c9610 540
f1e3656e
WD
541 send_msg(MSG_DONE, "", 0);
542 io_flush(FULL_FLUSH);
4a748188 543 /* finally we go to sleep until our parent kills us
9af87151
WD
544 * with a USR2 signal. We sleep for a short time as on
545 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
546 while (1)
547 msleep(20);
d186eb1a 548 }
dc5ddbcc 549
b695f242 550 am_generator = 1;
9eeb3b9c 551 close_multiplexing_in();
b9f592fb
WD
552 if (write_batch)
553 stop_write_batch();
b695f242 554
554e0a8d 555 close(error_pipe[1]);
41cfde6b
WD
556 if (need_name_pipe) {
557 close(name_pipe[0]);
558 set_nonblocking(name_pipe[1]);
559 } else
560 name_pipe[1] = -1;
3a69fad0
WD
561 if (f_in != f_out)
562 close(f_in);
e1b3d5c4 563
da3478b2 564 io_start_buffering_out();
b3e10ed7 565
f1e3656e 566 set_msg_fd_in(error_pipe[0]);
554e0a8d 567
41cfde6b 568 generate_files(f_out, flist, local_name, name_pipe[1]);
8d9dc9f9 569
e5fbaa71 570 report(-1);
f1e3656e 571 io_flush(FULL_FLUSH);
d04e9c51 572 if (protocol_version >= 24) {
8ada7518
AT
573 /* send a final goodbye message */
574 write_int(f_out, -1);
575 }
f1e3656e 576 io_flush(FULL_FLUSH);
8ada7518 577
f1e3656e 578 set_msg_fd_in(-1);
089a2435 579 kill(pid, SIGUSR2);
d79d1c69 580 wait_process(pid, &status);
d186eb1a 581 return status;
dc5ddbcc
AT
582}
583
c627d613 584
9486289c 585static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 586{
7a6421fa
AT
587 int status;
588 struct file_list *flist;
6c2e5b56 589 char *local_name = NULL;
7a6421fa 590 char *dir = NULL;
07bff66f
WD
591 int save_verbose = verbose;
592
593 if (filesfrom_fd >= 0) {
594 /* We can't mix messages with files-from data on the socket,
595 * so temporarily turn off verbose messages. */
596 verbose = 0;
597 }
f0fca04e 598
45e08edb
WD
599 if (verbose > 2) {
600 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
601 argc, (long)getpid());
602 }
09b7f5db 603
2adbcdc7 604 if (am_daemon && lp_read_only(module_id)) {
09b7f5db
AT
605 rprintf(FERROR,"ERROR: module is read only\n");
606 exit_cleanup(RERR_SYNTAX);
607 return;
608 }
609
d9c7edf6 610
7a6421fa
AT
611 if (argc > 0) {
612 dir = argv[0];
613 argc--;
614 argv++;
59187666 615 if (!am_daemon && !push_dir(dir)) {
982e05bb
WD
616 rsyserr(FERROR, errno, "push_dir#4 %s failed",
617 full_fname(dir));
65417579 618 exit_cleanup(RERR_FILESELECT);
d9c7edf6 619 }
7a6421fa 620 }
c627d613 621
da3478b2 622 io_start_buffering_in();
57dee64e 623 recv_filter_list(f_in);
c627d613 624
7c2a9e76 625 if (filesfrom_fd >= 0) {
07bff66f
WD
626 /* We need to send the files-from names to the sender at the
627 * same time that we receive the file-list from them, so we
628 * need the IO routines to automatically write out the names
629 * onto our f_out socket as we read the file-list. This
630 * avoids both deadlock and extra delays/buffers. */
7c2a9e76
WD
631 io_set_filesfrom_fds(filesfrom_fd, f_out);
632 filesfrom_fd = -1;
633 }
634
b9f592fb 635 flist = recv_file_list(f_in);
07bff66f 636 verbose = save_verbose;
4c36a13e
AT
637 if (!flist) {
638 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 639 exit_cleanup(RERR_FILESELECT);
7a6421fa 640 }
d9c7edf6
WD
641
642 if (argc > 0) {
7a6421fa
AT
643 if (strcmp(dir,".")) {
644 argv[0] += strlen(dir);
3a69fad0
WD
645 if (argv[0][0] == '/')
646 argv[0]++;
7a6421fa
AT
647 }
648 local_name = get_local_name(flist,argv[0]);
649 }
c627d613 650
7a6421fa
AT
651 status = do_recv(f_in,f_out,flist,local_name);
652 exit_cleanup(status);
c627d613
AT
653}
654
655
734a94a2 656int child_main(int argc, char *argv[])
25d34a5c
MP
657{
658 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 659 return 0;
25d34a5c
MP
660}
661
662
9486289c 663void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 664{
f0359dd0
AT
665 set_nonblocking(f_in);
666 set_nonblocking(f_out);
667
da3478b2
WD
668 io_set_sock_fds(f_in, f_out);
669 setup_protocol(f_out, f_in);
670
d04e9c51 671 if (protocol_version >= 23)
da3478b2 672 io_start_multiplex_out();
7a6421fa 673
7a6421fa 674 if (am_sender) {
83926d3c 675 keep_dirlinks = 0; /* Must be disabled on the sender. */
9b3318b0 676
7842418b 677 recv_filter_list(f_in);
7a6421fa
AT
678 do_server_sender(f_in, f_out, argc, argv);
679 } else {
680 do_server_recv(f_in, f_out, argc, argv);
681 }
682 exit_cleanup(0);
366345fe
AT
683}
684
0ba48136
MP
685
686/*
687 * This is called once the connection has been negotiated. It is used
688 * for rsyncd, remote-shell, and local connections.
689 */
19b27a48 690int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 691{
088aac85 692 struct file_list *flist = NULL;
9486289c
AT
693 int status = 0, status2 = 0;
694 char *local_name = NULL;
19b27a48
AT
695
696 cleanup_child_pid = pid;
67a28eb2 697 if (!read_batch) {
b9f592fb
WD
698 set_nonblocking(f_in);
699 set_nonblocking(f_out);
700 }
f0359dd0 701
da3478b2 702 io_set_sock_fds(f_in, f_out);
6d7b6081
AT
703 setup_protocol(f_out,f_in);
704
b9f592fb 705 if (protocol_version >= 23 && !read_batch)
da3478b2 706 io_start_multiplex_in();
d9c7edf6 707
18882701
WD
708 /* We set our stderr file handle to blocking because ssh might have
709 * set it to non-blocking. This can be particularly troublesome if
710 * stderr is a clone of stdout, because ssh would have set our stdout
711 * to non-blocking at the same time (which can easily cause us to lose
712 * output from our print statements). This kluge shouldn't cause ssh
713 * any problems for how we use it. Note also that we delayed setting
714 * this until after the above protocol setup so that we know for sure
715 * that ssh is done twiddling its file descriptors. */
716 set_blocking(STDERR_FILENO);
717
9486289c 718 if (am_sender) {
83926d3c 719 keep_dirlinks = 0; /* Must be disabled on the sender. */
da3478b2 720 io_start_buffering_out();
a0a33ee5
WD
721 if (!remote_filesfrom_file)
722 set_msg_fd_in(f_in);
57dee64e 723 send_filter_list(f_out);
7c2a9e76
WD
724 if (remote_filesfrom_file)
725 filesfrom_fd = f_in;
b9f592fb
WD
726
727 if (write_batch)
728 start_write_batch(f_out);
64c3523a 729 if (!read_batch) /* don't write to pipe */
d9c7edf6 730 flist = send_file_list(f_out,argc,argv);
a0a33ee5 731 set_msg_fd_in(-1);
d9c7edf6 732 if (verbose > 3)
9486289c 733 rprintf(FINFO,"file list sent\n");
e1b3d5c4 734
f1e3656e 735 io_flush(NORMAL_FLUSH);
9486289c 736 send_files(flist,f_out,f_in);
f1e3656e 737 io_flush(FULL_FLUSH);
d04e9c51 738 if (protocol_version >= 24) {
d9c7edf6 739 /* final goodbye message */
6c65e146
AT
740 read_int(f_in);
741 }
9486289c
AT
742 if (pid != -1) {
743 if (verbose > 3)
08a740ff 744 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 745 io_flush(FULL_FLUSH);
d79d1c69 746 wait_process(pid, &status);
9486289c 747 }
3d382777 748 report(-1);
f1e3656e 749 io_flush(FULL_FLUSH);
9486289c
AT
750 exit_cleanup(status);
751 }
f7632fc6 752
48a1ff0d
WD
753 if (argc == 0)
754 list_only |= 1;
d9c7edf6 755
57dee64e 756 send_filter_list(read_batch ? -1 : f_out);
d9c7edf6 757
7c2a9e76
WD
758 if (filesfrom_fd >= 0) {
759 io_set_filesfrom_fds(filesfrom_fd, f_out);
760 filesfrom_fd = -1;
761 }
762
b9f592fb
WD
763 if (write_batch)
764 start_write_batch(f_in);
9486289c
AT
765 flist = recv_file_list(f_in);
766 if (!flist || flist->count == 0) {
796d484b 767 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
768 "perhaps you need to specify some filenames or "
769 "the --recursive option?\n");
9486289c
AT
770 exit_cleanup(0);
771 }
d9c7edf6 772
9486289c 773 local_name = get_local_name(flist,argv[0]);
d9c7edf6 774
9486289c 775 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 776
9486289c 777 if (pid != -1) {
8d9dc9f9 778 if (verbose > 3)
08a740ff 779 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 780 io_flush(FULL_FLUSH);
d79d1c69 781 wait_process(pid, &status);
9486289c 782 }
d9c7edf6 783
ff81e809 784 return MAX(status, status2);
9486289c
AT
785}
786
7169bb4a
MP
787static int copy_argv (char *argv[])
788{
789 int i;
790
791 for (i = 0; argv[i]; i++) {
792 if (!(argv[i] = strdup(argv[i]))) {
793 rprintf (FERROR, "out of memory at %s(%d)\n",
794 __FILE__, __LINE__);
795 return RERR_MALLOC;
796 }
797 }
798
799 return 0;
800}
801
802
c1a04ecb 803/**
0ba48136
MP
804 * Start a client for either type of remote connection. Work out
805 * whether the arguments request a remote shell or rsyncd connection,
806 * and call the appropriate connection function, then run_client.
0b4af330
MP
807 *
808 * Calls either start_socket_client (for sockets) or do_cmd and
809 * client_run (for ssh).
c1a04ecb 810 **/
fc8a6b97 811static int start_client(int argc, char *argv[])
5d6bcd44
AT
812{
813 char *p;
814 char *shell_machine = NULL;
815 char *shell_path = NULL;
816 char *shell_user = NULL;
19b27a48
AT
817 int ret;
818 pid_t pid;
5d6bcd44 819 int f_in,f_out;
7169bb4a
MP
820 int rc;
821
822 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 823 * command line. */
75aeac44 824 if ((rc = copy_argv(argv)))
7169bb4a 825 return rc;
5d6bcd44 826
75aeac44 827 /* rsync:// always uses rsync server over direct socket connection */
b9f592fb
WD
828 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0
829 && !read_batch) {
f7632fc6
AT
830 char *host, *path;
831
7169bb4a 832 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
833 p = strchr(host,'/');
834 if (p) {
50b31539 835 *p = '\0';
f7632fc6 836 path = p+1;
50b31539 837 } else
a125c82a 838 path = "";
50b31539
WD
839 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
840 host++;
841 *p++ = '\0';
842 if (*p != ':')
843 p = NULL;
844 } else
845 p = strchr(host, ':');
2acf81eb
DD
846 if (p) {
847 rsync_port = atoi(p+1);
50b31539 848 *p = '\0';
cf510ad2 849 }
f7632fc6
AT
850 return start_socket_client(host, path, argc-1, argv+1);
851 }
852
d16c245f 853 if (!read_batch) { /* for read_batch, NO source is specified */
a125c82a 854 p = find_colon(argv[0]);
d16c245f 855 if (p) { /* source is remote */
7c2a9e76
WD
856 if (remote_filesfrom_file
857 && remote_filesfrom_file != files_from + 1
858 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
859 rprintf(FERROR,
50b31539 860 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
861 exit_cleanup(RERR_SYNTAX);
862 }
d9c7edf6
WD
863 if (p[1] == ':') { /* double colon */
864 *p = 0;
865 if (!shell_cmd) {
866 return start_socket_client(argv[0], p+2,
867 argc-1, argv+1);
868 }
869 p++;
870 daemon_over_rsh = 1;
75aeac44 871 }
3591c066 872
d16c245f 873 if (argc < 1) { /* destination required */
d9c7edf6
WD
874 usage(FERROR);
875 exit_cleanup(RERR_SYNTAX);
876 }
a125c82a 877
d9c7edf6
WD
878 am_sender = 0;
879 *p = 0;
880 shell_machine = argv[0];
881 shell_path = p+1;
d9c7edf6 882 argv++;
d16c245f 883 } else { /* source is local */
d9c7edf6
WD
884 am_sender = 1;
885
886 /* rsync:// destination uses rsync server over direct socket */
887 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
888 char *host, *path;
889
890 host = argv[argc-1] + strlen(URL_PREFIX);
891 p = strchr(host,'/');
892 if (p) {
50b31539 893 *p = '\0';
d9c7edf6 894 path = p+1;
50b31539 895 } else
d9c7edf6 896 path = "";
50b31539
WD
897 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
898 host++;
899 *p++ = '\0';
900 if (*p != ':')
901 p = NULL;
902 } else
903 p = strchr(host, ':');
d9c7edf6
WD
904 if (p) {
905 rsync_port = atoi(p+1);
50b31539 906 *p = '\0';
cf510ad2 907 }
d9c7edf6 908 return start_socket_client(host, path, argc-1, argv);
a125c82a 909 }
d9c7edf6 910
d16c245f 911 p = find_colon(argv[argc-1]); /* look in dest arg */
7c2a9e76
WD
912 if (p && remote_filesfrom_file
913 && remote_filesfrom_file != files_from + 1
914 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
915 rprintf(FERROR,
50b31539 916 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
917 exit_cleanup(RERR_SYNTAX);
918 }
d16c245f 919 if (!p) { /* no colon found, so src & dest are local */
d9c7edf6 920 local_server = 1;
7c2a9e76
WD
921 if (remote_filesfrom_file) {
922 rprintf(FERROR,
50b31539 923 "--files-from cannot be remote when the transfer is local\n");
7c2a9e76
WD
924 exit_cleanup(RERR_SYNTAX);
925 }
d9c7edf6 926 } else if (p[1] == ':') { /* double colon */
a125c82a 927 *p = 0;
d9c7edf6
WD
928 if (!shell_cmd) {
929 return start_socket_client(argv[argc-1], p+2,
930 argc-1, argv);
931 }
932 p++;
933 daemon_over_rsh = 1;
a125c82a 934 }
a125c82a 935
d9c7edf6
WD
936 if (argc < 2) {
937 usage(FERROR);
938 exit_cleanup(RERR_SYNTAX);
75aeac44 939 }
3591c066 940
d9c7edf6
WD
941 if (local_server) {
942 shell_machine = NULL;
943 shell_path = argv[argc-1];
944 } else {
945 *p = 0;
946 shell_machine = argv[argc-1];
947 shell_path = p+1;
948 }
5d6bcd44 949 }
d16c245f
WD
950 argc--;
951 } else { /* read_batch */
d9c7edf6
WD
952 local_server = 1;
953 shell_path = argv[argc-1];
b9f592fb
WD
954 if (find_colon(shell_path)) {
955 rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
956 exit_cleanup(RERR_SYNTAX);
957 }
6902ed17
MP
958 }
959
5d6bcd44 960 if (shell_machine) {
6fc048f4 961 p = strrchr(shell_machine,'@');
5d6bcd44
AT
962 if (p) {
963 *p = 0;
964 shell_user = shell_machine;
965 shell_machine = p+1;
966 }
967 }
968
969 if (verbose > 3) {
9486289c 970 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
71903f60
WD
971 shell_cmd ? safe_fname(shell_cmd) : "",
972 shell_machine ? safe_fname(shell_machine) : "",
973 shell_user ? safe_fname(shell_user) : "",
974 shell_path ? safe_fname(shell_path) : "");
5d6bcd44 975 }
d9c7edf6 976
d16c245f 977 /* for remote source, only single dest arg can remain ... */
f7632fc6 978 if (!am_sender && argc > 1) {
5d6bcd44 979 usage(FERROR);
65417579 980 exit_cleanup(RERR_SYNTAX);
5d6bcd44 981 }
27e3e9c9 982
d16c245f 983 /* ... or no dest at all */
48a1ff0d
WD
984 if (!am_sender && argc == 0)
985 list_only |= 1;
d9c7edf6 986
75aeac44
WD
987 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
988 &f_in,&f_out);
989
990 /* if we're running an rsync server on the remote host over a
9af87151 991 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
992 if (daemon_over_rsh) {
993 int tmpret;
994 tmpret = start_inband_exchange(shell_user, shell_path,
995 f_in, f_out, argc);
996 if (tmpret < 0)
997 return tmpret;
998 }
999
fc8a6b97
AT
1000 ret = client_run(f_in, f_out, pid, argc, argv);
1001
1002 fflush(stdout);
1003 fflush(stderr);
1004
1005 return ret;
5d6bcd44
AT
1006}
1007
366345fe 1008
067669da
WD
1009static RETSIGTYPE sigusr1_handler(UNUSED(int val))
1010{
65417579 1011 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
1012}
1013
067669da
WD
1014static RETSIGTYPE sigusr2_handler(UNUSED(int val))
1015{
19b27a48 1016 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
1017 _exit(0);
1018}
1019
067669da
WD
1020static RETSIGTYPE sigchld_handler(UNUSED(int val))
1021{
029c1713 1022#ifdef WNOHANG
ee7118a8
DD
1023 int cnt, status;
1024 pid_t pid;
1025 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 1026 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
1027 * out we're instead saving the child exit statuses for later use.
1028 * The waitpid() loop presumably eliminates all possibility of leaving
1029 * zombie children, maybe that's why he did it.
1030 */
1031 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
1032 /* save the child's exit status */
1033 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
1034 if (pid_stat_table[cnt].pid == 0) {
1035 pid_stat_table[cnt].pid = pid;
1036 pid_stat_table[cnt].status = status;
1037 break;
1038 }
1039 }
ee7118a8 1040 }
029c1713 1041#endif
19b27a48
AT
1042}
1043
c0531332
MP
1044
1045/**
1046 * This routine catches signals and tries to send them to gdb.
1047 *
1048 * Because it's called from inside a signal handler it ought not to
1049 * use too many library routines.
1050 *
1051 * @todo Perhaps use "screen -X" instead/as well, to help people
1052 * debugging without easy access to X. Perhaps use an environment
1053 * variable, or just call a script?
1054 *
1055 * @todo The /proc/ magic probably only works on Linux (and
1056 * Solaris?) Can we be more portable?
1057 **/
1058#ifdef MAINTAINER_MODE
4fdc39dd
MP
1059const char *get_panic_action(void)
1060{
1061 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
1062
1063 if (cmd_fmt)
1064 return cmd_fmt;
1065 else
1066 return "xterm -display :0 -T Panic -n Panic "
1067 "-e gdb /proc/%d/exe %d";
1068}
1069
1070
9fb3f7a9
MP
1071/**
1072 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
1073 *
1074 * This signal handler is only installed if we were configured with
1075 * --enable-maintainer-mode. Perhaps it should always be on and we
1076 * should just look at the environment variable, but I'm a bit leery
1077 * of a signal sending us into a busy loop.
1078 **/
067669da 1079static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
1080{
1081 char cmd_buf[300];
1082 int ret;
4fdc39dd
MP
1083
1084 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
1085 getpid(), getpid());
1086
1087 /* Unless we failed to execute gdb, we allow the process to
1088 * continue. I'm not sure if that's right. */
1089 ret = system(cmd_buf);
1090 if (ret)
1091 _exit(ret);
1092}
1093#endif
1094
1095
5d6bcd44 1096int main(int argc,char *argv[])
d9c7edf6 1097{
ff81e809 1098 int ret;
66a9dc96
WD
1099 int orig_argc = argc;
1100 char **orig_argv = argv;
5d6bcd44 1101
7a6421fa 1102 signal(SIGUSR1, sigusr1_handler);
8b35435f 1103 signal(SIGUSR2, sigusr2_handler);
19b27a48 1104 signal(SIGCHLD, sigchld_handler);
c0531332
MP
1105#ifdef MAINTAINER_MODE
1106 signal(SIGSEGV, rsync_panic_handler);
1107 signal(SIGFPE, rsync_panic_handler);
1108 signal(SIGABRT, rsync_panic_handler);
1109 signal(SIGBUS, rsync_panic_handler);
1110#endif /* def MAINTAINER_MODE */
5d6bcd44 1111
7a6421fa 1112 starttime = time(NULL);
6fe05820 1113 am_root = (MY_UID() == 0);
c627d613 1114
a800434a
AT
1115 memset(&stats, 0, sizeof(stats));
1116
df5e03da
AT
1117 if (argc < 2) {
1118 usage(FERROR);
65417579 1119 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
1120 }
1121
7a6421fa 1122 /* we set a 0 umask so that correct file permissions can be
9af87151 1123 * carried across */
7a6421fa 1124 orig_umask = (int)umask(0);
5d6bcd44 1125
50135767 1126 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
1127 /* FIXME: We ought to call the same error-handling
1128 * code here, rather than relying on getopt. */
50135767 1129 option_error();
65417579 1130 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1131 }
5d6bcd44 1132
7a6421fa 1133 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1134 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1135 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1136
34758d5c
MP
1137 /* Ignore SIGPIPE; we consistently check error codes and will
1138 * see the EPIPE. */
1139 signal(SIGPIPE, SIG_IGN);
1140
c226b7c2 1141 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1142 * (implemented by forking "pwd" and reading its output) doesn't
1143 * work when there are other child processes. Also, on all systems
1144 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1145 push_dir(NULL);
c226b7c2 1146
44e9e221
WD
1147 init_flist();
1148
b9f592fb
WD
1149 if (write_batch || read_batch) {
1150 if (write_batch)
66a9dc96 1151 write_batch_shell_file(orig_argc, orig_argv, argc);
b9f592fb 1152
dbbab0c4
WD
1153 if (read_batch && strcmp(batch_name, "-") == 0)
1154 batch_fd = STDIN_FILENO;
1155 else {
1156 batch_fd = do_open(batch_name,
b9f592fb
WD
1157 write_batch ? O_WRONLY | O_CREAT | O_TRUNC
1158 : O_RDONLY, S_IRUSR | S_IWUSR);
dbbab0c4 1159 }
b9f592fb
WD
1160 if (batch_fd < 0) {
1161 rsyserr(FERROR, errno, "Batch file %s open error",
71903f60 1162 full_fname(batch_name));
b9f592fb
WD
1163 exit_cleanup(RERR_FILEIO);
1164 }
9459290a
WD
1165 if (read_batch)
1166 read_stream_flags(batch_fd);
6902ed17
MP
1167 }
1168
75aeac44 1169 if (am_daemon && !am_server)
7a6421fa 1170 return daemon_main();
f0fca04e 1171
08ac228f
AT
1172 if (argc < 1) {
1173 usage(FERROR);
65417579 1174 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1175 }
1176
b78296cb 1177 if (dry_run && !verbose && !itemize_changes)
93c31c1a 1178 verbose = 1;
c627d613 1179
7a6421fa 1180 if (am_server) {
f0359dd0
AT
1181 set_nonblocking(STDIN_FILENO);
1182 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1183 if (am_daemon)
1184 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1185 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1186 }
c627d613 1187
ff81e809 1188 ret = start_client(argc, argv);
d9c7edf6 1189 if (ret == -1)
9098bbf3 1190 exit_cleanup(RERR_STARTCLIENT);
088aac85 1191 else
9098bbf3
MP
1192 exit_cleanup(ret);
1193
0f5a04e3 1194 return ret;
c627d613 1195}