A minor change to the HAVE_GETPGRP code.
[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",
f846a9bf
WD
236 getpid(), am_server ? "server " : "",
237 am_daemon ? "daemon " : "", who_am_i());
238 rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
239 (long)mi.arena);
240 rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n",
241 (long)mi.ordblks);
242 rprintf(FINFO, " smblks: %10ld\n",
243 (long)mi.smblks);
244 rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n",
245 (long)mi.hblks);
246 rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n",
247 (long)mi.hblkhd);
248 rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n",
249 (long)mi.arena + mi.hblkhd);
250 rprintf(FINFO, " usmblks: %10ld\n",
251 (long)mi.usmblks);
252 rprintf(FINFO, " fsmblks: %10ld\n",
253 (long)mi.fsmblks);
254 rprintf(FINFO, " uordblks: %10ld (bytes used)\n",
255 (long)mi.uordblks);
256 rprintf(FINFO, " fordblks: %10ld (bytes free)\n",
257 (long)mi.fordblks);
258 rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n",
259 (long)mi.keepcost);
e5a2b854
MP
260#endif /* HAVE_MALLINFO */
261}
262
263
0882faa2 264/* Start the remote shell. cmd may be NULL to use the default. */
6c2e5b56
WD
265static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
266 int *f_in, int *f_out)
c627d613 267{
6c2e5b56 268 int i, argc = 0;
887e553f 269 char *args[MAX_ARGS];
19b27a48 270 pid_t ret;
6c2e5b56 271 char *tok, *dir = NULL;
bb4aa89c 272 int dash_l_set = 0;
366345fe 273
088aac85 274 if (!read_batch && !local_server) {
9af87151 275 char *rsh_env = getenv(RSYNC_RSH_ENV);
366345fe 276 if (!cmd)
9af87151 277 cmd = rsh_env;
366345fe
AT
278 if (!cmd)
279 cmd = RSYNC_RSH;
280 cmd = strdup(cmd);
d9c7edf6 281 if (!cmd)
366345fe
AT
282 goto oom;
283
887e553f 284 for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
e7a392c7
WD
285 /* Comparison leaves rooms for server_options(). */
286 if (argc >= MAX_ARGS - 100) {
287 rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
887e553f
WD
288 exit_cleanup(RERR_SYNTAX);
289 }
366345fe 290 args[argc++] = tok;
887e553f 291 }
c627d613 292
d9c7edf6 293 /* check to see if we've already been given '-l user' in
9af87151 294 * the remote-shell command */
bb4aa89c
WD
295 for (i = 0; i < argc-1; i++) {
296 if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
297 dash_l_set = 1;
298 }
299
7b8356d0 300#if HAVE_REMSH
366345fe
AT
301 /* remsh (on HPUX) takes the arguments the other way around */
302 args[argc++] = machine;
bb4aa89c 303 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
304 args[argc++] = "-l";
305 args[argc++] = user;
306 }
7b8356d0 307#else
bb4aa89c 308 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
309 args[argc++] = "-l";
310 args[argc++] = user;
311 }
312 args[argc++] = machine;
7b8356d0 313#endif
c627d613 314
366345fe 315 args[argc++] = rsync_path;
c627d613 316
9af87151 317 if (blocking_io < 0) {
90e22f4b
WD
318 char *cp;
319 if ((cp = strrchr(cmd, '/')) != NULL)
320 cp++;
321 else
322 cp = cmd;
323 if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
324 blocking_io = 1;
66b71163 325 }
e384bfbd 326
93689aa5 327 server_options(args,&argc);
e7a392c7
WD
328
329 if (argc >= MAX_ARGS - 2) {
330 rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
331 exit_cleanup(RERR_SYNTAX);
332 }
366345fe 333 }
c627d613 334
366345fe 335 args[argc++] = ".";
76076c4b 336
d9c7edf6 337 if (!daemon_over_rsh && path && *path)
366345fe 338 args[argc++] = path;
c627d613 339
366345fe 340 args[argc] = NULL;
c627d613 341
366345fe 342 if (verbose > 3) {
9486289c 343 rprintf(FINFO,"cmd=");
e7a392c7 344 for (i = 0; i < argc; i++)
9486289c
AT
345 rprintf(FINFO,"%s ",args[i]);
346 rprintf(FINFO,"\n");
366345fe
AT
347 }
348
c0d8e84c
WD
349 if (read_batch) {
350 int from_gen_pipe[2];
351 if (fd_pair(from_gen_pipe) < 0) {
352 rsyserr(FERROR, errno, "pipe");
353 exit_cleanup(RERR_IPC);
354 }
355 batch_gen_fd = from_gen_pipe[0];
356 *f_out = from_gen_pipe[1];
357 *f_in = batch_fd;
358 ret = -1; /* no child pid */
359 } else if (local_server) {
b1df18d7
WD
360 /* If the user didn't request --[no-]whole-file, force
361 * it on, but only if we're not batch processing. */
c0d8e84c 362 if (whole_file < 0 && !write_batch)
b1df18d7 363 whole_file = 1;
25d34a5c 364 ret = local_child(argc, args, f_in, f_out, child_main);
c0d8e84c 365 } else
366345fe 366 ret = piped_child(args,f_in,f_out);
c627d613 367
3a69fad0
WD
368 if (dir)
369 free(dir);
82306bf6 370
366345fe 371 return ret;
c627d613
AT
372
373oom:
366345fe
AT
374 out_of_memory("do_cmd");
375 return 0; /* not reached */
c627d613
AT
376}
377
378
c627d613
AT
379static char *get_local_name(struct file_list *flist,char *name)
380{
7a6421fa 381 STRUCT_STAT st;
87cc45e1 382 int e;
c627d613 383
c95da96a 384 if (verbose > 2)
d9c7edf6 385 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
386 flist->count, NS(name));
387
d9c7edf6 388 if (!name)
1f0610ef 389 return NULL;
c95da96a 390
1ff5450d
AT
391 if (do_stat(name,&st) == 0) {
392 if (S_ISDIR(st.st_mode)) {
59187666 393 if (!push_dir(name)) {
982e05bb
WD
394 rsyserr(FERROR, errno, "push_dir#1 %s failed",
395 full_fname(name));
65417579 396 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
397 }
398 return NULL;
399 }
400 if (flist->count > 1) {
401 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 402 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
403 }
404 return name;
405 }
406
87cc45e1 407 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
1ff5450d
AT
408 return name;
409
1ff5450d 410 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
982e05bb 411 rsyserr(FERROR, errno, "mkdir %s failed", full_fname(name));
65417579 412 exit_cleanup(RERR_FILEIO);
e5a96f0f
WD
413 }
414 if (verbose > 0)
415 rprintf(FINFO, "created directory %s\n", name);
416
417 if (dry_run) {
418 dry_run++;
419 return NULL;
1ff5450d
AT
420 }
421
59187666 422 if (!push_dir(name)) {
982e05bb
WD
423 rsyserr(FERROR, errno, "push_dir#2 %s failed",
424 full_fname(name));
65417579 425 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
426 }
427
428 return NULL;
c627d613
AT
429}
430
431
9486289c 432static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 433{
7a6421fa
AT
434 int i;
435 struct file_list *flist;
436 char *dir = argv[0];
c627d613 437
45e08edb
WD
438 if (verbose > 2) {
439 rprintf(FINFO, "server_sender starting pid=%ld\n",
440 (long)getpid());
441 }
d9c7edf6 442
2adbcdc7 443 if (am_daemon && lp_write_only(module_id)) {
7a92ded3
WD
444 rprintf(FERROR, "ERROR: module is write only\n");
445 exit_cleanup(RERR_SYNTAX);
446 return;
447 }
448
59187666 449 if (!relative_paths && !push_dir(dir)) {
982e05bb
WD
450 rsyserr(FERROR, errno, "push_dir#3 %s failed",
451 full_fname(dir));
65417579 452 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
453 }
454 argc--;
455 argv++;
d9c7edf6 456
7a6421fa
AT
457 if (strcmp(dir,".")) {
458 int l = strlen(dir);
d9c7edf6 459 if (strcmp(dir,"/") == 0)
7a6421fa 460 l = 0;
e7a392c7 461 for (i = 0; i < argc; i++)
7a6421fa
AT
462 argv[i] += l+1;
463 }
c627d613 464
48a1ff0d 465 if (argc == 0 && (recurse || list_only)) {
e1f67417 466 argc = 1;
7a6421fa
AT
467 argv--;
468 argv[0] = ".";
469 }
d9c7edf6 470
7a6421fa 471 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
472 if (!flist || flist->count == 0) {
473 exit_cleanup(0);
474 }
475
da3478b2
WD
476 io_start_buffering_in();
477 io_start_buffering_out();
478
7a6421fa 479 send_files(flist,f_out,f_in);
f1e3656e 480 io_flush(FULL_FLUSH);
7a6421fa 481 report(f_out);
d04e9c51 482 if (protocol_version >= 24) {
d9c7edf6 483 /* final goodbye message */
64c3523a
WD
484 read_int(f_in);
485 }
f1e3656e 486 io_flush(FULL_FLUSH);
7a6421fa 487 exit_cleanup(0);
c627d613
AT
488}
489
490
dc5ddbcc
AT
491static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
492{
d186eb1a 493 int pid;
e1f67417 494 int status = 0;
41cfde6b 495 int error_pipe[2], name_pipe[2];
7162c65d 496 BOOL need_name_pipe = (basis_dir[0] || partial_dir) && !dry_run;
dc5ddbcc 497
bb6721dc
WD
498 /* The receiving side mustn't obey this, or an existing symlink that
499 * points to an identical file won't be replaced by the referent. */
500 copy_links = 0;
501
d186eb1a
AT
502 if (preserve_hard_links)
503 init_hard_links(flist);
dc5ddbcc 504
48a1ff0d 505 if (delete_before) {
6957ae33 506 /* I moved this here from recv_files() to prevent a race condition */
b98f040e 507 if (recurse && !local_name && flist->count > 0)
6957ae33 508 delete_files(flist);
6957ae33
AT
509 }
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();
b33b791e 626 if (delete_mode && !delete_excluded)
7842418b 627 recv_filter_list(f_in);
ddf64101
WD
628 if (cvs_exclude)
629 add_cvs_excludes();
c627d613 630
7c2a9e76 631 if (filesfrom_fd >= 0) {
07bff66f
WD
632 /* We need to send the files-from names to the sender at the
633 * same time that we receive the file-list from them, so we
634 * need the IO routines to automatically write out the names
635 * onto our f_out socket as we read the file-list. This
636 * avoids both deadlock and extra delays/buffers. */
7c2a9e76
WD
637 io_set_filesfrom_fds(filesfrom_fd, f_out);
638 filesfrom_fd = -1;
639 }
640
b9f592fb 641 flist = recv_file_list(f_in);
07bff66f 642 verbose = save_verbose;
4c36a13e
AT
643 if (!flist) {
644 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 645 exit_cleanup(RERR_FILESELECT);
7a6421fa 646 }
d9c7edf6
WD
647
648 if (argc > 0) {
7a6421fa
AT
649 if (strcmp(dir,".")) {
650 argv[0] += strlen(dir);
3a69fad0
WD
651 if (argv[0][0] == '/')
652 argv[0]++;
7a6421fa
AT
653 }
654 local_name = get_local_name(flist,argv[0]);
655 }
c627d613 656
7a6421fa
AT
657 status = do_recv(f_in,f_out,flist,local_name);
658 exit_cleanup(status);
c627d613
AT
659}
660
661
734a94a2 662int child_main(int argc, char *argv[])
25d34a5c
MP
663{
664 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 665 return 0;
25d34a5c
MP
666}
667
668
9486289c 669void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 670{
f0359dd0
AT
671 set_nonblocking(f_in);
672 set_nonblocking(f_out);
673
da3478b2
WD
674 io_set_sock_fds(f_in, f_out);
675 setup_protocol(f_out, f_in);
676
d04e9c51 677 if (protocol_version >= 23)
da3478b2 678 io_start_multiplex_out();
7a6421fa 679
7a6421fa 680 if (am_sender) {
83926d3c 681 keep_dirlinks = 0; /* Must be disabled on the sender. */
9b3318b0 682
7842418b 683 recv_filter_list(f_in);
b9f592fb
WD
684 if (cvs_exclude)
685 add_cvs_excludes();
7a6421fa
AT
686 do_server_sender(f_in, f_out, argc, argv);
687 } else {
688 do_server_recv(f_in, f_out, argc, argv);
689 }
690 exit_cleanup(0);
366345fe
AT
691}
692
0ba48136
MP
693
694/*
695 * This is called once the connection has been negotiated. It is used
696 * for rsyncd, remote-shell, and local connections.
697 */
19b27a48 698int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 699{
088aac85 700 struct file_list *flist = NULL;
9486289c
AT
701 int status = 0, status2 = 0;
702 char *local_name = NULL;
19b27a48
AT
703
704 cleanup_child_pid = pid;
67a28eb2 705 if (!read_batch) {
b9f592fb
WD
706 set_nonblocking(f_in);
707 set_nonblocking(f_out);
708 }
f0359dd0 709
da3478b2 710 io_set_sock_fds(f_in, f_out);
6d7b6081
AT
711 setup_protocol(f_out,f_in);
712
b9f592fb 713 if (protocol_version >= 23 && !read_batch)
da3478b2 714 io_start_multiplex_in();
d9c7edf6 715
18882701
WD
716 /* We set our stderr file handle to blocking because ssh might have
717 * set it to non-blocking. This can be particularly troublesome if
718 * stderr is a clone of stdout, because ssh would have set our stdout
719 * to non-blocking at the same time (which can easily cause us to lose
720 * output from our print statements). This kluge shouldn't cause ssh
721 * any problems for how we use it. Note also that we delayed setting
722 * this until after the above protocol setup so that we know for sure
723 * that ssh is done twiddling its file descriptors. */
724 set_blocking(STDERR_FILENO);
725
9486289c 726 if (am_sender) {
83926d3c 727 keep_dirlinks = 0; /* Must be disabled on the sender. */
da3478b2 728 io_start_buffering_out();
a0a33ee5
WD
729 if (!remote_filesfrom_file)
730 set_msg_fd_in(f_in);
9486289c
AT
731 if (cvs_exclude)
732 add_cvs_excludes();
d9c7edf6 733 if (delete_mode && !delete_excluded)
7842418b 734 send_filter_list(f_out);
7c2a9e76
WD
735 if (remote_filesfrom_file)
736 filesfrom_fd = f_in;
b9f592fb
WD
737
738 if (write_batch)
739 start_write_batch(f_out);
64c3523a 740 if (!read_batch) /* don't write to pipe */
d9c7edf6 741 flist = send_file_list(f_out,argc,argv);
a0a33ee5 742 set_msg_fd_in(-1);
d9c7edf6 743 if (verbose > 3)
9486289c 744 rprintf(FINFO,"file list sent\n");
e1b3d5c4 745
f1e3656e 746 io_flush(NORMAL_FLUSH);
9486289c 747 send_files(flist,f_out,f_in);
f1e3656e 748 io_flush(FULL_FLUSH);
d04e9c51 749 if (protocol_version >= 24) {
d9c7edf6 750 /* final goodbye message */
6c65e146
AT
751 read_int(f_in);
752 }
9486289c
AT
753 if (pid != -1) {
754 if (verbose > 3)
08a740ff 755 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 756 io_flush(FULL_FLUSH);
d79d1c69 757 wait_process(pid, &status);
9486289c 758 }
3d382777 759 report(-1);
f1e3656e 760 io_flush(FULL_FLUSH);
9486289c
AT
761 exit_cleanup(status);
762 }
f7632fc6 763
48a1ff0d
WD
764 if (argc == 0)
765 list_only |= 1;
d9c7edf6 766
1082b52b 767 if (!read_batch)
7842418b 768 send_filter_list(f_out);
928a00c4
WD
769 if (cvs_exclude)
770 add_cvs_excludes();
d9c7edf6 771
7c2a9e76
WD
772 if (filesfrom_fd >= 0) {
773 io_set_filesfrom_fds(filesfrom_fd, f_out);
774 filesfrom_fd = -1;
775 }
776
b9f592fb
WD
777 if (write_batch)
778 start_write_batch(f_in);
9486289c
AT
779 flist = recv_file_list(f_in);
780 if (!flist || flist->count == 0) {
796d484b 781 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
782 "perhaps you need to specify some filenames or "
783 "the --recursive option?\n");
9486289c
AT
784 exit_cleanup(0);
785 }
d9c7edf6 786
9486289c 787 local_name = get_local_name(flist,argv[0]);
d9c7edf6 788
9486289c 789 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 790
9486289c 791 if (pid != -1) {
8d9dc9f9 792 if (verbose > 3)
08a740ff 793 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 794 io_flush(FULL_FLUSH);
d79d1c69 795 wait_process(pid, &status);
9486289c 796 }
d9c7edf6 797
ff81e809 798 return MAX(status, status2);
9486289c
AT
799}
800
7169bb4a
MP
801static int copy_argv (char *argv[])
802{
803 int i;
804
805 for (i = 0; argv[i]; i++) {
806 if (!(argv[i] = strdup(argv[i]))) {
807 rprintf (FERROR, "out of memory at %s(%d)\n",
808 __FILE__, __LINE__);
809 return RERR_MALLOC;
810 }
811 }
812
813 return 0;
814}
815
816
c1a04ecb 817/**
0ba48136
MP
818 * Start a client for either type of remote connection. Work out
819 * whether the arguments request a remote shell or rsyncd connection,
820 * and call the appropriate connection function, then run_client.
0b4af330
MP
821 *
822 * Calls either start_socket_client (for sockets) or do_cmd and
823 * client_run (for ssh).
c1a04ecb 824 **/
fc8a6b97 825static int start_client(int argc, char *argv[])
5d6bcd44
AT
826{
827 char *p;
828 char *shell_machine = NULL;
829 char *shell_path = NULL;
830 char *shell_user = NULL;
19b27a48
AT
831 int ret;
832 pid_t pid;
5d6bcd44 833 int f_in,f_out;
7169bb4a
MP
834 int rc;
835
836 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 837 * command line. */
75aeac44 838 if ((rc = copy_argv(argv)))
7169bb4a 839 return rc;
5d6bcd44 840
75aeac44 841 /* rsync:// always uses rsync server over direct socket connection */
b9f592fb
WD
842 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0
843 && !read_batch) {
f7632fc6
AT
844 char *host, *path;
845
7169bb4a 846 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
847 p = strchr(host,'/');
848 if (p) {
50b31539 849 *p = '\0';
f7632fc6 850 path = p+1;
50b31539 851 } else
a125c82a 852 path = "";
50b31539
WD
853 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
854 host++;
855 *p++ = '\0';
856 if (*p != ':')
857 p = NULL;
858 } else
859 p = strchr(host, ':');
2acf81eb
DD
860 if (p) {
861 rsync_port = atoi(p+1);
50b31539 862 *p = '\0';
cf510ad2 863 }
f7632fc6
AT
864 return start_socket_client(host, path, argc-1, argv+1);
865 }
866
d16c245f 867 if (!read_batch) { /* for read_batch, NO source is specified */
a125c82a 868 p = find_colon(argv[0]);
d16c245f 869 if (p) { /* source is remote */
7c2a9e76
WD
870 if (remote_filesfrom_file
871 && remote_filesfrom_file != files_from + 1
872 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
873 rprintf(FERROR,
50b31539 874 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
875 exit_cleanup(RERR_SYNTAX);
876 }
d9c7edf6
WD
877 if (p[1] == ':') { /* double colon */
878 *p = 0;
879 if (!shell_cmd) {
880 return start_socket_client(argv[0], p+2,
881 argc-1, argv+1);
882 }
883 p++;
884 daemon_over_rsh = 1;
75aeac44 885 }
3591c066 886
d16c245f 887 if (argc < 1) { /* destination required */
d9c7edf6
WD
888 usage(FERROR);
889 exit_cleanup(RERR_SYNTAX);
890 }
a125c82a 891
d9c7edf6
WD
892 am_sender = 0;
893 *p = 0;
894 shell_machine = argv[0];
895 shell_path = p+1;
d9c7edf6 896 argv++;
d16c245f 897 } else { /* source is local */
d9c7edf6
WD
898 am_sender = 1;
899
900 /* rsync:// destination uses rsync server over direct socket */
901 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
902 char *host, *path;
903
904 host = argv[argc-1] + strlen(URL_PREFIX);
905 p = strchr(host,'/');
906 if (p) {
50b31539 907 *p = '\0';
d9c7edf6 908 path = p+1;
50b31539 909 } else
d9c7edf6 910 path = "";
50b31539
WD
911 if (*host == '[' && (p = strchr(host, ']')) != NULL) {
912 host++;
913 *p++ = '\0';
914 if (*p != ':')
915 p = NULL;
916 } else
917 p = strchr(host, ':');
d9c7edf6
WD
918 if (p) {
919 rsync_port = atoi(p+1);
50b31539 920 *p = '\0';
cf510ad2 921 }
d9c7edf6 922 return start_socket_client(host, path, argc-1, argv);
a125c82a 923 }
d9c7edf6 924
d16c245f 925 p = find_colon(argv[argc-1]); /* look in dest arg */
7c2a9e76
WD
926 if (p && remote_filesfrom_file
927 && remote_filesfrom_file != files_from + 1
928 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
929 rprintf(FERROR,
50b31539 930 "--files-from hostname is not the same as the transfer hostname\n");
7c2a9e76
WD
931 exit_cleanup(RERR_SYNTAX);
932 }
d16c245f 933 if (!p) { /* no colon found, so src & dest are local */
d9c7edf6 934 local_server = 1;
7c2a9e76
WD
935 if (remote_filesfrom_file) {
936 rprintf(FERROR,
50b31539 937 "--files-from cannot be remote when the transfer is local\n");
7c2a9e76
WD
938 exit_cleanup(RERR_SYNTAX);
939 }
d9c7edf6 940 } else if (p[1] == ':') { /* double colon */
a125c82a 941 *p = 0;
d9c7edf6
WD
942 if (!shell_cmd) {
943 return start_socket_client(argv[argc-1], p+2,
944 argc-1, argv);
945 }
946 p++;
947 daemon_over_rsh = 1;
a125c82a 948 }
a125c82a 949
d9c7edf6
WD
950 if (argc < 2) {
951 usage(FERROR);
952 exit_cleanup(RERR_SYNTAX);
75aeac44 953 }
3591c066 954
d9c7edf6
WD
955 if (local_server) {
956 shell_machine = NULL;
957 shell_path = argv[argc-1];
958 } else {
959 *p = 0;
960 shell_machine = argv[argc-1];
961 shell_path = p+1;
962 }
5d6bcd44 963 }
d16c245f
WD
964 argc--;
965 } else { /* read_batch */
d9c7edf6
WD
966 local_server = 1;
967 shell_path = argv[argc-1];
b9f592fb
WD
968 if (find_colon(shell_path)) {
969 rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
970 exit_cleanup(RERR_SYNTAX);
971 }
6902ed17
MP
972 }
973
5d6bcd44 974 if (shell_machine) {
6fc048f4 975 p = strrchr(shell_machine,'@');
5d6bcd44
AT
976 if (p) {
977 *p = 0;
978 shell_user = shell_machine;
979 shell_machine = p+1;
980 }
981 }
982
983 if (verbose > 3) {
9486289c 984 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
985 shell_cmd?shell_cmd:"",
986 shell_machine?shell_machine:"",
987 shell_user?shell_user:"",
988 shell_path?shell_path:"");
989 }
d9c7edf6 990
d16c245f 991 /* for remote source, only single dest arg can remain ... */
f7632fc6 992 if (!am_sender && argc > 1) {
5d6bcd44 993 usage(FERROR);
65417579 994 exit_cleanup(RERR_SYNTAX);
5d6bcd44 995 }
27e3e9c9 996
d16c245f 997 /* ... or no dest at all */
48a1ff0d
WD
998 if (!am_sender && argc == 0)
999 list_only |= 1;
d9c7edf6 1000
75aeac44
WD
1001 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
1002 &f_in,&f_out);
1003
1004 /* if we're running an rsync server on the remote host over a
9af87151 1005 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
1006 if (daemon_over_rsh) {
1007 int tmpret;
1008 tmpret = start_inband_exchange(shell_user, shell_path,
1009 f_in, f_out, argc);
1010 if (tmpret < 0)
1011 return tmpret;
1012 }
1013
fc8a6b97
AT
1014 ret = client_run(f_in, f_out, pid, argc, argv);
1015
1016 fflush(stdout);
1017 fflush(stderr);
1018
1019 return ret;
5d6bcd44
AT
1020}
1021
366345fe 1022
067669da
WD
1023static RETSIGTYPE sigusr1_handler(UNUSED(int val))
1024{
65417579 1025 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
1026}
1027
067669da
WD
1028static RETSIGTYPE sigusr2_handler(UNUSED(int val))
1029{
19b27a48 1030 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
1031 _exit(0);
1032}
1033
067669da
WD
1034static RETSIGTYPE sigchld_handler(UNUSED(int val))
1035{
029c1713 1036#ifdef WNOHANG
ee7118a8
DD
1037 int cnt, status;
1038 pid_t pid;
1039 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 1040 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
1041 * out we're instead saving the child exit statuses for later use.
1042 * The waitpid() loop presumably eliminates all possibility of leaving
1043 * zombie children, maybe that's why he did it.
1044 */
1045 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
1046 /* save the child's exit status */
1047 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
1048 if (pid_stat_table[cnt].pid == 0) {
1049 pid_stat_table[cnt].pid = pid;
1050 pid_stat_table[cnt].status = status;
1051 break;
1052 }
1053 }
ee7118a8 1054 }
029c1713 1055#endif
19b27a48
AT
1056}
1057
c0531332
MP
1058
1059/**
1060 * This routine catches signals and tries to send them to gdb.
1061 *
1062 * Because it's called from inside a signal handler it ought not to
1063 * use too many library routines.
1064 *
1065 * @todo Perhaps use "screen -X" instead/as well, to help people
1066 * debugging without easy access to X. Perhaps use an environment
1067 * variable, or just call a script?
1068 *
1069 * @todo The /proc/ magic probably only works on Linux (and
1070 * Solaris?) Can we be more portable?
1071 **/
1072#ifdef MAINTAINER_MODE
4fdc39dd
MP
1073const char *get_panic_action(void)
1074{
1075 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
1076
1077 if (cmd_fmt)
1078 return cmd_fmt;
1079 else
1080 return "xterm -display :0 -T Panic -n Panic "
1081 "-e gdb /proc/%d/exe %d";
1082}
1083
1084
9fb3f7a9
MP
1085/**
1086 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
1087 *
1088 * This signal handler is only installed if we were configured with
1089 * --enable-maintainer-mode. Perhaps it should always be on and we
1090 * should just look at the environment variable, but I'm a bit leery
1091 * of a signal sending us into a busy loop.
1092 **/
067669da 1093static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
1094{
1095 char cmd_buf[300];
1096 int ret;
4fdc39dd
MP
1097
1098 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
1099 getpid(), getpid());
1100
1101 /* Unless we failed to execute gdb, we allow the process to
1102 * continue. I'm not sure if that's right. */
1103 ret = system(cmd_buf);
1104 if (ret)
1105 _exit(ret);
1106}
1107#endif
1108
1109
5d6bcd44 1110int main(int argc,char *argv[])
d9c7edf6 1111{
ff81e809 1112 int ret;
66a9dc96
WD
1113 int orig_argc = argc;
1114 char **orig_argv = argv;
5d6bcd44 1115
7a6421fa 1116 signal(SIGUSR1, sigusr1_handler);
8b35435f 1117 signal(SIGUSR2, sigusr2_handler);
19b27a48 1118 signal(SIGCHLD, sigchld_handler);
c0531332
MP
1119#ifdef MAINTAINER_MODE
1120 signal(SIGSEGV, rsync_panic_handler);
1121 signal(SIGFPE, rsync_panic_handler);
1122 signal(SIGABRT, rsync_panic_handler);
1123 signal(SIGBUS, rsync_panic_handler);
1124#endif /* def MAINTAINER_MODE */
5d6bcd44 1125
7a6421fa 1126 starttime = time(NULL);
6fe05820 1127 am_root = (MY_UID() == 0);
c627d613 1128
a800434a
AT
1129 memset(&stats, 0, sizeof(stats));
1130
df5e03da
AT
1131 if (argc < 2) {
1132 usage(FERROR);
65417579 1133 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
1134 }
1135
7a6421fa 1136 /* we set a 0 umask so that correct file permissions can be
9af87151 1137 * carried across */
7a6421fa 1138 orig_umask = (int)umask(0);
5d6bcd44 1139
50135767 1140 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
1141 /* FIXME: We ought to call the same error-handling
1142 * code here, rather than relying on getopt. */
50135767 1143 option_error();
65417579 1144 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1145 }
5d6bcd44 1146
7a6421fa 1147 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1148 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1149 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1150
34758d5c
MP
1151 /* Ignore SIGPIPE; we consistently check error codes and will
1152 * see the EPIPE. */
1153 signal(SIGPIPE, SIG_IGN);
1154
c226b7c2 1155 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1156 * (implemented by forking "pwd" and reading its output) doesn't
1157 * work when there are other child processes. Also, on all systems
1158 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1159 push_dir(NULL);
c226b7c2 1160
44e9e221
WD
1161 init_flist();
1162
b9f592fb
WD
1163 if (write_batch || read_batch) {
1164 if (write_batch)
66a9dc96 1165 write_batch_shell_file(orig_argc, orig_argv, argc);
b9f592fb 1166
dbbab0c4
WD
1167 if (read_batch && strcmp(batch_name, "-") == 0)
1168 batch_fd = STDIN_FILENO;
1169 else {
1170 batch_fd = do_open(batch_name,
b9f592fb
WD
1171 write_batch ? O_WRONLY | O_CREAT | O_TRUNC
1172 : O_RDONLY, S_IRUSR | S_IWUSR);
dbbab0c4 1173 }
b9f592fb
WD
1174 if (batch_fd < 0) {
1175 rsyserr(FERROR, errno, "Batch file %s open error",
9b3318b0 1176 batch_name);
b9f592fb
WD
1177 exit_cleanup(RERR_FILEIO);
1178 }
9459290a
WD
1179 if (read_batch)
1180 read_stream_flags(batch_fd);
6902ed17
MP
1181 }
1182
75aeac44 1183 if (am_daemon && !am_server)
7a6421fa 1184 return daemon_main();
f0fca04e 1185
08ac228f
AT
1186 if (argc < 1) {
1187 usage(FERROR);
65417579 1188 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1189 }
1190
7a6421fa
AT
1191 if (dry_run)
1192 verbose = MAX(verbose,1);
c627d613 1193
7a6421fa 1194 if (am_server) {
f0359dd0
AT
1195 set_nonblocking(STDIN_FILENO);
1196 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1197 if (am_daemon)
1198 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1199 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1200 }
c627d613 1201
ff81e809 1202 ret = start_client(argc, argv);
d9c7edf6 1203 if (ret == -1)
9098bbf3 1204 exit_cleanup(RERR_STARTCLIENT);
088aac85 1205 else
9098bbf3
MP
1206 exit_cleanup(ret);
1207
0f5a04e3 1208 return ret;
c627d613 1209}