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