improved error handling again. Now we report messages for the remote
authorAndrew Tridgell <tridge@samba.org>
Fri, 23 Mar 2001 01:26:04 +0000 (01:26 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 23 Mar 2001 01:26:04 +0000 (01:26 +0000)
shell failing and propogate errors in a better fashion

cleanup.c
errcode.h
log.c
main.c
util.c

index 4b9cad3..480c200 100644 (file)
--- a/cleanup.c
+++ b/cleanup.c
@@ -33,6 +33,7 @@ static struct map_struct *cleanup_buf;
 static int cleanup_pid = 0;
 extern int io_error;
 
+pid_t cleanup_child_pid = -1;
 
 /*
  * Code is one of the RERR_* codes from errcode.h.
@@ -42,11 +43,17 @@ void _exit_cleanup(int code, const char *file, int line)
        extern int keep_partial;
        extern int log_got_error;
 
-       if (code == 0 && io_error) code = RERR_FILEIO;
-
        signal(SIGUSR1, SIG_IGN);
        signal(SIGUSR2, SIG_IGN);
 
+       if (cleanup_child_pid != -1) {
+               int status;
+               if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
+                       status = WEXITSTATUS(status);
+                       if (status > code) code = status;
+               }
+       }
+
        if (cleanup_got_literal && cleanup_fname && keep_partial) {
                char *fname = cleanup_fname;
                cleanup_fname = NULL;
@@ -68,14 +75,12 @@ void _exit_cleanup(int code, const char *file, int line)
                }
        }
 
-       if (code) log_exit(code, file, line);
-
-       if (code == 0) {
-               if (log_got_error) {
-                       code = RERR_FILEIO;
-               }
+       if (code == 0 && (io_error || log_got_error)) {
+               code = RERR_PARTIAL;
        }
 
+       if (code) log_exit(code, file, line);
+
        exit(code);
 }
 
index 997e2d2..fc1eca7 100644 (file)
--- a/errcode.h
+++ b/errcode.h
 #define RERR_SIGNAL     20      /* status returned when sent SIGUSR1, SIGINT */
 #define RERR_WAITCHILD  21      /* some error returned by waitpid() */
 #define RERR_MALLOC     22      /* error allocating core memory buffers */
+#define RERR_PARTIAL    23      /* partial transfer */
 
 #define RERR_TIMEOUT    30      /* timeout in data send/receive */
+
+/* Although it doesn't seem to be specified anywhere,
+ * ssh and the shell seem to return these values:
+ *
+ * 124 if the command exited with status 255
+ * 125 if the command is killed by a signal
+ * 126 if the command cannot be run
+ * 127 if the command is not found
+ *
+ * and we could use this to give a better explanation if the remote
+ * command is not found.
+ */
+#define RERR_CMD_FAILED 124
+#define RERR_CMD_KILLED 125
+#define RERR_CMD_RUN 126
+#define RERR_CMD_NOTFOUND 127
diff --git a/log.c b/log.c
index 492948b..e67477b 100644 (file)
--- a/log.c
+++ b/log.c
@@ -40,7 +40,7 @@ struct {
        { RERR_SYNTAX     , "syntax or usage error" }, 
        { RERR_PROTOCOL   , "protocol incompatibility" }, 
        { RERR_FILESELECT , "errors selecting input/output files, dirs" }, 
-       { RERR_UNSUPPORTED , "requested action not supported" }, 
+       { RERR_UNSUPPORTED, "requested action not supported" }, 
        { RERR_SOCKETIO   , "error in socket IO" }, 
        { RERR_FILEIO     , "error in file IO" }, 
        { RERR_STREAMIO   , "error in rsync protocol data stream" }, 
@@ -49,7 +49,12 @@ struct {
        { RERR_SIGNAL     , "received SIGUSR1 or SIGINT" }, 
        { RERR_WAITCHILD  , "some error returned by waitpid()" }, 
        { RERR_MALLOC     , "error allocating core memory buffers" }, 
+       { RERR_PARTIAL    , "partial transfer" }, 
        { RERR_TIMEOUT    , "timeout in data send/receive" }, 
+       { RERR_CMD_FAILED , "remote shell failed" },
+       { RERR_CMD_KILLED , "remote shell killed" },
+       { RERR_CMD_RUN,     "remote command could not be run" },
+        { RERR_CMD_NOTFOUND, "remote command not found" },
         { 0, NULL }
 };
 
@@ -506,7 +511,7 @@ void log_exit(int code, const char *file, int line)
                 if (!name)
                         name = "unexplained error";
                 
-               rprintf(FLOG,"transfer interrupted: %s (code %d) at %s(%d)\n", 
+               rprintf(FERROR,"transfer error: %s (code %d) at %s(%d)\n", 
                        name, code, file, line);
        }
 }
diff --git a/main.c b/main.c
index dae6e79..f696474 100644 (file)
--- a/main.c
+++ b/main.c
@@ -126,23 +126,11 @@ static void report(int f)
 
 
 /* Start the remote shell.   cmd may be NULL to use the default. */
-/* TODO: When the shell exits, look at its return value, as this may
- * well tell us if something went wrong in trying to connect to the
- * remote machine.  Although it doesn't seem to be specified anywhere,
- * ssh and the shell seem to return these values:
- *
- * 124 if the command exited with status 255
- * 125 if the command is killed by a signal
- * 126 if the command cannot be run
- * 127 if the command is not found
- *
- * and we could use this to give a better explanation if the remote
- * command is not found.
- */
-static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
+static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
 {
        char *args[100];
-       int i,argc=0, ret;
+       int i,argc=0;
+       pid_t ret;
        char *tok,*dir=NULL;
        extern int local_server;
        extern char *rsync_path;
@@ -484,13 +472,16 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
  * This is called once the connection has been negotiated.  It is used
  * for rsyncd, remote-shell, and local connections.
  */
-int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
+int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 {
        struct file_list *flist;
        int status = 0, status2 = 0;
        char *local_name = NULL;
        extern int am_sender;
        extern int remote_version;
+       extern pid_t cleanup_child_pid;
+
+       cleanup_child_pid = pid;
 
        set_nonblocking(f_in);
        set_nonblocking(f_out);
@@ -583,7 +574,8 @@ static int start_client(int argc, char *argv[])
        char *shell_machine = NULL;
        char *shell_path = NULL;
        char *shell_user = NULL;
-       int pid, ret;
+       int ret;
+       pid_t pid;
        int f_in,f_out;
        extern int local_server;
        extern int am_sender;
@@ -700,10 +692,13 @@ static RETSIGTYPE sigusr1_handler(int val) {
 
 static RETSIGTYPE sigusr2_handler(int val) {
        extern int log_got_error;
-       if (log_got_error) _exit(RERR_FILEIO);
+       if (log_got_error) _exit(RERR_PARTIAL);
        _exit(0);
 }
 
+static RETSIGTYPE sigchld_handler(int val) {
+}
+
 int main(int argc,char *argv[])
 {       
        extern int am_root;
@@ -715,6 +710,7 @@ int main(int argc,char *argv[])
 
        signal(SIGUSR1, sigusr1_handler);
        signal(SIGUSR2, sigusr2_handler);
+       signal(SIGCHLD, sigchld_handler);
 
        starttime = time(NULL);
        am_root = (getuid() == 0);
diff --git a/util.c b/util.c
index 48935cc..d917f07 100644 (file)
--- a/util.c
+++ b/util.c
@@ -93,9 +93,9 @@ int fd_pair(int fd[2])
    used to cope with badly broken rsh implementations like the one on
    solaris.
  */
-int piped_child(char **command,int *f_in,int *f_out)
+pid_t piped_child(char **command,int *f_in,int *f_out)
 {
-  int pid;
+  pid_t pid;
   int to_child_pipe[2];
   int from_child_pipe[2];
   extern int blocking_io;
@@ -108,7 +108,7 @@ int piped_child(char **command,int *f_in,int *f_out)
 
 
   pid = do_fork();
-  if (pid < 0) {
+  if (pid == -1) {
     rprintf(FERROR,"fork: %s\n",strerror(errno));
     exit_cleanup(RERR_IPC);
   }
@@ -148,9 +148,9 @@ int piped_child(char **command,int *f_in,int *f_out)
   return pid;
 }
 
-int local_child(int argc, char **argv,int *f_in,int *f_out)
+pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
 {
-       int pid;
+       pid_t pid;
        int to_child_pipe[2];
        int from_child_pipe[2];
 
@@ -162,7 +162,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
 
 
        pid = do_fork();
-       if (pid < 0) {
+       if (pid == -1) {
                rprintf(FERROR,"fork: %s\n",strerror(errno));
                exit_cleanup(RERR_IPC);
        }