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