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