[Bug 369] Inconsistant exiit status from scp

Thomas Binder binder at arago.de
Wed Sep 11 03:36:45 EST 2002


Hi!

> ------- Additional Comments From markus at openbsd.org  2002-09-10 22:45 -------
> do you have a patch for checking the exit status of ssh? 

I attached a rough patch for that. It probably (I haven't been
able to check) has one drawback, though: If the remote sshd has
the "scp hangs on exit" problem, then the patched local scp will
now do so, too.

Besides, the patch also adds a check for fork() returning an
error.


Ciao

Thomas
-------------- next part --------------
? confdefs.h
Index: scp.c
===================================================================
RCS file: /cvs/openssh/scp.c,v
retrieving revision 1.97
diff -u -r1.97 scp.c
--- scp.c	21 Jun 2002 00:41:52 -0000	1.97
+++ scp.c	10 Sep 2002 17:16:29 -0000
@@ -125,6 +125,9 @@
 /* This is the program to execute for the secured connection. ("ssh" or -S) */
 char *ssh_program = _PATH_SSH_PROGRAM;
 
+/* This is used to store the pid of ssh_program */
+pid_t do_cmd_pid;
+
 /*
  * This function executes the given command as the specified user on the
  * given host.  This returns < 0 if execution fails, and >= 0 otherwise. This
@@ -159,7 +162,8 @@
 	close(reserved[1]);
 
 	/* For a child to execute the command on the remote host using ssh. */
-	if (fork() == 0)  {
+	do_cmd_pid = fork();
+	if (do_cmd_pid == 0) {
 		/* Child. */
 		close(pin[1]);
 		close(pout[0]);
@@ -178,6 +182,10 @@
 		perror(ssh_program);
 		exit(1);
 	}
+	else if (do_cmd_pid == (pid_t)-1) {
+		/* fork() failed */
+		fatal("fork: %s", strerror(errno));
+	}
 	/* Parent.  Close the other side, and return the local side. */
 	close(pin[0]);
 	*fdout = pin[1];
@@ -219,7 +227,7 @@
 	int argc;
 	char *argv[];
 {
-	int ch, fflag, tflag;
+	int ch, fflag, tflag, status;
 	char *targ;
 	extern char *optarg;
 	extern int optind;
@@ -317,6 +325,7 @@
 		targetshouldbedirectory = 1;
 
 	remin = remout = -1;
+	do_cmd_pid = (pid_t)-1;
 	/* Command to be executed on remote system using "ssh". */
 	(void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
 	    verbose_mode ? " -v" : "",
@@ -331,6 +340,22 @@
 		tolocal(argc, argv);	/* Dest is local host. */
 		if (targetshouldbedirectory)
 			verifydir(argv[argc - 1]);
+	}
+	/*
+	 * Finally check the exit status of the ssh process, if one was forked
+	 * and no error has occured yet
+	 */
+	if (do_cmd_pid != (pid_t)-1 && errs == 0) {
+		if (remin != -1)
+		    (void) close(remin);
+		if (remout != -1)
+		    (void) close(remout);
+		if (waitpid(do_cmd_pid, &status, 0) == -1)
+			errs = 1;
+		else {
+			if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+				errs = 1;
+		}
 	}
 	exit(errs != 0);
 }


More information about the openssh-unix-dev mailing list