don't pprint the IO timeout message if we are a server or daemon (can
[rsync/rsync.git] / main.c
CommitLineData
c627d613
AT
1/*
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include "rsync.h"
21
f0fca04e 22time_t starttime = 0;
a800434a
AT
23
24struct stats stats;
5d6bcd44 25
7a6421fa 26extern int verbose;
c627d613
AT
27
28static void report(int f)
29{
7a6421fa
AT
30 time_t t = time(NULL);
31 extern int am_server;
32 extern int am_sender;
248fbb8c 33 extern int am_daemon;
a800434a 34 extern int do_stats;
17d31b38
DD
35 extern int remote_version;
36 int send_stats;
7a6421fa 37
248fbb8c 38 if (am_daemon) {
a9766ef1 39 log_exit(0, __FILE__, __LINE__);
7b372642 40 if (f == -1 || !am_sender) return;
248fbb8c
AT
41 }
42
ebb00c8e 43 send_stats = verbose || (remote_version >= 20);
e19452a9 44 if (am_server) {
17d31b38 45 if (am_sender && send_stats) {
23c5aef1
DD
46 int64 w;
47 /* store total_written in a temporary
48 because write_longint changes it */
49 w = stats.total_written;
e19452a9 50 write_longint(f,stats.total_read);
23c5aef1 51 write_longint(f,w);
e19452a9
DD
52 write_longint(f,stats.total_size);
53 }
7a6421fa
AT
54 return;
55 }
e19452a9
DD
56
57 /* this is the client */
58
17d31b38 59 if (!am_sender && send_stats) {
23c5aef1 60 int64 r;
a800434a 61 stats.total_written = read_longint(f);
23c5aef1
DD
62 /* store total_read in a temporary, read_longint changes it */
63 r = read_longint(f);
a800434a 64 stats.total_size = read_longint(f);
23c5aef1 65 stats.total_read = r;
a800434a
AT
66 }
67
68 if (do_stats) {
17d31b38
DD
69 if (!am_sender && !send_stats) {
70 /* missing the bytes written by the generator */
ebb00c8e 71 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
17d31b38
DD
72 rprintf(FINFO, "Use --stats -v to show stats\n");
73 return;
74 }
1f658d42
AT
75 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
76 rprintf(FINFO,"Number of files transferred: %d\n",
a800434a 77 stats.num_transferred_files);
1f658d42 78 rprintf(FINFO,"Total file size: %.0f bytes\n",
a800434a 79 (double)stats.total_size);
1f658d42 80 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
a800434a 81 (double)stats.total_transferred_size);
1f658d42 82 rprintf(FINFO,"Literal data: %.0f bytes\n",
a800434a 83 (double)stats.literal_data);
1f658d42 84 rprintf(FINFO,"Matched data: %.0f bytes\n",
a800434a 85 (double)stats.matched_data);
1f658d42
AT
86 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
87 rprintf(FINFO,"Total bytes written: %.0f\n",
a800434a 88 (double)stats.total_written);
1f658d42 89 rprintf(FINFO,"Total bytes read: %.0f\n\n",
a800434a 90 (double)stats.total_read);
7a6421fa
AT
91 }
92
e19452a9
DD
93 if (verbose || do_stats) {
94 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
95 (double)stats.total_written,
96 (double)stats.total_read,
97 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
98 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
99 (double)stats.total_size,
100 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
101 }
fc8a6b97
AT
102
103 fflush(stdout);
104 fflush(stderr);
c627d613
AT
105}
106
107
e3cd198f 108static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
c627d613 109{
366345fe
AT
110 char *args[100];
111 int i,argc=0, ret;
112 char *tok,*dir=NULL;
7a6421fa
AT
113 extern int local_server;
114 extern char *rsync_path;
366345fe
AT
115
116 if (!local_server) {
117 if (!cmd)
118 cmd = getenv(RSYNC_RSH_ENV);
119 if (!cmd)
120 cmd = RSYNC_RSH;
121 cmd = strdup(cmd);
122 if (!cmd)
123 goto oom;
124
125 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
126 args[argc++] = tok;
127 }
c627d613 128
7b8356d0 129#if HAVE_REMSH
366345fe
AT
130 /* remsh (on HPUX) takes the arguments the other way around */
131 args[argc++] = machine;
132 if (user) {
133 args[argc++] = "-l";
134 args[argc++] = user;
135 }
7b8356d0 136#else
366345fe
AT
137 if (user) {
138 args[argc++] = "-l";
139 args[argc++] = user;
140 }
141 args[argc++] = machine;
7b8356d0 142#endif
c627d613 143
366345fe 144 args[argc++] = rsync_path;
c627d613 145
366345fe
AT
146 server_options(args,&argc);
147 }
c627d613 148
366345fe 149 args[argc++] = ".";
76076c4b 150
366345fe
AT
151 if (path && *path)
152 args[argc++] = path;
c627d613 153
366345fe 154 args[argc] = NULL;
c627d613 155
366345fe 156 if (verbose > 3) {
9486289c 157 rprintf(FINFO,"cmd=");
366345fe 158 for (i=0;i<argc;i++)
9486289c
AT
159 rprintf(FINFO,"%s ",args[i]);
160 rprintf(FINFO,"\n");
366345fe
AT
161 }
162
163 if (local_server) {
164 ret = local_child(argc, args, f_in, f_out);
165 } else {
166 ret = piped_child(args,f_in,f_out);
167 }
c627d613 168
366345fe 169 if (dir) free(dir);
82306bf6 170
366345fe 171 return ret;
c627d613
AT
172
173oom:
366345fe
AT
174 out_of_memory("do_cmd");
175 return 0; /* not reached */
c627d613
AT
176}
177
178
179
180
181static char *get_local_name(struct file_list *flist,char *name)
182{
7a6421fa
AT
183 STRUCT_STAT st;
184 extern int orig_umask;
c627d613 185
c95da96a
AT
186 if (verbose > 2)
187 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
188 flist->count, NS(name));
189
190 if (!name)
191 return NULL;
c95da96a 192
1ff5450d
AT
193 if (do_stat(name,&st) == 0) {
194 if (S_ISDIR(st.st_mode)) {
5243c216
AT
195 if (!push_dir(name, 0)) {
196 rprintf(FERROR,"push_dir %s : %s (1)\n",
1ff5450d 197 name,strerror(errno));
65417579 198 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
199 }
200 return NULL;
201 }
202 if (flist->count > 1) {
203 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 204 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
205 }
206 return name;
207 }
208
cec8aa77 209 if (flist->count <= 1)
1ff5450d
AT
210 return name;
211
1ff5450d
AT
212 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
213 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
65417579 214 exit_cleanup(RERR_FILEIO);
1ff5450d 215 } else {
b536f47e
AT
216 if (verbose > 0)
217 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
218 }
219
5243c216
AT
220 if (!push_dir(name, 0)) {
221 rprintf(FERROR,"push_dir %s : %s (2)\n",
222 name,strerror(errno));
65417579 223 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
224 }
225
226 return NULL;
c627d613
AT
227}
228
229
230
231
9486289c 232static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 233{
7a6421fa
AT
234 int i;
235 struct file_list *flist;
236 char *dir = argv[0];
237 extern int relative_paths;
7a6421fa 238 extern int recurse;
c627d613 239
7a6421fa
AT
240 if (verbose > 2)
241 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
c627d613 242
5243c216
AT
243 if (!relative_paths && !push_dir(dir, 0)) {
244 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
65417579 245 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
246 }
247 argc--;
248 argv++;
c627d613 249
7a6421fa
AT
250 if (strcmp(dir,".")) {
251 int l = strlen(dir);
252 if (strcmp(dir,"/") == 0)
253 l = 0;
254 for (i=0;i<argc;i++)
255 argv[i] += l+1;
256 }
c627d613 257
7a6421fa
AT
258 if (argc == 0 && recurse) {
259 argc=1;
260 argv--;
261 argv[0] = ".";
262 }
263
7a6421fa 264 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
265 if (!flist || flist->count == 0) {
266 exit_cleanup(0);
267 }
268
7a6421fa
AT
269 send_files(flist,f_out,f_in);
270 report(f_out);
8d9dc9f9 271 io_flush();
7a6421fa 272 exit_cleanup(0);
c627d613
AT
273}
274
275
dc5ddbcc
AT
276static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
277{
d186eb1a
AT
278 int pid;
279 int status=0;
280 int recv_pipe[2];
554e0a8d 281 int error_pipe[2];
d186eb1a 282 extern int preserve_hard_links;
6957ae33
AT
283 extern int delete_after;
284 extern int recurse;
285 extern int delete_mode;
8ada7518 286 extern int remote_version;
dc5ddbcc 287
d186eb1a
AT
288 if (preserve_hard_links)
289 init_hard_links(flist);
dc5ddbcc 290
6957ae33
AT
291 if (!delete_after) {
292 /* I moved this here from recv_files() to prevent a race condition */
293 if (recurse && delete_mode && !local_name && flist->count>0) {
294 delete_files(flist);
295 }
296 }
297
08f15335 298 if (fd_pair(recv_pipe) < 0) {
d186eb1a 299 rprintf(FERROR,"pipe failed in do_recv\n");
65417579 300 exit_cleanup(RERR_SOCKETIO);
d186eb1a 301 }
554e0a8d 302
08f15335 303 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
304 rprintf(FERROR,"error pipe failed in do_recv\n");
305 exit_cleanup(RERR_SOCKETIO);
306 }
c6e7fcb4 307
8d9dc9f9 308 io_flush();
c6e7fcb4 309
d186eb1a 310 if ((pid=do_fork()) == 0) {
e08c9610 311 close(recv_pipe[0]);
554e0a8d 312 close(error_pipe[0]);
e08c9610
AT
313 if (f_in != f_out) close(f_out);
314
554e0a8d
AT
315 /* we can't let two processes write to the socket at one time */
316 io_multiplexing_close();
317
318 /* set place to send errors */
319 set_error_fd(error_pipe[1]);
320
e08c9610 321 recv_files(f_in,flist,local_name,recv_pipe[1]);
ba5e128d 322 report(f_in);
e08c9610 323
8b35435f
AT
324 write_int(recv_pipe[1],1);
325 close(recv_pipe[1]);
8d9dc9f9 326 io_flush();
8b35435f
AT
327 /* finally we go to sleep until our parent kills us with
328 a USR2 signal */
329 while (1) sleep(60);
d186eb1a 330 }
dc5ddbcc 331
e08c9610 332 close(recv_pipe[1]);
554e0a8d 333 close(error_pipe[1]);
e08c9610
AT
334 io_close_input(f_in);
335 if (f_in != f_out) close(f_in);
e1b3d5c4 336
b3e10ed7
AT
337 io_start_buffering(f_out);
338
554e0a8d
AT
339 io_set_error_fd(error_pipe[0]);
340
e08c9610 341 generate_files(f_out,flist,local_name,recv_pipe[0]);
8d9dc9f9 342
8b35435f
AT
343 read_int(recv_pipe[0]);
344 close(recv_pipe[0]);
8ada7518
AT
345 if (remote_version >= 24) {
346 /* send a final goodbye message */
347 write_int(f_out, -1);
348 }
8d9dc9f9 349 io_flush();
8ada7518 350
8b35435f 351 kill(pid, SIGUSR2);
d79d1c69 352 wait_process(pid, &status);
d186eb1a 353 return status;
dc5ddbcc
AT
354}
355
c627d613 356
9486289c 357static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 358{
7a6421fa
AT
359 int status;
360 struct file_list *flist;
361 char *local_name=NULL;
362 char *dir = NULL;
363 extern int delete_mode;
b33b791e 364 extern int delete_excluded;
7a6421fa 365 extern int am_daemon;
09b7f5db
AT
366 extern int module_id;
367 extern int am_sender;
f0fca04e 368
7a6421fa
AT
369 if (verbose > 2)
370 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
09b7f5db
AT
371
372 if (am_daemon && lp_read_only(module_id) && !am_sender) {
373 rprintf(FERROR,"ERROR: module is read only\n");
374 exit_cleanup(RERR_SYNTAX);
375 return;
376 }
377
7a6421fa 378
7a6421fa
AT
379 if (argc > 0) {
380 dir = argv[0];
381 argc--;
382 argv++;
5243c216
AT
383 if (!am_daemon && !push_dir(dir, 0)) {
384 rprintf(FERROR,"push_dir %s : %s (4)\n",
7a6421fa 385 dir,strerror(errno));
65417579 386 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
387 }
388 }
c627d613 389
b33b791e 390 if (delete_mode && !delete_excluded)
7a6421fa 391 recv_exclude_list(f_in);
c627d613 392
7a6421fa 393 flist = recv_file_list(f_in);
4c36a13e
AT
394 if (!flist) {
395 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 396 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
397 }
398
399 if (argc > 0) {
400 if (strcmp(dir,".")) {
401 argv[0] += strlen(dir);
402 if (argv[0][0] == '/') argv[0]++;
403 }
404 local_name = get_local_name(flist,argv[0]);
405 }
c627d613 406
7a6421fa
AT
407 status = do_recv(f_in,f_out,flist,local_name);
408 exit_cleanup(status);
c627d613
AT
409}
410
411
9486289c 412void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 413{
7a6421fa
AT
414 extern int cvs_exclude;
415 extern int am_sender;
ff41a59f
AT
416 extern int remote_version;
417
6d7b6081
AT
418 setup_protocol(f_out, f_in);
419
f0359dd0
AT
420 set_nonblocking(f_in);
421 set_nonblocking(f_out);
422
ff41a59f
AT
423 if (remote_version >= 23)
424 io_start_multiplex_out(f_out);
7a6421fa 425
7a6421fa
AT
426 if (am_sender) {
427 recv_exclude_list(f_in);
428 if (cvs_exclude)
429 add_cvs_excludes();
430 do_server_sender(f_in, f_out, argc, argv);
431 } else {
432 do_server_recv(f_in, f_out, argc, argv);
433 }
434 exit_cleanup(0);
366345fe
AT
435}
436
3591c066 437int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
9486289c
AT
438{
439 struct file_list *flist;
440 int status = 0, status2 = 0;
441 char *local_name = NULL;
7a6421fa 442 extern int am_sender;
f7632fc6 443 extern int list_only;
ff41a59f
AT
444 extern int remote_version;
445
f0359dd0
AT
446 set_nonblocking(f_in);
447 set_nonblocking(f_out);
448
6d7b6081
AT
449 setup_protocol(f_out,f_in);
450
ff41a59f
AT
451 if (remote_version >= 23)
452 io_start_multiplex_in(f_in);
9486289c
AT
453
454 if (am_sender) {
7a6421fa
AT
455 extern int cvs_exclude;
456 extern int delete_mode;
b33b791e 457 extern int delete_excluded;
9486289c
AT
458 if (cvs_exclude)
459 add_cvs_excludes();
b33b791e 460 if (delete_mode && !delete_excluded)
9486289c
AT
461 send_exclude_list(f_out);
462 flist = send_file_list(f_out,argc,argv);
463 if (verbose > 3)
464 rprintf(FINFO,"file list sent\n");
e1b3d5c4 465
9486289c
AT
466 send_files(flist,f_out,f_in);
467 if (pid != -1) {
468 if (verbose > 3)
8d9dc9f9
AT
469 rprintf(FINFO,"client_run waiting on %d\n",pid);
470 io_flush();
d79d1c69 471 wait_process(pid, &status);
9486289c
AT
472 }
473 report(-1);
8ada7518
AT
474 if (remote_version >= 24) {
475 /* final goodbye message */
476 read_int(f_in);
477 }
9486289c
AT
478 exit_cleanup(status);
479 }
f7632fc6
AT
480
481 if (argc == 0) list_only = 1;
9486289c
AT
482
483 send_exclude_list(f_out);
484
485 flist = recv_file_list(f_in);
486 if (!flist || flist->count == 0) {
8d9dc9f9 487 rprintf(FINFO,"client: nothing to do\n");
9486289c
AT
488 exit_cleanup(0);
489 }
490
491 local_name = get_local_name(flist,argv[0]);
492
493 status2 = do_recv(f_in,f_out,flist,local_name);
494
9486289c 495 if (pid != -1) {
8d9dc9f9
AT
496 if (verbose > 3)
497 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
498 io_flush();
d79d1c69 499 wait_process(pid, &status);
9486289c
AT
500 }
501
502 return status | status2;
503}
504
ca6c93f8
AT
505static char *find_colon(char *s)
506{
507 char *p, *p2;
508
509 p = strchr(s,':');
510 if (!p) return NULL;
511
512 /* now check to see if there is a / in the string before the : - if there is then
513 discard the colon on the assumption that the : is part of a filename */
514 p2 = strchr(s,'/');
515 if (p2 && p2 < p) return NULL;
516
517 return p;
518}
9486289c 519
fc8a6b97 520static int start_client(int argc, char *argv[])
5d6bcd44
AT
521{
522 char *p;
523 char *shell_machine = NULL;
524 char *shell_path = NULL;
525 char *shell_user = NULL;
fc8a6b97 526 int pid, ret;
5d6bcd44 527 int f_in,f_out;
7a6421fa
AT
528 extern int local_server;
529 extern int am_sender;
530 extern char *shell_cmd;
2acf81eb 531 extern int rsync_port;
5d6bcd44 532
f7632fc6
AT
533 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
534 char *host, *path;
535
536 host = argv[0] + strlen(URL_PREFIX);
537 p = strchr(host,'/');
538 if (p) {
539 *p = 0;
540 path = p+1;
541 } else {
542 path="";
543 }
2acf81eb
DD
544 p = strchr(host,':');
545 if (p) {
546 rsync_port = atoi(p+1);
547 *p = 0;
548 }
f7632fc6
AT
549 return start_socket_client(host, path, argc-1, argv+1);
550 }
551
ca6c93f8 552 p = find_colon(argv[0]);
5d6bcd44
AT
553
554 if (p) {
9486289c
AT
555 if (p[1] == ':') {
556 *p = 0;
557 return start_socket_client(argv[0], p+2, argc-1, argv+1);
558 }
3591c066 559
f7632fc6 560 if (argc < 1) {
3591c066 561 usage(FERROR);
65417579 562 exit_cleanup(RERR_SYNTAX);
3591c066
AT
563 }
564
5d6bcd44
AT
565 am_sender = 0;
566 *p = 0;
567 shell_machine = argv[0];
568 shell_path = p+1;
569 argc--;
570 argv++;
571 } else {
572 am_sender = 1;
9486289c 573
ca6c93f8 574 p = find_colon(argv[argc-1]);
5d6bcd44
AT
575 if (!p) {
576 local_server = 1;
9486289c
AT
577 } else if (p[1] == ':') {
578 *p = 0;
579 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 580 }
3591c066
AT
581
582 if (argc < 2) {
583 usage(FERROR);
65417579 584 exit_cleanup(RERR_SYNTAX);
3591c066 585 }
9486289c 586
5d6bcd44
AT
587 if (local_server) {
588 shell_machine = NULL;
589 shell_path = argv[argc-1];
590 } else {
591 *p = 0;
592 shell_machine = argv[argc-1];
593 shell_path = p+1;
594 }
595 argc--;
596 }
597
598 if (shell_machine) {
599 p = strchr(shell_machine,'@');
600 if (p) {
601 *p = 0;
602 shell_user = shell_machine;
603 shell_machine = p+1;
604 }
605 }
606
607 if (verbose > 3) {
9486289c 608 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
609 shell_cmd?shell_cmd:"",
610 shell_machine?shell_machine:"",
611 shell_user?shell_user:"",
612 shell_path?shell_path:"");
613 }
614
f7632fc6 615 if (!am_sender && argc > 1) {
5d6bcd44 616 usage(FERROR);
65417579 617 exit_cleanup(RERR_SYNTAX);
5d6bcd44
AT
618 }
619
620 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
621
fc8a6b97
AT
622 ret = client_run(f_in, f_out, pid, argc, argv);
623
624 fflush(stdout);
625 fflush(stderr);
626
627 return ret;
5d6bcd44
AT
628}
629
366345fe 630
6e4fb64e 631static RETSIGTYPE sigusr1_handler(int val) {
65417579 632 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
633}
634
8b35435f
AT
635static RETSIGTYPE sigusr2_handler(int val) {
636 _exit(0);
637}
638
5d6bcd44 639int main(int argc,char *argv[])
7a6421fa
AT
640{
641 extern int am_root;
642 extern int orig_umask;
643 extern int dry_run;
644 extern int am_daemon;
645 extern int am_server;
5d6bcd44 646
7a6421fa 647 signal(SIGUSR1, sigusr1_handler);
8b35435f 648 signal(SIGUSR2, sigusr2_handler);
5d6bcd44 649
7a6421fa
AT
650 starttime = time(NULL);
651 am_root = (getuid() == 0);
c627d613 652
a800434a
AT
653 memset(&stats, 0, sizeof(stats));
654
df5e03da
AT
655 if (argc < 2) {
656 usage(FERROR);
65417579 657 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
658 }
659
7a6421fa
AT
660 /* we set a 0 umask so that correct file permissions can be
661 carried across */
662 orig_umask = (int)umask(0);
5d6bcd44 663
b86f0cef 664 if (!parse_arguments(argc, argv, 1)) {
65417579 665 exit_cleanup(RERR_SYNTAX);
b11ed3b1 666 }
5d6bcd44 667
7a6421fa
AT
668 argc -= optind;
669 argv += optind;
670 optind = 0;
c627d613 671
7a6421fa
AT
672 signal(SIGCHLD,SIG_IGN);
673 signal(SIGINT,SIGNAL_CAST sig_int);
674 signal(SIGPIPE,SIGNAL_CAST sig_int);
675 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 676 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 677
c226b7c2
DD
678 /* Initialize push_dir here because on some old systems getcwd
679 (implemented by forking "pwd" and reading its output) doesn't
680 work when there are other child processes. Also, on all systems
681 that implement getcwd that way "pwd" can't be found after chroot. */
682 push_dir(NULL,0);
683
7a6421fa
AT
684 if (am_daemon) {
685 return daemon_main();
686 }
f0fca04e 687
08ac228f
AT
688 if (argc < 1) {
689 usage(FERROR);
65417579 690 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
691 }
692
7a6421fa
AT
693 if (dry_run)
694 verbose = MAX(verbose,1);
c627d613 695
cbbe4892 696#ifndef SUPPORT_LINKS
7a6421fa
AT
697 if (!am_server && preserve_links) {
698 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 699 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 700 }
cbbe4892
AT
701#endif
702
7a6421fa 703 if (am_server) {
f0359dd0
AT
704 set_nonblocking(STDIN_FILENO);
705 set_nonblocking(STDOUT_FILENO);
7a6421fa
AT
706 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
707 }
c627d613 708
7a6421fa 709 return start_client(argc, argv);
c627d613 710}
82306bf6 711