Handle the new server-daemon via remote-shell mode.
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 86eca2c..cf2674d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,8 +23,7 @@
 
 time_t starttime = 0;
 
-struct stats stats;
-
+extern struct stats stats;
 extern int verbose;
 
 static void show_malloc_stats(void);
@@ -175,6 +174,7 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
        extern int local_server;
        extern char *rsync_path;
        extern int blocking_io;
+       extern int daemon_over_rsh;
        extern int read_batch;
 
        if (!read_batch && !local_server) {
@@ -216,7 +216,7 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
 
        args[argc++] = ".";
 
-       if (path && *path) 
+       if (!daemon_over_rsh && path && *path) 
                args[argc++] = path;
 
        args[argc] = NULL;
@@ -493,9 +493,10 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
 }
 
 
-void child_main(int argc, char *argv[])
+int child_main(int argc, char *argv[])
 {
        start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
+       return 0;
 }
 
 
@@ -667,16 +668,16 @@ static int start_client(int argc, char *argv[])
        extern int am_sender;
        extern char *shell_cmd;
        extern int rsync_port;
-       extern int whole_file;
-       extern int write_batch;
+       extern int daemon_over_rsh;
        extern int read_batch;
        int rc;
 
        /* Don't clobber argv[] so that ps(1) can still show the right
            command line. */
-       if ((rc = copy_argv (argv)))
+       if ((rc = copy_argv(argv)))
                return rc;
 
+       /* rsync:// always uses rsync server over direct socket connection */
        if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
                char *host, *path;
 
@@ -702,7 +703,12 @@ static int start_client(int argc, char *argv[])
        if (p) {
                if (p[1] == ':') { /* double colon */
                        *p = 0;
-                       return start_socket_client(argv[0], p+2, argc-1, argv+1);
+                       if (!shell_cmd) {
+                               return start_socket_client(argv[0], p+2,
+                                                          argc-1, argv+1);
+                       }
+                       p++;
+                       daemon_over_rsh = 1;
                }
 
                if (argc < 1) {
@@ -722,9 +728,14 @@ static int start_client(int argc, char *argv[])
                p = find_colon(argv[argc-1]);
                if (!p) {
                        local_server = 1;
-               } else if (p[1] == ':') {
+               } else if (p[1] == ':') { /* double colon */
                        *p = 0;
-                       return start_socket_client(argv[argc-1], p+2, argc-1, argv);
+                       if (!shell_cmd) {
+                               return start_socket_client(argv[argc-1], p+2,
+                                                          argc-1, argv);
+                       }
+                       p++;
+                       daemon_over_rsh = 1;
                }
 
                if (argc < 2) {
@@ -775,8 +786,19 @@ static int start_client(int argc, char *argv[])
                list_only = 1;
        }
        
-       pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
-       
+       pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
+                    &f_in,&f_out);
+
+       /* if we're running an rsync server on the remote host over a
+          remote shell command, we need to do the RSYNCD protocol first */
+       if (daemon_over_rsh) {
+               int tmpret;
+               tmpret = start_inband_exchange(shell_user, shell_path,
+                                              f_in, f_out, argc);
+               if (tmpret < 0)
+                       return tmpret;
+       }
+
        ret = client_run(f_in, f_out, pid, argc, argv);
 
        fflush(stdout);
@@ -817,13 +839,32 @@ static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
  * Solaris?)  Can we be more portable?
  **/
 #ifdef MAINTAINER_MODE
+const char *get_panic_action(void)
+{
+       const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
+
+       if (cmd_fmt)
+               return cmd_fmt;
+       else
+               return "xterm -display :0 -T Panic -n Panic "
+                       "-e gdb /proc/%d/exe %d";
+}
+
+
+/**
+ * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
+ *
+ * This signal handler is only installed if we were configured with
+ * --enable-maintainer-mode.  Perhaps it should always be on and we
+ * should just look at the environment variable, but I'm a bit leery
+ * of a signal sending us into a busy loop.
+ **/
 static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
 {
        char cmd_buf[300];
        int ret;
-       sprintf(cmd_buf, 
-               "xterm -display :0 -T Panic -n Panic "
-               "-e gdb /proc/%d/exe %d", 
+
+       sprintf(cmd_buf, get_panic_action(),
                getpid(), getpid());
 
        /* Unless we failed to execute gdb, we allow the process to
@@ -899,9 +940,8 @@ int main(int argc,char *argv[])
            write_batch_argvs_file(orig_argc, orig_argv);
        }
 
-       if (am_daemon) {
+       if (am_daemon && !am_server)
                return daemon_main();
-       }
 
        if (argc < 1) {
                usage(FERROR);
@@ -921,6 +961,8 @@ int main(int argc,char *argv[])
        if (am_server) {
                set_nonblocking(STDIN_FILENO);
                set_nonblocking(STDOUT_FILENO);
+               if (am_daemon)
+                       return start_daemon(STDIN_FILENO, STDOUT_FILENO);
                start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
        }