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