Don't loop forever when the receiver is waiting around to be killed
[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;
051182cb 38extern int kluge_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 562
40df65fd
WD
563 /* Handle any keep-alive packets from the post-processing work
564 * that the generator does. */
4e0fcd85 565 if (protocol_version >= 29) {
051182cb 566 kluge_around_eof = -1;
4e0fcd85
WD
567 while (read_int(f_in) == flist->count) {
568 if (read_shortint(f_in) != ITEM_IS_NEW)
569 break; /* Complain? */
570 }
571 }
572
40df65fd
WD
573 /* Finally, we hang around waiting for our parent to kills
574 * us with a USR2 signal. We sleep for a short time, as on
575 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
576 while (1)
577 msleep(20);
d186eb1a 578 }
dc5ddbcc 579
b695f242 580 am_generator = 1;
9eeb3b9c 581 close_multiplexing_in();
b9f592fb
WD
582 if (write_batch)
583 stop_write_batch();
b695f242 584
554e0a8d 585 close(error_pipe[1]);
41cfde6b
WD
586 if (need_name_pipe) {
587 close(name_pipe[0]);
588 set_nonblocking(name_pipe[1]);
589 } else
590 name_pipe[1] = -1;
3a69fad0
WD
591 if (f_in != f_out)
592 close(f_in);
e1b3d5c4 593
da3478b2 594 io_start_buffering_out();
b3e10ed7 595
f1e3656e 596 set_msg_fd_in(error_pipe[0]);
554e0a8d 597
41cfde6b 598 generate_files(f_out, flist, local_name, name_pipe[1]);
8d9dc9f9 599
e5fbaa71 600 report(-1);
f1e3656e 601 io_flush(FULL_FLUSH);
d04e9c51 602 if (protocol_version >= 24) {
8ada7518
AT
603 /* send a final goodbye message */
604 write_int(f_out, -1);
605 }
f1e3656e 606 io_flush(FULL_FLUSH);
8ada7518 607
f1e3656e 608 set_msg_fd_in(-1);
089a2435 609 kill(pid, SIGUSR2);
d79d1c69 610 wait_process(pid, &status);
d186eb1a 611 return status;
dc5ddbcc
AT
612}
613
c627d613 614
9486289c 615static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 616{
7a6421fa
AT
617 int status;
618 struct file_list *flist;
6c2e5b56 619 char *local_name = NULL;
7a6421fa 620 char *dir = NULL;
07bff66f
WD
621 int save_verbose = verbose;
622
623 if (filesfrom_fd >= 0) {
624 /* We can't mix messages with files-from data on the socket,
625 * so temporarily turn off verbose messages. */
626 verbose = 0;
627 }
f0fca04e 628
45e08edb
WD
629 if (verbose > 2) {
630 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
631 argc, (long)getpid());
632 }
09b7f5db 633
2adbcdc7 634 if (am_daemon && lp_read_only(module_id)) {
09b7f5db
AT
635 rprintf(FERROR,"ERROR: module is read only\n");
636 exit_cleanup(RERR_SYNTAX);
637 return;
638 }
639
d9c7edf6 640
7a6421fa
AT
641 if (argc > 0) {
642 dir = argv[0];
643 argc--;
644 argv++;
59187666 645 if (!am_daemon && !push_dir(dir)) {
982e05bb
WD
646 rsyserr(FERROR, errno, "push_dir#4 %s failed",
647 full_fname(dir));
65417579 648 exit_cleanup(RERR_FILESELECT);
d9c7edf6 649 }
7a6421fa 650 }
c627d613 651
da3478b2 652 io_start_buffering_in();
57dee64e 653 recv_filter_list(f_in);
c627d613 654
7c2a9e76 655 if (filesfrom_fd >= 0) {
07bff66f
WD
656 /* We need to send the files-from names to the sender at the
657 * same time that we receive the file-list from them, so we
658 * need the IO routines to automatically write out the names
659 * onto our f_out socket as we read the file-list. This
660 * avoids both deadlock and extra delays/buffers. */
7c2a9e76
WD
661 io_set_filesfrom_fds(filesfrom_fd, f_out);
662 filesfrom_fd = -1;
663 }
664
b9f592fb 665 flist = recv_file_list(f_in);
07bff66f 666 verbose = save_verbose;
4c36a13e
AT
667 if (!flist) {
668 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 669 exit_cleanup(RERR_FILESELECT);
7a6421fa 670 }
d9c7edf6
WD
671
672 if (argc > 0) {
7a6421fa
AT
673 if (strcmp(dir,".")) {
674 argv[0] += strlen(dir);
3a69fad0
WD
675 if (argv[0][0] == '/')
676 argv[0]++;
7a6421fa
AT
677 }
678 local_name = get_local_name(flist,argv[0]);
679 }
c627d613 680
7a6421fa
AT
681 status = do_recv(f_in,f_out,flist,local_name);
682 exit_cleanup(status);
c627d613
AT
683}
684
685
734a94a2 686int child_main(int argc, char *argv[])
25d34a5c
MP
687{
688 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 689 return 0;
25d34a5c
MP
690}
691
692
9486289c 693void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 694{
f0359dd0
AT
695 set_nonblocking(f_in);
696 set_nonblocking(f_out);
697
da3478b2
WD
698 io_set_sock_fds(f_in, f_out);
699 setup_protocol(f_out, f_in);
700
d04e9c51 701 if (protocol_version >= 23)
da3478b2 702 io_start_multiplex_out();
7a6421fa 703
7a6421fa 704 if (am_sender) {
83926d3c 705 keep_dirlinks = 0; /* Must be disabled on the sender. */
bf26aa22
WD
706 if (need_messages_from_generator)
707 io_start_multiplex_in();
9b3318b0 708
7842418b 709 recv_filter_list(f_in);
7a6421fa
AT
710 do_server_sender(f_in, f_out, argc, argv);
711 } else {
712 do_server_recv(f_in, f_out, argc, argv);
713 }
714 exit_cleanup(0);
366345fe
AT
715}
716
0ba48136
MP
717
718/*
719 * This is called once the connection has been negotiated. It is used
720 * for rsyncd, remote-shell, and local connections.
721 */
19b27a48 722int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 723{
088aac85 724 struct file_list *flist = NULL;
9486289c
AT
725 int status = 0, status2 = 0;
726 char *local_name = NULL;
19b27a48
AT
727
728 cleanup_child_pid = pid;
67a28eb2 729 if (!read_batch) {
b9f592fb
WD
730 set_nonblocking(f_in);
731 set_nonblocking(f_out);
732 }
f0359dd0 733
da3478b2 734 io_set_sock_fds(f_in, f_out);
6d7b6081
AT
735 setup_protocol(f_out,f_in);
736
b9f592fb 737 if (protocol_version >= 23 && !read_batch)
da3478b2 738 io_start_multiplex_in();
d9c7edf6 739
18882701
WD
740 /* We set our stderr file handle to blocking because ssh might have
741 * set it to non-blocking. This can be particularly troublesome if
742 * stderr is a clone of stdout, because ssh would have set our stdout
743 * to non-blocking at the same time (which can easily cause us to lose
744 * output from our print statements). This kluge shouldn't cause ssh
745 * any problems for how we use it. Note also that we delayed setting
746 * this until after the above protocol setup so that we know for sure
747 * that ssh is done twiddling its file descriptors. */
748 set_blocking(STDERR_FILENO);
749
9486289c 750 if (am_sender) {
83926d3c 751 keep_dirlinks = 0; /* Must be disabled on the sender. */
da3478b2 752 io_start_buffering_out();
a0a33ee5
WD
753 if (!remote_filesfrom_file)
754 set_msg_fd_in(f_in);
57dee64e 755 send_filter_list(f_out);
7c2a9e76
WD
756 if (remote_filesfrom_file)
757 filesfrom_fd = f_in;
b9f592fb
WD
758
759 if (write_batch)
760 start_write_batch(f_out);
64c3523a 761 if (!read_batch) /* don't write to pipe */
d9c7edf6 762 flist = send_file_list(f_out,argc,argv);
a0a33ee5 763 set_msg_fd_in(-1);
d9c7edf6 764 if (verbose > 3)
9486289c 765 rprintf(FINFO,"file list sent\n");
e1b3d5c4 766
f1e3656e 767 io_flush(NORMAL_FLUSH);
9486289c 768 send_files(flist,f_out,f_in);
f1e3656e 769 io_flush(FULL_FLUSH);
4e0fcd85
WD
770 if (protocol_version >= 24)
771 read_final_goodbye(f_in, f_out, flist->count);
9486289c
AT
772 if (pid != -1) {
773 if (verbose > 3)
08a740ff 774 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 775 io_flush(FULL_FLUSH);
d79d1c69 776 wait_process(pid, &status);
9486289c 777 }
3d382777 778 report(-1);
f1e3656e 779 io_flush(FULL_FLUSH);
9486289c
AT
780 exit_cleanup(status);
781 }
f7632fc6 782
bf26aa22
WD
783 if (need_messages_from_generator && !read_batch)
784 io_start_multiplex_out();
785
48a1ff0d
WD
786 if (argc == 0)
787 list_only |= 1;
d9c7edf6 788
57dee64e 789 send_filter_list(read_batch ? -1 : f_out);
d9c7edf6 790
7c2a9e76
WD
791 if (filesfrom_fd >= 0) {
792 io_set_filesfrom_fds(filesfrom_fd, f_out);
793 filesfrom_fd = -1;
794 }
795
b9f592fb
WD
796 if (write_batch)
797 start_write_batch(f_in);
9486289c
AT
798 flist = recv_file_list(f_in);
799 if (!flist || flist->count == 0) {
796d484b 800 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
801 "perhaps you need to specify some filenames or "
802 "the --recursive option?\n");
9486289c
AT
803 exit_cleanup(0);
804 }
d9c7edf6 805
9486289c 806 local_name = get_local_name(flist,argv[0]);
d9c7edf6 807
9486289c 808 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 809
9486289c 810 if (pid != -1) {
8d9dc9f9 811 if (verbose > 3)
08a740ff 812 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 813 io_flush(FULL_FLUSH);
d79d1c69 814 wait_process(pid, &status);
9486289c 815 }
d9c7edf6 816
ff81e809 817 return MAX(status, status2);
9486289c
AT
818}
819
7169bb4a
MP
820static int copy_argv (char *argv[])
821{
822 int i;
823
824 for (i = 0; argv[i]; i++) {
825 if (!(argv[i] = strdup(argv[i]))) {
826 rprintf (FERROR, "out of memory at %s(%d)\n",
827 __FILE__, __LINE__);
828 return RERR_MALLOC;
829 }
830 }
831
832 return 0;
833}
834
835
c1a04ecb 836/**
0ba48136
MP
837 * Start a client for either type of remote connection. Work out
838 * whether the arguments request a remote shell or rsyncd connection,
839 * and call the appropriate connection function, then run_client.
0b4af330
MP
840 *
841 * Calls either start_socket_client (for sockets) or do_cmd and
842 * client_run (for ssh).
c1a04ecb 843 **/
fc8a6b97 844static int start_client(int argc, char *argv[])
5d6bcd44
AT
845{
846 char *p;
847 char *shell_machine = NULL;
848 char *shell_path = NULL;
849 char *shell_user = NULL;
19b27a48
AT
850 int ret;
851 pid_t pid;
5d6bcd44 852 int f_in,f_out;
7169bb4a
MP
853 int rc;
854
855 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 856 * command line. */
75aeac44 857 if ((rc = copy_argv(argv)))
7169bb4a 858 return rc;
5d6bcd44 859
75aeac44 860 /* rsync:// always uses rsync server over direct socket connection */
b9f592fb
WD
861 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0
862 && !read_batch) {
f7632fc6
AT
863 char *host, *path;
864
7169bb4a 865 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
866 p = strchr(host,'/');
867 if (p) {
50b31539 868 *p = '\0';
f7632fc6 869 path = p+1;
50b31539 870 } else
a125c82a 871 path = "";
50b31539
WD
872 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
873 host++;
874 *p++ = '\0';
875 if (*p != ':')
876 p = NULL;
877 } else
878 p = strchr(host, ':');
2acf81eb
DD
879 if (p) {
880 rsync_port = atoi(p+1);
50b31539 881 *p = '\0';
cf510ad2 882 }
f7632fc6
AT
883 return start_socket_client(host, path, argc-1, argv+1);
884 }
885
d16c245f 886 if (!read_batch) { /* for read_batch, NO source is specified */
a125c82a 887 p = find_colon(argv[0]);
d16c245f 888 if (p) { /* source is remote */
7c2a9e76
WD
889 if (remote_filesfrom_file
890 && remote_filesfrom_file != files_from + 1
891 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
892 rprintf(FERROR,
50b31539 893 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
894 exit_cleanup(RERR_SYNTAX);
895 }
d9c7edf6
WD
896 if (p[1] == ':') { /* double colon */
897 *p = 0;
898 if (!shell_cmd) {
899 return start_socket_client(argv[0], p+2,
900 argc-1, argv+1);
901 }
902 p++;
903 daemon_over_rsh = 1;
75aeac44 904 }
3591c066 905
d16c245f 906 if (argc < 1) { /* destination required */
d9c7edf6
WD
907 usage(FERROR);
908 exit_cleanup(RERR_SYNTAX);
909 }
a125c82a 910
d9c7edf6
WD
911 am_sender = 0;
912 *p = 0;
913 shell_machine = argv[0];
914 shell_path = p+1;
d9c7edf6 915 argv++;
d16c245f 916 } else { /* source is local */
d9c7edf6
WD
917 am_sender = 1;
918
919 /* rsync:// destination uses rsync server over direct socket */
920 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
921 char *host, *path;
922
923 host = argv[argc-1] + strlen(URL_PREFIX);
924 p = strchr(host,'/');
925 if (p) {
50b31539 926 *p = '\0';
d9c7edf6 927 path = p+1;
50b31539 928 } else
d9c7edf6 929 path = "";
50b31539
WD
930 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
931 host++;
932 *p++ = '\0';
933 if (*p != ':')
934 p = NULL;
935 } else
936 p = strchr(host, ':');
d9c7edf6
WD
937 if (p) {
938 rsync_port = atoi(p+1);
50b31539 939 *p = '\0';
cf510ad2 940 }
d9c7edf6 941 return start_socket_client(host, path, argc-1, argv);
a125c82a 942 }
d9c7edf6 943
d16c245f 944 p = find_colon(argv[argc-1]); /* look in dest arg */
7c2a9e76
WD
945 if (p && remote_filesfrom_file
946 && remote_filesfrom_file != files_from + 1
947 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
948 rprintf(FERROR,
50b31539 949 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
950 exit_cleanup(RERR_SYNTAX);
951 }
d16c245f 952 if (!p) { /* no colon found, so src & dest are local */
d9c7edf6 953 local_server = 1;
7c2a9e76
WD
954 if (remote_filesfrom_file) {
955 rprintf(FERROR,
50b31539 956 "--files-from cannot be remote when the transfer is local\n");
7c2a9e76
WD
957 exit_cleanup(RERR_SYNTAX);
958 }
d9c7edf6 959 } else if (p[1] == ':') { /* double colon */
a125c82a 960 *p = 0;
d9c7edf6
WD
961 if (!shell_cmd) {
962 return start_socket_client(argv[argc-1], p+2,
963 argc-1, argv);
964 }
965 p++;
966 daemon_over_rsh = 1;
a125c82a 967 }
a125c82a 968
d9c7edf6
WD
969 if (argc < 2) {
970 usage(FERROR);
971 exit_cleanup(RERR_SYNTAX);
75aeac44 972 }
3591c066 973
d9c7edf6
WD
974 if (local_server) {
975 shell_machine = NULL;
976 shell_path = argv[argc-1];
977 } else {
978 *p = 0;
979 shell_machine = argv[argc-1];
980 shell_path = p+1;
981 }
5d6bcd44 982 }
d16c245f
WD
983 argc--;
984 } else { /* read_batch */
d9c7edf6
WD
985 local_server = 1;
986 shell_path = argv[argc-1];
b9f592fb
WD
987 if (find_colon(shell_path)) {
988 rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
989 exit_cleanup(RERR_SYNTAX);
990 }
6902ed17
MP
991 }
992
5d6bcd44 993 if (shell_machine) {
6fc048f4 994 p = strrchr(shell_machine,'@');
5d6bcd44
AT
995 if (p) {
996 *p = 0;
997 shell_user = shell_machine;
998 shell_machine = p+1;
999 }
1000 }
1001
1002 if (verbose > 3) {
9486289c 1003 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
71903f60
WD
1004 shell_cmd ? safe_fname(shell_cmd) : "",
1005 shell_machine ? safe_fname(shell_machine) : "",
1006 shell_user ? safe_fname(shell_user) : "",
1007 shell_path ? safe_fname(shell_path) : "");
5d6bcd44 1008 }
d9c7edf6 1009
d16c245f 1010 /* for remote source, only single dest arg can remain ... */
f7632fc6 1011 if (!am_sender && argc > 1) {
5d6bcd44 1012 usage(FERROR);
65417579 1013 exit_cleanup(RERR_SYNTAX);
5d6bcd44 1014 }
27e3e9c9 1015
d16c245f 1016 /* ... or no dest at all */
48a1ff0d
WD
1017 if (!am_sender && argc == 0)
1018 list_only |= 1;
d9c7edf6 1019
75aeac44
WD
1020 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
1021 &f_in,&f_out);
1022
1023 /* if we're running an rsync server on the remote host over a
9af87151 1024 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
1025 if (daemon_over_rsh) {
1026 int tmpret;
1027 tmpret = start_inband_exchange(shell_user, shell_path,
1028 f_in, f_out, argc);
1029 if (tmpret < 0)
1030 return tmpret;
1031 }
1032
fc8a6b97
AT
1033 ret = client_run(f_in, f_out, pid, argc, argv);
1034
1035 fflush(stdout);
1036 fflush(stderr);
1037
1038 return ret;
5d6bcd44
AT
1039}
1040
366345fe 1041
067669da
WD
1042static RETSIGTYPE sigusr1_handler(UNUSED(int val))
1043{
65417579 1044 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
1045}
1046
067669da
WD
1047static RETSIGTYPE sigusr2_handler(UNUSED(int val))
1048{
40df65fd 1049 close_all();
19b27a48 1050 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
1051 _exit(0);
1052}
1053
067669da
WD
1054static RETSIGTYPE sigchld_handler(UNUSED(int val))
1055{
029c1713 1056#ifdef WNOHANG
ee7118a8
DD
1057 int cnt, status;
1058 pid_t pid;
1059 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 1060 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
1061 * out we're instead saving the child exit statuses for later use.
1062 * The waitpid() loop presumably eliminates all possibility of leaving
1063 * zombie children, maybe that's why he did it.
1064 */
1065 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
1066 /* save the child's exit status */
1067 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
1068 if (pid_stat_table[cnt].pid == 0) {
1069 pid_stat_table[cnt].pid = pid;
1070 pid_stat_table[cnt].status = status;
1071 break;
1072 }
1073 }
ee7118a8 1074 }
029c1713 1075#endif
19b27a48
AT
1076}
1077
c0531332
MP
1078
1079/**
1080 * This routine catches signals and tries to send them to gdb.
1081 *
1082 * Because it's called from inside a signal handler it ought not to
1083 * use too many library routines.
1084 *
1085 * @todo Perhaps use "screen -X" instead/as well, to help people
1086 * debugging without easy access to X. Perhaps use an environment
1087 * variable, or just call a script?
1088 *
1089 * @todo The /proc/ magic probably only works on Linux (and
1090 * Solaris?) Can we be more portable?
1091 **/
1092#ifdef MAINTAINER_MODE
4fdc39dd
MP
1093const char *get_panic_action(void)
1094{
1095 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
1096
1097 if (cmd_fmt)
1098 return cmd_fmt;
1099 else
1100 return "xterm -display :0 -T Panic -n Panic "
1101 "-e gdb /proc/%d/exe %d";
1102}
1103
1104
9fb3f7a9
MP
1105/**
1106 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
1107 *
1108 * This signal handler is only installed if we were configured with
1109 * --enable-maintainer-mode. Perhaps it should always be on and we
1110 * should just look at the environment variable, but I'm a bit leery
1111 * of a signal sending us into a busy loop.
1112 **/
067669da 1113static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
1114{
1115 char cmd_buf[300];
1116 int ret;
4fdc39dd
MP
1117
1118 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
1119 getpid(), getpid());
1120
1121 /* Unless we failed to execute gdb, we allow the process to
1122 * continue. I'm not sure if that's right. */
1123 ret = system(cmd_buf);
1124 if (ret)
1125 _exit(ret);
1126}
1127#endif
1128
1129
5d6bcd44 1130int main(int argc,char *argv[])
d9c7edf6 1131{
ff81e809 1132 int ret;
66a9dc96
WD
1133 int orig_argc = argc;
1134 char **orig_argv = argv;
5d6bcd44 1135
7a6421fa 1136 signal(SIGUSR1, sigusr1_handler);
8b35435f 1137 signal(SIGUSR2, sigusr2_handler);
19b27a48 1138 signal(SIGCHLD, sigchld_handler);
c0531332
MP
1139#ifdef MAINTAINER_MODE
1140 signal(SIGSEGV, rsync_panic_handler);
1141 signal(SIGFPE, rsync_panic_handler);
1142 signal(SIGABRT, rsync_panic_handler);
1143 signal(SIGBUS, rsync_panic_handler);
1144#endif /* def MAINTAINER_MODE */
5d6bcd44 1145
7a6421fa 1146 starttime = time(NULL);
6fe05820 1147 am_root = (MY_UID() == 0);
c627d613 1148
a800434a
AT
1149 memset(&stats, 0, sizeof(stats));
1150
df5e03da
AT
1151 if (argc < 2) {
1152 usage(FERROR);
65417579 1153 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
1154 }
1155
7a6421fa 1156 /* we set a 0 umask so that correct file permissions can be
9af87151 1157 * carried across */
7a6421fa 1158 orig_umask = (int)umask(0);
5d6bcd44 1159
50135767 1160 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
1161 /* FIXME: We ought to call the same error-handling
1162 * code here, rather than relying on getopt. */
50135767 1163 option_error();
65417579 1164 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1165 }
5d6bcd44 1166
7a6421fa 1167 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1168 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1169 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1170
34758d5c
MP
1171 /* Ignore SIGPIPE; we consistently check error codes and will
1172 * see the EPIPE. */
1173 signal(SIGPIPE, SIG_IGN);
1174
c226b7c2 1175 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1176 * (implemented by forking "pwd" and reading its output) doesn't
1177 * work when there are other child processes. Also, on all systems
1178 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1179 push_dir(NULL);
c226b7c2 1180
44e9e221
WD
1181 init_flist();
1182
b9f592fb
WD
1183 if (write_batch || read_batch) {
1184 if (write_batch)
66a9dc96 1185 write_batch_shell_file(orig_argc, orig_argv, argc);
b9f592fb 1186
dbbab0c4
WD
1187 if (read_batch && strcmp(batch_name, "-") == 0)
1188 batch_fd = STDIN_FILENO;
1189 else {
1190 batch_fd = do_open(batch_name,
b9f592fb
WD
1191 write_batch ? O_WRONLY | O_CREAT | O_TRUNC
1192 : O_RDONLY, S_IRUSR | S_IWUSR);
dbbab0c4 1193 }
b9f592fb
WD
1194 if (batch_fd < 0) {
1195 rsyserr(FERROR, errno, "Batch file %s open error",
71903f60 1196 full_fname(batch_name));
b9f592fb
WD
1197 exit_cleanup(RERR_FILEIO);
1198 }
9459290a
WD
1199 if (read_batch)
1200 read_stream_flags(batch_fd);
6902ed17
MP
1201 }
1202
75aeac44 1203 if (am_daemon && !am_server)
7a6421fa 1204 return daemon_main();
f0fca04e 1205
08ac228f
AT
1206 if (argc < 1) {
1207 usage(FERROR);
65417579 1208 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1209 }
1210
7a6421fa 1211 if (am_server) {
f0359dd0
AT
1212 set_nonblocking(STDIN_FILENO);
1213 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1214 if (am_daemon)
1215 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1216 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1217 }
c627d613 1218
ff81e809 1219 ret = start_client(argc, argv);
d9c7edf6 1220 if (ret == -1)
9098bbf3 1221 exit_cleanup(RERR_STARTCLIENT);
088aac85 1222 else
9098bbf3
MP
1223 exit_cleanup(ret);
1224
0f5a04e3 1225 return ret;
c627d613 1226}