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