Commenting out link-dest test for now.
[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
50839b4b
WD
26extern int verbose;
27extern int dry_run;
28extern int list_only;
32eda096 29extern int am_root;
d9c7edf6
WD
30extern int am_server;
31extern int am_sender;
b695f242 32extern int am_generator;
d9c7edf6 33extern int am_daemon;
32eda096 34extern int blocking_io;
48a1ff0d 35extern int delete_before;
bf26aa22 36extern int remove_sent_files;
32eda096 37extern int daemon_over_rsh;
bf26aa22 38extern int need_messages_from_generator;
32eda096 39extern int do_stats;
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;
cb8240a2 51extern int inplace;
b1df18d7 52extern int whole_file;
32eda096
WD
53extern int read_batch;
54extern int write_batch;
b9f592fb 55extern int batch_fd;
c0d8e84c 56extern int batch_gen_fd;
32eda096
WD
57extern int filesfrom_fd;
58extern pid_t cleanup_child_pid;
50839b4b 59extern struct stats stats;
32eda096
WD
60extern char *files_from;
61extern char *remote_filesfrom_file;
7162c65d 62extern char *partial_dir;
c3fad2e2 63extern char *basis_dir[];
32eda096
WD
64extern char *rsync_path;
65extern char *shell_cmd;
9b3318b0 66extern char *batch_name;
57dee64e
WD
67
68int local_server = 0;
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{
4f5b0756 229#ifdef 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
4f5b0756 299#ifdef 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++)
71903f60 344 rprintf(FINFO, "%s ", safe_fname(args[i]));
9486289c 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)
71903f60 414 rprintf(FINFO, "created directory %s\n", safe_fname(name));
e5a96f0f
WD
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 }
bf26aa22
WD
447 if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
448 rprintf(FERROR,
449 "ERROR: --remove-sent-files cannot be used with a read-only module\n");
450 exit_cleanup(RERR_SYNTAX);
451 return;
452 }
7a92ded3 453
59187666 454 if (!relative_paths && !push_dir(dir)) {
982e05bb
WD
455 rsyserr(FERROR, errno, "push_dir#3 %s failed",
456 full_fname(dir));
65417579 457 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
458 }
459 argc--;
460 argv++;
d9c7edf6 461
7a6421fa
AT
462 if (strcmp(dir,".")) {
463 int l = strlen(dir);
d9c7edf6 464 if (strcmp(dir,"/") == 0)
7a6421fa 465 l = 0;
e7a392c7 466 for (i = 0; i < argc; i++)
7a6421fa
AT
467 argv[i] += l+1;
468 }
c627d613 469
48a1ff0d 470 if (argc == 0 && (recurse || list_only)) {
e1f67417 471 argc = 1;
7a6421fa
AT
472 argv--;
473 argv[0] = ".";
474 }
d9c7edf6 475
7a6421fa 476 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
477 if (!flist || flist->count == 0) {
478 exit_cleanup(0);
479 }
480
da3478b2
WD
481 io_start_buffering_in();
482 io_start_buffering_out();
483
7a6421fa 484 send_files(flist,f_out,f_in);
f1e3656e 485 io_flush(FULL_FLUSH);
7a6421fa 486 report(f_out);
d04e9c51 487 if (protocol_version >= 24) {
d9c7edf6 488 /* final goodbye message */
64c3523a
WD
489 read_int(f_in);
490 }
f1e3656e 491 io_flush(FULL_FLUSH);
7a6421fa 492 exit_cleanup(0);
c627d613
AT
493}
494
495
dc5ddbcc
AT
496static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
497{
d186eb1a 498 int pid;
e1f67417 499 int status = 0;
41cfde6b 500 int error_pipe[2], name_pipe[2];
cb8240a2
WD
501 BOOL need_name_pipe = (basis_dir[0] || partial_dir || fuzzy_basis
502 || inplace) && !dry_run;
dc5ddbcc 503
bb6721dc
WD
504 /* The receiving side mustn't obey this, or an existing symlink that
505 * points to an identical file won't be replaced by the referent. */
506 copy_links = 0;
507
d186eb1a
AT
508 if (preserve_hard_links)
509 init_hard_links(flist);
dc5ddbcc 510
864146de
WD
511 if (delete_before && !local_name && flist->count > 0) {
512 /* Moved here from recv_files() to prevent a race condition */
513 delete_files(flist);
6957ae33
AT
514 }
515
41cfde6b
WD
516 if (fd_pair(error_pipe) < 0
517 || (need_name_pipe && fd_pair(name_pipe) < 0)) {
ab759cd2 518 rsyserr(FERROR, errno, "pipe failed in do_recv");
c8f2f857 519 exit_cleanup(RERR_IPC);
554e0a8d 520 }
d9c7edf6 521
f1e3656e 522 io_flush(NORMAL_FLUSH);
c6e7fcb4 523
ba449e44 524 if ((pid = do_fork()) == -1) {
c8f2f857 525 rsyserr(FERROR, errno, "fork failed in do_recv");
ba449e44
WD
526 exit_cleanup(RERR_IPC);
527 }
528
529 if (pid == 0) {
554e0a8d 530 close(error_pipe[0]);
41cfde6b
WD
531 if (need_name_pipe) {
532 close(name_pipe[1]);
533 set_blocking(name_pipe[0]);
534 } else
535 name_pipe[0] = -1;
3a69fad0
WD
536 if (f_in != f_out)
537 close(f_out);
e08c9610 538
554e0a8d 539 /* we can't let two processes write to the socket at one time */
9eeb3b9c 540 close_multiplexing_out();
554e0a8d
AT
541
542 /* set place to send errors */
f1e3656e 543 set_msg_fd_out(error_pipe[1]);
554e0a8d 544
41cfde6b 545 recv_files(f_in, flist, local_name, name_pipe[0]);
f1e3656e 546 io_flush(FULL_FLUSH);
ba5e128d 547 report(f_in);
e08c9610 548
f1e3656e
WD
549 send_msg(MSG_DONE, "", 0);
550 io_flush(FULL_FLUSH);
4a748188 551 /* finally we go to sleep until our parent kills us
9af87151
WD
552 * with a USR2 signal. We sleep for a short time as on
553 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
554 while (1)
555 msleep(20);
d186eb1a 556 }
dc5ddbcc 557
b695f242 558 am_generator = 1;
9eeb3b9c 559 close_multiplexing_in();
b9f592fb
WD
560 if (write_batch)
561 stop_write_batch();
b695f242 562
554e0a8d 563 close(error_pipe[1]);
41cfde6b
WD
564 if (need_name_pipe) {
565 close(name_pipe[0]);
566 set_nonblocking(name_pipe[1]);
567 } else
568 name_pipe[1] = -1;
3a69fad0
WD
569 if (f_in != f_out)
570 close(f_in);
e1b3d5c4 571
da3478b2 572 io_start_buffering_out();
b3e10ed7 573
f1e3656e 574 set_msg_fd_in(error_pipe[0]);
554e0a8d 575
41cfde6b 576 generate_files(f_out, flist, local_name, name_pipe[1]);
8d9dc9f9 577
e5fbaa71 578 report(-1);
f1e3656e 579 io_flush(FULL_FLUSH);
d04e9c51 580 if (protocol_version >= 24) {
8ada7518
AT
581 /* send a final goodbye message */
582 write_int(f_out, -1);
583 }
f1e3656e 584 io_flush(FULL_FLUSH);
8ada7518 585
f1e3656e 586 set_msg_fd_in(-1);
089a2435 587 kill(pid, SIGUSR2);
d79d1c69 588 wait_process(pid, &status);
d186eb1a 589 return status;
dc5ddbcc
AT
590}
591
c627d613 592
9486289c 593static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 594{
7a6421fa
AT
595 int status;
596 struct file_list *flist;
6c2e5b56 597 char *local_name = NULL;
7a6421fa 598 char *dir = NULL;
07bff66f
WD
599 int save_verbose = verbose;
600
601 if (filesfrom_fd >= 0) {
602 /* We can't mix messages with files-from data on the socket,
603 * so temporarily turn off verbose messages. */
604 verbose = 0;
605 }
f0fca04e 606
45e08edb
WD
607 if (verbose > 2) {
608 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
609 argc, (long)getpid());
610 }
09b7f5db 611
2adbcdc7 612 if (am_daemon && lp_read_only(module_id)) {
09b7f5db
AT
613 rprintf(FERROR,"ERROR: module is read only\n");
614 exit_cleanup(RERR_SYNTAX);
615 return;
616 }
617
d9c7edf6 618
7a6421fa
AT
619 if (argc > 0) {
620 dir = argv[0];
621 argc--;
622 argv++;
59187666 623 if (!am_daemon && !push_dir(dir)) {
982e05bb
WD
624 rsyserr(FERROR, errno, "push_dir#4 %s failed",
625 full_fname(dir));
65417579 626 exit_cleanup(RERR_FILESELECT);
d9c7edf6 627 }
7a6421fa 628 }
c627d613 629
da3478b2 630 io_start_buffering_in();
57dee64e 631 recv_filter_list(f_in);
c627d613 632
7c2a9e76 633 if (filesfrom_fd >= 0) {
07bff66f
WD
634 /* We need to send the files-from names to the sender at the
635 * same time that we receive the file-list from them, so we
636 * need the IO routines to automatically write out the names
637 * onto our f_out socket as we read the file-list. This
638 * avoids both deadlock and extra delays/buffers. */
7c2a9e76
WD
639 io_set_filesfrom_fds(filesfrom_fd, f_out);
640 filesfrom_fd = -1;
641 }
642
b9f592fb 643 flist = recv_file_list(f_in);
07bff66f 644 verbose = save_verbose;
4c36a13e
AT
645 if (!flist) {
646 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 647 exit_cleanup(RERR_FILESELECT);
7a6421fa 648 }
d9c7edf6
WD
649
650 if (argc > 0) {
7a6421fa
AT
651 if (strcmp(dir,".")) {
652 argv[0] += strlen(dir);
3a69fad0
WD
653 if (argv[0][0] == '/')
654 argv[0]++;
7a6421fa
AT
655 }
656 local_name = get_local_name(flist,argv[0]);
657 }
c627d613 658
7a6421fa
AT
659 status = do_recv(f_in,f_out,flist,local_name);
660 exit_cleanup(status);
c627d613
AT
661}
662
663
734a94a2 664int child_main(int argc, char *argv[])
25d34a5c
MP
665{
666 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 667 return 0;
25d34a5c
MP
668}
669
670
9486289c 671void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 672{
f0359dd0
AT
673 set_nonblocking(f_in);
674 set_nonblocking(f_out);
675
da3478b2
WD
676 io_set_sock_fds(f_in, f_out);
677 setup_protocol(f_out, f_in);
678
d04e9c51 679 if (protocol_version >= 23)
da3478b2 680 io_start_multiplex_out();
7a6421fa 681
7a6421fa 682 if (am_sender) {
83926d3c 683 keep_dirlinks = 0; /* Must be disabled on the sender. */
bf26aa22
WD
684 if (need_messages_from_generator)
685 io_start_multiplex_in();
9b3318b0 686
7842418b 687 recv_filter_list(f_in);
7a6421fa
AT
688 do_server_sender(f_in, f_out, argc, argv);
689 } else {
690 do_server_recv(f_in, f_out, argc, argv);
691 }
692 exit_cleanup(0);
366345fe
AT
693}
694
0ba48136
MP
695
696/*
697 * This is called once the connection has been negotiated. It is used
698 * for rsyncd, remote-shell, and local connections.
699 */
19b27a48 700int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 701{
088aac85 702 struct file_list *flist = NULL;
9486289c
AT
703 int status = 0, status2 = 0;
704 char *local_name = NULL;
19b27a48
AT
705
706 cleanup_child_pid = pid;
67a28eb2 707 if (!read_batch) {
b9f592fb
WD
708 set_nonblocking(f_in);
709 set_nonblocking(f_out);
710 }
f0359dd0 711
da3478b2 712 io_set_sock_fds(f_in, f_out);
6d7b6081
AT
713 setup_protocol(f_out,f_in);
714
b9f592fb 715 if (protocol_version >= 23 && !read_batch)
da3478b2 716 io_start_multiplex_in();
d9c7edf6 717
18882701
WD
718 /* We set our stderr file handle to blocking because ssh might have
719 * set it to non-blocking. This can be particularly troublesome if
720 * stderr is a clone of stdout, because ssh would have set our stdout
721 * to non-blocking at the same time (which can easily cause us to lose
722 * output from our print statements). This kluge shouldn't cause ssh
723 * any problems for how we use it. Note also that we delayed setting
724 * this until after the above protocol setup so that we know for sure
725 * that ssh is done twiddling its file descriptors. */
726 set_blocking(STDERR_FILENO);
727
9486289c 728 if (am_sender) {
83926d3c 729 keep_dirlinks = 0; /* Must be disabled on the sender. */
da3478b2 730 io_start_buffering_out();
a0a33ee5
WD
731 if (!remote_filesfrom_file)
732 set_msg_fd_in(f_in);
57dee64e 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
bf26aa22
WD
763 if (need_messages_from_generator && !read_batch)
764 io_start_multiplex_out();
765
48a1ff0d
WD
766 if (argc == 0)
767 list_only |= 1;
d9c7edf6 768
57dee64e 769 send_filter_list(read_batch ? -1 : f_out);
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",
71903f60
WD
984 shell_cmd ? safe_fname(shell_cmd) : "",
985 shell_machine ? safe_fname(shell_machine) : "",
986 shell_user ? safe_fname(shell_user) : "",
987 shell_path ? safe_fname(shell_path) : "");
5d6bcd44 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",
71903f60 1175 full_fname(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 1190 if (am_server) {
f0359dd0
AT
1191 set_nonblocking(STDIN_FILENO);
1192 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1193 if (am_daemon)
1194 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1195 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1196 }
c627d613 1197
ff81e809 1198 ret = start_client(argc, argv);
d9c7edf6 1199 if (ret == -1)
9098bbf3 1200 exit_cleanup(RERR_STARTCLIENT);
088aac85 1201 else
9098bbf3
MP
1202 exit_cleanup(ret);
1203
0f5a04e3 1204 return ret;
c627d613 1205}