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