Remove tempname length problem and files-from from TODO.
[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
35 /* there's probably never more than at most 2 outstanding child processes,
36  * but set it higher just in case.
37  */
38 #define MAXCHILDPROCS 5
39
40 struct pid_status {
41         pid_t pid;
42         int   status;
43 } pid_stat_table[MAXCHILDPROCS];
44
45 static void show_malloc_stats(void);
46
47 /****************************************************************************
48 wait for a process to exit, calling io_flush while waiting
49 ****************************************************************************/
50 void wait_process(pid_t pid, int *status)
51 {
52         pid_t waited_pid;
53         int cnt;
54
55         while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
56                 msleep(20);
57                 io_flush();
58         }
59
60         if ((waited_pid == -1) && (errno == ECHILD)) {
61                 /* status of requested child no longer available.
62                  * check to see if it was processed by the sigchld_handler.
63                  */
64                 for (cnt = 0;  cnt < MAXCHILDPROCS; cnt++) {
65                         if (pid == pid_stat_table[cnt].pid) {
66                                 *status = pid_stat_table[cnt].status;
67                                 pid_stat_table[cnt].pid = 0;
68                                 break;
69                         }
70                 }
71         }
72
73         /* TODO: If the child exited on a signal, then log an
74          * appropriate error message.  Perhaps we should also accept a
75          * message describing the purpose of the child.  Also indicate
76          * this to the caller so that thhey know something went
77          * wrong.  */
78         *status = WEXITSTATUS(*status);
79 }
80
81 static void report(int f)
82 {
83         time_t t = time(NULL);
84         extern int do_stats;
85         extern int remote_version;
86         int send_stats;
87
88         if (do_stats) {
89                 /* These come out from every process */
90                 show_malloc_stats();
91                 show_flist_stats();
92         }
93
94         if (am_daemon) {
95                 log_exit(0, __FILE__, __LINE__);
96                 if (f == -1 || !am_sender) return;
97         }
98
99         send_stats = verbose || (remote_version >= 20);
100         if (am_server) {
101                 if (am_sender && send_stats) {
102                         int64 w;
103                         /* store total_written in a temporary
104                          * because write_longint changes it */
105                         w = stats.total_written;
106                         write_longint(f,stats.total_read);
107                         write_longint(f,w);
108                         write_longint(f,stats.total_size);
109                 }
110                 return;
111         }
112
113         /* this is the client */
114
115         if (!am_sender && send_stats) {
116                 int64 r;
117                 stats.total_written = read_longint(f);
118                 /* store total_read in a temporary, read_longint changes it */
119                 r = read_longint(f);
120                 stats.total_size = read_longint(f);
121                 stats.total_read = r;
122         }
123
124         if (do_stats) {
125                 if (!am_sender && !send_stats) {
126                         /* missing the bytes written by the generator */
127                         rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
128                         rprintf(FINFO, "Use --stats -v to show stats\n");
129                         return;
130                 }
131                 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
132                 rprintf(FINFO,"Number of files transferred: %d\n",
133                         stats.num_transferred_files);
134                 rprintf(FINFO,"Total file size: %.0f bytes\n",
135                         (double)stats.total_size);
136                 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
137                         (double)stats.total_transferred_size);
138                 rprintf(FINFO,"Literal data: %.0f bytes\n",
139                         (double)stats.literal_data);
140                 rprintf(FINFO,"Matched data: %.0f bytes\n",
141                         (double)stats.matched_data);
142                 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
143                 rprintf(FINFO,"Total bytes written: %.0f\n",
144                         (double)stats.total_written);
145                 rprintf(FINFO,"Total bytes read: %.0f\n\n",
146                         (double)stats.total_read);
147         }
148
149         if (verbose || do_stats) {
150                 rprintf(FINFO,"wrote %.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         extern int orig_umask;
289
290         if (verbose > 2)
291                 rprintf(FINFO,"get_local_name count=%d %s\n",
292                         flist->count, NS(name));
293
294         if (!name)
295                 return NULL;
296
297         if (do_stat(name,&st) == 0) {
298                 if (S_ISDIR(st.st_mode)) {
299                         if (!push_dir(name, 0)) {
300                                 rprintf(FERROR,"push_dir %s : %s (1)\n",
301                                         name,strerror(errno));
302                                 exit_cleanup(RERR_FILESELECT);
303                         }
304                         return NULL;
305                 }
306                 if (flist->count > 1) {
307                         rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
308                         exit_cleanup(RERR_FILESELECT);
309                 }
310                 return name;
311         }
312
313         if (flist->count <= 1)
314                 return name;
315
316         if (do_mkdir(name,0777 & ~orig_umask) != 0) {
317                 rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
318                         name, strerror(errno));
319                 exit_cleanup(RERR_FILEIO);
320         } else {
321                 if (verbose > 0)
322                         rprintf(FINFO,"created directory %s\n",name);
323         }
324
325         if (!push_dir(name, 0)) {
326                 rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
327                         name, strerror(errno));
328                 exit_cleanup(RERR_FILESELECT);
329         }
330
331         return NULL;
332 }
333
334
335
336
337 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
338 {
339         int i;
340         struct file_list *flist;
341         char *dir = argv[0];
342         extern int relative_paths;
343         extern int recurse;
344         extern int remote_version;
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 (remote_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         extern int remote_version;
398
399         if (preserve_hard_links)
400                 init_hard_links(flist);
401
402         if (!delete_after) {
403                 /* I moved this here from recv_files() to prevent a race condition */
404                 if (recurse && delete_mode && !local_name && flist->count>0) {
405                         delete_files(flist);
406                 }
407         }
408
409         if (fd_pair(recv_pipe) < 0) {
410                 rprintf(FERROR,"pipe failed in do_recv\n");
411                 exit_cleanup(RERR_SOCKETIO);
412         }
413
414         if (fd_pair(error_pipe) < 0) {
415                 rprintf(FERROR,"error pipe failed in do_recv\n");
416                 exit_cleanup(RERR_SOCKETIO);
417         }
418
419         io_flush();
420
421         if ((pid=do_fork()) == 0) {
422                 close(recv_pipe[0]);
423                 close(error_pipe[0]);
424                 if (f_in != f_out) close(f_out);
425
426                 /* we can't let two processes write to the socket at one time */
427                 io_multiplexing_close();
428
429                 /* set place to send errors */
430                 set_error_fd(error_pipe[1]);
431
432                 recv_files(f_in,flist,local_name,recv_pipe[1]);
433                 io_flush();
434                 report(f_in);
435
436                 write_int(recv_pipe[1],1);
437                 close(recv_pipe[1]);
438                 io_flush();
439                 /* finally we go to sleep until our parent kills us
440                    with a USR2 signal. We sleep for a short time as on
441                    some OSes a signal won't interrupt a sleep! */
442                 while (msleep(20))
443                         ;
444         }
445
446         close(recv_pipe[1]);
447         close(error_pipe[1]);
448         if (f_in != f_out) close(f_in);
449
450         io_start_buffering(f_out);
451
452         io_set_error_fd(error_pipe[0]);
453
454         generate_files(f_out,flist,local_name,recv_pipe[0]);
455
456         read_int(recv_pipe[0]);
457         close(recv_pipe[0]);
458         if (remote_version >= 24) {
459                 /* send a final goodbye message */
460                 write_int(f_out, -1);
461         }
462         io_flush();
463
464         io_set_error_fd(-1);
465         kill(pid, SIGUSR2);
466         wait_process(pid, &status);
467         return status;
468 }
469
470
471 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
472 {
473         int status;
474         struct file_list *flist;
475         char *local_name=NULL;
476         char *dir = NULL;
477         extern int delete_mode;
478         extern int delete_excluded;
479         extern int module_id;
480         extern int read_batch;
481         extern struct file_list *batch_flist;
482
483         if (verbose > 2)
484                 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
485
486         if (am_daemon && lp_read_only(module_id) && !am_sender) {
487                 rprintf(FERROR,"ERROR: module is read only\n");
488                 exit_cleanup(RERR_SYNTAX);
489                 return;
490         }
491
492
493         if (argc > 0) {
494                 dir = argv[0];
495                 argc--;
496                 argv++;
497                 if (!am_daemon && !push_dir(dir, 0)) {
498                         rprintf(FERROR,"push_dir %s : %s (4)\n",
499                                 dir,strerror(errno));
500                         exit_cleanup(RERR_FILESELECT);
501                 }
502         }
503
504         if (delete_mode && !delete_excluded)
505                 recv_exclude_list(f_in);
506
507         if (filesfrom_fd >= 0) {
508                 /* We're receiving the file info from the sender, so we need
509                  * the IO routines to automatically write out the names onto
510                  * our f_out socket as we read the list info from the sender.
511                  * This avoids both deadlock and extra delays/buffers. */
512                 io_set_filesfrom_fds(filesfrom_fd, f_out);
513                 filesfrom_fd = -1;
514         }
515
516         if (read_batch)
517                 flist = batch_flist;
518         else
519                 flist = recv_file_list(f_in);
520         if (!flist) {
521                 rprintf(FERROR,"server_recv: recv_file_list error\n");
522                 exit_cleanup(RERR_FILESELECT);
523         }
524
525         if (argc > 0) {
526                 if (strcmp(dir,".")) {
527                         argv[0] += strlen(dir);
528                         if (argv[0][0] == '/') argv[0]++;
529                 }
530                 local_name = get_local_name(flist,argv[0]);
531         }
532
533         status = do_recv(f_in,f_out,flist,local_name);
534         exit_cleanup(status);
535 }
536
537
538 int child_main(int argc, char *argv[])
539 {
540         start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
541         return 0;
542 }
543
544
545 void start_server(int f_in, int f_out, int argc, char *argv[])
546 {
547         extern int cvs_exclude;
548         extern int remote_version;
549         extern int read_batch;
550
551         setup_protocol(f_out, f_in);
552
553         set_nonblocking(f_in);
554         set_nonblocking(f_out);
555
556         if (remote_version >= 23)
557                 io_start_multiplex_out(f_out);
558
559         if (am_sender) {
560                 if (!read_batch) {
561                         recv_exclude_list(f_in);
562                         if (cvs_exclude)
563                                 add_cvs_excludes();
564                 }
565                 do_server_sender(f_in, f_out, argc, argv);
566         } else {
567                 do_server_recv(f_in, f_out, argc, argv);
568         }
569         exit_cleanup(0);
570 }
571
572
573 /*
574  * This is called once the connection has been negotiated.  It is used
575  * for rsyncd, remote-shell, and local connections.
576  */
577 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
578 {
579         struct file_list *flist = NULL;
580         int status = 0, status2 = 0;
581         char *local_name = NULL;
582         extern int remote_version;
583         extern pid_t cleanup_child_pid;
584         extern int write_batch;
585         extern int read_batch;
586         extern struct file_list *batch_flist;
587
588         cleanup_child_pid = pid;
589         if (read_batch)
590                 flist = batch_flist;
591
592         set_nonblocking(f_in);
593         set_nonblocking(f_out);
594
595         setup_protocol(f_out,f_in);
596
597         if (remote_version >= 23)
598                 io_start_multiplex_in(f_in);
599
600         if (am_sender) {
601                 extern int cvs_exclude;
602                 extern int delete_mode;
603                 extern int delete_excluded;
604                 if (cvs_exclude)
605                         add_cvs_excludes();
606                 if (delete_mode && !delete_excluded)
607                         send_exclude_list(f_out);
608                 if (remote_filesfrom_file)
609                         filesfrom_fd = f_in;
610                 if (!read_batch) /*  dw -- don't write to pipe */
611                         flist = send_file_list(f_out,argc,argv);
612                 if (verbose > 3)
613                         rprintf(FINFO,"file list sent\n");
614
615                 send_files(flist,f_out,f_in);
616                 if (remote_version >= 24) {
617                         /* final goodbye message */
618                         read_int(f_in);
619                 }
620                 if (pid != -1) {
621                         if (verbose > 3)
622                                 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
623                         io_flush();
624                         wait_process(pid, &status);
625                 }
626                 report(-1);
627                 exit_cleanup(status);
628         }
629
630         if (argc == 0) {
631                 extern int list_only;
632                 list_only = 1;
633         }
634
635         if (!write_batch)
636                 send_exclude_list(f_out);
637
638         if (filesfrom_fd >= 0) {
639                 io_set_filesfrom_fds(filesfrom_fd, f_out);
640                 filesfrom_fd = -1;
641         }
642
643         flist = recv_file_list(f_in);
644         if (!flist || flist->count == 0) {
645                 rprintf(FINFO, "client: nothing to do: "
646                         "perhaps you need to specify some filenames or "
647                         "the --recursive option?\n");
648                 exit_cleanup(0);
649         }
650
651         local_name = get_local_name(flist,argv[0]);
652
653         status2 = do_recv(f_in,f_out,flist,local_name);
654
655         if (pid != -1) {
656                 if (verbose > 3)
657                         rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
658                 io_flush();
659                 wait_process(pid, &status);
660         }
661
662         return MAX(status, status2);
663 }
664
665 static int copy_argv (char *argv[])
666 {
667         int i;
668
669         for (i = 0; argv[i]; i++) {
670                 if (!(argv[i] = strdup(argv[i]))) {
671                         rprintf (FERROR, "out of memory at %s(%d)\n",
672                                  __FILE__, __LINE__);
673                         return RERR_MALLOC;
674                 }
675         }
676
677         return 0;
678 }
679
680
681 /**
682  * Start a client for either type of remote connection.  Work out
683  * whether the arguments request a remote shell or rsyncd connection,
684  * and call the appropriate connection function, then run_client.
685  *
686  * Calls either start_socket_client (for sockets) or do_cmd and
687  * client_run (for ssh).
688  **/
689 static int start_client(int argc, char *argv[])
690 {
691         char *p;
692         char *shell_machine = NULL;
693         char *shell_path = NULL;
694         char *shell_user = NULL;
695         int ret;
696         pid_t pid;
697         int f_in,f_out;
698         extern int local_server;
699         extern char *shell_cmd;
700         extern int rsync_port;
701         extern int daemon_over_rsh;
702         extern int read_batch;
703         int rc;
704
705         /* Don't clobber argv[] so that ps(1) can still show the right
706          * command line. */
707         if ((rc = copy_argv(argv)))
708                 return rc;
709
710         /* rsync:// always uses rsync server over direct socket connection */
711         if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
712                 char *host, *path;
713
714                 host = argv[0] + strlen(URL_PREFIX);
715                 p = strchr(host,'/');
716                 if (p) {
717                         *p = 0;
718                         path = p+1;
719                 } else {
720                         path = "";
721                 }
722                 p = strchr(host,':');
723                 if (p) {
724                         rsync_port = atoi(p+1);
725                         *p = 0;
726                 }
727                 return start_socket_client(host, path, argc-1, argv+1);
728         }
729
730         if (!read_batch) {
731                 p = find_colon(argv[0]);
732                 if (p) {
733                         if (remote_filesfrom_file
734                          && remote_filesfrom_file != files_from + 1
735                          && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
736                                 rprintf(FERROR,
737                                         "--files-from hostname is not transfer hostname\n");
738                                 exit_cleanup(RERR_SYNTAX);
739                         }
740                         if (p[1] == ':') { /* double colon */
741                                 *p = 0;
742                                 if (!shell_cmd) {
743                                         return start_socket_client(argv[0], p+2,
744                                                                    argc-1, argv+1);
745                                 }
746                                 p++;
747                                 daemon_over_rsh = 1;
748                         }
749
750                         if (argc < 1) {
751                                 usage(FERROR);
752                                 exit_cleanup(RERR_SYNTAX);
753                         }
754
755                         am_sender = 0;
756                         *p = 0;
757                         shell_machine = argv[0];
758                         shell_path = p+1;
759                         argc--;
760                         argv++;
761                 } else {
762                         am_sender = 1;
763
764                         /* rsync:// destination uses rsync server over direct socket */
765                         if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
766                                 char *host, *path;
767
768                                 host = argv[argc-1] + strlen(URL_PREFIX);
769                                 p = strchr(host,'/');
770                                 if (p) {
771                                         *p = 0;
772                                         path = p+1;
773                                 } else {
774                                         path = "";
775                                 }
776                                 p = strchr(host,':');
777                                 if (p) {
778                                         rsync_port = atoi(p+1);
779                                         *p = 0;
780                                 }
781                                 return start_socket_client(host, path, argc-1, argv);
782                         }
783
784                         p = find_colon(argv[argc-1]);
785                         if (p && remote_filesfrom_file
786                          && remote_filesfrom_file != files_from + 1
787                          && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
788                                 rprintf(FERROR,
789                                         "--files-from hostname is not transfer hostname\n");
790                                 exit_cleanup(RERR_SYNTAX);
791                         }
792                         if (!p) {
793                                 local_server = 1;
794                                 if (remote_filesfrom_file) {
795                                         rprintf(FERROR,
796                                                 "--files-from is remote but transfer is local\n");
797                                         exit_cleanup(RERR_SYNTAX);
798                                 }
799                         } else if (p[1] == ':') { /* double colon */
800                                 *p = 0;
801                                 if (!shell_cmd) {
802                                         return start_socket_client(argv[argc-1], p+2,
803                                                                    argc-1, argv);
804                                 }
805                                 p++;
806                                 daemon_over_rsh = 1;
807                         }
808
809                         if (argc < 2) {
810                                 usage(FERROR);
811                                 exit_cleanup(RERR_SYNTAX);
812                         }
813
814                         if (local_server) {
815                                 shell_machine = NULL;
816                                 shell_path = argv[argc-1];
817                         } else {
818                                 *p = 0;
819                                 shell_machine = argv[argc-1];
820                                 shell_path = p+1;
821                         }
822                         argc--;
823                 }
824         } else {
825                 am_sender = 1;
826                 local_server = 1;
827                 shell_path = argv[argc-1];
828         }
829
830         if (shell_machine) {
831                 p = strchr(shell_machine,'@');
832                 if (p) {
833                         *p = 0;
834                         shell_user = shell_machine;
835                         shell_machine = p+1;
836                 }
837         }
838
839         if (verbose > 3) {
840                 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
841                         shell_cmd?shell_cmd:"",
842                         shell_machine?shell_machine:"",
843                         shell_user?shell_user:"",
844                         shell_path?shell_path:"");
845         }
846
847         if (!am_sender && argc > 1) {
848                 usage(FERROR);
849                 exit_cleanup(RERR_SYNTAX);
850         }
851
852         if (argc == 0 && !am_sender) {
853                 extern int list_only;
854                 list_only = 1;
855         }
856
857         pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
858                      &f_in,&f_out);
859
860         /* if we're running an rsync server on the remote host over a
861            remote shell command, we need to do the RSYNCD protocol first */
862         if (daemon_over_rsh) {
863                 int tmpret;
864                 tmpret = start_inband_exchange(shell_user, shell_path,
865                                                f_in, f_out, argc);
866                 if (tmpret < 0)
867                         return tmpret;
868         }
869
870         ret = client_run(f_in, f_out, pid, argc, argv);
871
872         fflush(stdout);
873         fflush(stderr);
874
875         return ret;
876 }
877
878
879 static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
880         exit_cleanup(RERR_SIGNAL);
881 }
882
883 static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
884         extern int log_got_error;
885         if (log_got_error) _exit(RERR_PARTIAL);
886         _exit(0);
887 }
888
889 static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
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(int UNUSED(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         exit(ret);
1059         /* NOTREACHED */
1060 }