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