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