- avsm@cvs.openbsd.org 2005/05/24 17:32:44
     [atomicio.c atomicio.h authfd.c monitor_wrap.c msg.c scp.c sftp-client.c]
     [ssh-keyscan.c sshconnect.c]
     Switch atomicio to use a simpler interface; it now returns a size_t
     (containing number of bytes read/written), and indicates error by
     returning 0.  EOF is signalled by errno==EPIPE.
     Typical use now becomes:

     if (atomicio(read, ..., len) != len)
             err(1,"read");

     ok deraadt@, cloder@, djm@
diff --git a/ChangeLog b/ChangeLog
index 25bac49..b01e746 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -83,6 +83,18 @@
    - avsm@cvs.openbsd.org 2005/05/24 02:05:09
      [ssh-keygen.c]
      some style nits from dmiller@, and use a fatal() instead of a printf()/exit
+   - avsm@cvs.openbsd.org 2005/05/24 17:32:44
+     [atomicio.c atomicio.h authfd.c monitor_wrap.c msg.c scp.c sftp-client.c]
+     [ssh-keyscan.c sshconnect.c]
+     Switch atomicio to use a simpler interface; it now returns a size_t
+     (containing number of bytes read/written), and indicates error by
+     returning 0.  EOF is signalled by errno==EPIPE.
+     Typical use now becomes:
+
+     if (atomicio(read, ..., len) != len)
+             err(1,"read");
+
+     ok deraadt@, cloder@, djm@
 
 20050524
  - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
@@ -2582,4 +2594,4 @@
    - (djm) Trim deprecated options from INSTALL. Mention UsePAM
    - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
 
-$Id: ChangeLog,v 1.3785 2005/05/26 02:19:39 djm Exp $
+$Id: ChangeLog,v 1.3786 2005/05/26 02:23:44 djm Exp $
diff --git a/atomicio.c b/atomicio.c
index 7637e16..12abbda 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -24,14 +25,14 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: atomicio.c,v 1.12 2003/07/31 15:50:16 avsm Exp $");
+RCSID("$OpenBSD: atomicio.c,v 1.13 2005/05/24 17:32:43 avsm Exp $");
 
 #include "atomicio.h"
 
 /*
  * ensure all of data on socket comes through. f==read || f==vwrite
  */
-ssize_t
+size_t
 atomicio(f, fd, _s, n)
 	ssize_t (*f) (int, void *, size_t);
 	int fd;
@@ -39,7 +40,8 @@
 	size_t n;
 {
 	char *s = _s;
-	ssize_t res, pos = 0;
+	size_t pos = 0;
+	ssize_t res;
 
 	while (n > pos) {
 		res = (f) (fd, s + pos, n - pos);
@@ -51,10 +53,12 @@
 			if (errno == EINTR || errno == EAGAIN)
 #endif
 				continue;
+			return 0;
 		case 0:
-			return (res);
+			errno = EPIPE;
+			return pos;
 		default:
-			pos += res;
+			pos += (u_int)res;
 		}
 	}
 	return (pos);
diff --git a/atomicio.h b/atomicio.h
index 5c0f392..7eccf20 100644
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: atomicio.h,v 1.5 2003/06/28 16:23:06 deraadt Exp $	*/
+/*	$OpenBSD: atomicio.h,v 1.6 2005/05/24 17:32:43 avsm Exp $	*/
 
 /*
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
@@ -28,6 +28,6 @@
 /*
  * Ensure all of data on socket comes through. f==read || f==vwrite
  */
-ssize_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
+size_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
 
 #define vwrite (ssize_t (*)(int, void *, size_t))write
diff --git a/authfd.c b/authfd.c
index 662350c..9ce5b5e 100644
--- a/authfd.c
+++ b/authfd.c
@@ -35,7 +35,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.64 2004/08/11 21:44:31 avsm Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.65 2005/05/24 17:32:43 avsm Exp $");
 
 #include <openssl/evp.h>
 
@@ -149,8 +149,7 @@
 		l = len;
 		if (l > sizeof(buf))
 			l = sizeof(buf);
