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