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