-		l = atomicio(read, auth->fd, buf, l);
-		if (l <= 0) {
+		if (atomicio(read, auth->fd, buf, l) != l) {
 			error("Error reading response from authentication socket.");
 			return 0;
 		}
diff --git a/monitor_wrap.c b/monitor_wrap.c
index e1b6512..afa612f 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -25,7 +25,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: monitor_wrap.c,v 1.39 2004/07/17 05:31:41 dtucker Exp $");
+RCSID("$OpenBSD: monitor_wrap.c,v 1.40 2005/05/24 17:32:43 avsm Exp $");
 
 #include <openssl/bn.h>
 #include <openssl/dh.h>
@@ -95,9 +95,9 @@
 	PUT_32BIT(buf, mlen + 1);
 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
 	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
-		fatal("%s: write", __func__);
+		fatal("%s: write: %s", __func__, strerror(errno));
 	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
-		fatal("%s: write", __func__);
+		fatal("%s: write: %s", __func__, strerror(errno));
 }
 
 void
@@ -105,24 +105,21 @@
 {
 	u_char buf[4];
 	u_int msg_len;
-	ssize_t res;
 
 	debug3("%s entering", __func__);
 
-	res = atomicio(read, sock, buf, sizeof(buf));
-	if (res != sizeof(buf)) {
-		if (res == 0)
+	if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
+		if (errno == EPIPE)
 			cleanup_exit(255);
-		fatal("%s: read: %ld", __func__, (long)res);
+		fatal("%s: read: %s", __func__, strerror(errno));
 	}
 	msg_len = GET_32BIT(buf);
 	if (msg_len > 256 * 1024)
 		fatal("%s: read: bad msg_len %d", __func__, msg_len);
 	buffer_clear(m);
 	buffer_append_space(m, msg_len);
-	res = atomicio(read, sock, buffer_ptr(m), msg_len);
-	if (res != msg_len)
-		fatal("%s: read: %ld != msg_len", __func__, (long)res);
+	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
+		fatal("%s: read: %s", __func__, strerror(errno));
 }
 
 void
diff --git a/msg.c b/msg.c
index 30bc3f1..3e4c288 100644
--- a/msg.c
+++ b/msg.c
@@ -22,7 +22,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "includes.h"
-RCSID("$OpenBSD: msg.c,v 1.7 2003/11/17 09:45:39 djm Exp $");
+RCSID("$OpenBSD: msg.c,v 1.8 2005/05/24 17:32:43 avsm Exp $");
 
 #include "buffer.h"
 #include "getput.h"
@@ -55,15 +55,13 @@
 ssh_msg_recv(int fd, Buffer *m)
 {
 	u_char buf[4];
-	ssize_t res;
 	u_int msg_len;
 
 	debug3("ssh_msg_recv entering");
 
-	res = atomicio(read, fd, buf, sizeof(buf));
-	if (res != sizeof(buf)) {
-		if (res != 0)
-			error("ssh_msg_recv: read: header %ld", (long)res);
+	if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
+		if (errno != EPIPE)
+			error("ssh_msg_recv: read: header");
 		return (-1);
 	}
 	msg_len = GET_32BIT(buf);
@@ -73,9 +71,8 @@
 	}
 	buffer_clear(m);
 	buffer_append_space(m, msg_len);
-	res = atomicio(read, fd, buffer_ptr(m), msg_len);
-	if (res != msg_len) {
-		error("ssh_msg_recv: read: %ld != msg_len", (long)res);
+	if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) {
+		error("ssh_msg_recv: read: %s", strerror(errno));
 		return (-1);
 	}
 	return (0);
diff --git a/scp.c b/scp.c
index 1d34cc6..1455c18 100644
--- a/scp.c
+++ b/scp.c
@@ -71,7 +71,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.121 2005/04/02 12:41:16 djm Exp $");
+RCSID("$OpenBSD: scp.c,v 1.122 2005/05/24 17:32:43 avsm Exp $");
 
 #include "xmalloc.h"
 #include "atomicio.h"
@@ -502,7 +502,8 @@
 	struct stat stb;
 	static BUF buffer;
 	BUF *bp;
