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