Update to latest madtty.
[apps/madmutt.git] / lib-sys / mutt_socket.c
index e3874d1..8616440 100644 (file)
@@ -9,60 +9,52 @@
  * please see the file GPL in the top level source directory.
  */
 
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <lib-lib/lib-lib.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
 
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/macros.h>
-#include <lib-lib/debug.h>
+#include <lib-ui/lib-ui.h>
 
 #include "mutt.h"
 #include "globals.h"
+
+#include "unix.h"
 #include "mutt_socket.h"
 #include "mutt_tunnel.h"
-#if defined(USE_SSL) || defined(USE_GNUTLS)
-# include "mutt_ssl.h"
-#endif
+#include "mutt_signal.h"
 
+#ifdef HAVE_LIBIDN
+#include <idna.h>
+#endif
 #include "mutt_idna.h"
 
-
-#include <unistd.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <errno.h>
-
 /* support for multiple socket connections */
 static CONNECTION *Connections = NULL;
 
-/* forward declarations */
-static int socket_preconnect (void);
-static int socket_connect (int fd, struct sockaddr *sa);
-static CONNECTION *socket_new_conn (void);
-
 /* Wrappers */
 int mutt_socket_open (CONNECTION * conn)
 {
-  if (socket_preconnect ())
-    return -1;
+  int rc;
+
+  if (m_strlen(Preconnect)) {
+    rc = mutt_system (Preconnect);
+    if (rc) {
+      mutt_perror (_("Preconnect command failed."));
+      mutt_sleep (1);
+      return -1;
+    }
+  }
 
-  return conn->conn_open (conn);
+  return conn->conn_open(conn);
 }
 
 int mutt_socket_close (CONNECTION * conn)
 {
   int rc = -1;
 
-  if (conn->fd < 0)
-    debug_print (1, ("Attempt to close closed connection.\n"));
-  else
+  if (conn->fd >= 0)
     rc = conn->conn_close (conn);
 
   conn->fd = -1;
@@ -71,12 +63,11 @@ int mutt_socket_close (CONNECTION * conn)
   return rc;
 }
 
-int mutt_socket_read (CONNECTION * conn, char *buf, size_t len)
+int mutt_socket_read (CONNECTION * conn, char *buf, ssize_t len)
 {
   int rc;
 
   if (conn->fd < 0) {
-    debug_print (1, ("attempt to read from closed connection\n"));
     return -1;
   }
 
@@ -92,30 +83,22 @@ int mutt_socket_read (CONNECTION * conn, char *buf, size_t len)
   return rc;
 }
 
-int mutt_socket_write_d (CONNECTION * conn, const char *buf, int dbg)
+int mutt_socket_write(CONNECTION * conn, const char *buf)
 {
   int rc;
   int len;
 
-  debug_print (dbg, ("> %s", buf));
-
   if (conn->fd < 0) {
-    debug_print (1, ("attempt to write to closed connection\n"));
     return -1;
   }
 
   len = m_strlen(buf);
   if ((rc = conn->conn_write (conn, buf, len)) < 0) {
-    debug_print (1, ("error writing, closing socket\n"));
     mutt_socket_close (conn);
 
     return -1;
   }
 
-  if (rc < len) {
-    debug_print (1, ("ERROR: wrote %d of %d bytes!\n", rc, len));
-  }
-
   return rc;
 }
 
@@ -127,7 +110,6 @@ int mutt_socket_readchar (CONNECTION * conn, char *c)
       conn->available =
         conn->conn_read (conn, conn->inbuf, sizeof (conn->inbuf));
     else {
-      debug_print (1, ("attempt to read from closed connection.\n"));
       return -1;
     }
     conn->bufpos = 0;
@@ -145,8 +127,7 @@ int mutt_socket_readchar (CONNECTION * conn, char *c)
   return 1;
 }
 
