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