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