* 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 <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>
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/macros.h>
+#include <lib-ui/lib-ui.h>
#include "mutt.h"
#include "globals.h"
#include "mutt_socket.h"
#include "mutt_tunnel.h"
#include "mutt_signal.h"
-#include "mutt_ssl.h"
+#ifdef HAVE_LIBIDN
+#include <idna.h>
+#endif
#include "mutt_idna.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;
- return conn->conn_open (conn);
+ 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);
}
int mutt_socket_close (CONNECTION * conn)
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;
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) {
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;
return conn;
}
-static int socket_preconnect (void)
-{
- int rc;
- int save_errno;
-
- if (m_strlen(Preconnect)) {
- rc = mutt_system (Preconnect);
- 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)
{
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 {
return -1;
}
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);
char *host_idna = NULL;
-#ifdef HAVE_GETADDRINFO
-/* --- IPv4/6 --- */
-
/* "65536\0" */
char port[6];
struct addrinfo hints;
/* 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);
mutt_message (_("Looking up %s..."), conn->account.host);
-
rc = getaddrinfo (host_idna, port, &hints, &res);
# ifdef HAVE_LIBIDN
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"));