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