Call SIGACTION() instead of signal().
[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
eb598fac
WD
429/* The receiving side operates in one of two modes:
430 *
431 * 1. it enters a directory and receives one or more files, placing them
432 * according to their names in the file-list.
433 *
434 * 2. it receives a single file and saves it using the name in the
435 * destination path instead of its file-list name. This requires a
436 * "local name" for writing out the destination file.
437 *
438 * So, our task is to figure out what mode/local-name we need and return
439 * either a NULL for mode 1, or the local-name for mode 2. We also
440 * change directory if there are any path components in dest_path. */
441static char *get_local_name(struct file_list *flist, char *dest_path)
c627d613 442{
7a6421fa 443 STRUCT_STAT st;
eb598fac 444 char *cp;
c627d613 445
eb598fac
WD
446 if (verbose > 2) {
447 rprintf(FINFO, "get_local_name count=%d %s\n",
448 flist->count, NS(dest_path));
449 }
1f0610ef 450
eb598fac 451 if (!dest_path)
1f0610ef 452 return NULL;
c95da96a 453
eb598fac
WD
454 /* If the destination path refers to an existing directory, enter
455 * it and use mode 1. If there is something other than a directory
456 * at the destination path, we must be transferring one file
457 * (anything at the destination will be overwritten). */
458 if (do_stat(dest_path, &st) == 0) {
1ff5450d 459 if (S_ISDIR(st.st_mode)) {
eb598fac 460 if (!push_dir(dest_path)) {
982e05bb 461 rsyserr(FERROR, errno, "push_dir#1 %s failed",
eb598fac 462 full_fname(dest_path));
65417579 463 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
464 }
465 return NULL;
466 }
467 if (flist->count > 1) {
eb598fac
WD
468 rprintf(FERROR,
469 "ERROR: destination must be a directory when"
470 " copying more than 1 file\n");
65417579 471 exit_cleanup(RERR_FILESELECT);
1ff5450d 472 }
1ff5450d
AT
473 }
474
eb598fac
WD
475 cp = strrchr(dest_path, '/');
476
477 /* If the destination path ends in a slash or we are transferring
478 * multiple files, create a directory at the destination path,
479 * enter the new directory, and use mode 1. */
480 if (flist->count > 1 || (cp && !cp[1])) {
481 /* Lop off the final slash (if any). */
482 if (cp && !cp[1])
483 *cp = '\0';
484
485 umask(orig_umask);
486 if (do_mkdir(dest_path, 0777) != 0) {
487 rsyserr(FERROR, errno, "mkdir %s failed",
488 full_fname(dest_path));
489 exit_cleanup(RERR_FILEIO);
490 }
491 umask(0);
1ff5450d 492
eb598fac
WD
493 if (verbose)
494 rprintf(FINFO, "created directory %s\n", dest_path);
495
496 if (dry_run) {
497 /* Indicate that the destination directory doesn't
498 * really exist and return mode 1. */
499 dry_run++;
500 return NULL;
501 }
502
503 if (!push_dir(dest_path)) {
504 rsyserr(FERROR, errno, "push_dir#2 %s failed",
505 full_fname(dest_path));
506 exit_cleanup(RERR_FILESELECT);
507 }
e5a96f0f 508
e5a96f0f 509 return NULL;
1ff5450d
AT
510 }
511
eb598fac
WD
512 /* Otherwise, we are writing a single file, possibly on top of an
513 * existing non-directory. Change to the item's parent directory
514 * (if it has a path component), return the basename of the
515 * destination file as the local name, and use mode 2. */
516 if (!cp)
517 return dest_path;
518
519 if (cp == dest_path)
520 dest_path = "/";
521
522 *cp = '\0';
523 if (!push_dir(dest_path)) {
524 rsyserr(FERROR, errno, "push_dir#3 %s failed",
525 full_fname(dest_path));
65417579 526 exit_cleanup(RERR_FILESELECT);
1ff5450d 527 }
eb598fac 528 *cp = '/';
1ff5450d 529
eb598fac 530 return cp + 1;
c627d613
AT
531}
532
533
1a8e5c97 534/* This is only called by the sender. */
3485ae83 535static void read_final_goodbye(int f_in, int f_out)
4e0fcd85 536{
1a8e5c97
WD
537 int i;
538
539 if (protocol_version < 29)
540 i = read_int(f_in);
541 else {
3485ae83 542 while ((i = read_int(f_in)) == the_file_list->count
1a8e5c97
WD
543 && read_shortint(f_in) == ITEM_IS_NEW) {
544 /* Forward the keep-alive (no-op) to the receiver. */
3485ae83 545 write_int(f_out, the_file_list->count);
1a8e5c97
WD
546 write_shortint(f_out, ITEM_IS_NEW);
547 }
4e0fcd85
WD
548 }
549
1a8e5c97 550 if (i != -1) {
c7791b8c
WD
551 rprintf(FERROR, "Invalid packet at end of run (%d) [%s]\n",
552 i, who_am_i());
1a8e5c97 553 exit_cleanup(RERR_PROTOCOL);
4e0fcd85
WD
554 }
555}
556
557
eb598fac 558static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
c627d613 559{
7a6421fa
AT
560 struct file_list *flist;
561 char *dir = argv[0];
c627d613 562
45e08edb
WD
563 if (verbose > 2) {
564 rprintf(FINFO, "server_sender starting pid=%ld\n",
565 (long)getpid());
566 }
d9c7edf6 567
2adbcdc7 568 if (am_daemon && lp_write_only(module_id)) {
7a92ded3
WD
569 rprintf(FERROR, "ERROR: module is write only\n");
570 exit_cleanup(RERR_SYNTAX);
571 return;
572 }
bf26aa22
WD
573 if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
574 rprintf(FERROR,
575 "ERROR: --remove-sent-files cannot be used with a read-only module\n");
576 exit_cleanup(RERR_SYNTAX);
577 return;
578 }
7a92ded3 579
59187666 580 if (!relative_paths && !push_dir(dir)) {
982e05bb
WD
581 rsyserr(FERROR, errno, "push_dir#3 %s failed",
582 full_fname(dir));
65417579 583 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
584 }
585 argc--;
586 argv++;
d9c7edf6 587
48a1ff0d 588 if (argc == 0 && (recurse || list_only)) {
e1f67417 589 argc = 1;
7a6421fa
AT
590 argv--;
591 argv[0] = ".";
592 }
d9c7edf6 593
7a6421fa 594 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
595 if (!flist || flist->count == 0) {
596 exit_cleanup(0);
597 }
a00628b3 598 the_file_list = flist;
8d9dc9f9 599
da3478b2
WD
600 io_start_buffering_in();
601 io_start_buffering_out();
602
7a6421fa 603 send_files(flist,f_out,f_in);
f1e3656e 604 io_flush(FULL_FLUSH);
33c4b445 605 handle_stats(f_out);
4e0fcd85 606 if (protocol_version >= 24)
3485ae83 607 read_final_goodbye(f_in, f_out);
f1e3656e 608 io_flush(FULL_FLUSH);
7a6421fa 609 exit_cleanup(0);
c627d613
AT
610}
611
612
dc5ddbcc
AT
613static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
614{
d186eb1a 615 int pid;
84e6d6fd 616 int exit_code = 0;
c70e07d9 617 int error_pipe[2];
dc5ddbcc 618
bb6721dc
WD
619 /* The receiving side mustn't obey this, or an existing symlink that
620 * points to an identical file won't be replaced by the referent. */
621 copy_links = 0;
622
d186eb1a 623 if (preserve_hard_links)
3485ae83 624 init_hard_links();
dc5ddbcc 625
c70e07d9 626 if (fd_pair(error_pipe) < 0) {
ab759cd2 627 rsyserr(FERROR, errno, "pipe failed in do_recv");
c8f2f857 628 exit_cleanup(RERR_IPC);
554e0a8d 629 }
d9c7edf6 630
f1e3656e 631 io_flush(NORMAL_FLUSH);
c6e7fcb4 632
ba449e44 633 if ((pid = do_fork()) == -1) {
c8f2f857 634 rsyserr(FERROR, errno, "fork failed in do_recv");
ba449e44
WD
635 exit_cleanup(RERR_IPC);
636 }
637
638 if (pid == 0) {
554e0a8d 639 close(error_pipe[0]);
3a69fad0
WD
640 if (f_in != f_out)
641 close(f_out);
e08c9610 642
554e0a8d 643 /* we can't let two processes write to the socket at one time */
9eeb3b9c 644 close_multiplexing_out();
554e0a8d
AT
645
646 /* set place to send errors */
f1e3656e 647 set_msg_fd_out(error_pipe[1]);
554e0a8d 648
c70e07d9 649 recv_files(f_in, flist, local_name);
f1e3656e 650 io_flush(FULL_FLUSH);
33c4b445 651 handle_stats(f_in);
e08c9610 652
f1e3656e
WD
653 send_msg(MSG_DONE, "", 0);
654 io_flush(FULL_FLUSH);
4e0fcd85 655
40df65fd
WD
656 /* Handle any keep-alive packets from the post-processing work
657 * that the generator does. */
4e0fcd85 658 if (protocol_version >= 29) {
051182cb 659 kluge_around_eof = -1;
1a8e5c97
WD
660
661 /* This should only get stopped via a USR2 signal. */
662 while (read_int(f_in) == flist->count
663 && read_shortint(f_in) == ITEM_IS_NEW) {}
664
3485ae83
WD
665 rprintf(FERROR, "Invalid packet at end of run [%s]\n",
666 who_am_i());
1a8e5c97 667 exit_cleanup(RERR_PROTOCOL);
4e0fcd85
WD
668 }
669
9e0582f9
WD
670 /* Finally, we go to sleep until our parent kills us with a
671 * USR2 signal. We sleep for a short time, as on some OSes
672 * a signal won't interrupt a sleep! */
f1e3656e
WD
673 while (1)
674 msleep(20);
d186eb1a 675 }
dc5ddbcc 676
b695f242 677 am_generator = 1;
9eeb3b9c 678 close_multiplexing_in();
e8a96e27 679 if (write_batch && !am_server)
b9f592fb 680 stop_write_batch();
b695f242 681
554e0a8d 682 close(error_pipe[1]);
3a69fad0
WD
683 if (f_in != f_out)
684 close(f_in);
e1b3d5c4 685
da3478b2 686 io_start_buffering_out();
b3e10ed7 687
f1e3656e 688 set_msg_fd_in(error_pipe[0]);
554e0a8d 689
c70e07d9 690 generate_files(f_out, flist, local_name);
8d9dc9f9 691
33c4b445 692 handle_stats(-1);
f1e3656e 693 io_flush(FULL_FLUSH);
d04e9c51 694 if (protocol_version >= 24) {
8ada7518
AT
695 /* send a final goodbye message */
696 write_int(f_out, -1);
697 }
f1e3656e 698 io_flush(FULL_FLUSH);
8ada7518 699
f1e3656e 700 set_msg_fd_in(-1);
089a2435 701 kill(pid, SIGUSR2);
84e6d6fd
WD
702 wait_process_with_flush(pid, &exit_code);
703 return exit_code;
dc5ddbcc
AT
704}
705
c627d613 706
9486289c 707static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 708{
84e6d6fd 709 int exit_code;
7a6421fa 710 struct file_list *flist;
6c2e5b56 711 char *local_name = NULL;
7a6421fa 712 char *dir = NULL;
07bff66f
WD
713 int save_verbose = verbose;
714
715 if (filesfrom_fd >= 0) {
716 /* We can't mix messages with files-from data on the socket,
717 * so temporarily turn off verbose messages. */
718 verbose = 0;
719 }
f0fca04e 720
45e08edb
WD
721 if (verbose > 2) {
722 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
723 argc, (long)getpid());
724 }
09b7f5db 725
2adbcdc7 726 if (am_daemon && lp_read_only(module_id)) {
09b7f5db
AT
727 rprintf(FERROR,"ERROR: module is read only\n");
728 exit_cleanup(RERR_SYNTAX);
729 return;
730 }
731
7a6421fa
AT
732 if (argc > 0) {
733 dir = argv[0];
734 argc--;
735 argv++;
59187666 736 if (!am_daemon && !push_dir(dir)) {
982e05bb
WD
737 rsyserr(FERROR, errno, "push_dir#4 %s failed",
738 full_fname(dir));
65417579 739 exit_cleanup(RERR_FILESELECT);
d9c7edf6 740 }
7a6421fa 741 }
c627d613 742
da3478b2 743 io_start_buffering_in();
57dee64e 744 recv_filter_list(f_in);
c627d613 745
7c2a9e76 746 if (filesfrom_fd >= 0) {
07bff66f
WD
747 /* We need to send the files-from names to the sender at the
748 * same time that we receive the file-list from them, so we
749 * need the IO routines to automatically write out the names
750 * onto our f_out socket as we read the file-list. This
751 * avoids both deadlock and extra delays/buffers. */
7c2a9e76
WD
752 io_set_filesfrom_fds(filesfrom_fd, f_out);
753 filesfrom_fd = -1;
754 }
755
b9f592fb 756 flist = recv_file_list(f_in);
07bff66f 757 verbose = save_verbose;
4c36a13e
AT
758 if (!flist) {
759 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 760 exit_cleanup(RERR_FILESELECT);
7a6421fa 761 }
a00628b3 762 the_file_list = flist;
d9c7edf6 763
29fad7a3 764 if (argc > 0)
7a6421fa 765 local_name = get_local_name(flist,argv[0]);
c627d613 766
84e6d6fd
WD
767 exit_code = do_recv(f_in,f_out,flist,local_name);
768 exit_cleanup(exit_code);
c627d613
AT
769}
770
771
734a94a2 772int child_main(int argc, char *argv[])
25d34a5c
MP
773{
774 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 775 return 0;
25d34a5c
MP
776}
777
778
9486289c 779void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 780{
f0359dd0
AT
781 set_nonblocking(f_in);
782 set_nonblocking(f_out);
783
da3478b2
WD
784 io_set_sock_fds(f_in, f_out);
785 setup_protocol(f_out, f_in);
786
d04e9c51 787 if (protocol_version >= 23)
da3478b2 788 io_start_multiplex_out();
7a6421fa 789
7a6421fa 790 if (am_sender) {
83926d3c 791 keep_dirlinks = 0; /* Must be disabled on the sender. */
bf26aa22
WD
792 if (need_messages_from_generator)
793 io_start_multiplex_in();
9b3318b0 794
7842418b 795 recv_filter_list(f_in);
7a6421fa
AT
796 do_server_sender(f_in, f_out, argc, argv);
797 } else {
798 do_server_recv(f_in, f_out, argc, argv);
799 }
800 exit_cleanup(0);
366345fe
AT
801}
802
0ba48136
MP
803
804/*
805 * This is called once the connection has been negotiated. It is used
806 * for rsyncd, remote-shell, and local connections.
807 */
19b27a48 808int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 809{
088aac85 810 struct file_list *flist = NULL;
84e6d6fd 811 int exit_code = 0, exit_code2 = 0;
9486289c 812 char *local_name = NULL;
19b27a48
AT
813
814 cleanup_child_pid = pid;
67a28eb2 815 if (!read_batch) {
b9f592fb
WD
816 set_nonblocking(f_in);
817 set_nonblocking(f_out);
818 }
f0359dd0 819
da3478b2 820 io_set_sock_fds(f_in, f_out);
6d7b6081
AT
821 setup_protocol(f_out,f_in);
822
b9f592fb 823 if (protocol_version >= 23 && !read_batch)
da3478b2 824 io_start_multiplex_in();
d9c7edf6 825
18882701
WD
826 /* We set our stderr file handle to blocking because ssh might have
827 * set it to non-blocking. This can be particularly troublesome if
828 * stderr is a clone of stdout, because ssh would have set our stdout
829 * to non-blocking at the same time (which can easily cause us to lose
830 * output from our print statements). This kluge shouldn't cause ssh
831 * any problems for how we use it. Note also that we delayed setting
832 * this until after the above protocol setup so that we know for sure
833 * that ssh is done twiddling its file descriptors. */
834 set_blocking(STDERR_FILENO);
835
9486289c 836 if (am_sender) {
83926d3c 837 keep_dirlinks = 0; /* Must be disabled on the sender. */
da3478b2 838 io_start_buffering_out();
860236bf 839 if (!filesfrom_host)
a0a33ee5 840 set_msg_fd_in(f_in);
57dee64e 841 send_filter_list(f_out);
860236bf 842 if (filesfrom_host)
7c2a9e76 843 filesfrom_fd = f_in;
b9f592fb 844
e8a96e27 845 if (write_batch && !am_server)
b9f592fb 846 start_write_batch(f_out);
a00628b3 847 flist = send_file_list(f_out, argc, argv);
a0a33ee5 848 set_msg_fd_in(-1);
d9c7edf6 849 if (verbose > 3)
9486289c 850 rprintf(FINFO,"file list sent\n");
a00628b3 851 the_file_list = flist;
e1b3d5c4 852
f1e3656e 853 io_flush(NORMAL_FLUSH);
9486289c 854 send_files(flist,f_out,f_in);
f1e3656e 855 io_flush(FULL_FLUSH);
33c4b445 856 handle_stats(-1);
4e0fcd85 857 if (protocol_version >= 24)
3485ae83 858 read_final_goodbye(f_in, f_out);
9486289c
AT
859 if (pid != -1) {
860 if (verbose > 3)
08a740ff 861 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 862 io_flush(FULL_FLUSH);
84e6d6fd 863 wait_process_with_flush(pid, &exit_code);
9486289c 864 }
33c4b445 865 output_summary();
c87ae64a 866 io_flush(FULL_FLUSH);
84e6d6fd 867 exit_cleanup(exit_code);
9486289c 868 }
f7632fc6 869
bf26aa22
WD
870 if (need_messages_from_generator && !read_batch)
871 io_start_multiplex_out();
872
48a1ff0d
WD
873 if (argc == 0)
874 list_only |= 1;
d9c7edf6 875
57dee64e 876 send_filter_list(read_batch ? -1 : f_out);
d9c7edf6 877
7c2a9e76
WD
878 if (filesfrom_fd >= 0) {
879 io_set_filesfrom_fds(filesfrom_fd, f_out);
880 filesfrom_fd = -1;
881 }
882
e8a96e27 883 if (write_batch && !am_server)
b9f592fb 884 start_write_batch(f_in);
9486289c 885 flist = recv_file_list(f_in);
a00628b3 886 the_file_list = flist;
d9c7edf6 887
9d19f8a5
WD
888 if (flist && flist->count > 0) {
889 local_name = get_local_name(flist, argv[0]);
d9c7edf6 890
84e6d6fd 891 exit_code2 = do_recv(f_in, f_out, flist, local_name);
9d19f8a5
WD
892 } else {
893 handle_stats(-1);
894 output_summary();
895 }
d9c7edf6 896
9486289c 897 if (pid != -1) {
8d9dc9f9 898 if (verbose > 3)
08a740ff 899 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 900 io_flush(FULL_FLUSH);
84e6d6fd 901 wait_process_with_flush(pid, &exit_code);
9486289c 902 }
d9c7edf6 903
84e6d6fd 904 return MAX(exit_code, exit_code2);
9486289c
AT
905}
906
7169bb4a
MP
907static int copy_argv (char *argv[])
908{
909 int i;
910
911 for (i = 0; argv[i]; i++) {
912 if (!(argv[i] = strdup(argv[i]))) {
913 rprintf (FERROR, "out of memory at %s(%d)\n",
914 __FILE__, __LINE__);
915 return RERR_MALLOC;
916 }
917 }
918
919 return 0;
920}
921
922
c1a04ecb 923/**
0ba48136
MP
924 * Start a client for either type of remote connection. Work out
925 * whether the arguments request a remote shell or rsyncd connection,
926 * and call the appropriate connection function, then run_client.
0b4af330
MP
927 *
928 * Calls either start_socket_client (for sockets) or do_cmd and
929 * client_run (for ssh).
c1a04ecb 930 **/
fc8a6b97 931static int start_client(int argc, char *argv[])
5d6bcd44
AT
932{
933 char *p;
934 char *shell_machine = NULL;
935 char *shell_path = NULL;
936 char *shell_user = NULL;
19b27a48
AT
937 int ret;
938 pid_t pid;
5d6bcd44 939 int f_in,f_out;
7169bb4a
MP
940 int rc;
941
942 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 943 * command line. */
75aeac44 944 if ((rc = copy_argv(argv)))
7169bb4a 945 return rc;
5d6bcd44 946
d16c245f 947 if (!read_batch) { /* for read_batch, NO source is specified */
42ccb4c0 948 argc--;
860236bf
WD
949 shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
950 if (shell_path) { /* source is remote */
9425918d
WD
951 char *dummy1;
952 int dummy2;
3f7bfac2 953 if (argc && check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
9425918d
WD
954 rprintf(FERROR,
955 "The source and destination cannot both be remote.\n");
956 exit_cleanup(RERR_SYNTAX);
957 }
42ccb4c0 958 argv++;
860236bf
WD
959 if (filesfrom_host && *filesfrom_host
960 && strcmp(filesfrom_host, shell_machine) != 0) {
7c2a9e76 961 rprintf(FERROR,
50b31539 962 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
963 exit_cleanup(RERR_SYNTAX);
964 }
860236bf 965 if (rsync_port) {
d9c7edf6 966 if (!shell_cmd) {
860236bf
WD
967 return start_socket_client(shell_machine,
968 shell_path,
42ccb4c0 969 argc, argv);
d9c7edf6 970 }
d9c7edf6 971 daemon_over_rsh = 1;
75aeac44 972 }
3591c066 973
42ccb4c0
WD
974 am_sender = 0;
975 } else { /* source is local, check dest arg */
976 am_sender = 1;
977
d16c245f 978 if (argc < 1) { /* destination required */
d9c7edf6
WD
979 usage(FERROR);
980 exit_cleanup(RERR_SYNTAX);
981 }
a125c82a 982
42ccb4c0 983 shell_path = check_for_hostspec(argv[argc], &shell_machine, &rsync_port);
860236bf
WD
984 if (shell_path && filesfrom_host && *filesfrom_host
985 && strcmp(filesfrom_host, shell_machine) != 0) {
7c2a9e76 986 rprintf(FERROR,
50b31539 987 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
988 exit_cleanup(RERR_SYNTAX);
989 }
860236bf 990 if (!shell_path) { /* no hostspec found, so src & dest are local */
d9c7edf6 991 local_server = 1;
860236bf 992 if (filesfrom_host) {
7c2a9e76 993 rprintf(FERROR,
50b31539 994 "--files-from cannot be remote when the transfer is local\n");
7c2a9e76
WD
995 exit_cleanup(RERR_SYNTAX);
996 }
860236bf 997 shell_machine = NULL;
42ccb4c0 998 shell_path = argv[argc];
860236bf 999 } else if (rsync_port) {
d9c7edf6 1000 if (!shell_cmd) {
860236bf
WD
1001 return start_socket_client(shell_machine,
1002 shell_path,
42ccb4c0 1003 argc, argv);
d9c7edf6 1004 }
d9c7edf6 1005 daemon_over_rsh = 1;
a125c82a 1006 }
5d6bcd44 1007 }
d16c245f 1008 } else { /* read_batch */
d9c7edf6
WD
1009 local_server = 1;
1010 shell_path = argv[argc-1];
860236bf 1011 if (check_for_hostspec(shell_path, &shell_machine, &rsync_port)) {
b9f592fb
WD
1012 rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
1013 exit_cleanup(RERR_SYNTAX);
1014 }
6902ed17
MP
1015 }
1016
5d6bcd44 1017 if (shell_machine) {
6fc048f4 1018 p = strrchr(shell_machine,'@');
5d6bcd44
AT
1019 if (p) {
1020 *p = 0;
1021 shell_user = shell_machine;
1022 shell_machine = p+1;
1023 }
1024 }
1025
1026 if (verbose > 3) {
9486289c 1027 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
45c49b52
WD
1028 shell_cmd ? shell_cmd : "",
1029 shell_machine ? shell_machine : "",
1030 shell_user ? shell_user : "",
1031 shell_path ? shell_path : "");
5d6bcd44 1032 }
d9c7edf6 1033
d16c245f 1034 /* for remote source, only single dest arg can remain ... */
f7632fc6 1035 if (!am_sender && argc > 1) {
5d6bcd44 1036 usage(FERROR);
65417579 1037 exit_cleanup(RERR_SYNTAX);
5d6bcd44 1038 }
27e3e9c9 1039
d16c245f 1040 /* ... or no dest at all */
48a1ff0d
WD
1041 if (!am_sender && argc == 0)
1042 list_only |= 1;
d9c7edf6 1043
75aeac44
WD
1044 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
1045 &f_in,&f_out);
1046
1047 /* if we're running an rsync server on the remote host over a
9af87151 1048 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
1049 if (daemon_over_rsh) {
1050 int tmpret;
1051 tmpret = start_inband_exchange(shell_user, shell_path,
1052 f_in, f_out, argc);
1053 if (tmpret < 0)
1054 return tmpret;
1055 }
1056
fc8a6b97
AT
1057 ret = client_run(f_in, f_out, pid, argc, argv);
1058
1059 fflush(stdout);
1060 fflush(stderr);
1061
1062 return ret;
5d6bcd44
AT
1063}
1064
366345fe 1065
067669da
WD
1066static RETSIGTYPE sigusr1_handler(UNUSED(int val))
1067{
6bf32edb 1068 exit_cleanup(RERR_SIGNAL1);
82306bf6
AT
1069}
1070
067669da
WD
1071static RETSIGTYPE sigusr2_handler(UNUSED(int val))
1072{
33c4b445
WD
1073 if (!am_server)
1074 output_summary();
40df65fd 1075 close_all();
33c4b445
WD
1076 if (log_got_error)
1077 _exit(RERR_PARTIAL);
8b35435f
AT
1078 _exit(0);
1079}
1080
067669da
WD
1081static RETSIGTYPE sigchld_handler(UNUSED(int val))
1082{
029c1713 1083#ifdef WNOHANG
ee7118a8
DD
1084 int cnt, status;
1085 pid_t pid;
1086 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 1087 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
1088 * out we're instead saving the child exit statuses for later use.
1089 * The waitpid() loop presumably eliminates all possibility of leaving
97d8e709 1090 * zombie children, maybe that's why he did it. */
ee7118a8 1091 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
1092 /* save the child's exit status */
1093 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
1094 if (pid_stat_table[cnt].pid == 0) {
1095 pid_stat_table[cnt].pid = pid;
1096 pid_stat_table[cnt].status = status;
1097 break;
1098 }
1099 }
ee7118a8 1100 }
029c1713 1101#endif
97d8e709 1102 signal(SIGCHLD, sigchld_handler);
19b27a48
AT
1103}
1104
c0531332
MP
1105
1106/**
1107 * This routine catches signals and tries to send them to gdb.
1108 *
1109 * Because it's called from inside a signal handler it ought not to
1110 * use too many library routines.
1111 *
1112 * @todo Perhaps use "screen -X" instead/as well, to help people
1113 * debugging without easy access to X. Perhaps use an environment
1114 * variable, or just call a script?
1115 *
1116 * @todo The /proc/ magic probably only works on Linux (and
1117 * Solaris?) Can we be more portable?
1118 **/
1119#ifdef MAINTAINER_MODE
4fdc39dd
MP
1120const char *get_panic_action(void)
1121{
1122 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
1123
1124 if (cmd_fmt)
1125 return cmd_fmt;
1126 else
1127 return "xterm -display :0 -T Panic -n Panic "
1128 "-e gdb /proc/%d/exe %d";
1129}
1130
1131
9fb3f7a9
MP
1132/**
1133 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
1134 *
1135 * This signal handler is only installed if we were configured with
1136 * --enable-maintainer-mode. Perhaps it should always be on and we
1137 * should just look at the environment variable, but I'm a bit leery
1138 * of a signal sending us into a busy loop.
1139 **/
067669da 1140static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
1141{
1142 char cmd_buf[300];
1143 int ret;
4fdc39dd
MP
1144
1145 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
1146 getpid(), getpid());
1147
1148 /* Unless we failed to execute gdb, we allow the process to
1149 * continue. I'm not sure if that's right. */
1150 ret = system(cmd_buf);
1151 if (ret)
1152 _exit(ret);
1153}
1154#endif
1155
1156
5d6bcd44 1157int main(int argc,char *argv[])
d9c7edf6 1158{
ff81e809 1159 int ret;
66a9dc96
WD
1160 int orig_argc = argc;
1161 char **orig_argv = argv;
5d6bcd44 1162
7a6421fa 1163 signal(SIGUSR1, sigusr1_handler);
8b35435f 1164 signal(SIGUSR2, sigusr2_handler);
19b27a48 1165 signal(SIGCHLD, sigchld_handler);
c0531332
MP
1166#ifdef MAINTAINER_MODE
1167 signal(SIGSEGV, rsync_panic_handler);
1168 signal(SIGFPE, rsync_panic_handler);
1169 signal(SIGABRT, rsync_panic_handler);
1170 signal(SIGBUS, rsync_panic_handler);
1171#endif /* def MAINTAINER_MODE */
5d6bcd44 1172
7a6421fa 1173 starttime = time(NULL);
6fe05820 1174 am_root = (MY_UID() == 0);
c627d613 1175
a800434a
AT
1176 memset(&stats, 0, sizeof(stats));
1177
df5e03da
AT
1178 if (argc < 2) {
1179 usage(FERROR);
65417579 1180 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
1181 }
1182
7a6421fa 1183 /* we set a 0 umask so that correct file permissions can be
9af87151 1184 * carried across */
7a6421fa 1185 orig_umask = (int)umask(0);
5d6bcd44 1186
eb598fac
WD
1187#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
1188 setlocale(LC_CTYPE, "");
1189#endif
1190
50135767 1191 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
1192 /* FIXME: We ought to call the same error-handling
1193 * code here, rather than relying on getopt. */
50135767 1194 option_error();
65417579 1195 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1196 }
5d6bcd44 1197
7a6421fa 1198 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1199 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1200 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1201
34758d5c
MP
1202 /* Ignore SIGPIPE; we consistently check error codes and will
1203 * see the EPIPE. */
1204 signal(SIGPIPE, SIG_IGN);
1205
c226b7c2 1206 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1207 * (implemented by forking "pwd" and reading its output) doesn't
1208 * work when there are other child processes. Also, on all systems
1209 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1210 push_dir(NULL);
c226b7c2 1211
44e9e221
WD
1212 init_flist();
1213
e8a96e27 1214 if ((write_batch || read_batch) && !am_server) {
b9f592fb 1215 if (write_batch)
66a9dc96 1216 write_batch_shell_file(orig_argc, orig_argv, argc);
b9f592fb 1217
dbbab0c4
WD
1218 if (read_batch && strcmp(batch_name, "-") == 0)
1219 batch_fd = STDIN_FILENO;
1220 else {
1221 batch_fd = do_open(batch_name,
b9f592fb
WD
1222 write_batch ? O_WRONLY | O_CREAT | O_TRUNC
1223 : O_RDONLY, S_IRUSR | S_IWUSR);
dbbab0c4 1224 }
b9f592fb
WD
1225 if (batch_fd < 0) {
1226 rsyserr(FERROR, errno, "Batch file %s open error",
71903f60 1227 full_fname(batch_name));
b9f592fb
WD
1228 exit_cleanup(RERR_FILEIO);
1229 }
9459290a
WD
1230 if (read_batch)
1231 read_stream_flags(batch_fd);
6902ed17 1232 }
e8a96e27
WD
1233 if (write_batch < 0)
1234 dry_run = 1;
6902ed17 1235
75aeac44 1236 if (am_daemon && !am_server)
7a6421fa 1237 return daemon_main();
f0fca04e 1238
08ac228f
AT
1239 if (argc < 1) {
1240 usage(FERROR);
65417579 1241 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1242 }
1243
7a6421fa 1244 if (am_server) {
f0359dd0
AT
1245 set_nonblocking(STDIN_FILENO);
1246 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1247 if (am_daemon)
1248 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1249 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1250 }
c627d613 1251
ff81e809 1252 ret = start_client(argc, argv);
d9c7edf6 1253 if (ret == -1)
9098bbf3 1254 exit_cleanup(RERR_STARTCLIENT);
088aac85 1255 else
9098bbf3
MP
1256 exit_cleanup(ret);
1257
0f5a04e3 1258 return ret;
c627d613 1259}