patch from Alberto Accomazzi <aaccomazzi@cfa.harvard.edu> to add
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 3c4d99c..bc587cc 100644 (file)
--- a/main.c
+++ b/main.c
@@ -36,10 +36,7 @@ static void report(int f)
        extern int do_stats;
 
        if (am_daemon) {
-               syslog(LOG_INFO,"wrote %.0f bytes  read %.0f bytes  total size %.0f\n",
-                      (double)stats.total_written,
-                      (double)stats.total_read,
-                      (double)stats.total_size);
+               log_exit(0);
                if (f == -1 || !am_sender) return;
        }
 
@@ -63,29 +60,29 @@ static void report(int f)
        }
 
        if (do_stats) {
-               printf("\nNumber of files: %d\n", stats.num_files);
-               printf("Number of files transferred: %d\n", 
+               rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
+               rprintf(FINFO,"Number of files transferred: %d\n", 
                       stats.num_transferred_files);
-               printf("Total file size: %.0f bytes\n", 
+               rprintf(FINFO,"Total file size: %.0f bytes\n", 
                       (double)stats.total_size);
-               printf("Total transferred file size: %.0f bytes\n", 
+               rprintf(FINFO,"Total transferred file size: %.0f bytes\n", 
                       (double)stats.total_transferred_size);
-               printf("Literal data: %.0f bytes\n", 
+               rprintf(FINFO,"Literal data: %.0f bytes\n", 
                       (double)stats.literal_data);
-               printf("Matched data: %.0f bytes\n", 
+               rprintf(FINFO,"Matched data: %.0f bytes\n", 
                       (double)stats.matched_data);
-               printf("File list size: %d\n", stats.flist_size);
-               printf("Total bytes written: %.0f\n", 
+               rprintf(FINFO,"File list size: %d\n", stats.flist_size);
+               rprintf(FINFO,"Total bytes written: %.0f\n", 
                       (double)stats.total_written);
-               printf("Total bytes read: %.0f\n\n", 
+               rprintf(FINFO,"Total bytes read: %.0f\n\n", 
                       (double)stats.total_read);
        }
        
-       printf("wrote %.0f bytes  read %.0f bytes  %.2f bytes/sec\n",
+       rprintf(FINFO,"wrote %.0f bytes  read %.0f bytes  %.2f bytes/sec\n",
               (double)stats.total_written,
               (double)stats.total_read,
               (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
-       printf("total size is %.0f  speedup is %.2f\n",
+       rprintf(FINFO,"total size is %.0f  speedup is %.2f\n",
               (double)stats.total_size,
               (1.0*stats.total_size)/(stats.total_written+stats.total_read));
 
@@ -172,18 +169,22 @@ static char *get_local_name(struct file_list *flist,char *name)
        STRUCT_STAT st;
        extern int orig_umask;
 
+       if (verbose > 2)
+               rprintf(FINFO,"get_local_name count=%d %s\n", 
+                       flist->count, name);
+
        if (do_stat(name,&st) == 0) {
                if (S_ISDIR(st.st_mode)) {
                        if (!push_dir(name, 0)) {
                                rprintf(FERROR,"push_dir %s : %s (1)\n",
                                        name,strerror(errno));
-                               exit_cleanup(1);
+                               exit_cleanup(RERR_FILESELECT);
                        }
                        return NULL;
                }
                if (flist->count > 1) {
                        rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
-                       exit_cleanup(1);
+                       exit_cleanup(RERR_FILESELECT);
                }
                return name;
        }
@@ -196,15 +197,16 @@ static char *get_local_name(struct file_list *flist,char *name)
 
        if (do_mkdir(name,0777 & ~orig_umask) != 0) {
                rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
-               exit_cleanup(1);
+               exit_cleanup(RERR_FILEIO);
        } else {
-               rprintf(FINFO,"created directory %s\n",name);
+               if (verbose > 0)
+                       rprintf(FINFO,"created directory %s\n",name);
        }
 
        if (!push_dir(name, 0)) {
                rprintf(FERROR,"push_dir %s : %s (2)\n",
                        name,strerror(errno));
-               exit_cleanup(1);
+               exit_cleanup(RERR_FILESELECT);
        }
 
        return NULL;
@@ -226,7 +228,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
   
        if (!relative_paths && !push_dir(dir, 0)) {
                rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
-               exit_cleanup(1);
+               exit_cleanup(RERR_FILESELECT);
        }
        argc--;
        argv++;
@@ -245,15 +247,15 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
                argv[0] = ".";
        }
        
+       set_nonblocking(f_out);
+       if (f_in != f_out)
+               set_nonblocking(f_in);
+               
        flist = send_file_list(f_out,argc,argv);
        if (!flist || flist->count == 0) {
                exit_cleanup(0);
        }
 
-       set_nonblocking(f_out);
-       if (f_in != f_out)
-               set_nonblocking(f_in);
-               
        send_files(flist,f_out,f_in);
        report(f_out);
        io_flush();
@@ -273,7 +275,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
 
        if (pipe(recv_pipe) < 0) {
                rprintf(FERROR,"pipe failed in do_recv\n");
-               exit_cleanup(1);
+               exit_cleanup(RERR_SOCKETIO);
        }
   
        io_flush();
@@ -283,13 +285,11 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
                if (f_in != f_out) close(f_out);
 
                set_nonblocking(f_in);
+               set_nonblocking(recv_pipe[1]);
 
                recv_files(f_in,flist,local_name,recv_pipe[1]);
                report(f_in);
 
-               if (verbose > 3)
-                       rprintf(FINFO,"do_recv waiting on %d\n",pid);
-
                io_flush();
                _exit(0);
        }
@@ -299,6 +299,9 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
        if (f_in != f_out) close(f_in);
 
        set_nonblocking(f_out);
+       set_nonblocking(recv_pipe[0]);
+
+       io_start_buffering(f_out);
 
        generate_files(f_out,flist,local_name,recv_pipe[0]);
 
@@ -327,7 +330,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
                if (!am_daemon && !push_dir(dir, 0)) {
                        rprintf(FERROR,"push_dir %s : %s (4)\n",
                                dir,strerror(errno));
-                       exit_cleanup(1);
+                       exit_cleanup(RERR_FILESELECT);
                }    
        }
 
@@ -337,7 +340,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
        flist = recv_file_list(f_in);
        if (!flist || flist->count == 0) {
                rprintf(FERROR,"server_recv: nothing to do\n");
-               exit_cleanup(1);
+               exit_cleanup(RERR_FILESELECT);
        }
        
        if (argc > 0) {    
@@ -358,8 +361,12 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
        extern int cvs_exclude;
        extern int am_sender;
 
+       set_nonblocking(f_out);
+       if (f_in != f_out)
+               set_nonblocking(f_in);
+                       
        setup_protocol(f_out, f_in);
-       
+
        if (am_sender) {
                recv_exclude_list(f_in);
                if (cvs_exclude)
@@ -377,6 +384,7 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
        int status = 0, status2 = 0;
        char *local_name = NULL;
        extern int am_sender;
+       extern int list_only;
 
        setup_protocol(f_out,f_in);
        
@@ -405,6 +413,8 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
                report(-1);
                exit_cleanup(status);
        }
+
+       if (argc == 0) list_only = 1;
        
        send_exclude_list(f_out);
        
@@ -428,6 +438,20 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
        return status | status2;
 }
 
+static char *find_colon(char *s)
+{
+       char *p, *p2;
+
+       p = strchr(s,':');
+       if (!p) return NULL;
+       
+       /* now check to see if there is a / in the string before the : - if there is then
+          discard the colon on the assumption that the : is part of a filename */
+       p2 = strchr(s,'/');
+       if (p2 && p2 < p) return NULL;
+
+       return p;
+}
 
 static int start_client(int argc, char *argv[])
 {
@@ -441,7 +465,21 @@ static int start_client(int argc, char *argv[])
        extern int am_sender;
        extern char *shell_cmd;
 
-       p = strchr(argv[0],':');
+       if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
+               char *host, *path;
+
+               host = argv[0] + strlen(URL_PREFIX);
+               p = strchr(host,'/');
+               if (p) {
+                       *p = 0;
+                       path = p+1;
+               } else {
+                       path="";
+               }
+               return start_socket_client(host, path, argc-1, argv+1);
+       }
+
+       p = find_colon(argv[0]);
 
        if (p) {
                if (p[1] == ':') {
@@ -449,9 +487,9 @@ static int start_client(int argc, char *argv[])
                        return start_socket_client(argv[0], p+2, argc-1, argv+1);
                }
 
-               if (argc < 2) {
+               if (argc < 1) {
                        usage(FERROR);
-                       exit_cleanup(1);
+                       exit_cleanup(RERR_SYNTAX);
                }
 
                am_sender = 0;
@@ -463,7 +501,7 @@ static int start_client(int argc, char *argv[])
        } else {
                am_sender = 1;
 
-               p = strchr(argv[argc-1],':');
+               p = find_colon(argv[argc-1]);
                if (!p) {
                        local_server = 1;
                } else if (p[1] == ':') {
@@ -473,7 +511,7 @@ static int start_client(int argc, char *argv[])
 
                if (argc < 2) {
                        usage(FERROR);
-                       exit_cleanup(1);
+                       exit_cleanup(RERR_SYNTAX);
                }
                
                if (local_server) {
@@ -504,18 +542,13 @@ static int start_client(int argc, char *argv[])
                        shell_path?shell_path:"");
        }
        
-       if (!am_sender && argc != 1) {
+       if (!am_sender && argc > 1) {
                usage(FERROR);
-               exit_cleanup(1);
+               exit_cleanup(RERR_SYNTAX);
        }
        
        pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
        
-#if HAVE_SETLINEBUF
-       setlinebuf(stdout);
-       setlinebuf(stderr);
-#endif
-
        ret = client_run(f_in, f_out, pid, argc, argv);
 
        fflush(stdout);
@@ -525,8 +558,8 @@ static int start_client(int argc, char *argv[])
 }
 
 
-RETSIGTYPE sigusr1_handler(int val) {
-       exit_cleanup(1);
+static RETSIGTYPE sigusr1_handler(int val) {
+       exit_cleanup(RERR_SIGNAL);
 }
 
 int main(int argc,char *argv[])
@@ -546,14 +579,16 @@ int main(int argc,char *argv[])
 
        if (argc < 2) {
                usage(FERROR);
-               exit_cleanup(1);
+               exit_cleanup(RERR_SYNTAX);
        }
 
        /* we set a 0 umask so that correct file permissions can be
           carried across */
        orig_umask = (int)umask(0);
 
-       parse_arguments(argc, argv);
+       if (!parse_arguments(argc, argv)) {
+               exit_cleanup(RERR_SYNTAX);
+       }
 
        argc -= optind;
        argv += optind;
@@ -563,6 +598,7 @@ int main(int argc,char *argv[])
        signal(SIGINT,SIGNAL_CAST sig_int);
        signal(SIGPIPE,SIGNAL_CAST sig_int);
        signal(SIGHUP,SIGNAL_CAST sig_int);
+       signal(SIGTERM,SIGNAL_CAST sig_int);
 
        if (am_daemon) {
                return daemon_main();
@@ -570,7 +606,7 @@ int main(int argc,char *argv[])
 
        if (argc < 1) {
                usage(FERROR);
-               exit_cleanup(1);
+               exit_cleanup(RERR_SYNTAX);
        }
 
        if (dry_run)
@@ -579,7 +615,7 @@ int main(int argc,char *argv[])
 #ifndef SUPPORT_LINKS
        if (!am_server && preserve_links) {
                rprintf(FERROR,"ERROR: symbolic links not supported\n");
-               exit_cleanup(1);
+               exit_cleanup(RERR_UNSUPPORTED);
        }
 #endif