Fixed wait_process() to handle cases where waitpid() fails or
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index f589aa3..da9946b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -46,11 +46,8 @@ extern int keep_dirlinks;
 extern int preserve_hard_links;
 extern int protocol_version;
 extern int recurse;
-extern int fuzzy_basis;
 extern int relative_paths;
 extern int rsync_port;
-extern int inplace;
-extern int make_backups;
 extern int whole_file;
 extern int read_batch;
 extern int write_batch;
@@ -60,8 +57,6 @@ extern int filesfrom_fd;
 extern pid_t cleanup_child_pid;
 extern struct stats stats;
 extern char *filesfrom_host;
-extern char *partial_dir;
-extern char *basis_dir[];
 extern char *rsync_path;
 extern char *shell_cmd;
 extern char *batch_name;
@@ -86,12 +81,12 @@ static void show_malloc_stats(void);
 /****************************************************************************
 wait for a process to exit, calling io_flush while waiting
 ****************************************************************************/
-void wait_process(pid_t pid, int *status)
+static void wait_process(pid_t pid, int *code_ptr)
 {
        pid_t waited_pid;
-       int cnt;
+       int cnt, status;
 
-       while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
+       while ((waited_pid = waitpid(pid, &status, WNOHANG)) == 0) {
                msleep(20);
                io_flush(FULL_FLUSH);
        }
@@ -102,7 +97,8 @@ void wait_process(pid_t pid, int *status)
                 */
                for (cnt = 0;  cnt < MAXCHILDPROCS; cnt++) {
                        if (pid == pid_stat_table[cnt].pid) {
-                               *status = pid_stat_table[cnt].status;
+                               waited_pid = pid;
+                               status = pid_stat_table[cnt].status;
                                pid_stat_table[cnt].pid = 0;
                                break;
                        }
@@ -112,9 +108,18 @@ void wait_process(pid_t pid, int *status)
        /* TODO: If the child exited on a signal, then log an
         * appropriate error message.  Perhaps we should also accept a
         * message describing the purpose of the child.  Also indicate
-        * this to the caller so that thhey know something went
-        * wrong.  */
-       *status = WEXITSTATUS(*status);
+        * this to the caller so that they know something went wrong. */
+       if (waited_pid < 0)
+               *code_ptr = RERR_WAITCHILD;
+       else if (!WIFEXITED(status)) {
+               if (WCOREDUMP(status))
+                       *code_ptr = RERR_CRASHED;
+               else if (WIFSIGNALED(status))
+                       *code_ptr = RERR_TERMINATED;
+               else
+                       *code_ptr = RERR_WAITCHILD;
+       } else
+               *code_ptr = WEXITSTATUS(status);
 }
 
 /* This function gets called from all 3 processes.  We want the client side
@@ -175,7 +180,7 @@ static void handle_stats(int f)
                        stats.flist_buildtime = read_longint(f);
                        stats.flist_xfertime = read_longint(f);
                }
-       } else if (write_batch && !am_server) {
+       } else if (write_batch) {
                /* The --read-batch process is going to be a client
                 * receiver, so we need to give it the stats. */
                write_longint(batch_fd, total_read);
@@ -186,7 +191,10 @@ static void handle_stats(int f)
                        write_longint(batch_fd, stats.flist_xfertime);
                }
        }
+}
 
+static void output_summary(void)
+{
        if (do_stats) {
                rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
                rprintf(FINFO,"Number of files transferred: %d\n",
@@ -214,12 +222,6 @@ static void handle_stats(int f)
                        (double)total_read);
        }
 
-       fflush(stdout);
-       fflush(stderr);
-}
-
-static void output_summary(void)
-{
        if (verbose || do_stats) {
                rprintf(FINFO,
                        "\nsent %.0f bytes  received %.0f bytes  %.2f bytes/sec\n",
@@ -468,7 +470,6 @@ static void read_final_goodbye(int f_in, int f_out)
 
 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
 {
-       int i;
        struct file_list *flist;
        char *dir = argv[0];
 
@@ -497,14 +498,6 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
        argc--;
        argv++;
 
-       if (strcmp(dir,".")) {
-               int l = strlen(dir);
-               if (strcmp(dir,"/") == 0)
-                       l = 0;
-               for (i = 0; i < argc; i++)
-                       argv[i] += l+1;
-       }
-
        if (argc == 0 && (recurse || list_only)) {
                argc = 1;
                argv--;
@@ -682,14 +675,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
        }
        the_file_list = flist;
 
-       if (argc > 0) {
-               if (strcmp(dir,".")) {
-                       argv[0] += strlen(dir);
-                       if (argv[0][0] == '/')
-                               argv[0]++;
-               }
+       if (argc > 0)
                local_name = get_local_name(flist,argv[0]);
-       }
 
        status = do_recv(f_in,f_out,flist,local_name);
        exit_cleanup(status);
@@ -875,6 +862,13 @@ static int start_client(int argc, char *argv[])
                argc--;
                shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
                if (shell_path) { /* source is remote */
+                       char *dummy1;
+                       int dummy2;
+                       if (argc && check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
+                               rprintf(FERROR,
+                                       "The source and destination cannot both be remote.\n");
+                               exit_cleanup(RERR_SYNTAX);
+                       }
                        argv++;
                        if (filesfrom_host && *filesfrom_host
                            && strcmp(filesfrom_host, shell_machine) != 0) {