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