Got rid of setgroups() caveat for OSX -- we fixed that a while back.
[rsync.git] / main.c
blobdca839913adf5af164cf4b33a93fcb04d459f144
1 /* -*- c-file-style: "linux" -*-
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>
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.
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.
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.
22 #include "rsync.h"
24 time_t starttime = 0;
26 extern struct stats stats;
27 extern char *files_from;
28 extern int filesfrom_fd;
29 extern char *remote_filesfrom_file;
30 extern int am_server;
31 extern int am_sender;
32 extern int am_daemon;
33 extern int verbose;
34 extern int protocol_version;
36 /* there's probably never more than at most 2 outstanding child processes,
37 * but set it higher just in case.
39 #define MAXCHILDPROCS 5
41 struct pid_status {
42 pid_t pid;
43 int status;
44 } pid_stat_table[MAXCHILDPROCS];
46 static void show_malloc_stats(void);
48 /****************************************************************************
49 wait for a process to exit, calling io_flush while waiting
50 ****************************************************************************/
51 void wait_process(pid_t pid, int *status)
53 pid_t waited_pid;
54 int cnt;
56 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
57 msleep(20);
58 io_flush();
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.
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;
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);
82 static void report(int f)
84 time_t t = time(NULL);
85 extern int do_stats;
86 int send_stats;
88 if (do_stats && verbose > 1) {
89 /* These come out from every process */
90 show_malloc_stats();
91 show_flist_stats();
94 if (am_daemon) {
95 log_exit(0, __FILE__, __LINE__);
96 if (f == -1 || !am_sender) return;
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);
110 return;
113 /* this is the client */
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;
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;
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);
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));
159 fflush(stdout);
160 fflush(stderr);
165 * If our C library can get malloc statistics, then show them to FINFO
167 static void show_malloc_stats(void)
169 #ifdef HAVE_MALLINFO
170 struct mallinfo mi;
172 mi = mallinfo();
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 */
193 /* Start the remote shell. cmd may be NULL to use the default. */
194 static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
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;
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;
216 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
217 args[argc++] = tok;
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;
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;
234 #else
235 if (user && !(daemon_over_rsh && dash_l_set)) {
236 args[argc++] = "-l";
237 args[argc++] = user;
239 args[argc++] = machine;
240 #endif
242 args[argc++] = rsync_path;
244 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
245 blocking_io = 1;
247 server_options(args,&argc);
251 args[argc++] = ".";
253 if (!daemon_over_rsh && path && *path)
254 args[argc++] = path;
256 args[argc] = NULL;
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");
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);
273 if (dir) free(dir);
275 return ret;
277 oom:
278 out_of_memory("do_cmd");
279 return 0; /* not reached */
285 static char *get_local_name(struct file_list *flist,char *name)
287 STRUCT_STAT st;
288 int e;
289 extern int orig_umask;
291 if (verbose > 2)
292 rprintf(FINFO,"get_local_name count=%d %s\n",
293 flist->count, NS(name));
295 if (!name)
296 return NULL;
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);
305 return NULL;
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);
311 return name;
314 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
315 return name;
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);
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);
332 return NULL;
338 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
340 int i;
341 struct file_list *flist;
342 char *dir = argv[0];
343 extern int relative_paths;
344 extern int recurse;
346 if (verbose > 2)
347 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
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);
354 argc--;
355 argv++;
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;
365 if (argc == 0 && recurse) {
366 argc=1;
367 argv--;
368 argv[0] = ".";
371 flist = send_file_list(f_out,argc,argv);
372 if (!flist || flist->count == 0) {
373 exit_cleanup(0);
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);
383 io_flush();
384 exit_cleanup(0);
388 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
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;
399 if (preserve_hard_links)
400 init_hard_links(flist);
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);
409 if (fd_pair(recv_pipe) < 0) {
410 rprintf(FERROR,"pipe failed in do_recv\n");
411 exit_cleanup(RERR_SOCKETIO);
414 if (fd_pair(error_pipe) < 0) {
415 rprintf(FERROR,"error pipe failed in do_recv\n");
416 exit_cleanup(RERR_SOCKETIO);
419 io_flush();
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);
426 /* we can't let two processes write to the socket at one time */
427 io_multiplexing_close();
429 /* set place to send errors */
430 set_error_fd(error_pipe[1]);
432 recv_files(f_in,flist,local_name,recv_pipe[1]);
433 io_flush();
434 report(f_in);
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))
446 close(recv_pipe[1]);
447 close(error_pipe[1]);
448 if (f_in != f_out) close(f_in);
450 io_start_buffering(f_out);
452 io_set_error_fd(error_pipe[0]);
454 generate_files(f_out,flist,local_name,recv_pipe[0]);
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);
462 io_flush();
464 io_set_error_fd(-1);
465 kill(pid, SIGUSR2);
466 wait_process(pid, &status);
467 return status;
471 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
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;
483 if (verbose > 2)
484 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
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;
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);
504 if (delete_mode && !delete_excluded)
505 recv_exclude_list(f_in);
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;
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);
525 if (argc > 0) {
526 if (strcmp(dir,".")) {
527 argv[0] += strlen(dir);
528 if (argv[0][0] == '/') argv[0]++;
530 local_name = get_local_name(flist,argv[0]);
533 status = do_recv(f_in,f_out,flist,local_name);
534 exit_cleanup(status);
538 int child_main(int argc, char *argv[])
540 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
541 return 0;
545 void start_server(int f_in, int f_out, int argc, char *argv[])
547 extern int cvs_exclude;
548 extern int read_batch;
550 setup_protocol(f_out, f_in);
552 set_nonblocking(f_in);
553 set_nonblocking(f_out);
555 if (protocol_version >= 23)
556 io_start_multiplex_out(f_out);
558 if (am_sender) {
559 if (!read_batch) {
560 recv_exclude_list(f_in);
561 if (cvs_exclude)
562 add_cvs_excludes();
564 do_server_sender(f_in, f_out, argc, argv);
565 } else {
566 do_server_recv(f_in, f_out, argc, argv);
568 exit_cleanup(0);
573 * This is called once the connection has been negotiated. It is used
574 * for rsyncd, remote-shell, and local connections.
576 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
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;
586 cleanup_child_pid = pid;
587 if (read_batch)
588 flist = batch_flist;
590 set_nonblocking(f_in);
591 set_nonblocking(f_out);
593 setup_protocol(f_out,f_in);
595 if (protocol_version >= 23)
596 io_start_multiplex_in(f_in);
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");
613 send_files(flist,f_out,f_in);
614 if (protocol_version >= 24) {
615 /* final goodbye message */
616 read_int(f_in);
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);
624 report(-1);
625 exit_cleanup(status);
628 if (argc == 0) {
629 extern int list_only;
630 list_only = 1;
633 if (!write_batch)
634 send_exclude_list(f_out);
636 if (filesfrom_fd >= 0) {
637 io_set_filesfrom_fds(filesfrom_fd, f_out);
638 filesfrom_fd = -1;
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);
649 local_name = get_local_name(flist,argv[0]);
651 status2 = do_recv(f_in,f_out,flist,local_name);
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);
660 return MAX(status, status2);
663 static int copy_argv (char *argv[])
665 int i;
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;
675 return 0;
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.
684 * Calls either start_socket_client (for sockets) or do_cmd and
685 * client_run (for ssh).
687 static int start_client(int argc, char *argv[])
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;
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;
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;
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 = "";
720 p = strchr(host,':');
721 if (p) {
722 rsync_port = atoi(p+1);
723 *p = 0;
725 return start_socket_client(host, path, argc-1, argv+1);
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);
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);
744 p++;
745 daemon_over_rsh = 1;
748 if (argc < 1) {
749 usage(FERROR);
750 exit_cleanup(RERR_SYNTAX);
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;
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;
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 = "";
774 p = strchr(host,':');
775 if (p) {
776 rsync_port = atoi(p+1);
777 *p = 0;
779 return start_socket_client(host, path, argc-1, argv);
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);
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);
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);
803 p++;
804 daemon_over_rsh = 1;
807 if (argc < 2) {
808 usage(FERROR);
809 exit_cleanup(RERR_SYNTAX);
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;
820 argc--;
822 } else {
823 am_sender = 1;
824 local_server = 1;
825 shell_path = argv[argc-1];
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;
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:"");
845 if (!am_sender && argc > 1) {
846 usage(FERROR);
847 exit_cleanup(RERR_SYNTAX);
850 if (argc == 0 && !am_sender) {
851 extern int list_only;
852 list_only = 1;
855 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
856 &f_in,&f_out);
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;
868 ret = client_run(f_in, f_out, pid, argc, argv);
870 fflush(stdout);
871 fflush(stderr);
873 return ret;
877 static RETSIGTYPE sigusr1_handler(UNUSED(int val))
879 exit_cleanup(RERR_SIGNAL);
882 static RETSIGTYPE sigusr2_handler(UNUSED(int val))
884 extern int log_got_error;
885 if (log_got_error) _exit(RERR_PARTIAL);
886 _exit(0);
889 static RETSIGTYPE sigchld_handler(UNUSED(int 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.
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;
910 #endif
915 * This routine catches signals and tries to send them to gdb.
917 * Because it's called from inside a signal handler it ought not to
918 * use too many library routines.
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?
924 * @todo The /proc/ magic probably only works on Linux (and
925 * Solaris?) Can we be more portable?
927 #ifdef MAINTAINER_MODE
928 const char *get_panic_action(void)
930 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
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";
941 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
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.
948 static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
950 char cmd_buf[300];
951 int ret;
953 sprintf(cmd_buf, get_panic_action(),
954 getpid(), getpid());
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);
962 #endif
965 int main(int argc,char *argv[])
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;
975 orig_argc = argc;
976 orig_argv = argv;
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 */
988 starttime = time(NULL);
989 am_root = (getuid() == 0);
991 memset(&stats, 0, sizeof(stats));
993 if (argc < 2) {
994 usage(FERROR);
995 exit_cleanup(RERR_SYNTAX);
998 /* we set a 0 umask so that correct file permissions can be
999 carried across */
1000 orig_umask = (int)umask(0);
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);
1009 signal(SIGINT,SIGNAL_CAST sig_int);
1010 signal(SIGHUP,SIGNAL_CAST sig_int);
1011 signal(SIGTERM,SIGNAL_CAST sig_int);
1013 /* Ignore SIGPIPE; we consistently check error codes and will
1014 * see the EPIPE. */
1015 signal(SIGPIPE, SIG_IGN);
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);
1023 if (write_batch && !am_server) {
1024 write_batch_argvs_file(orig_argc, orig_argv);
1027 if (am_daemon && !am_server)
1028 return daemon_main();
1030 if (argc < 1) {
1031 usage(FERROR);
1032 exit_cleanup(RERR_SYNTAX);
1035 if (dry_run)
1036 verbose = MAX(verbose,1);
1038 #ifndef SUPPORT_LINKS
1039 if (!am_server && preserve_links) {
1040 rprintf(FERROR,"ERROR: symbolic links not supported\n");
1041 exit_cleanup(RERR_UNSUPPORTED);
1043 #endif
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);
1053 ret = start_client(argc, argv);
1054 if (ret == -1)
1055 exit_cleanup(RERR_STARTCLIENT);
1056 else
1057 exit_cleanup(ret);
1059 return ret;