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