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