]> granicus.if.org Git - neomutt/commitdiff
Fix raw socket read/write to follow expected behavior
authorKevin McCarthy <kevin@8t8.us>
Mon, 21 Jan 2019 23:19:08 +0000 (15:19 -0800)
committerRichard Russon <rich@flatcap.org>
Tue, 9 Apr 2019 11:54:27 +0000 (12:54 +0100)
The mutt_sasl.c code expects conn_write() to write the entire buffer.
This is inconsistent with mutt_socket.c, but since other conn_write()
implementations guarantee this, change raw_socket_write() to do so too
for now.

Also, update reading and writing to loop on EINTR, as gnutls does.
They won't return EAGAIN or EWOULDBLOCK because we don't mark sockets
as non-blocking.

Co-authored-by: Richard Russon <rich@flatcap.org>
conn/conn_raw.c

index 40206a389e4c029b9a34f7d989a09cb72dfcc751..e85b13068fe58206a320d5eff564da73c7161865 100644 (file)
@@ -267,8 +267,12 @@ int raw_socket_read(struct Connection *conn, char *buf, size_t count)
   int rc;
 
   mutt_sig_allow_interrupt(1);
-  rc = read(conn->fd, buf, count);
-  if (rc == -1)
+  do
+  {
+    rc = read(conn->fd, buf, count);
+  } while (rc < 0 && (errno == EINTR));
+
+  if (rc < 0)
   {
     mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
     SigInt = 0;
@@ -291,24 +295,28 @@ int raw_socket_read(struct Connection *conn, char *buf, size_t count)
 int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
 {
   int rc;
+  size_t sent = 0;
 
   mutt_sig_allow_interrupt(1);
-  rc = write(conn->fd, buf, count);
-  if (rc == -1)
+  do
   {
-    mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
-    SigInt = 0;
-  }
-  mutt_sig_allow_interrupt(0);
+    do
+    {
+      rc = write(conn->fd, buf + sent, count - sent);
+    } while (rc < 0 && (errno == EINTR));
 
-  if (SigInt)
-  {
-    mutt_error(_("Connection to %s has been aborted"), conn->account.host);
-    SigInt = 0;
-    rc = -1;
-  }
+    if (rc < 0)
+    {
+      mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
+      mutt_sig_allow_interrupt(0);
+      return -1;
+    }
 
-  return rc;
+    sent += rc;
+  } while ((sent < count) && (SigInt == 0));
+
+  mutt_sig_allow_interrupt(0);
+  return sent;
 }
 
 /**