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