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