Mark unused vars.
[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;
34
35/* there's probably never more than at most 2 outstanding child processes,
36 * but set it higher just in case.
37 */
38#define MAXCHILDPROCS 5
39
40struct pid_status {
41 pid_t pid;
42 int status;
43} pid_stat_table[MAXCHILDPROCS];
44
45static void show_malloc_stats(void);
46
47/****************************************************************************
48wait for a process to exit, calling io_flush while waiting
49****************************************************************************/
50void wait_process(pid_t pid, int *status)
51{
52 pid_t waited_pid;
53 int cnt;
54
55 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
56 msleep(20);
57 io_flush();
58 }
59
60 if ((waited_pid == -1) && (errno == ECHILD)) {
61 /* status of requested child no longer available.
62 * check to see if it was processed by the sigchld_handler.
63 */
64 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
65 if (pid == pid_stat_table[cnt].pid) {
66 *status = pid_stat_table[cnt].status;
67 pid_stat_table[cnt].pid = 0;
68 break;
69 }
70 }
71 }
72
73 /* TODO: If the child exited on a signal, then log an
74 * appropriate error message. Perhaps we should also accept a
75 * message describing the purpose of the child. Also indicate
76 * this to the caller so that thhey know something went
77 * wrong. */
78 *status = WEXITSTATUS(*status);
79}
80
81static void report(int f)
82{
83 time_t t = time(NULL);
84 extern int do_stats;
85 extern int remote_version;
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 || (remote_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 : %s (1)\n",
302 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, RSYNC_NAME ": mkdir %s: %s\n",
319 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, RSYNC_NAME ": push_dir %s: %s\n",
328 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 extern int remote_version;
346
347 if (verbose > 2)
348 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
349
350 if (!relative_paths && !push_dir(dir, 0)) {
351 rprintf(FERROR,"push_dir %s: %s (3)\n",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 (remote_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 extern int remote_version;
399
400 if (preserve_hard_links)
401 init_hard_links(flist);
402
403 if (!delete_after) {
404 /* I moved this here from recv_files() to prevent a race condition */
405 if (recurse && delete_mode && !local_name && flist->count>0) {
406 delete_files(flist);
407 }
408 }
409
410 if (fd_pair(recv_pipe) < 0) {
411 rprintf(FERROR,"pipe failed in do_recv\n");
412 exit_cleanup(RERR_SOCKETIO);
413 }
414
415 if (fd_pair(error_pipe) < 0) {
416 rprintf(FERROR,"error pipe failed in do_recv\n");
417 exit_cleanup(RERR_SOCKETIO);
418 }
419
420 io_flush();
421
422 if ((pid=do_fork()) == 0) {
423 close(recv_pipe[0]);
424 close(error_pipe[0]);
425 if (f_in != f_out) close(f_out);
426
427 /* we can't let two processes write to the socket at one time */
428 io_multiplexing_close();
429
430 /* set place to send errors */
431 set_error_fd(error_pipe[1]);
432
433 recv_files(f_in,flist,local_name,recv_pipe[1]);
434 io_flush();
435 report(f_in);
436
437 write_int(recv_pipe[1],1);
438 close(recv_pipe[1]);
439 io_flush();
440 /* finally we go to sleep until our parent kills us
441 with a USR2 signal. We sleep for a short time as on
442 some OSes a signal won't interrupt a sleep! */
443 while (msleep(20))
444 ;
445 }
446
447 close(recv_pipe[1]);
448 close(error_pipe[1]);
449 if (f_in != f_out) close(f_in);
450
451 io_start_buffering(f_out);
452
453 io_set_error_fd(error_pipe[0]);
454
455 generate_files(f_out,flist,local_name,recv_pipe[0]);
456
457 read_int(recv_pipe[0]);
458 close(recv_pipe[0]);
459 if (remote_version >= 24) {
460 /* send a final goodbye message */
461 write_int(f_out, -1);
462 }
463 io_flush();
464
465 io_set_error_fd(-1);
466 kill(pid, SIGUSR2);
467 wait_process(pid, &status);
468 return status;
469}
470
471
472static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
473{
474 int status;
475 struct file_list *flist;
476 char *local_name=NULL;
477 char *dir = NULL;
478 extern int delete_mode;
479 extern int delete_excluded;
480 extern int module_id;
481 extern int read_batch;
482 extern struct file_list *batch_flist;
483
484 if (verbose > 2)
485 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
486
487 if (am_daemon && lp_read_only(module_id) && !am_sender) {
488 rprintf(FERROR,"ERROR: module is read only\n");
489 exit_cleanup(RERR_SYNTAX);
490 return;
491 }
492
493
494 if (argc > 0) {
495 dir = argv[0];
496 argc--;
497 argv++;
498 if (!am_daemon && !push_dir(dir, 0)) {
499 rprintf(FERROR,"push_dir %s : %s (4)\n",
500 dir,strerror(errno));
501 exit_cleanup(RERR_FILESELECT);
502 }
503 }
504
505 if (delete_mode && !delete_excluded)
506 recv_exclude_list(f_in);
507
508 if (filesfrom_fd >= 0) {
509 /* We're receiving the file info from the sender, so we need
510 * the IO routines to automatically write out the names onto
511 * our f_out socket as we read the list info from the sender.
512 * This avoids both deadlock and extra delays/buffers. */
513 io_set_filesfrom_fds(filesfrom_fd, f_out);
514 filesfrom_fd = -1;
515 }
516
517 if (read_batch)
518 flist = batch_flist;
519 else
520 flist = recv_file_list(f_in);
521 if (!flist) {
522 rprintf(FERROR,"server_recv: recv_file_list error\n");
523 exit_cleanup(RERR_FILESELECT);
524 }
525
526 if (argc > 0) {
527 if (strcmp(dir,".")) {
528 argv[0] += strlen(dir);
529 if (argv[0][0] == '/') argv[0]++;
530 }
531 local_name = get_local_name(flist,argv[0]);
532 }
533
534 status = do_recv(f_in,f_out,flist,local_name);
535 exit_cleanup(status);
536}
537
538
539int child_main(int argc, char *argv[])
540{
541 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
542 return 0;
543}
544
545
546void start_server(int f_in, int f_out, int argc, char *argv[])
547{
548 extern int cvs_exclude;
549 extern int remote_version;
550 extern int read_batch;
551
552 setup_protocol(f_out, f_in);
553
554 set_nonblocking(f_in);
555 set_nonblocking(f_out);
556
557 if (remote_version >= 23)
558 io_start_multiplex_out(f_out);
559
560 if (am_sender) {
561 if (!read_batch) {
562 recv_exclude_list(f_in);
563 if (cvs_exclude)
564 add_cvs_excludes();
565 }
566 do_server_sender(f_in, f_out, argc, argv);
567 } else {
568 do_server_recv(f_in, f_out, argc, argv);
569 }
570 exit_cleanup(0);
571}
572
573
574/*
575 * This is called once the connection has been negotiated. It is used
576 * for rsyncd, remote-shell, and local connections.
577 */
578int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
579{
580 struct file_list *flist = NULL;
581 int status = 0, status2 = 0;
582 char *local_name = NULL;
583 extern int remote_version;
584 extern pid_t cleanup_child_pid;
585 extern int write_batch;
586 extern int read_batch;
587 extern struct file_list *batch_flist;
588
589 cleanup_child_pid = pid;
590 if (read_batch)
591 flist = batch_flist;
592
593 set_nonblocking(f_in);
594 set_nonblocking(f_out);
595
596 setup_protocol(f_out,f_in);
597
598 if (remote_version >= 23)
599 io_start_multiplex_in(f_in);
600
601 if (am_sender) {
602 extern int cvs_exclude;
603 extern int delete_mode;
604 extern int delete_excluded;
605 if (cvs_exclude)
606 add_cvs_excludes();
607 if (delete_mode && !delete_excluded)
608 send_exclude_list(f_out);
609 if (remote_filesfrom_file)
610 filesfrom_fd = f_in;
611 if (!read_batch) /* dw -- don't write to pipe */
612 flist = send_file_list(f_out,argc,argv);
613 if (verbose > 3)
614 rprintf(FINFO,"file list sent\n");
615
616 send_files(flist,f_out,f_in);
617 if (remote_version >= 24) {
618 /* final goodbye message */
619 read_int(f_in);
620 }
621 if (pid != -1) {
622 if (verbose > 3)
623 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
624 io_flush();
625 wait_process(pid, &status);
626 }
627 report(-1);
628 exit_cleanup(status);
629 }
630
631 if (argc == 0) {
632 extern int list_only;
633 list_only = 1;
634 }
635
636 if (!write_batch)
637 send_exclude_list(f_out);
638
639 if (filesfrom_fd >= 0) {
640 io_set_filesfrom_fds(filesfrom_fd, f_out);
641 filesfrom_fd = -1;
642 }
643
644 flist = recv_file_list(f_in);
645 if (!flist || flist->count == 0) {
646 rprintf(FINFO, "client: nothing to do: "
647 "perhaps you need to specify some filenames or "
648 "the --recursive option?\n");
649 exit_cleanup(0);
650 }
651
652 local_name = get_local_name(flist,argv[0]);
653
654 status2 = do_recv(f_in,f_out,flist,local_name);
655
656 if (pid != -1) {
657 if (verbose > 3)
658 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
659 io_flush();
660 wait_process(pid, &status);
661 }
662
663 return MAX(status, status2);
664}
665
666static int copy_argv (char *argv[])
667{
668 int i;
669
670 for (i = 0; argv[i]; i++) {
671 if (!(argv[i] = strdup(argv[i]))) {
672 rprintf (FERROR, "out of memory at %s(%d)\n",
673 __FILE__, __LINE__);
674 return RERR_MALLOC;
675 }
676 }
677
678 return 0;
679}
680
681
682/**
683 * Start a client for either type of remote connection. Work out
684 * whether the arguments request a remote shell or rsyncd connection,
685 * and call the appropriate connection function, then run_client.
686 *
687 * Calls either start_socket_client (for sockets) or do_cmd and
688 * client_run (for ssh).
689 **/
690static int start_client(int argc, char *argv[])
691{
692 char *p;
693 char *shell_machine = NULL;
694 char *shell_path = NULL;
695 char *shell_user = NULL;
696 int ret;
697 pid_t pid;
698 int f_in,f_out;
699 extern int local_server;
700 extern char *shell_cmd;
701 extern int rsync_port;
702 extern int daemon_over_rsh;
703 extern int read_batch;
704 int rc;
705
706 /* Don't clobber argv[] so that ps(1) can still show the right
707 * command line. */
708 if ((rc = copy_argv(argv)))
709 return rc;
710
711 /* rsync:// always uses rsync server over direct socket connection */
712 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
713 char *host, *path;
714
715 host = argv[0] + strlen(URL_PREFIX);
716 p = strchr(host,'/');
717 if (p) {
718 *p = 0;
719 path = p+1;
720 } else {
721 path = "";
722 }
723 p = strchr(host,':');
724 if (p) {
725 rsync_port = atoi(p+1);
726 *p = 0;
727 }
728 return start_socket_client(host, path, argc-1, argv+1);
729 }
730
731 if (!read_batch) {
732 p = find_colon(argv[0]);
733 if (p) {
734 if (remote_filesfrom_file
735 && remote_filesfrom_file != files_from + 1
736 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
737 rprintf(FERROR,
738 "--files-from hostname is not transfer hostname\n");
739 exit_cleanup(RERR_SYNTAX);
740 }
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 && remote_filesfrom_file
787 && remote_filesfrom_file != files_from + 1
788 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
789 rprintf(FERROR,
790 "--files-from hostname is not transfer hostname\n");
791 exit_cleanup(RERR_SYNTAX);
792 }
793 if (!p) {
794 local_server = 1;
795 if (remote_filesfrom_file) {
796 rprintf(FERROR,
797 "--files-from is remote but transfer is local\n");
798 exit_cleanup(RERR_SYNTAX);
799 }
800 } else if (p[1] == ':') { /* double colon */
801 *p = 0;
802 if (!shell_cmd) {
803 return start_socket_client(argv[argc-1], p+2,
804 argc-1, argv);
805 }
806 p++;
807 daemon_over_rsh = 1;
808 }
809
810 if (argc < 2) {
811 usage(FERROR);
812 exit_cleanup(RERR_SYNTAX);
813 }
814
815 if (local_server) {
816 shell_machine = NULL;
817 shell_path = argv[argc-1];
818 } else {
819 *p = 0;
820 shell_machine = argv[argc-1];
821 shell_path = p+1;
822 }
823 argc--;
824 }
825 } else {
826 am_sender = 1;
827 local_server = 1;
828 shell_path = argv[argc-1];
829 }
830
831 if (shell_machine) {
832 p = strchr(shell_machine,'@');
833 if (p) {
834 *p = 0;
835 shell_user = shell_machine;
836 shell_machine = p+1;
837 }
838 }
839
840 if (verbose > 3) {
841 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
842 shell_cmd?shell_cmd:"",
843 shell_machine?shell_machine:"",
844 shell_user?shell_user:"",
845 shell_path?shell_path:"");
846 }
847
848 if (!am_sender && argc > 1) {
849 usage(FERROR);
850 exit_cleanup(RERR_SYNTAX);
851 }
852
853 if (argc == 0 && !am_sender) {
854 extern int list_only;
855 list_only = 1;
856 }
857
858 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
859 &f_in,&f_out);
860
861 /* if we're running an rsync server on the remote host over a
862 remote shell command, we need to do the RSYNCD protocol first */
863 if (daemon_over_rsh) {
864 int tmpret;
865 tmpret = start_inband_exchange(shell_user, shell_path,
866 f_in, f_out, argc);
867 if (tmpret < 0)
868 return tmpret;
869 }
870
871 ret = client_run(f_in, f_out, pid, argc, argv);
872
873 fflush(stdout);
874 fflush(stderr);
875
876 return ret;
877}
878
879
880static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
881 exit_cleanup(RERR_SIGNAL);
882}
883
884static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
885 extern int log_got_error;
886 if (log_got_error) _exit(RERR_PARTIAL);
887 _exit(0);
888}
889
890static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
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(int UNUSED(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}