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