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