-	off_t i, amt, result, statbytes;
+	off_t i, amt, statbytes;
+	size_t result;
 	int fd, haderr, indx;
 	char *last, *name, buf[2048];
 	int len;
@@ -578,14 +579,14 @@
 			if (!haderr) {
 				result = atomicio(read, fd, bp->buf, amt);
 				if (result != amt)
-					haderr = result >= 0 ? EIO : errno;
+					haderr = errno;
 			}
 			if (haderr)
 				(void) atomicio(vwrite, remout, bp->buf, amt);
 			else {
 				result = atomicio(vwrite, remout, bp->buf, amt);
 				if (result != amt)
-					haderr = result >= 0 ? EIO : errno;
+					haderr = errno;
 				statbytes += result;
 			}
 			if (limit_rate)
@@ -720,7 +721,8 @@
 		YES, NO, DISPLAYED
 	} wrerr;
 	BUF *bp;
-	off_t i, j;
+	off_t i;
+	size_t j;
 	int amt, count, exists, first, mask, mode, ofd, omode;
 	off_t size, statbytes;
 	int setimes, targisdir, wrerrno = 0;
@@ -748,7 +750,7 @@
 		targisdir = 1;
 	for (first = 1;; first = 0) {
 		cp = buf;
-		if (atomicio(read, remin, cp, 1) <= 0)
+		if (atomicio(read, remin, cp, 1) != 1)
 			return;
 		if (*cp++ == '\n')
 			SCREWUP("unexpected <newline>");
@@ -902,7 +904,7 @@
 			count += amt;
 			do {
 				j = atomicio(read, remin, cp, amt);
-				if (j <= 0) {
+				if (j == 0) {
 					run_err("%s", j ? strerror(errno) :
 					    "dropped connection");
 					exit(1);
@@ -918,10 +920,10 @@
 			if (count == bp->cnt) {
 				/* Keep reading so we stay sync'd up. */
 				if (wrerr == NO) {
-					j = atomicio(vwrite, ofd, bp->buf, count);
-					if (j != count) {
+					if (atomicio(vwrite, ofd, bp->buf,
+					    count) != count) {
 						wrerr = YES;
-						wrerrno = j >= 0 ? EIO : errno;
+						wrerrno = errno;
 					}
 				}
 				count = 0;
@@ -931,9 +933,9 @@
 		if (showprogress)
 			stop_progress_meter();
 		if (count != 0 && wrerr == NO &&
-		    (j = atomicio(vwrite, ofd, bp->buf, count)) != count) {
+		    atomicio(vwrite, ofd, bp->buf, count) != count) {
 			wrerr = YES;
-			wrerrno = j >= 0 ? EIO : errno;
+			wrerrno = errno;
 		}
 		if (wrerr == NO && ftruncate(ofd, size) != 0) {
 			run_err("%s: truncate: %s", np, strerror(errno));
diff --git a/sftp-client.c b/sftp-client.c
index 92df427..4729789 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -20,7 +20,7 @@
 /* XXX: copy between two remote sites */
 
 #include "includes.h"
-RCSID("$OpenBSD: sftp-client.c,v 1.53 2005/03/10 22:01:05 deraadt Exp $");
+RCSID("$OpenBSD: sftp-client.c,v 1.54 2005/05/24 17:32:44 avsm Exp $");
 
 #include "openbsd-compat/sys-queue.h"
 
@@ -64,10 +64,10 @@
 
 	/* Send length first */
 	PUT_32BIT(mlen, buffer_len(m));
-	if (atomicio(vwrite, fd, mlen, sizeof(mlen)) <= 0)
+	if (atomicio(vwrite, fd, mlen, sizeof(mlen)) != sizeof(mlen))
 		fatal("Couldn't send packet: %s", strerror(errno));
 
-	if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) <= 0)
+	if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) != buffer_len(m))
 		fatal("Couldn't send packet: %s", strerror(errno));
 
 	buffer_clear(m);
@@ -76,26 +76,27 @@
 static void
 get_msg(int fd, Buffer *m)
 {
-	ssize_t len;
 	u_int msg_len;
 
 	buffer_append_space(m, 4);
-	len = atomicio(read, fd, buffer_ptr(m), 4);
-	if (len == 0)
-		fatal("Connection closed");
-	else if (len == -1)
-		fatal("Couldn't read packet: %s", strerror(errno));
+	if (atomicio(read, fd, buffer_ptr(m), 4) != 4) {
+		if (errno == EPIPE)
+			fatal("Connection closed");
+		else
+			fatal("Couldn't read packet: %s", strerror(errno));
+	}
 
 	msg_len = buffer_get_int(m);
 	if (msg_len > MAX_MSG_LENGTH)
 		fatal("Received message too long %u", msg_len);
 
 	buffer_append_space(m, msg_len);
-	len = atomicio(read, fd, buffer_ptr(m), msg_len);
-	if (len == 0)
-		fatal("Connection closed");
-	else if (len == -1)
-		fatal("Read packet: %s", strerror(errno));
+	if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) {
+		if (errno == EPIPE)
+			fatal("Connection closed");
+		else
+			fatal("Read packet: %s", strerror(errno));
+	}
 }
 
 static void
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index fdcfc5b..7dffb85 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -7,7 +7,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh-keyscan.c,v 1.53 2005/04/28 10:17:56 moritz Exp $");
+RCSID("$OpenBSD: ssh-keyscan.c,v 1.54 2005/05/24 17:32:44 avsm Exp $");
 
 #include "openbsd-compat/sys-queue.h"
 
@@ -493,10 +493,10 @@
 static void
 congreet(int s)
 {
-	int remote_major = 0, remote_minor = 0, n = 0;
+	int remote_major = 0, remote_minor = 0;
 	char buf[256], *cp;
 	char remote_version[sizeof buf];
-	size_t bufsiz;
+	size_t bufsiz, n = 0;
 	con *c = &fdcon[s];
 
 	bufsiz = sizeof(buf);
@@ -506,14 +506,17 @@
 			*cp = '\n';
 		cp++;
 	}
-	if (n < 0) {
-		if (errno != ECONNREFUSED)
-			error("read (%s): %s", c->c_name, strerror(errno));
-		conrecycle(s);
-		return;
-	}
 	if (n == 0) {
-		error("%s: Connection closed by remote host", c->c_name);
+		switch (errno) {
+		case EPIPE:
+			error("%s: Connection closed by remote host", c->c_name);
+			break;
+		case ECONNREFUSED:
+			break;
+		default:
+			error("read (%s): %s", c->c_name, strerror(errno));
+			break;
+		}
 		conrecycle(s);
 		return;
 	}
@@ -566,14 +569,14 @@
 conread(int s)
 {
 	con *c = &fdcon[s];
-	int n;
+	size_t n;
 
 	if (c->c_status == CS_CON) {
 		congreet(s);
 		return;
 	}
 	n = atomicio(read, s, c->c_data + c->c_off, c->c_len - c->c_off);
-	if (n < 0) {
+	if (n == 0) {
 		error("read (%s): %s", c->c_name, strerror(errno));
 		confree(s);
 		return;
diff --git a/sshconnect.c b/sshconnect.c
index 07703cf..b79cead 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.162 2005/03/10 22:01:06 deraadt Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.163 2005/05/24 17:32:44 avsm Exp $");
 
 #include <openssl/bn.h>
 
@@ -426,14 +426,15 @@
 	int connection_out = packet_get_connection_out();
 	int minor1 = PROTOCOL_MINOR_1;
 
-	/* Read other side\'s version identification. */
+	/* Read other side's version identification. */
 	for (;;) {
 		for (i = 0; i < sizeof(buf) - 1; i++) {
-			int len = atomicio(read, connection_in, &buf[i], 1);
-			if (len < 0)
-				fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
-			if (len != 1)
+			size_t len = atomicio(read, connection_in, &buf[i], 1);
+
+			if (len != 1 && errno == EPIPE) 
 				fatal("ssh_exchange_identification: Connection closed by remote host");
+			else if (len != 1)
+				fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
 			if (buf[i] == '\r') {
 				buf[i] = '\n';
 				buf[i + 1] = 0;