-int mutt_socket_readln_d (char *buf, ssize_t buflen, CONNECTION * conn,
-                          int dbg)
+int mutt_socket_readln(char *buf, ssize_t buflen, CONNECTION * conn)
 {
   char ch;
   ssize_t i;
@@ -168,12 +149,27 @@ int mutt_socket_readln_d (char *buf, ssize_t buflen, CONNECTION * conn,
   else
     buf[i] = '\0';
 
-  debug_print (dbg, ("< %s\n", buf));
-
   /* number of bytes read, not m_strlen*/
   return i + 1;
 }
 
+int mutt_socket_readln2(buffer_t *buf, CONNECTION *conn)
+{
+    char ch;
+
+    while (mutt_socket_readchar(conn, &ch) == 1) {
+        if (ch == '\n') {
+            if (buf->len && buf->data[buf->len - 1] == '\r') {
+                buf->data[--buf->len] = '\0';
+            }
+            return 0;
+        }
+        buffer_addch(buf, ch);
+    }
+
+    return -1;
+}
+
 CONNECTION *mutt_socket_head (void)
 {
   return Connections;
@@ -213,14 +209,6 @@ void mutt_socket_free (CONNECTION * conn)
 CONNECTION *mutt_conn_find (const CONNECTION * start, const ACCOUNT * account)
 {
   CONNECTION *conn;
-  ciss_url_t url;
-  char hook[LONG_STRING];
-
-  /* account isn't actually modified, since url isn't either */
-  mutt_account_tourl ((ACCOUNT *) account, &url);
-  url.path = NULL;
-  url_ciss_tostring (&url, hook, sizeof (hook), 0);
-  mutt_account_hook (hook);
 
   conn = start ? start->next : Connections;
   while (conn) {
@@ -229,30 +217,20 @@ CONNECTION *mutt_conn_find (const CONNECTION * start, const ACCOUNT * account)
     conn = conn->next;
   }
 
-  conn = socket_new_conn ();
-  memcpy (&conn->account, account, sizeof (ACCOUNT));
-
-  conn->next = Connections;
+  conn = p_new(CONNECTION, 1);
+  conn->fd = -1;
+  conn->account = *account;
+  conn->next  = Connections;
   Connections = conn;
 
   if (Tunnel && *Tunnel)
     mutt_tunnel_socket_setup (conn);
-  else if (account->flags & M_ACCT_SSL) {
-#if defined (USE_SSL) || defined (USE_GNUTLS)
+  else if (account->has_ssl) {
     if (mutt_ssl_socket_setup (conn) < 0) {
       mutt_socket_free (conn);
       return NULL;
     }
-#else
-    mutt_error _("SSL is unavailable.");
-
-    mutt_sleep (2);
-    mutt_socket_free (conn);
-
-    return NULL;
-#endif
-  }
-  else {
+  } else {
     conn->conn_read = raw_socket_read;
     conn->conn_write = raw_socket_write;
     conn->conn_open = raw_socket_open;
@@ -262,27 +240,6 @@ CONNECTION *mutt_conn_find (const CONNECTION * start, const ACCOUNT * account)
   return conn;
 }
 
-static int socket_preconnect (void)
-{
-  int rc;
-  int save_errno;
-
-  if (m_strlen(Preconnect)) {
-    debug_print (2, ("Executing preconnect: %s\n", Preconnect));
-    rc = mutt_system (Preconnect);
-    debug_print (2, ("Preconnect result: %d\n", rc));
-    if (rc) {
-      save_errno = errno;
-      mutt_perror (_("Preconnect command failed."));
-      mutt_sleep (1);
-
-      return save_errno;
-    }
-  }
-
-  return 0;
-}
-
 /* socket_connect: set up to connect to a socket fd. */
 static int socket_connect (int fd, struct sockaddr *sa)
 {
@@ -291,12 +248,9 @@ static int socket_connect (int fd, struct sockaddr *sa)
 
   if (sa->sa_family == AF_INET)
     sa_size = sizeof (struct sockaddr_in);
-#ifdef HAVE_GETADDRINFO
   else if (sa->sa_family == AF_INET6)
     sa_size = sizeof (struct sockaddr_in6);
-#endif
   else {
-    debug_print (1, ("Unknown address family!\n"));
     return -1;
   }
 
@@ -309,7 +263,6 @@ static int socket_connect (int fd, struct sockaddr *sa)
 
   if (connect (fd, sa, sa_size) < 0) {
     save_errno = errno;
-    debug_print (2, ("Connection failed. errno: %d...\n", errno));
     SigInt = 0;                 /* reset in case we caught SIGINTR while in connect() */
   }
 
@@ -320,23 +273,12 @@ static int socket_connect (int fd, struct sockaddr *sa)
   return save_errno;
 }
 
-/* socket_new_conn: allocate and initialise a new connection. */
-static CONNECTION *socket_new_conn (void)
-{
-  CONNECTION *conn;
-
-  conn = p_new(CONNECTION, 1);
-  conn->fd = -1;
-
-  return conn;
-}
-
 int raw_socket_close (CONNECTION * conn)
 {
   return close (conn->fd);
 }
 
-int raw_socket_read (CONNECTION * conn, char *buf, size_t len)
+int raw_socket_read (CONNECTION * conn, char *buf, ssize_t len)
 {
   int rc;
 
@@ -349,7 +291,7 @@ int raw_socket_read (CONNECTION * conn, char *buf, size_t len)
   return rc;
 }
 
-int raw_socket_write (CONNECTION * conn, const char *buf, size_t count)
+int raw_socket_write (CONNECTION * conn, const char *buf, ssize_t count)
 {
   int rc;
 
@@ -369,9 +311,6 @@ int raw_socket_open (CONNECTION * conn)
 
   char *host_idna = NULL;
 
-#ifdef HAVE_GETADDRINFO
-/* --- IPv4/6 --- */
-
   /* "65536\0" */
   char port[6];
   struct addrinfo hints;
@@ -381,11 +320,7 @@ int raw_socket_open (CONNECTION * conn)
   /* we accept v4 or v6 STREAM sockets */
   p_clear(&hints, 1);
 
-  if (option (OPTUSEIPV6))
-    hints.ai_family = AF_UNSPEC;
-  else
-    hints.ai_family = AF_INET;
-
+  hints.ai_family   = AF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
 
   snprintf (port, sizeof (port), "%d", conn->account.port);
@@ -401,7 +336,6 @@ int raw_socket_open (CONNECTION * conn)
 
   mutt_message (_("Looking up %s..."), conn->account.host);
 
-
   rc = getaddrinfo (host_idna, port, &hints, &res);
 
 # ifdef HAVE_LIBIDN
@@ -432,60 +366,6 @@ int raw_socket_open (CONNECTION * conn)
 
   freeaddrinfo (res);
 
-#else
-  /* --- IPv4 only --- */
-
-  struct sockaddr_in sin;
-  struct hostent *he;
-  int i;
-
-  p_clear(&sin, 1);
-  sin.sin_port = htons (conn->account.port);
-  sin.sin_family = AF_INET;
-
-# ifdef HAVE_LIBIDN
-  if (idna_to_ascii_lz (conn->account.host, &host_idna, 1) != IDNA_SUCCESS) {
-    mutt_error (_("Bad IDN \"%s\"."), conn->account.host);
-    return -1;
-  }
-# else
-  host_idna = conn->account.host;
-# endif
-
-  mutt_message (_("Looking up %s..."), conn->account.host);
-
-  if ((he = gethostbyname (host_idna)) == NULL) {
-# ifdef HAVE_LIBIDN
-    p_delete(&host_idna);
-# endif
-    mutt_error (_("Could not find the host \"%s\""), conn->account.host);
-
-    return -1;
-  }
-
-# ifdef HAVE_LIBIDN
-  p_delete(&host_idna);
-# endif
-
-  mutt_message (_("Connecting to %s..."), conn->account.host);
-
-  rc = -1;
-  for (i = 0; he->h_addr_list[i] != NULL; i++) {
-    memcpy (&sin.sin_addr, he->h_addr_list[i], he->h_length);
-    fd = socket (PF_INET, SOCK_STREAM, IPPROTO_IP);
-
-    if (fd >= 0) {
-      if ((rc = socket_connect (fd, (struct sockaddr *) &sin)) == 0) {
-        fcntl (fd, F_SETFD, FD_CLOEXEC);
-        conn->fd = fd;
-        break;
-      }
-      else
-        close (fd);
-    }
-  }
-
-#endif
   if (rc) {
     mutt_error (_("Could not connect to %s (%s)."), conn->account.host,
                 (rc > 0) ? strerror (rc) : _("unknown error"));