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