Insert a 100ms sleep just before sending the USR2 signal to the
[rsync/rsync.git] / main.c
... / ...
CommitLineData
1/* -*- c-file-style: "linux" -*-
2
3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) Paul Mackerras 1996
5 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rsync.h"
23
24time_t starttime = 0;
25
26extern struct stats stats;
27extern int verbose;
28
29/* there's probably never more than at most 2 outstanding child processes,
30 * but set it higher just in case.
31 */
32#define MAXCHILDPROCS 5
33
34struct pid_status {
35 pid_t pid;
36 int status;
37} pid_stat_table[MAXCHILDPROCS];
38
39static void show_malloc_stats(void);
40
41/****************************************************************************
42wait for a process to exit, calling io_flush while waiting
43****************************************************************************/
44void wait_process(pid_t pid, int *status)
45{
46 pid_t waited_pid;
47 int cnt;
48
49 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
50 msleep(20);
51 io_flush();
52 }
53
54 if ((waited_pid == -1) && (errno == ECHILD)) {
55 /* status of requested child no longer available.
56 * check to see if it was processed by the sigchld_handler.
57 */
58 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
59 if (pid == pid_stat_table[cnt].pid) {
60 *status = pid_stat_table[cnt].status;
61 pid_stat_table[cnt].pid = 0;
62 break;
63 }
64 }
65 }
66
67 /* TODO: If the child exited on a signal, then log an
68 * appropriate error message. Perhaps we should also accept a
69 * message describing the purpose of the child. Also indicate
70 * this to the caller so that thhey know something went
71 * wrong. */
72 *status = WEXITSTATUS(*status);
73}
74
75static void report(int f)
76{
77 time_t t = time(NULL);
78 extern int am_server;
79 extern int am_sender;
80 extern int am_daemon;
81 extern int do_stats;
82 extern int remote_version;
83 int send_stats;
84
85 if (do_stats) {
86 /* These come out from every process */
87 show_malloc_stats();
88 show_flist_stats();
89 }
90
91 if (am_daemon) {
92 log_exit(0, __FILE__, __LINE__);
93 if (f == -1 || !am_sender) return;
94 }
95
96 send_stats = verbose || (remote_version >= 20);
97 if (am_server) {
98 if (am_sender && send_stats) {
99 int64 w;
100 /* store total_written in a temporary
101 because write_longint changes it */
102 w = stats.total_written;
103 write_longint(f,stats.total_read);
104 write_longint(f,w);
105 write_longint(f,stats.total_size);
106 }
107 return;
108 }
109
110 /* this is the client */
111
112 if (!am_sender && send_stats) {
113 int64 r;
114 stats.total_written = read_longint(f);
115 /* store total_read in a temporary, read_longint changes it */
116 r = read_longint(f);
117 stats.total_size = read_longint(f);
118 stats.total_read = r;
119 }
120
121 if (do_stats) {
122 if (!am_sender && !send_stats) {
123 /* missing the bytes written by the generator */
124 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
125 rprintf(FINFO, "Use --stats -v to show stats\n");
126 return;
127 }
128 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
129 rprintf(FINFO,"Number of files transferred: %d\n",
130 stats.num_transferred_files);
131 rprintf(FINFO,"Total file size: %.0f bytes\n",
132 (double)stats.total_size);
133 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
134 (double)stats.total_transferred_size);
135 rprintf(FINFO,"Literal data: %.0f bytes\n",
136 (double)stats.literal_data);
137 rprintf(FINFO,"Matched data: %.0f bytes\n",
138 (double)stats.matched_data);
139 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
140 rprintf(FINFO,"Total bytes written: %.0f\n",
141 (double)stats.total_written);
142 rprintf(FINFO,"Total bytes read: %.0f\n\n",
143 (double)stats.total_read);
144 }
145
146 if (verbose || do_stats) {
147 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
148 (double)stats.total_written,
149 (double)stats.total_read,
150 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
151 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
152 (double)stats.total_size,
153 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
154 }
155
156 fflush(stdout);
157 fflush(stderr);
158}
159
160
161/**
162 * If our C library can get malloc statistics, then show them to FINFO
163 **/
164static void show_malloc_stats(void)
165{
166#ifdef HAVE_MALLINFO
167 struct mallinfo mi;
168 extern int am_server;
169 extern int am_sender;
170 extern int am_daemon;
171
172 mi = mallinfo();
173
174 rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
175 getpid(),
176 am_server ? "server " : "",
177 am_daemon ? "daemon " : "",
178 am_sender ? "sender" : "receiver");
179 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
180 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
181 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
182 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
183 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
184 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
185 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
186 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
187 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
188 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
189#endif /* HAVE_MALLINFO */
190}
191
192
193/* Start the remote shell. cmd may be NULL to use the default. */
194static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
195{
196 char *args[100];
197 int i,argc=0;
198 pid_t ret;
199 char *tok,*dir=NULL;
200 int dash_l_set = 0;
201 extern int local_server;
202 extern char *rsync_path;
203 extern int blocking_io;
204 extern int daemon_over_rsh;
205 extern int read_batch;
206
207 if (!read_batch && !local_server) {
208 if (!cmd)
209 cmd = getenv(RSYNC_RSH_ENV);
210 if (!cmd)
211 cmd = RSYNC_RSH;
212 cmd = strdup(cmd);
213 if (!cmd)
214 goto oom;
215
216 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
217 args[argc++] = tok;
218 }
219
220 /* check to see if we've already been given '-l user' in
221 the remote-shell command */
222 for (i = 0; i < argc-1; i++) {
223 if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
224 dash_l_set = 1;
225 }
226
227#if HAVE_REMSH
228 /* remsh (on HPUX) takes the arguments the other way around */
229 args[argc++] = machine;
230 if (user && !(daemon_over_rsh && dash_l_set)) {
231 args[argc++] = "-l";
232 args[argc++] = user;
233 }
234#else
235 if (user && !(daemon_over_rsh && dash_l_set)) {
236 args[argc++] = "-l";
237 args[argc++] = user;
238 }
239 args[argc++] = machine;
240#endif
241
242 args[argc++] = rsync_path;
243
244 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
245 blocking_io = 1;
246
247 server_options(args,&argc);
248
249 }
250
251 args[argc++] = ".";
252
253 if (!daemon_over_rsh && path && *path)
254 args[argc++] = path;
255
256 args[argc] = NULL;
257
258 if (verbose > 3) {
259 rprintf(FINFO,"cmd=");
260 for (i=0;i<argc;i++)
261 rprintf(FINFO,"%s ",args[i]);
262 rprintf(FINFO,"\n");
263 }
264
265 if (local_server) {
266 if (read_batch)
267 create_flist_from_batch(); /* sets batch_flist */
268 ret = local_child(argc, args, f_in, f_out, child_main);
269 } else {
270 ret = piped_child(args,f_in,f_out);
271 }
272
273 if (dir) free(dir);
274
275 return ret;
276
277oom:
278 out_of_memory("do_cmd");
279 return 0; /* not reached */
280}
281
282
283
284
285static char *get_local_name(struct file_list *flist,char *name)
286{
287 STRUCT_STAT st;
288 extern int orig_umask;
289
290 if (verbose > 2)
291 rprintf(FINFO,"get_local_name count=%d %s\n",
292 flist->count, NS(name));
293
294 if (!name)
295 return NULL;
296
297 if (do_stat(name,&st) == 0) {
298 if (S_ISDIR(st.st_mode)) {
299 if (!push_dir(name, 0)) {
300 rprintf(FERROR,"push_dir %s : %s (1)\n",
301 name,strerror(errno));
302 exit_cleanup(RERR_FILESELECT);
303 }
304 return NULL;
305 }
306 if (flist->count > 1) {
307 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
308 exit_cleanup(RERR_FILESELECT);
309 }
310 return name;
311 }
312
313 if (flist->count <= 1)
314 return name;
315
316 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
317 rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
318 name, strerror(errno));
319 exit_cleanup(RERR_FILEIO);
320 } else {
321 if (verbose > 0)
322 rprintf(FINFO,"created directory %s\n",name);
323 }
324
325 if (!push_dir(name, 0)) {
326 rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
327 name, strerror(errno));
328 exit_cleanup(RERR_FILESELECT);
329 }
330
331 return NULL;
332}
333
334
335
336
337static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
338{
339 int i;
340 struct file_list *flist;
341 char *dir = argv[0];
342 extern int relative_paths;
343 extern int recurse;
344 extern int remote_version;
345
346 if (verbose > 2)
347 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
348
349 if (!relative_paths && !push_dir(dir, 0)) {
350 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
351 exit_cleanup(RERR_FILESELECT);
352 }
353 argc--;
354 argv++;
355
356 if (strcmp(dir,".")) {
357 int l = strlen(dir);
358 if (strcmp(dir,"/") == 0)
359 l = 0;
360 for (i=0;i<argc;i++)
361 argv[i] += l+1;
362 }
363
364 if (argc == 0 && recurse) {
365 argc=1;
366 argv--;
367 argv[0] = ".";
368 }
369
370 flist = send_file_list(f_out,argc,argv);
371 if (!flist || flist->count == 0) {
372 exit_cleanup(0);
373 }
374
375 send_files(flist,f_out,f_in);
376 io_flush();
377 report(f_out);
378 if (remote_version >= 24) {
379 /* final goodbye message */
380 read_int(f_in);
381 }
382 io_flush();
383 exit_cleanup(0);
384}
385
386
387static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
388{
389 int pid;
390 int status=0;
391 int recv_pipe[2];
392 int error_pipe[2];
393 extern int preserve_hard_links;
394 extern int delete_after;
395 extern int recurse;
396 extern int delete_mode;
397 extern int remote_version;
398
399 if (preserve_hard_links)
400 init_hard_links(flist);
401
402 if (!delete_after) {
403 /* I moved this here from recv_files() to prevent a race condition */
404 if (recurse && delete_mode && !local_name && flist->count>0) {
405 delete_files(flist);
406 }
407 }
408
409 if (fd_pair(recv_pipe) < 0) {
410 rprintf(FERROR,"pipe failed in do_recv\n");
411 exit_cleanup(RERR_SOCKETIO);
412 }
413
414 if (fd_pair(error_pipe) < 0) {
415 rprintf(FERROR,"error pipe failed in do_recv\n");
416 exit_cleanup(RERR_SOCKETIO);
417 }
418
419 io_flush();
420
421 if ((pid=do_fork()) == 0) {
422 close(recv_pipe[0]);
423 close(error_pipe[0]);
424 if (f_in != f_out) close(f_out);
425
426 /* we can't let two processes write to the socket at one time */
427 io_multiplexing_close();
428
429 /* set place to send errors */
430 set_error_fd(error_pipe[1]);
431
432 recv_files(f_in,flist,local_name,recv_pipe[1]);
433 io_flush();
434 report(f_in);
435
436 write_int(recv_pipe[1],1);
437 close(recv_pipe[1]);
438 io_flush();
439 /* finally we go to sleep until our parent kills us
440 with a USR2 signal. We sleep for a short time as on
441 some OSes a signal won't interrupt a sleep! */
442 while (msleep(20))
443 ;
444 }
445
446 close(recv_pipe[1]);
447 close(error_pipe[1]);
448 if (f_in != f_out) close(f_in);
449
450 io_start_buffering(f_out);
451
452 io_set_error_fd(error_pipe[0]);
453
454 generate_files(f_out,flist,local_name,recv_pipe[0]);
455
456 read_int(recv_pipe[0]);
457 close(recv_pipe[0]);
458 if (remote_version >= 24) {
459 /* send a final goodbye message */
460 write_int(f_out, -1);
461 }
462 io_flush();
463
464 io_set_error_fd(-1);
465 /* workaround for cygwin hangs; wait to make sure child is ready */
466 msleep(100);
467 kill(pid, SIGUSR2);
468 wait_process(pid, &status);
469 return status;
470}
471
472
473static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
474{
475 int status;
476 struct file_list *flist;
477 char *local_name=NULL;
478 char *dir = NULL;
479 extern int delete_mode;
480 extern int delete_excluded;
481 extern int am_daemon;
482 extern int module_id;
483 extern int am_sender;
484 extern int read_batch;
485 extern struct file_list *batch_flist;
486
487 if (verbose > 2)
488 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
489
490 if (am_daemon && lp_read_only(module_id) && !am_sender) {
491 rprintf(FERROR,"ERROR: module is read only\n");
492 exit_cleanup(RERR_SYNTAX);
493 return;
494 }
495
496
497 if (argc > 0) {
498 dir = argv[0];
499 argc--;
500 argv++;
501 if (!am_daemon && !push_dir(dir, 0)) {
502 rprintf(FERROR,"push_dir %s : %s (4)\n",
503 dir,strerror(errno));
504 exit_cleanup(RERR_FILESELECT);
505 }
506 }
507
508 if (delete_mode && !delete_excluded)
509 recv_exclude_list(f_in);
510
511 if (read_batch)
512 flist = batch_flist;
513 else
514 flist = recv_file_list(f_in);
515 if (!flist) {
516 rprintf(FERROR,"server_recv: recv_file_list error\n");
517 exit_cleanup(RERR_FILESELECT);
518 }
519
520 if (argc > 0) {
521 if (strcmp(dir,".")) {
522 argv[0] += strlen(dir);
523 if (argv[0][0] == '/') argv[0]++;
524 }
525 local_name = get_local_name(flist,argv[0]);
526 }
527
528 status = do_recv(f_in,f_out,flist,local_name);
529 exit_cleanup(status);
530}
531
532
533int child_main(int argc, char *argv[])
534{
535 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
536 return 0;
537}
538
539
540void start_server(int f_in, int f_out, int argc, char *argv[])
541{
542 extern int cvs_exclude;
543 extern int am_sender;
544 extern int remote_version;
545 extern int read_batch;
546
547 setup_protocol(f_out, f_in);
548
549 set_nonblocking(f_in);
550 set_nonblocking(f_out);
551
552 if (remote_version >= 23)
553 io_start_multiplex_out(f_out);
554
555 if (am_sender) {
556 if (!read_batch) {
557 recv_exclude_list(f_in);
558 if (cvs_exclude)
559 add_cvs_excludes();
560 }
561 do_server_sender(f_in, f_out, argc, argv);
562 } else {
563 do_server_recv(f_in, f_out, argc, argv);
564 }
565 exit_cleanup(0);
566}
567
568
569/*
570 * This is called once the connection has been negotiated. It is used
571 * for rsyncd, remote-shell, and local connections.
572 */
573int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
574{
575 struct file_list *flist = NULL;
576 int status = 0, status2 = 0;
577 char *local_name = NULL;
578 extern int am_sender;
579 extern int remote_version;
580 extern pid_t cleanup_child_pid;
581 extern int write_batch;
582 extern int read_batch;
583 extern struct file_list *batch_flist;
584
585 cleanup_child_pid = pid;
586 if (read_batch)
587 flist = batch_flist;
588
589 set_nonblocking(f_in);
590 set_nonblocking(f_out);
591
592 setup_protocol(f_out,f_in);
593
594 if (remote_version >= 23)
595 io_start_multiplex_in(f_in);
596
597 if (am_sender) {
598 extern int cvs_exclude;
599 extern int delete_mode;
600 extern int delete_excluded;
601 if (cvs_exclude)
602 add_cvs_excludes();
603 if (delete_mode && !delete_excluded)
604 send_exclude_list(f_out);
605 if (!read_batch) /* dw -- don't write to pipe */
606 flist = send_file_list(f_out,argc,argv);
607 if (verbose > 3)
608 rprintf(FINFO,"file list sent\n");
609
610 send_files(flist,f_out,f_in);
611 if (remote_version >= 24) {
612 /* final goodbye message */
613 read_int(f_in);
614 }
615 if (pid != -1) {
616 if (verbose > 3)
617 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
618 io_flush();
619 wait_process(pid, &status);
620 }
621 report(-1);
622 exit_cleanup(status);
623 }
624
625 if (argc == 0) {
626 extern int list_only;
627 list_only = 1;
628 }
629
630 if (!write_batch)
631 send_exclude_list(f_out);
632
633 flist = recv_file_list(f_in);
634 if (!flist || flist->count == 0) {
635 rprintf(FINFO, "client: nothing to do: "
636 "perhaps you need to specify some filenames or "
637 "the --recursive option?\n");
638 exit_cleanup(0);
639 }
640
641 local_name = get_local_name(flist,argv[0]);
642
643 status2 = do_recv(f_in,f_out,flist,local_name);
644
645 if (pid != -1) {
646 if (verbose > 3)
647 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
648 io_flush();
649 wait_process(pid, &status);
650 }
651
652 return MAX(status, status2);
653}
654
655static char *find_colon(char *s)
656{
657 char *p, *p2;
658
659 p = strchr(s,':');
660 if (!p) return NULL;
661
662 /* now check to see if there is a / in the string before the : - if there is then
663 discard the colon on the assumption that the : is part of a filename */
664 p2 = strchr(s,'/');
665 if (p2 && p2 < p) return NULL;
666
667 return p;
668}
669
670
671static int copy_argv (char *argv[])
672{
673 int i;
674
675 for (i = 0; argv[i]; i++) {
676 if (!(argv[i] = strdup(argv[i]))) {
677 rprintf (FERROR, "out of memory at %s(%d)\n",
678 __FILE__, __LINE__);
679 return RERR_MALLOC;
680 }
681 }
682
683 return 0;
684}
685
686
687/**
688 * Start a client for either type of remote connection. Work out
689 * whether the arguments request a remote shell or rsyncd connection,
690 * and call the appropriate connection function, then run_client.
691 *
692 * Calls either start_socket_client (for sockets) or do_cmd and
693 * client_run (for ssh).
694 **/
695static int start_client(int argc, char *argv[])
696{
697 char *p;
698 char *shell_machine = NULL;
699 char *shell_path = NULL;
700 char *shell_user = NULL;
701 int ret;
702 pid_t pid;
703 int f_in,f_out;
704 extern int local_server;
705 extern int am_sender;
706 extern char *shell_cmd;
707 extern int rsync_port;
708 extern int daemon_over_rsh;
709 extern int read_batch;
710 int rc;
711
712 /* Don't clobber argv[] so that ps(1) can still show the right
713 command line. */
714 if ((rc = copy_argv(argv)))
715 return rc;
716
717 /* rsync:// always uses rsync server over direct socket connection */
718 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
719 char *host, *path;
720
721 host = argv[0] + strlen(URL_PREFIX);
722 p = strchr(host,'/');
723 if (p) {
724 *p = 0;
725 path = p+1;
726 } else {
727 path = "";
728 }
729 p = strchr(host,':');
730 if (p) {
731 rsync_port = atoi(p+1);
732 *p = 0;
733 }
734 return start_socket_client(host, path, argc-1, argv+1);
735 }
736
737 if (!read_batch) {
738 p = find_colon(argv[0]);
739
740 if (p) {
741 if (p[1] == ':') { /* double colon */
742 *p = 0;
743 if (!shell_cmd) {
744 return start_socket_client(argv[0], p+2,
745 argc-1, argv+1);
746 }
747 p++;
748 daemon_over_rsh = 1;
749 }
750
751 if (argc < 1) {
752 usage(FERROR);
753 exit_cleanup(RERR_SYNTAX);
754 }
755
756 am_sender = 0;
757 *p = 0;
758 shell_machine = argv[0];
759 shell_path = p+1;
760 argc--;
761 argv++;
762 } else {
763 am_sender = 1;
764
765 /* rsync:// destination uses rsync server over direct socket */
766 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
767 char *host, *path;
768
769 host = argv[argc-1] + strlen(URL_PREFIX);
770 p = strchr(host,'/');
771 if (p) {
772 *p = 0;
773 path = p+1;
774 } else {
775 path = "";
776 }
777 p = strchr(host,':');
778 if (p) {
779 rsync_port = atoi(p+1);
780 *p = 0;
781 }
782 return start_socket_client(host, path, argc-1, argv);
783 }
784
785 p = find_colon(argv[argc-1]);
786 if (!p) {
787 local_server = 1;
788 } else if (p[1] == ':') { /* double colon */
789 *p = 0;
790 if (!shell_cmd) {
791 return start_socket_client(argv[argc-1], p+2,
792 argc-1, argv);
793 }
794 p++;
795 daemon_over_rsh = 1;
796 }
797
798 if (argc < 2) {
799 usage(FERROR);
800 exit_cleanup(RERR_SYNTAX);
801 }
802
803 if (local_server) {
804 shell_machine = NULL;
805 shell_path = argv[argc-1];
806 } else {
807 *p = 0;
808 shell_machine = argv[argc-1];
809 shell_path = p+1;
810 }
811 argc--;
812 }
813 } else {
814 am_sender = 1;
815 local_server = 1;
816 shell_path = argv[argc-1];
817 }
818
819 if (shell_machine) {
820 p = strchr(shell_machine,'@');
821 if (p) {
822 *p = 0;
823 shell_user = shell_machine;
824 shell_machine = p+1;
825 }
826 }
827
828 if (verbose > 3) {
829 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
830 shell_cmd?shell_cmd:"",
831 shell_machine?shell_machine:"",
832 shell_user?shell_user:"",
833 shell_path?shell_path:"");
834 }
835
836 if (!am_sender && argc > 1) {
837 usage(FERROR);
838 exit_cleanup(RERR_SYNTAX);
839 }
840
841 if (argc == 0 && !am_sender) {
842 extern int list_only;
843 list_only = 1;
844 }
845
846 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
847 &f_in,&f_out);
848
849 /* if we're running an rsync server on the remote host over a
850 remote shell command, we need to do the RSYNCD protocol first */
851 if (daemon_over_rsh) {
852 int tmpret;
853 tmpret = start_inband_exchange(shell_user, shell_path,
854 f_in, f_out, argc);
855 if (tmpret < 0)
856 return tmpret;
857 }
858
859 ret = client_run(f_in, f_out, pid, argc, argv);
860
861 fflush(stdout);
862 fflush(stderr);
863
864 return ret;
865}
866
867
868static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
869 exit_cleanup(RERR_SIGNAL);
870}
871
872static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
873 extern int log_got_error;
874 if (log_got_error) _exit(RERR_PARTIAL);
875 _exit(0);
876}
877
878static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
879#ifdef WNOHANG
880 int cnt, status;
881 pid_t pid;
882 /* An empty waitpid() loop was put here by Tridge and we could never
883 * get him to explain why he put it in, so rather than taking it
884 * out we're instead saving the child exit statuses for later use.
885 * The waitpid() loop presumably eliminates all possibility of leaving
886 * zombie children, maybe that's why he did it.
887 */
888 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
889 /* save the child's exit status */
890 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
891 if (pid_stat_table[cnt].pid == 0) {
892 pid_stat_table[cnt].pid = pid;
893 pid_stat_table[cnt].status = status;
894 break;
895 }
896 }
897 }
898#endif
899}
900
901
902/**
903 * This routine catches signals and tries to send them to gdb.
904 *
905 * Because it's called from inside a signal handler it ought not to
906 * use too many library routines.
907 *
908 * @todo Perhaps use "screen -X" instead/as well, to help people
909 * debugging without easy access to X. Perhaps use an environment
910 * variable, or just call a script?
911 *
912 * @todo The /proc/ magic probably only works on Linux (and
913 * Solaris?) Can we be more portable?
914 **/
915#ifdef MAINTAINER_MODE
916const char *get_panic_action(void)
917{
918 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
919
920 if (cmd_fmt)
921 return cmd_fmt;
922 else
923 return "xterm -display :0 -T Panic -n Panic "
924 "-e gdb /proc/%d/exe %d";
925}
926
927
928/**
929 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
930 *
931 * This signal handler is only installed if we were configured with
932 * --enable-maintainer-mode. Perhaps it should always be on and we
933 * should just look at the environment variable, but I'm a bit leery
934 * of a signal sending us into a busy loop.
935 **/
936static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
937{
938 char cmd_buf[300];
939 int ret;
940
941 sprintf(cmd_buf, get_panic_action(),
942 getpid(), getpid());
943
944 /* Unless we failed to execute gdb, we allow the process to
945 * continue. I'm not sure if that's right. */
946 ret = system(cmd_buf);
947 if (ret)
948 _exit(ret);
949}
950#endif
951
952
953int main(int argc,char *argv[])
954{
955 extern int am_root;
956 extern int orig_umask;
957 extern int dry_run;
958 extern int am_daemon;
959 extern int am_server;
960 int ret;
961 extern int write_batch;
962 int orig_argc;
963 char **orig_argv;
964
965 orig_argc = argc;
966 orig_argv = argv;
967
968 signal(SIGUSR1, sigusr1_handler);
969 signal(SIGUSR2, sigusr2_handler);
970 signal(SIGCHLD, sigchld_handler);
971#ifdef MAINTAINER_MODE
972 signal(SIGSEGV, rsync_panic_handler);
973 signal(SIGFPE, rsync_panic_handler);
974 signal(SIGABRT, rsync_panic_handler);
975 signal(SIGBUS, rsync_panic_handler);
976#endif /* def MAINTAINER_MODE */
977
978 starttime = time(NULL);
979 am_root = (getuid() == 0);
980
981 memset(&stats, 0, sizeof(stats));
982
983 if (argc < 2) {
984 usage(FERROR);
985 exit_cleanup(RERR_SYNTAX);
986 }
987
988 /* we set a 0 umask so that correct file permissions can be
989 carried across */
990 orig_umask = (int)umask(0);
991
992 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
993 /* FIXME: We ought to call the same error-handling
994 * code here, rather than relying on getopt. */
995 option_error();
996 exit_cleanup(RERR_SYNTAX);
997 }
998
999 signal(SIGINT,SIGNAL_CAST sig_int);
1000 signal(SIGHUP,SIGNAL_CAST sig_int);
1001 signal(SIGTERM,SIGNAL_CAST sig_int);
1002
1003 /* Ignore SIGPIPE; we consistently check error codes and will
1004 * see the EPIPE. */
1005 signal(SIGPIPE, SIG_IGN);
1006
1007 /* Initialize push_dir here because on some old systems getcwd
1008 (implemented by forking "pwd" and reading its output) doesn't
1009 work when there are other child processes. Also, on all systems
1010 that implement getcwd that way "pwd" can't be found after chroot. */
1011 push_dir(NULL,0);
1012
1013 if (write_batch && !am_server) {
1014 write_batch_argvs_file(orig_argc, orig_argv);
1015 }
1016
1017 if (am_daemon && !am_server)
1018 return daemon_main();
1019
1020 if (argc < 1) {
1021 usage(FERROR);
1022 exit_cleanup(RERR_SYNTAX);
1023 }
1024
1025 if (dry_run)
1026 verbose = MAX(verbose,1);
1027
1028#ifndef SUPPORT_LINKS
1029 if (!am_server && preserve_links) {
1030 rprintf(FERROR,"ERROR: symbolic links not supported\n");
1031 exit_cleanup(RERR_UNSUPPORTED);
1032 }
1033#endif
1034
1035 if (am_server) {
1036 set_nonblocking(STDIN_FILENO);
1037 set_nonblocking(STDOUT_FILENO);
1038 if (am_daemon)
1039 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
1040 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1041 }
1042
1043 ret = start_client(argc, argv);
1044 if (ret == -1)
1045 exit_cleanup(RERR_STARTCLIENT);
1046 else
1047 exit_cleanup(ret);
1048
1049 exit(ret);
1050 /* NOTREACHED */
1051}