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