00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "rsync.h"
00023
00024 time_t starttime = 0;
00025
00026 extern struct stats stats;
00027 extern int verbose;
00028
00029 static void show_malloc_stats(void);
00030
00031
00032
00033
00034 void wait_process(pid_t pid, int *status)
00035 {
00036 while (waitpid(pid, status, WNOHANG) == 0) {
00037 msleep(20);
00038 io_flush();
00039 }
00040
00041
00042
00043
00044
00045
00046 *status = WEXITSTATUS(*status);
00047 }
00048
00049 static void report(int f)
00050 {
00051 time_t t = time(NULL);
00052 extern int am_server;
00053 extern int am_sender;
00054 extern int am_daemon;
00055 extern int do_stats;
00056 extern int remote_version;
00057 int send_stats;
00058
00059 if (do_stats) {
00060
00061 show_malloc_stats();
00062 show_flist_stats();
00063 }
00064
00065 if (am_daemon) {
00066 log_exit(0, __FILE__, __LINE__);
00067 if (f == -1 || !am_sender) return;
00068 }
00069
00070 send_stats = verbose || (remote_version >= 20);
00071 if (am_server) {
00072 if (am_sender && send_stats) {
00073 int64 w;
00074
00075
00076 w = stats.total_written;
00077 write_longint(f,stats.total_read);
00078 write_longint(f,w);
00079 write_longint(f,stats.total_size);
00080 }
00081 return;
00082 }
00083
00084
00085
00086 if (!am_sender && send_stats) {
00087 int64 r;
00088 stats.total_written = read_longint(f);
00089
00090 r = read_longint(f);
00091 stats.total_size = read_longint(f);
00092 stats.total_read = r;
00093 }
00094
00095 if (do_stats) {
00096 if (!am_sender && !send_stats) {
00097
00098 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
00099 rprintf(FINFO, "Use --stats -v to show stats\n");
00100 return;
00101 }
00102 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
00103 rprintf(FINFO,"Number of files transferred: %d\n",
00104 stats.num_transferred_files);
00105 rprintf(FINFO,"Total file size: %.0f bytes\n",
00106 (double)stats.total_size);
00107 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
00108 (double)stats.total_transferred_size);
00109 rprintf(FINFO,"Literal data: %.0f bytes\n",
00110 (double)stats.literal_data);
00111 rprintf(FINFO,"Matched data: %.0f bytes\n",
00112 (double)stats.matched_data);
00113 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
00114 rprintf(FINFO,"Total bytes written: %.0f\n",
00115 (double)stats.total_written);
00116 rprintf(FINFO,"Total bytes read: %.0f\n\n",
00117 (double)stats.total_read);
00118 }
00119
00120 if (verbose || do_stats) {
00121 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
00122 (double)stats.total_written,
00123 (double)stats.total_read,
00124 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
00125 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
00126 (double)stats.total_size,
00127 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
00128 }
00129
00130 fflush(stdout);
00131 fflush(stderr);
00132 }
00133
00134
00135
00136
00137
00138 static void show_malloc_stats(void)
00139 {
00140 #ifdef HAVE_MALLINFO
00141 struct mallinfo mi;
00142 extern int am_server;
00143 extern int am_sender;
00144 extern int am_daemon;
00145
00146 mi = mallinfo();
00147
00148 rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
00149 getpid(),
00150 am_server ? "server " : "",
00151 am_daemon ? "daemon " : "",
00152 am_sender ? "sender" : "receiver");
00153 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
00154 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
00155 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
00156 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
00157 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
00158 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
00159 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
00160 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
00161 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
00162 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
00163 #endif
00164 }
00165
00166
00167
00168 static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
00169 {
00170 char *args[100];
00171 int i,argc=0;
00172 pid_t ret;
00173 char *tok,*dir=NULL;
00174 extern int local_server;
00175 extern char *rsync_path;
00176 extern int blocking_io;
00177 extern int read_batch;
00178
00179 if (!read_batch && !local_server) {
00180 if (!cmd)
00181 cmd = getenv(RSYNC_RSH_ENV);
00182 if (!cmd)
00183 cmd = RSYNC_RSH;
00184 cmd = strdup(cmd);
00185 if (!cmd)
00186 goto oom;
00187
00188 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
00189 args[argc++] = tok;
00190 }
00191
00192 #if HAVE_REMSH
00193
00194 args[argc++] = machine;
00195 if (user) {
00196 args[argc++] = "-l";
00197 args[argc++] = user;
00198 }
00199 #else
00200 if (user) {
00201 args[argc++] = "-l";
00202 args[argc++] = user;
00203 }
00204 args[argc++] = machine;
00205 #endif
00206
00207 args[argc++] = rsync_path;
00208
00209 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
00210 blocking_io = 1;
00211
00212 server_options(args,&argc);
00213
00214 }
00215
00216 args[argc++] = ".";
00217
00218 if (path && *path)
00219 args[argc++] = path;
00220
00221 args[argc] = NULL;
00222
00223 if (verbose > 3) {
00224 rprintf(FINFO,"cmd=");
00225 for (i=0;i<argc;i++)
00226 rprintf(FINFO,"%s ",args[i]);
00227 rprintf(FINFO,"\n");
00228 }
00229
00230 if (local_server) {
00231 if (read_batch)
00232 create_flist_from_batch();
00233 ret = local_child(argc, args, f_in, f_out, child_main);
00234 } else {
00235 ret = piped_child(args,f_in,f_out);
00236 }
00237
00238 if (dir) free(dir);
00239
00240 return ret;
00241
00242 oom:
00243 out_of_memory("do_cmd");
00244 return 0;
00245 }
00246
00247
00248
00249
00250 static char *get_local_name(struct file_list *flist,char *name)
00251 {
00252 STRUCT_STAT st;
00253 extern int orig_umask;
00254
00255 if (verbose > 2)
00256 rprintf(FINFO,"get_local_name count=%d %s\n",
00257 flist->count, NS(name));
00258
00259 if (!name)
00260 return NULL;
00261
00262 if (do_stat(name,&st) == 0) {
00263 if (S_ISDIR(st.st_mode)) {
00264 if (!push_dir(name, 0)) {
00265 rprintf(FERROR,"push_dir %s : %s (1)\n",
00266 name,strerror(errno));
00267 exit_cleanup(RERR_FILESELECT);
00268 }
00269 return NULL;
00270 }
00271 if (flist->count > 1) {
00272 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
00273 exit_cleanup(RERR_FILESELECT);
00274 }
00275 return name;
00276 }
00277
00278 if (flist->count <= 1)
00279 return name;
00280
00281 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
00282 rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
00283 name, strerror(errno));
00284 exit_cleanup(RERR_FILEIO);
00285 } else {
00286 if (verbose > 0)
00287 rprintf(FINFO,"created directory %s\n",name);
00288 }
00289
00290 if (!push_dir(name, 0)) {
00291 rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
00292 name, strerror(errno));
00293 exit_cleanup(RERR_FILESELECT);
00294 }
00295
00296 return NULL;
00297 }
00298
00299
00300
00301
00302 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
00303 {
00304 int i;
00305 struct file_list *flist;
00306 char *dir = argv[0];
00307 extern int relative_paths;
00308 extern int recurse;
00309 extern int remote_version;
00310
00311 if (verbose > 2)
00312 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
00313
00314 if (!relative_paths && !push_dir(dir, 0)) {
00315 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
00316 exit_cleanup(RERR_FILESELECT);
00317 }
00318 argc--;
00319 argv++;
00320
00321 if (strcmp(dir,".")) {
00322 int l = strlen(dir);
00323 if (strcmp(dir,"/") == 0)
00324 l = 0;
00325 for (i=0;i<argc;i++)
00326 argv[i] += l+1;
00327 }
00328
00329 if (argc == 0 && recurse) {
00330 argc=1;
00331 argv--;
00332 argv[0] = ".";
00333 }
00334
00335 flist = send_file_list(f_out,argc,argv);
00336 if (!flist || flist->count == 0) {
00337 exit_cleanup(0);
00338 }
00339
00340 send_files(flist,f_out,f_in);
00341 io_flush();
00342 report(f_out);
00343 if (remote_version >= 24) {
00344
00345 read_int(f_in);
00346 }
00347 io_flush();
00348 exit_cleanup(0);
00349 }
00350
00351
00352 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
00353 {
00354 int pid;
00355 int status=0;
00356 int recv_pipe[2];
00357 int error_pipe[2];
00358 extern int preserve_hard_links;
00359 extern int delete_after;
00360 extern int recurse;
00361 extern int delete_mode;
00362 extern int remote_version;
00363
00364 if (preserve_hard_links)
00365 init_hard_links(flist);
00366
00367 if (!delete_after) {
00368
00369 if (recurse && delete_mode && !local_name && flist->count>0) {
00370 delete_files(flist);
00371 }
00372 }
00373
00374 if (fd_pair(recv_pipe) < 0) {
00375 rprintf(FERROR,"pipe failed in do_recv\n");
00376 exit_cleanup(RERR_SOCKETIO);
00377 }
00378
00379 if (fd_pair(error_pipe) < 0) {
00380 rprintf(FERROR,"error pipe failed in do_recv\n");
00381 exit_cleanup(RERR_SOCKETIO);
00382 }
00383
00384 io_flush();
00385
00386 if ((pid=do_fork()) == 0) {
00387 close(recv_pipe[0]);
00388 close(error_pipe[0]);
00389 if (f_in != f_out) close(f_out);
00390
00391
00392 io_multiplexing_close();
00393
00394
00395 set_error_fd(error_pipe[1]);
00396
00397 recv_files(f_in,flist,local_name,recv_pipe[1]);
00398 io_flush();
00399 report(f_in);
00400
00401 write_int(recv_pipe[1],1);
00402 close(recv_pipe[1]);
00403 io_flush();
00404
00405
00406
00407 while (msleep(20))
00408 ;
00409 }
00410
00411 close(recv_pipe[1]);
00412 close(error_pipe[1]);
00413 if (f_in != f_out) close(f_in);
00414
00415 io_start_buffering(f_out);
00416
00417 io_set_error_fd(error_pipe[0]);
00418
00419 generate_files(f_out,flist,local_name,recv_pipe[0]);
00420
00421 read_int(recv_pipe[0]);
00422 close(recv_pipe[0]);
00423 if (remote_version >= 24) {
00424
00425 write_int(f_out, -1);
00426 }
00427 io_flush();
00428
00429 kill(pid, SIGUSR2);
00430 wait_process(pid, &status);
00431 return status;
00432 }
00433
00434
00435 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
00436 {
00437 int status;
00438 struct file_list *flist;
00439 char *local_name=NULL;
00440 char *dir = NULL;
00441 extern int delete_mode;
00442 extern int delete_excluded;
00443 extern int am_daemon;
00444 extern int module_id;
00445 extern int am_sender;
00446 extern int read_batch;
00447 extern struct file_list *batch_flist;
00448
00449 if (verbose > 2)
00450 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
00451
00452 if (am_daemon && lp_read_only(module_id) && !am_sender) {
00453 rprintf(FERROR,"ERROR: module is read only\n");
00454 exit_cleanup(RERR_SYNTAX);
00455 return;
00456 }
00457
00458
00459 if (argc > 0) {
00460 dir = argv[0];
00461 argc--;
00462 argv++;
00463 if (!am_daemon && !push_dir(dir, 0)) {
00464 rprintf(FERROR,"push_dir %s : %s (4)\n",
00465 dir,strerror(errno));
00466 exit_cleanup(RERR_FILESELECT);
00467 }
00468 }
00469
00470 if (delete_mode && !delete_excluded)
00471 recv_exclude_list(f_in);
00472
00473 if (read_batch)
00474 flist = batch_flist;
00475 else
00476 flist = recv_file_list(f_in);
00477 if (!flist) {
00478 rprintf(FERROR,"server_recv: recv_file_list error\n");
00479 exit_cleanup(RERR_FILESELECT);
00480 }
00481
00482 if (argc > 0) {
00483 if (strcmp(dir,".")) {
00484 argv[0] += strlen(dir);
00485 if (argv[0][0] == '/') argv[0]++;
00486 }
00487 local_name = get_local_name(flist,argv[0]);
00488 }
00489
00490 status = do_recv(f_in,f_out,flist,local_name);
00491 exit_cleanup(status);
00492 }
00493
00494
00495 int child_main(int argc, char *argv[])
00496 {
00497 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
00498 return 0;
00499 }
00500
00501
00502 void start_server(int f_in, int f_out, int argc, char *argv[])
00503 {
00504 extern int cvs_exclude;
00505 extern int am_sender;
00506 extern int remote_version;
00507 extern int read_batch;
00508
00509 setup_protocol(f_out, f_in);
00510
00511 set_nonblocking(f_in);
00512 set_nonblocking(f_out);
00513
00514 if (remote_version >= 23)
00515 io_start_multiplex_out(f_out);
00516
00517 if (am_sender) {
00518 if (!read_batch) {
00519 recv_exclude_list(f_in);
00520 if (cvs_exclude)
00521 add_cvs_excludes();
00522 }
00523 do_server_sender(f_in, f_out, argc, argv);
00524 } else {
00525 do_server_recv(f_in, f_out, argc, argv);
00526 }
00527 exit_cleanup(0);
00528 }
00529
00530
00531
00532
00533
00534
00535 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
00536 {
00537 struct file_list *flist = NULL;
00538 int status = 0, status2 = 0;
00539 char *local_name = NULL;
00540 extern int am_sender;
00541 extern int remote_version;
00542 extern pid_t cleanup_child_pid;
00543 extern int write_batch;
00544 extern int read_batch;
00545 extern struct file_list *batch_flist;
00546
00547 cleanup_child_pid = pid;
00548 if (read_batch)
00549 flist = batch_flist;
00550
00551 set_nonblocking(f_in);
00552 set_nonblocking(f_out);
00553
00554 setup_protocol(f_out,f_in);
00555
00556 if (remote_version >= 23)
00557 io_start_multiplex_in(f_in);
00558
00559 if (am_sender) {
00560 extern int cvs_exclude;
00561 extern int delete_mode;
00562 extern int delete_excluded;
00563 if (cvs_exclude)
00564 add_cvs_excludes();
00565 if (delete_mode && !delete_excluded)
00566 send_exclude_list(f_out);
00567 if (!read_batch)
00568 flist = send_file_list(f_out,argc,argv);
00569 if (verbose > 3)
00570 rprintf(FINFO,"file list sent\n");
00571
00572 send_files(flist,f_out,f_in);
00573 if (remote_version >= 24) {
00574
00575 read_int(f_in);
00576 }
00577 if (pid != -1) {
00578 if (verbose > 3)
00579 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
00580 io_flush();
00581 wait_process(pid, &status);
00582 }
00583 report(-1);
00584 exit_cleanup(status);
00585 }
00586
00587 if (argc == 0) {
00588 extern int list_only;
00589 list_only = 1;
00590 }
00591
00592 if (!write_batch)
00593 send_exclude_list(f_out);
00594
00595 flist = recv_file_list(f_in);
00596 if (!flist || flist->count == 0) {
00597 rprintf(FINFO, "client: nothing to do: "
00598 "perhaps you need to specify some filenames or "
00599 "the --recursive option?\n");
00600 exit_cleanup(0);
00601 }
00602
00603 local_name = get_local_name(flist,argv[0]);
00604
00605 status2 = do_recv(f_in,f_out,flist,local_name);
00606
00607 if (pid != -1) {
00608 if (verbose > 3)
00609 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
00610 io_flush();
00611 wait_process(pid, &status);
00612 }
00613
00614 return MAX(status, status2);
00615 }
00616
00617 static char *find_colon(char *s)
00618 {
00619 char *p, *p2;
00620
00621 p = strchr(s,':');
00622 if (!p) return NULL;
00623
00624
00625
00626 p2 = strchr(s,'/');
00627 if (p2 && p2 < p) return NULL;
00628
00629 return p;
00630 }
00631
00632
00633 static int copy_argv (char *argv[])
00634 {
00635 int i;
00636
00637 for (i = 0; argv[i]; i++) {
00638 if (!(argv[i] = strdup(argv[i]))) {
00639 rprintf (FERROR, "out of memory at %s(%d)\n",
00640 __FILE__, __LINE__);
00641 return RERR_MALLOC;
00642 }
00643 }
00644
00645 return 0;
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 static int start_client(int argc, char *argv[])
00658 {
00659 char *p;
00660 char *shell_machine = NULL;
00661 char *shell_path = NULL;
00662 char *shell_user = NULL;
00663 int ret;
00664 pid_t pid;
00665 int f_in,f_out;
00666 extern int local_server;
00667 extern int am_sender;
00668 extern char *shell_cmd;
00669 extern int rsync_port;
00670 extern int read_batch;
00671 int rc;
00672
00673
00674
00675 if ((rc = copy_argv (argv)))
00676 return rc;
00677
00678 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
00679 char *host, *path;
00680
00681 host = argv[0] + strlen(URL_PREFIX);
00682 p = strchr(host,'/');
00683 if (p) {
00684 *p = 0;
00685 path = p+1;
00686 } else {
00687 path="";
00688 }
00689 p = strchr(host,':');
00690 if (p) {
00691 rsync_port = atoi(p+1);
00692 *p = 0;
00693 }
00694 return start_socket_client(host, path, argc-1, argv+1);
00695 }
00696
00697 if (!read_batch) {
00698 p = find_colon(argv[0]);
00699
00700 if (p) {
00701 if (p[1] == ':') {
00702 *p = 0;
00703 return start_socket_client(argv[0], p+2, argc-1, argv+1);
00704 }
00705
00706 if (argc < 1) {
00707 usage(FERROR);
00708 exit_cleanup(RERR_SYNTAX);
00709 }
00710
00711 am_sender = 0;
00712 *p = 0;
00713 shell_machine = argv[0];
00714 shell_path = p+1;
00715 argc--;
00716 argv++;
00717 } else {
00718 am_sender = 1;
00719
00720 p = find_colon(argv[argc-1]);
00721 if (!p) {
00722 local_server = 1;
00723 } else if (p[1] == ':') {
00724 *p = 0;
00725 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
00726 }
00727
00728 if (argc < 2) {
00729 usage(FERROR);
00730 exit_cleanup(RERR_SYNTAX);
00731 }
00732
00733 if (local_server) {
00734 shell_machine = NULL;
00735 shell_path = argv[argc-1];
00736 } else {
00737 *p = 0;
00738 shell_machine = argv[argc-1];
00739 shell_path = p+1;
00740 }
00741 argc--;
00742 }
00743 } else {
00744 am_sender = 1;
00745 local_server = 1;
00746 shell_path = argv[argc-1];
00747 }
00748
00749 if (shell_machine) {
00750 p = strchr(shell_machine,'@');
00751 if (p) {
00752 *p = 0;
00753 shell_user = shell_machine;
00754 shell_machine = p+1;
00755 }
00756 }
00757
00758 if (verbose > 3) {
00759 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
00760 shell_cmd?shell_cmd:"",
00761 shell_machine?shell_machine:"",
00762 shell_user?shell_user:"",
00763 shell_path?shell_path:"");
00764 }
00765
00766 if (!am_sender && argc > 1) {
00767 usage(FERROR);
00768 exit_cleanup(RERR_SYNTAX);
00769 }
00770
00771 if (argc == 0 && !am_sender) {
00772 extern int list_only;
00773 list_only = 1;
00774 }
00775
00776 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
00777
00778 ret = client_run(f_in, f_out, pid, argc, argv);
00779
00780 fflush(stdout);
00781 fflush(stderr);
00782
00783 return ret;
00784 }
00785
00786
00787 static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
00788 exit_cleanup(RERR_SIGNAL);
00789 }
00790
00791 static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
00792 extern int log_got_error;
00793 if (log_got_error) _exit(RERR_PARTIAL);
00794 _exit(0);
00795 }
00796
00797 static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
00798 #ifdef WNOHANG
00799 while (waitpid(-1, NULL, WNOHANG) > 0) ;
00800 #endif
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 #ifdef MAINTAINER_MODE
00818 const char *get_panic_action(void)
00819 {
00820 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
00821
00822 if (cmd_fmt)
00823 return cmd_fmt;
00824 else
00825 return "xterm -display :0 -T Panic -n Panic "
00826 "-e gdb /proc/%d/exe %d";
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
00839 {
00840 char cmd_buf[300];
00841 int ret;
00842
00843 sprintf(cmd_buf, get_panic_action(),
00844 getpid(), getpid());
00845
00846
00847
00848 ret = system(cmd_buf);
00849 if (ret)
00850 _exit(ret);
00851 }
00852 #endif
00853
00854
00855 int main(int argc,char *argv[])
00856 {
00857 extern int am_root;
00858 extern int orig_umask;
00859 extern int dry_run;
00860 extern int am_daemon;
00861 extern int am_server;
00862 int ret;
00863 extern int write_batch;
00864 int orig_argc;
00865 char **orig_argv;
00866
00867 orig_argc = argc;
00868 orig_argv = argv;
00869
00870 signal(SIGUSR1, sigusr1_handler);
00871 signal(SIGUSR2, sigusr2_handler);
00872 signal(SIGCHLD, sigchld_handler);
00873 #ifdef MAINTAINER_MODE
00874 signal(SIGSEGV, rsync_panic_handler);
00875 signal(SIGFPE, rsync_panic_handler);
00876 signal(SIGABRT, rsync_panic_handler);
00877 signal(SIGBUS, rsync_panic_handler);
00878 #endif
00879
00880 starttime = time(NULL);
00881 am_root = (getuid() == 0);
00882
00883 memset(&stats, 0, sizeof(stats));
00884
00885 if (argc < 2) {
00886 usage(FERROR);
00887 exit_cleanup(RERR_SYNTAX);
00888 }
00889
00890
00891
00892 orig_umask = (int)umask(0);
00893
00894 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
00895
00896
00897 option_error();
00898 exit_cleanup(RERR_SYNTAX);
00899 }
00900
00901 signal(SIGINT,SIGNAL_CAST sig_int);
00902 signal(SIGHUP,SIGNAL_CAST sig_int);
00903 signal(SIGTERM,SIGNAL_CAST sig_int);
00904
00905
00906
00907 signal(SIGPIPE, SIG_IGN);
00908
00909
00910
00911
00912
00913 push_dir(NULL,0);
00914
00915 if (write_batch && !am_server) {
00916 write_batch_argvs_file(orig_argc, orig_argv);
00917 }
00918
00919 if (am_daemon) {
00920 return daemon_main();
00921 }
00922
00923 if (argc < 1) {
00924 usage(FERROR);
00925 exit_cleanup(RERR_SYNTAX);
00926 }
00927
00928 if (dry_run)
00929 verbose = MAX(verbose,1);
00930
00931 #ifndef SUPPORT_LINKS
00932 if (!am_server && preserve_links) {
00933 rprintf(FERROR,"ERROR: symbolic links not supported\n");
00934 exit_cleanup(RERR_UNSUPPORTED);
00935 }
00936 #endif
00937
00938 if (am_server) {
00939 set_nonblocking(STDIN_FILENO);
00940 set_nonblocking(STDOUT_FILENO);
00941 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
00942 }
00943
00944 ret = start_client(argc, argv);
00945 if (ret == -1)
00946 exit_cleanup(RERR_STARTCLIENT);
00947 else
00948 exit_cleanup(ret);
00949
00950 exit(ret);
00951
00952 }