Made the default remote-shell be "ssh" (override with --with-rsh=FOO).
[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) && (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 int e;
289 extern int orig_umask;
290
291 if (verbose > 2)
292 rprintf(FINFO,"get_local_name count=%d %s\n",
293 flist->count, NS(name));
294
295 if (!name)
296 return NULL;
297
298 if (do_stat(name,&st) == 0) {
299 if (S_ISDIR(st.st_mode)) {
300 if (!push_dir(name, 0)) {
301 rprintf(FERROR, "push_dir %s failed: %s (1)\n",
302 full_fname(name), strerror(errno));
303 exit_cleanup(RERR_FILESELECT);
304 }
305 return NULL;
306 }
307 if (flist->count > 1) {
308 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
309 exit_cleanup(RERR_FILESELECT);
310 }
311 return name;
312 }
313
314 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
315 return name;
316
317 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
318 rprintf(FERROR, "mkdir %s failed: %s\n",
319 full_fname(name), strerror(errno));
320 exit_cleanup(RERR_FILEIO);
321 } else {
322 if (verbose > 0)
323 rprintf(FINFO,"created directory %s\n",name);
324 }
325
326 if (!push_dir(name, 0)) {
327 rprintf(FERROR, "push_dir %s failed: %s (2)\n",
328 full_fname(name), strerror(errno));
329 exit_cleanup(RERR_FILESELECT);
330 }
331
332 return NULL;
333}
334
335
336
337
338static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
339{
340 int i;
341 struct file_list *flist;
342 char *dir = argv[0];
343 extern int relative_paths;
344 extern int recurse;
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 failed: %s (3)\n",
351 full_fname(dir), strerror(errno));
352 exit_cleanup(RERR_FILESELECT);
353 }
354 argc--;
355 argv++;
356
357 if (strcmp(dir,".")) {
358 int l = strlen(dir);
359 if (strcmp(dir,"/") == 0)
360 l = 0;
361 for (i=0;i<argc;i++)
362 argv[i] += l+1;
363 }
364
365 if (argc == 0 && recurse) {
366 argc=1;
367 argv--;
368 argv[0] = ".";
369 }
370
371 flist = send_file_list(f_out,argc,argv);
372 if (!flist || flist->count == 0) {
373 exit_cleanup(0);
374 }
375
376 send_files(flist,f_out,f_in);
377 io_flush();
378 report(f_out);
379 if (protocol_version >= 24) {
380 /* final goodbye message */
381 read_int(f_in);
382 }
383 io_flush();
384 exit_cleanup(0);
385}
386
387
388static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
389{
390 int pid;
391 int status=0;
392 int recv_pipe[2];
393 int error_pipe[2];
394 extern int preserve_hard_links;
395 extern int delete_after;
396 extern int recurse;
397 extern int delete_mode;
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 (protocol_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 kill(pid, SIGUSR2);
466 wait_process(pid, &status);
467 return status;
468}
469
470
471static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
472{
473 int status;
474 struct file_list *flist;
475 char *local_name=NULL;
476 char *dir = NULL;
477 extern int delete_mode;
478 extern int delete_excluded;
479 extern int module_id;
480 extern int read_batch;
481 extern struct file_list *batch_flist;
482
483 if (verbose > 2)
484 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
485
486 if (am_daemon && lp_read_only(module_id) && !am_sender) {
487 rprintf(FERROR,"ERROR: module is read only\n");
488 exit_cleanup(RERR_SYNTAX);
489 return;
490 }
491
492
493 if (argc > 0) {
494 dir = argv[0];
495 argc--;
496 argv++;
497 if (!am_daemon && !push_dir(dir, 0)) {
498 rprintf(FERROR, "push_dir %s failed: %s (4)\n",
499 full_fname(dir), strerror(errno));
500 exit_cleanup(RERR_FILESELECT);
501 }
502 }
503
504 if (delete_mode && !delete_excluded)
505 recv_exclude_list(f_in);
506
507 if (filesfrom_fd >= 0) {
508 /* We're receiving the file info from the sender, so we need
509 * the IO routines to automatically write out the names onto
510 * our f_out socket as we read the list info from the sender.
511 * This avoids both deadlock and extra delays/buffers. */
512 io_set_filesfrom_fds(filesfrom_fd, f_out);
513 filesfrom_fd = -1;
514 }
515
516 if (read_batch)
517 flist = batch_flist;
518 else
519 flist = recv_file_list(f_in);
520 if (!flist) {
521 rprintf(FERROR,"server_recv: recv_file_list error\n");
522 exit_cleanup(RERR_FILESELECT);
523 }
524
525 if (argc > 0) {
526 if (strcmp(dir,".")) {
527 argv[0] += strlen(dir);
528 if (argv[0][0] == '/') argv[0]++;
529 }
530 local_name = get_local_name(flist,argv[0]);
531 }
532
533 status = do_recv(f_in,f_out,flist,local_name);
534 exit_cleanup(status);
535}
536
537
538int child_main(int argc, char *argv[])
539{
540 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
541 return 0;
542}
543
544
545void start_server(int f_in, int f_out, int argc, char *argv[])
546{
547 extern int cvs_exclude;
548 extern int read_batch;
549
550 setup_protocol(f_out, f_in);
551
552 set_nonblocking(f_in);
553 set_nonblocking(f_out);
554
555 if (protocol_version >= 23)
556 io_start_multiplex_out(f_out);
557
558 if (am_sender) {
559 if (!read_batch) {
560 recv_exclude_list(f_in);
561 if (cvs_exclude)
562 add_cvs_excludes();
563 }
564 do_server_sender(f_in, f_out, argc, argv);
565 } else {
566 do_server_recv(f_in, f_out, argc, argv);
567 }
568 exit_cleanup(0);
569}
570
571
572/*
573 * This is called once the connection has been negotiated. It is used
574 * for rsyncd, remote-shell, and local connections.
575 */
576int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
577{
578 struct file_list *flist = NULL;
579 int status = 0, status2 = 0;
580 char *local_name = NULL;
581 extern pid_t cleanup_child_pid;
582 extern int write_batch;
583 extern int read_batch;
584 extern struct file_list *batch_flist;
585
586 cleanup_child_pid = pid;
587 if (read_batch)
588 flist = batch_flist;
589
590 set_nonblocking(f_in);
591 set_nonblocking(f_out);
592
593 setup_protocol(f_out,f_in);
594
595 if (protocol_version >= 23)
596 io_start_multiplex_in(f_in);
597
598 if (am_sender) {
599 extern int cvs_exclude;
600 extern int delete_mode;
601 extern int delete_excluded;
602 if (cvs_exclude)
603 add_cvs_excludes();
604 if (delete_mode && !delete_excluded)
605 send_exclude_list(f_out);
606 if (remote_filesfrom_file)
607 filesfrom_fd = f_in;
608 if (!read_batch) /* dw -- don't write to pipe */
609 flist = send_file_list(f_out,argc,argv);
610 if (verbose > 3)
611 rprintf(FINFO,"file list sent\n");
612
613 send_files(flist,f_out,f_in);
614 if (protocol_version >= 24) {
615 /* final goodbye message */
616 read_int(f_in);
617 }
618 if (pid != -1) {
619 if (verbose > 3)
620 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
621 io_flush();
622 wait_process(pid, &status);
623 }
624 report(-1);
625 exit_cleanup(status);
626 }
627
628 if (argc == 0) {
629 extern int list_only;
630 list_only = 1;
631 }
632
633 if (!write_batch)
634 send_exclude_list(f_out);
635
636 if (filesfrom_fd >= 0) {
637 io_set_filesfrom_fds(filesfrom_fd, f_out);
638 filesfrom_fd = -1;
639 }
640
641 flist = recv_file_list(f_in);
642 if (!flist || flist->count == 0) {
643 rprintf(FINFO, "client: nothing to do: "
644 "perhaps you need to specify some filenames or "
645 "the --recursive option?\n");
646 exit_cleanup(0);
647 }
648
649 local_name = get_local_name(flist,argv[0]);
650
651 status2 = do_recv(f_in,f_out,flist,local_name);
652
653 if (pid != -1) {
654 if (verbose > 3)
655 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
656 io_flush();
657 wait_process(pid, &status);
658 }
659
660 return MAX(status, status2);
661}
662
663static int copy_argv (char *argv[])
664{
665 int i;
666
667 for (i = 0; argv[i]; i++) {
668 if (!(argv[i] = strdup(argv[i]))) {
669 rprintf (FERROR, "out of memory at %s(%d)\n",
670 __FILE__, __LINE__);
671 return RERR_MALLOC;
672 }
673 }
674
675 return 0;
676}
677
678
679/**
680 * Start a client for either type of remote connection. Work out
681 * whether the arguments request a remote shell or rsyncd connection,
682 * and call the appropriate connection function, then run_client.
683 *
684 * Calls either start_socket_client (for sockets) or do_cmd and
685 * client_run (for ssh).
686 **/
687static int start_client(int argc, char *argv[])
688{
689 char *p;
690 char *shell_machine = NULL;
691 char *shell_path = NULL;
692 char *shell_user = NULL;
693 int ret;
694 pid_t pid;
695 int f_in,f_out;
696 extern int local_server;
697 extern char *shell_cmd;
698 extern int rsync_port;
699 extern int daemon_over_rsh;
700 extern int read_batch;
701 int rc;
702
703 /* Don't clobber argv[] so that ps(1) can still show the right
704 * command line. */
705 if ((rc = copy_argv(argv)))
706 return rc;
707
708 /* rsync:// always uses rsync server over direct socket connection */
709 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
710 char *host, *path;
711
712 host = argv[0] + strlen(URL_PREFIX);
713 p = strchr(host,'/');
714 if (p) {
715 *p = 0;
716 path = p+1;
717 } else {
718 path = "";
719 }
720 p = strchr(host,':');
721 if (p) {
722 rsync_port = atoi(p+1);
723 *p = 0;
724 }
725 return start_socket_client(host, path, argc-1, argv+1);
726 }
727
728 if (!read_batch) {
729 p = find_colon(argv[0]);
730 if (p) {
731 if (remote_filesfrom_file
732 && remote_filesfrom_file != files_from + 1
733 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
734 rprintf(FERROR,
735 "--files-from hostname is not transfer hostname\n");
736 exit_cleanup(RERR_SYNTAX);
737 }
738 if (p[1] == ':') { /* double colon */
739 *p = 0;
740 if (!shell_cmd) {
741 return start_socket_client(argv[0], p+2,
742 argc-1, argv+1);
743 }
744 p++;
745 daemon_over_rsh = 1;
746 }
747
748 if (argc < 1) {
749 usage(FERROR);
750 exit_cleanup(RERR_SYNTAX);
751 }
752
753 am_sender = 0;
754 *p = 0;
755 shell_machine = argv[0];
756 shell_path = p+1;
757 argc--;
758 argv++;
759 } else {
760 am_sender = 1;
761
762 /* rsync:// destination uses rsync server over direct socket */
763 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
764 char *host, *path;
765
766 host = argv[argc-1] + strlen(URL_PREFIX);
767 p = strchr(host,'/');
768 if (p) {
769 *p = 0;
770 path = p+1;
771 } else {
772 path = "";
773 }
774 p = strchr(host,':');
775 if (p) {
776 rsync_port = atoi(p+1);
777 *p = 0;
778 }
779 return start_socket_client(host, path, argc-1, argv);
780 }
781
782 p = find_colon(argv[argc-1]);
783 if (p && remote_filesfrom_file
784 && remote_filesfrom_file != files_from + 1
785 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
786 rprintf(FERROR,
787 "--files-from hostname is not transfer hostname\n");
788 exit_cleanup(RERR_SYNTAX);
789 }
790 if (!p) {
791 local_server = 1;
792 if (remote_filesfrom_file) {
793 rprintf(FERROR,
794 "--files-from is remote but transfer is local\n");
795 exit_cleanup(RERR_SYNTAX);
796 }
797 } else if (p[1] == ':') { /* double colon */
798 *p = 0;
799 if (!shell_cmd) {
800 return start_socket_client(argv[argc-1], p+2,
801 argc-1, argv);
802 }
803 p++;
804 daemon_over_rsh = 1;
805 }
806
807 if (argc < 2) {
808 usage(FERROR);
809 exit_cleanup(RERR_SYNTAX);
810 }
811
812 if (local_server) {
813 shell_machine = NULL;
814 shell_path = argv[argc-1];
815 } else {
816 *p = 0;
817 shell_machine = argv[argc-1];
818 shell_path = p+1;
819 }
820 argc--;
821 }
822 } else {
823 am_sender = 1;
824 local_server = 1;
825 shell_path = argv[argc-1];
826 }
827
828 if (shell_machine) {
829 p = strchr(shell_machine,'@');
830 if (p) {
831 *p = 0;
832 shell_user = shell_machine;
833 shell_machine = p+1;
834 }
835 }
836
837 if (verbose > 3) {
838 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
839 shell_cmd?shell_cmd:"",
840 shell_machine?shell_machine:"",
841 shell_user?shell_user:"",
842 shell_path?shell_path:"");
843 }
844
845 if (!am_sender && argc > 1) {
846 usage(FERROR);
847 exit_cleanup(RERR_SYNTAX);
848 }
849
850 if (argc == 0 && !am_sender) {
851 extern int list_only;
852 list_only = 1;
853 }
854
855 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
856 &f_in,&f_out);
857
858 /* if we're running an rsync server on the remote host over a
859 remote shell command, we need to do the RSYNCD protocol first */
860 if (daemon_over_rsh) {
861 int tmpret;
862 tmpret = start_inband_exchange(shell_user, shell_path,
863 f_in, f_out, argc);
864 if (tmpret < 0)
865 return tmpret;
866 }
867
868 ret = client_run(f_in, f_out, pid, argc, argv);
869
870 fflush(stdout);
871 fflush(stderr);
872
873 return ret;
874}
875
876
877static RETSIGTYPE sigusr1_handler(UNUSED(int val))
878{
879 exit_cleanup(RERR_SIGNAL);
880}
881
882static RETSIGTYPE sigusr2_handler(UNUSED(int val))
883{
884 extern int log_got_error;
885 if (log_got_error) _exit(RERR_PARTIAL);
886 _exit(0);
887}
888
889static RETSIGTYPE sigchld_handler(UNUSED(int val))
890{
891#ifdef WNOHANG
892 int cnt, status;
893 pid_t pid;
894 /* An empty waitpid() loop was put here by Tridge and we could never
895 * get him to explain why he put it in, so rather than taking it
896 * out we're instead saving the child exit statuses for later use.
897 * The waitpid() loop presumably eliminates all possibility of leaving
898 * zombie children, maybe that's why he did it.
899 */
900 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
901 /* save the child's exit status */
902 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
903 if (pid_stat_table[cnt].pid == 0) {
904 pid_stat_table[cnt].pid = pid;
905 pid_stat_table[cnt].status = status;
906 break;
907 }
908 }
909 }
910#endif
911}
912
913
914/**
915 * This routine catches signals and tries to send them to gdb.
916 *
917 * Because it's called from inside a signal handler it ought not to
918 * use too many library routines.
919 *
920 * @todo Perhaps use "screen -X" instead/as well, to help people
921 * debugging without easy access to X. Perhaps use an environment
922 * variable, or just call a script?
923 *
924 * @todo The /proc/ magic probably only works on Linux (and
925 * Solaris?) Can we be more portable?
926 **/
927#ifdef MAINTAINER_MODE
928const char *get_panic_action(void)
929{
930 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
931
932 if (cmd_fmt)
933 return cmd_fmt;
934 else
935 return "xterm -display :0 -T Panic -n Panic "
936 "-e gdb /proc/%d/exe %d";
937}
938
939
940/**
941 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
942 *
943 * This signal handler is only installed if we were configured with
944 * --enable-maintainer-mode. Perhaps it should always be on and we
945 * should just look at the environment variable, but I'm a bit leery
946 * of a signal sending us into a busy loop.
947 **/
948static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
949{
950 char cmd_buf[300];
951 int ret;
952
953 sprintf(cmd_buf, get_panic_action(),
954 getpid(), getpid());
955
956 /* Unless we failed to execute gdb, we allow the process to
957 * continue. I'm not sure if that's right. */
958 ret = system(cmd_buf);
959 if (ret)
960 _exit(ret);
961}
962#endif
963
964
965int main(int argc,char *argv[])
966{
967 extern int am_root;
968 extern int orig_umask;
969 extern int dry_run;
970 int ret;
971 extern int write_batch;
972 int orig_argc;
973 char **orig_argv;
974
975 orig_argc = argc;
976 orig_argv = argv;
977
978 signal(SIGUSR1, sigusr1_handler);
979 signal(SIGUSR2, sigusr2_handler);
980 signal(SIGCHLD, sigchld_handler);
981#ifdef MAINTAINER_MODE
982 signal(SIGSEGV, rsync_panic_handler);
983 signal(SIGFPE, rsync_panic_handler);
984 signal(SIGABRT, rsync_panic_handler);
985 signal(SIGBUS, rsync_panic_handler);
986#endif /* def MAINTAINER_MODE */
987
988 starttime = time(NULL);
989 am_root = (getuid() == 0);
990
991 memset(&stats, 0, sizeof(stats));
992
993 if (argc < 2) {
994 usage(FERROR);
995 exit_cleanup(RERR_SYNTAX);
996 }
997
998 /* we set a 0 umask so that correct file permissions can be
999 carried across */
1000 orig_umask = (int)umask(0);
1001
1002 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
1003 /* FIXME: We ought to call the same error-handling
1004 * code here, rather than relying on getopt. */
1005 option_error();
1006 exit_cleanup(RERR_SYNTAX);
1007 }
1008
1009 signal(SIGINT,SIGNAL_CAST sig_int);
1010 signal(SIGHUP,SIGNAL_CAST sig_int);
1011 signal(SIGTERM,SIGNAL_CAST sig_int);
1012
1013 /* Ignore SIGPIPE; we consistently check error codes and will
1014 * see the EPIPE. */
1015 signal(SIGPIPE, SIG_IGN);
1016
1017 /* Initialize push_dir here because on some old systems getcwd
1018 (implemented by forking "pwd" and reading its output) doesn't
1019 work when there are other child processes. Also, on all systems
1020 that implement getcwd that way "pwd" can't be found after chroot. */
1021 push_dir(NULL,0);
1022
1023 if (write_batch && !am_server) {
1024 write_batch_argvs_file(orig_argc, orig_argv);
1025 }
1026
1027 if (am_daemon && !am_server)
1028 return daemon_main();
1029
1030 if (argc < 1) {
1031 usage(FERROR);
1032 exit_cleanup(RERR_SYNTAX);
1033 }
1034
1035 if (dry_run)
1036 verbose = MAX(verbose,1);
1037
1038#ifndef SUPPORT_LINKS
1039 if (!am_server && preserve_links) {
1040 rprintf(FERROR,"ERROR: symbolic links not supported\n");
1041 exit_cleanup(RERR_UNSUPPORTED);
1042 }
1043#endif
1044
1045 if (am_server) {
1046 set_nonblocking(STDIN_FILENO);
1047 set_nonblocking(STDOUT_FILENO);
1048 if (am_daemon)
1049 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
1050 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1051 }
1052
1053 ret = start_client(argc, argv);
1054 if (ret == -1)
1055 exit_cleanup(RERR_STARTCLIENT);
1056 else
1057 exit_cleanup(ret);
1058
1059 return ret;
1060}