added blocking-io docs
[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;
e384bfbd 115 extern int blocking_io;
366345fe
AT
116
117 if (!local_server) {
118 if (!cmd)
119 cmd = getenv(RSYNC_RSH_ENV);
120 if (!cmd)
121 cmd = RSYNC_RSH;
122 cmd = strdup(cmd);
123 if (!cmd)
124 goto oom;
125
126 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
127 args[argc++] = tok;
128 }
c627d613 129
7b8356d0 130#if HAVE_REMSH
366345fe
AT
131 /* remsh (on HPUX) takes the arguments the other way around */
132 args[argc++] = machine;
133 if (user) {
134 args[argc++] = "-l";
135 args[argc++] = user;
136 }
7b8356d0 137#else
366345fe
AT
138 if (user) {
139 args[argc++] = "-l";
140 args[argc++] = user;
141 }
142 args[argc++] = machine;
7b8356d0 143#endif
c627d613 144
366345fe 145 args[argc++] = rsync_path;
c627d613 146
366345fe 147 server_options(args,&argc);
e384bfbd
AT
148
149
150 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
366345fe 151 }
c627d613 152
366345fe 153 args[argc++] = ".";
76076c4b 154
366345fe
AT
155 if (path && *path)
156 args[argc++] = path;
c627d613 157
366345fe 158 args[argc] = NULL;
c627d613 159
366345fe 160 if (verbose > 3) {
9486289c 161 rprintf(FINFO,"cmd=");
366345fe 162 for (i=0;i<argc;i++)
9486289c
AT
163 rprintf(FINFO,"%s ",args[i]);
164 rprintf(FINFO,"\n");
366345fe
AT
165 }
166
167 if (local_server) {
168 ret = local_child(argc, args, f_in, f_out);
169 } else {
170 ret = piped_child(args,f_in,f_out);
171 }
c627d613 172
366345fe 173 if (dir) free(dir);
82306bf6 174
366345fe 175 return ret;
c627d613
AT
176
177oom:
366345fe
AT
178 out_of_memory("do_cmd");
179 return 0; /* not reached */
c627d613
AT
180}
181
182
183
184
185static char *get_local_name(struct file_list *flist,char *name)
186{
7a6421fa
AT
187 STRUCT_STAT st;
188 extern int orig_umask;
c627d613 189
c95da96a
AT
190 if (verbose > 2)
191 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
192 flist->count, NS(name));
193
194 if (!name)
195 return NULL;
c95da96a 196
1ff5450d
AT
197 if (do_stat(name,&st) == 0) {
198 if (S_ISDIR(st.st_mode)) {
5243c216
AT
199 if (!push_dir(name, 0)) {
200 rprintf(FERROR,"push_dir %s : %s (1)\n",
1ff5450d 201 name,strerror(errno));
65417579 202 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
203 }
204 return NULL;
205 }
206 if (flist->count > 1) {
207 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 208 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
209 }
210 return name;
211 }
212
cec8aa77 213 if (flist->count <= 1)
1ff5450d
AT
214 return name;
215
1ff5450d
AT
216 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
217 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
65417579 218 exit_cleanup(RERR_FILEIO);
1ff5450d 219 } else {
b536f47e
AT
220 if (verbose > 0)
221 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
222 }
223
5243c216
AT
224 if (!push_dir(name, 0)) {
225 rprintf(FERROR,"push_dir %s : %s (2)\n",
226 name,strerror(errno));
65417579 227 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
228 }
229
230 return NULL;
c627d613
AT
231}
232
233
234
235
9486289c 236static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 237{
7a6421fa
AT
238 int i;
239 struct file_list *flist;
240 char *dir = argv[0];
241 extern int relative_paths;
7a6421fa 242 extern int recurse;
c627d613 243
7a6421fa
AT
244 if (verbose > 2)
245 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
c627d613 246
5243c216
AT
247 if (!relative_paths && !push_dir(dir, 0)) {
248 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
65417579 249 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
250 }
251 argc--;
252 argv++;
c627d613 253
7a6421fa
AT
254 if (strcmp(dir,".")) {
255 int l = strlen(dir);
256 if (strcmp(dir,"/") == 0)
257 l = 0;
258 for (i=0;i<argc;i++)
259 argv[i] += l+1;
260 }
c627d613 261
7a6421fa
AT
262 if (argc == 0 && recurse) {
263 argc=1;
264 argv--;
265 argv[0] = ".";
266 }
267
7a6421fa 268 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
269 if (!flist || flist->count == 0) {
270 exit_cleanup(0);
271 }
272
7a6421fa
AT
273 send_files(flist,f_out,f_in);
274 report(f_out);
8d9dc9f9 275 io_flush();
7a6421fa 276 exit_cleanup(0);
c627d613
AT
277}
278
279
dc5ddbcc
AT
280static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
281{
d186eb1a
AT
282 int pid;
283 int status=0;
284 int recv_pipe[2];
554e0a8d 285 int error_pipe[2];
d186eb1a 286 extern int preserve_hard_links;
6957ae33
AT
287 extern int delete_after;
288 extern int recurse;
289 extern int delete_mode;
8ada7518 290 extern int remote_version;
dc5ddbcc 291
d186eb1a
AT
292 if (preserve_hard_links)
293 init_hard_links(flist);
dc5ddbcc 294
6957ae33
AT
295 if (!delete_after) {
296 /* I moved this here from recv_files() to prevent a race condition */
297 if (recurse && delete_mode && !local_name && flist->count>0) {
298 delete_files(flist);
299 }
300 }
301
08f15335 302 if (fd_pair(recv_pipe) < 0) {
d186eb1a 303 rprintf(FERROR,"pipe failed in do_recv\n");
65417579 304 exit_cleanup(RERR_SOCKETIO);
d186eb1a 305 }
554e0a8d 306
08f15335 307 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
308 rprintf(FERROR,"error pipe failed in do_recv\n");
309 exit_cleanup(RERR_SOCKETIO);
310 }
c6e7fcb4 311
8d9dc9f9 312 io_flush();
c6e7fcb4 313
d186eb1a 314 if ((pid=do_fork()) == 0) {
e08c9610 315 close(recv_pipe[0]);
554e0a8d 316 close(error_pipe[0]);
e08c9610
AT
317 if (f_in != f_out) close(f_out);
318
554e0a8d
AT
319 /* we can't let two processes write to the socket at one time */
320 io_multiplexing_close();
321
322 /* set place to send errors */
323 set_error_fd(error_pipe[1]);
324
e08c9610 325 recv_files(f_in,flist,local_name,recv_pipe[1]);
ba5e128d 326 report(f_in);
e08c9610 327
8b35435f
AT
328 write_int(recv_pipe[1],1);
329 close(recv_pipe[1]);
8d9dc9f9 330 io_flush();
4a748188
AT
331 /* finally we go to sleep until our parent kills us
332 with a USR2 signal. We sleepp for a short time as on
333 some OSes a signal won't interrupt a sleep! */
334 while (1) sleep(1);
d186eb1a 335 }
dc5ddbcc 336
e08c9610 337 close(recv_pipe[1]);
554e0a8d 338 close(error_pipe[1]);
e08c9610
AT
339 io_close_input(f_in);
340 if (f_in != f_out) close(f_in);
e1b3d5c4 341
b3e10ed7
AT
342 io_start_buffering(f_out);
343
554e0a8d
AT
344 io_set_error_fd(error_pipe[0]);
345
e08c9610 346 generate_files(f_out,flist,local_name,recv_pipe[0]);
8d9dc9f9 347
8b35435f
AT
348 read_int(recv_pipe[0]);
349 close(recv_pipe[0]);
8ada7518
AT
350 if (remote_version >= 24) {
351 /* send a final goodbye message */
352 write_int(f_out, -1);
353 }
8d9dc9f9 354 io_flush();
8ada7518 355
8b35435f 356 kill(pid, SIGUSR2);
d79d1c69 357 wait_process(pid, &status);
d186eb1a 358 return status;
dc5ddbcc
AT
359}
360
c627d613 361
9486289c 362static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 363{
7a6421fa
AT
364 int status;
365 struct file_list *flist;
366 char *local_name=NULL;
367 char *dir = NULL;
368 extern int delete_mode;
b33b791e 369 extern int delete_excluded;
7a6421fa 370 extern int am_daemon;
09b7f5db
AT
371 extern int module_id;
372 extern int am_sender;
f0fca04e 373
7a6421fa
AT
374 if (verbose > 2)
375 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
09b7f5db
AT
376
377 if (am_daemon && lp_read_only(module_id) && !am_sender) {
378 rprintf(FERROR,"ERROR: module is read only\n");
379 exit_cleanup(RERR_SYNTAX);
380 return;
381 }
382
7a6421fa 383
7a6421fa
AT
384 if (argc > 0) {
385 dir = argv[0];
386 argc--;
387 argv++;
5243c216
AT
388 if (!am_daemon && !push_dir(dir, 0)) {
389 rprintf(FERROR,"push_dir %s : %s (4)\n",
7a6421fa 390 dir,strerror(errno));
65417579 391 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
392 }
393 }
c627d613 394
b33b791e 395 if (delete_mode && !delete_excluded)
7a6421fa 396 recv_exclude_list(f_in);
c627d613 397
7a6421fa 398 flist = recv_file_list(f_in);
4c36a13e
AT
399 if (!flist) {
400 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 401 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
402 }
403
404 if (argc > 0) {
405 if (strcmp(dir,".")) {
406 argv[0] += strlen(dir);
407 if (argv[0][0] == '/') argv[0]++;
408 }
409 local_name = get_local_name(flist,argv[0]);
410 }
c627d613 411
7a6421fa
AT
412 status = do_recv(f_in,f_out,flist,local_name);
413 exit_cleanup(status);
c627d613
AT
414}
415
416
9486289c 417void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 418{
7a6421fa
AT
419 extern int cvs_exclude;
420 extern int am_sender;
ff41a59f
AT
421 extern int remote_version;
422
6d7b6081
AT
423 setup_protocol(f_out, f_in);
424
f0359dd0
AT
425 set_nonblocking(f_in);
426 set_nonblocking(f_out);
427
ff41a59f
AT
428 if (remote_version >= 23)
429 io_start_multiplex_out(f_out);
7a6421fa 430
7a6421fa
AT
431 if (am_sender) {
432 recv_exclude_list(f_in);
433 if (cvs_exclude)
434 add_cvs_excludes();
435 do_server_sender(f_in, f_out, argc, argv);
436 } else {
437 do_server_recv(f_in, f_out, argc, argv);
438 }
439 exit_cleanup(0);
366345fe
AT
440}
441
3591c066 442int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
9486289c
AT
443{
444 struct file_list *flist;
445 int status = 0, status2 = 0;
446 char *local_name = NULL;
7a6421fa 447 extern int am_sender;
f7632fc6 448 extern int list_only;
ff41a59f
AT
449 extern int remote_version;
450
f0359dd0
AT
451 set_nonblocking(f_in);
452 set_nonblocking(f_out);
453
6d7b6081
AT
454 setup_protocol(f_out,f_in);
455
ff41a59f
AT
456 if (remote_version >= 23)
457 io_start_multiplex_in(f_in);
9486289c
AT
458
459 if (am_sender) {
7a6421fa
AT
460 extern int cvs_exclude;
461 extern int delete_mode;
b33b791e 462 extern int delete_excluded;
9486289c
AT
463 if (cvs_exclude)
464 add_cvs_excludes();
b33b791e 465 if (delete_mode && !delete_excluded)
9486289c
AT
466 send_exclude_list(f_out);
467 flist = send_file_list(f_out,argc,argv);
468 if (verbose > 3)
469 rprintf(FINFO,"file list sent\n");
e1b3d5c4 470
9486289c
AT
471 send_files(flist,f_out,f_in);
472 if (pid != -1) {
473 if (verbose > 3)
8d9dc9f9
AT
474 rprintf(FINFO,"client_run waiting on %d\n",pid);
475 io_flush();
d79d1c69 476 wait_process(pid, &status);
9486289c
AT
477 }
478 report(-1);
8ada7518
AT
479 if (remote_version >= 24) {
480 /* final goodbye message */
481 read_int(f_in);
482 }
9486289c
AT
483 exit_cleanup(status);
484 }
f7632fc6
AT
485
486 if (argc == 0) list_only = 1;
9486289c
AT
487
488 send_exclude_list(f_out);
489
490 flist = recv_file_list(f_in);
491 if (!flist || flist->count == 0) {
8d9dc9f9 492 rprintf(FINFO,"client: nothing to do\n");
9486289c
AT
493 exit_cleanup(0);
494 }
495
496 local_name = get_local_name(flist,argv[0]);
497
498 status2 = do_recv(f_in,f_out,flist,local_name);
499
9486289c 500 if (pid != -1) {
8d9dc9f9
AT
501 if (verbose > 3)
502 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
503 io_flush();
d79d1c69 504 wait_process(pid, &status);
9486289c
AT
505 }
506
507 return status | status2;
508}
509
ca6c93f8
AT
510static char *find_colon(char *s)
511{
512 char *p, *p2;
513
514 p = strchr(s,':');
515 if (!p) return NULL;
516
517 /* now check to see if there is a / in the string before the : - if there is then
518 discard the colon on the assumption that the : is part of a filename */
519 p2 = strchr(s,'/');
520 if (p2 && p2 < p) return NULL;
521
522 return p;
523}
9486289c 524
fc8a6b97 525static int start_client(int argc, char *argv[])
5d6bcd44
AT
526{
527 char *p;
528 char *shell_machine = NULL;
529 char *shell_path = NULL;
530 char *shell_user = NULL;
fc8a6b97 531 int pid, ret;
5d6bcd44 532 int f_in,f_out;
7a6421fa
AT
533 extern int local_server;
534 extern int am_sender;
535 extern char *shell_cmd;
2acf81eb 536 extern int rsync_port;
5d6bcd44 537
f7632fc6
AT
538 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
539 char *host, *path;
540
541 host = argv[0] + strlen(URL_PREFIX);
542 p = strchr(host,'/');
543 if (p) {
544 *p = 0;
545 path = p+1;
546 } else {
547 path="";
548 }
2acf81eb
DD
549 p = strchr(host,':');
550 if (p) {
551 rsync_port = atoi(p+1);
552 *p = 0;
553 }
f7632fc6
AT
554 return start_socket_client(host, path, argc-1, argv+1);
555 }
556
ca6c93f8 557 p = find_colon(argv[0]);
5d6bcd44
AT
558
559 if (p) {
9486289c
AT
560 if (p[1] == ':') {
561 *p = 0;
562 return start_socket_client(argv[0], p+2, argc-1, argv+1);
563 }
3591c066 564
f7632fc6 565 if (argc < 1) {
3591c066 566 usage(FERROR);
65417579 567 exit_cleanup(RERR_SYNTAX);
3591c066
AT
568 }
569
5d6bcd44
AT
570 am_sender = 0;
571 *p = 0;
572 shell_machine = argv[0];
573 shell_path = p+1;
574 argc--;
575 argv++;
576 } else {
577 am_sender = 1;
9486289c 578
ca6c93f8 579 p = find_colon(argv[argc-1]);
5d6bcd44
AT
580 if (!p) {
581 local_server = 1;
9486289c
AT
582 } else if (p[1] == ':') {
583 *p = 0;
584 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 585 }
3591c066
AT
586
587 if (argc < 2) {
588 usage(FERROR);
65417579 589 exit_cleanup(RERR_SYNTAX);
3591c066 590 }
9486289c 591
5d6bcd44
AT
592 if (local_server) {
593 shell_machine = NULL;
594 shell_path = argv[argc-1];
595 } else {
596 *p = 0;
597 shell_machine = argv[argc-1];
598 shell_path = p+1;
599 }
600 argc--;
601 }
602
603 if (shell_machine) {
604 p = strchr(shell_machine,'@');
605 if (p) {
606 *p = 0;
607 shell_user = shell_machine;
608 shell_machine = p+1;
609 }
610 }
611
612 if (verbose > 3) {
9486289c 613 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
614 shell_cmd?shell_cmd:"",
615 shell_machine?shell_machine:"",
616 shell_user?shell_user:"",
617 shell_path?shell_path:"");
618 }
619
f7632fc6 620 if (!am_sender && argc > 1) {
5d6bcd44 621 usage(FERROR);
65417579 622 exit_cleanup(RERR_SYNTAX);
5d6bcd44
AT
623 }
624
625 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
626
fc8a6b97
AT
627 ret = client_run(f_in, f_out, pid, argc, argv);
628
629 fflush(stdout);
630 fflush(stderr);
631
632 return ret;
5d6bcd44
AT
633}
634
366345fe 635
6e4fb64e 636static RETSIGTYPE sigusr1_handler(int val) {
65417579 637 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
638}
639
8b35435f
AT
640static RETSIGTYPE sigusr2_handler(int val) {
641 _exit(0);
642}
643
5d6bcd44 644int main(int argc,char *argv[])
7a6421fa
AT
645{
646 extern int am_root;
647 extern int orig_umask;
648 extern int dry_run;
649 extern int am_daemon;
650 extern int am_server;
5d6bcd44 651
7a6421fa 652 signal(SIGUSR1, sigusr1_handler);
8b35435f 653 signal(SIGUSR2, sigusr2_handler);
5d6bcd44 654
7a6421fa
AT
655 starttime = time(NULL);
656 am_root = (getuid() == 0);
c627d613 657
a800434a
AT
658 memset(&stats, 0, sizeof(stats));
659
df5e03da
AT
660 if (argc < 2) {
661 usage(FERROR);
65417579 662 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
663 }
664
7a6421fa
AT
665 /* we set a 0 umask so that correct file permissions can be
666 carried across */
667 orig_umask = (int)umask(0);
5d6bcd44 668
b86f0cef 669 if (!parse_arguments(argc, argv, 1)) {
65417579 670 exit_cleanup(RERR_SYNTAX);
b11ed3b1 671 }
5d6bcd44 672
7a6421fa
AT
673 argc -= optind;
674 argv += optind;
675 optind = 0;
c627d613 676
7a6421fa
AT
677 signal(SIGCHLD,SIG_IGN);
678 signal(SIGINT,SIGNAL_CAST sig_int);
679 signal(SIGPIPE,SIGNAL_CAST sig_int);
680 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 681 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 682
c226b7c2
DD
683 /* Initialize push_dir here because on some old systems getcwd
684 (implemented by forking "pwd" and reading its output) doesn't
685 work when there are other child processes. Also, on all systems
686 that implement getcwd that way "pwd" can't be found after chroot. */
687 push_dir(NULL,0);
688
7a6421fa
AT
689 if (am_daemon) {
690 return daemon_main();
691 }
f0fca04e 692
08ac228f
AT
693 if (argc < 1) {
694 usage(FERROR);
65417579 695 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
696 }
697
7a6421fa
AT
698 if (dry_run)
699 verbose = MAX(verbose,1);
c627d613 700
cbbe4892 701#ifndef SUPPORT_LINKS
7a6421fa
AT
702 if (!am_server && preserve_links) {
703 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 704 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 705 }
cbbe4892
AT
706#endif
707
7a6421fa 708 if (am_server) {
f0359dd0
AT
709 set_nonblocking(STDIN_FILENO);
710 set_nonblocking(STDOUT_FILENO);
7a6421fa
AT
711 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
712 }
c627d613 713
7a6421fa 714 return start_client(argc, argv);
c627d613 715}
82306bf6 716