#include <memory.h>
#endif /* HAVE_MEMORY_H */
#include <sys/types.h>
+#ifndef HAVE_NET_SOCKET_H
#include <sys/socket.h>
+#else
+#include <net/socket.h>
+#endif
#include <netinet/in.h>
+#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
+#endif
#include <netdb.h>
#if defined(STDC_HEADERS)
#include <stdlib.h>
#include "fetchmail.h"
#include "i18n.h"
+/* Defines to allow BeOS to play nice... */
+#ifdef __BEOS__
+static char peeked;
+#define fm_close(a) closesocket(a)
+#define fm_write(a,b,c) send(a,b,c,0)
+#define fm_peek(a,b,c) recv(a,b,c,0)
+#define fm_read(a,b,c) recv(a,b,c,0)
+#else
+#define fm_close(a) close(a)
+#define fm_write(a,b,c) write(a,b,c)
+#define fm_peek(a,b,c) recv(a,b,c, MSG_PEEK)
+#define fm_read(a,b,c) read(a,b,c)
+#endif
+
/* We need to define h_errno only if it is not already */
#ifndef h_errno
int SockOpen(const char *host, const char *service, const char *options,
const char *plugin)
{
- struct addrinfo *ai, req;
+ struct addrinfo *ai, *ai0, req;
int i;
#if NET_SECURITY
void *request = NULL;
int requestlen;
#endif /* NET_SECURITY */
- int i;
#ifdef HAVE_SOCKETPAIR
if (plugin)
memset(&req, 0, sizeof(struct addrinfo));
req.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(host, service, &req, &ai)) {
+ if (getaddrinfo(host, service, &req, &ai0)) {
report(stderr, _("fetchmail: getaddrinfo(%s.%s)\n"), host,service);
return -1;
- };
+ }
#if NET_SECURITY
if (!options)
if (net_security_strtorequest((char *)options, &request, &requestlen))
goto ret;
- i = inner_connect(ai, request, requestlen, NULL, NULL, "fetchmail", NULL);
+ i = inner_connect(ai0, request, requestlen, NULL, NULL, "fetchmail", NULL);
if (request)
free(request);
ret:
#else /* NET_SECURITY */
- i = inner_connect(ai, NULL, 0, NULL, NULL, "fetchmail", NULL);
+#ifdef HAVE_INNER_CONNECT
+ i = inner_connect(ai0, NULL, 0, NULL, NULL, "fetchmail", NULL);
+ if (i >= 0)
+ break;
+#else
+ i = -1;
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ i = socket(ai->ai_family, ai->ai_socktype, 0);
+ if (i < 0)
+ continue;
+ if (connect(i, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) {
+ fm_close(i);
+ i = -1;
+ continue;
+ }
+ break;
+ }
+#endif
#endif /* NET_SECURITY */
- freeaddrinfo(ai);
+ freeaddrinfo(ai0);
return i;
-};
+}
#else /* INET6_ENABLE */
#ifndef HAVE_INET_ATON
#ifndef INADDR_NONE
if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0)
{
int olderr = errno;
- close(sock);
+ fm_close(sock); /* don't use SockClose, no traffic yet */
h_errno = 0;
errno = olderr;
return -1;
memcpy(&ad.sin_addr, *pptr, sizeof(struct in_addr));
if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) == 0)
break; /* success */
- close(sock);
+ fm_close(sock); /* don't use SockClose, no traffic yet */
memset(&ad, 0, sizeof(ad));
ad.sin_family = AF_INET;
}
if(*pptr == NULL)
{
int olderr = errno;
- close(sock);
+ fm_close(sock); /* don't use SockClose, no traffic yet */
h_errno = 0;
errno = olderr;
return -1;
}
}
+
return(sock);
}
#endif /* INET6_ENABLE */
if( NULL != ( ssl = SSLGetContext( sock ) ) )
n = SSL_write(ssl, buf, len);
else
- n = write(sock, buf, len);
+ n = fm_write(sock, buf, len);
#else
- n = write(sock, buf, len);
+ n = fm_write(sock, buf, len);
#endif
if (n <= 0)
return -1;
if (--len < 1)
return(-1);
+#ifdef __BEOS__
+ if (peeked != 0){
+ (*bp) = peeked;
+ bp++;
+ len--;
+ peeked = 0;
+ }
+#endif
do {
/*
* The reason for these gymnastics is that we want two things:
newline = bp;
}
} else {
- if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
+ if ((n = fm_peek(sock, bp, len)) <= 0)
return(-1);
if ((newline = memchr(bp, '\n', n)) != NULL)
n = newline - bp + 1;
- if ((n = read(sock, bp, n)) == -1)
+ if ((n = fm_read(sock, bp, n)) == -1)
return(-1);
}
#else
- if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
- return(-1);
+
+#ifdef __BEOS__
+ if ((n = fm_read(sock, bp, 1)) <= 0)
+#else
+ if ((n = fm_peek(sock, bp, len)) <= 0)
+#endif
+ return (-1);
if ((newline = memchr(bp, '\n', n)) != NULL)
n = newline - bp + 1;
- if ((n = read(sock, bp, n)) == -1)
+#ifndef __BEOS__
+ if ((n = fm_read(sock, bp, n)) == -1)
return(-1);
+#endif /* __BEOS__ */
#endif
bp += n;
len -= n;
return 0; /* Give him a '\0' character */
}
} else {
- n = recv(sock, &ch, 1, MSG_PEEK);
+ n = fm_peek(sock, &ch, 1);
}
#else
- n = recv(sock, &ch, 1, MSG_PEEK);
-#endif
+
+ n = fm_peek(sock, &ch, 1);
+
+#endif /* SSL_ENABLE */
if (n == -1)
return -1;
- else
- return(ch);
+
+#ifdef __BEOS__
+ peeked = ch;
+#endif
+ return(ch);
}
#ifdef SSL_ENABLE
*str_ptr = '\0';
}
if (outlevel == O_VERBOSE)
- report(stdout, "Issuer Organization: %s", cbuf );
+ report(stdout, "Issuer Organization: %s\n", cbuf );
} else {
if (outlevel == O_VERBOSE)
- report(stdout, "Unknown Organization", cbuf );
+ report(stdout, "Unknown Organization\n", cbuf );
}
if( ( str_ptr = strstr( ibuf, "/CN=" ) ) ) {
str_ptr += 4;
*str_ptr = '\0';
}
if (outlevel == O_VERBOSE)
- report(stdout, "Issuer CommonName: %s", cbuf );
+ report(stdout, "Issuer CommonName: %s\n", cbuf );
} else {
if (outlevel == O_VERBOSE)
- report(stdout, "Unknown Issuer CommonName", cbuf );
+ report(stdout, "Unknown Issuer CommonName\n", cbuf );
}
if( ( str_ptr = strstr( buf, "/CN=" ) ) ) {
str_ptr += 4;
*str_ptr = '\0';
}
if (outlevel == O_VERBOSE)
- report(stdout, "Server CommonName: %s", cbuf );
+ report(stdout, "Server CommonName: %s\n", cbuf );
/* Should we have some wildcarding here? */
- if ( NULL != _ssl_server_cname && 0 != strcmp( cbuf, _ssl_server_cname ) ) {
- report(stdout, "Server CommonName mismatch: %s != %s", cbuf, _ssl_server_cname );
+ if ( NULL != _ssl_server_cname
+ && 0 != strcasemp( cbuf, _ssl_server_cname ) ) {
+ report(stdout,
+ "Server CommonName mismatch: %s != %s\n",
+ cbuf, _ssl_server_cname );
}
} else {
if (outlevel == O_VERBOSE)
- report(stdout, "Unknown Server CommonName", cbuf );
+ report(stdout, "Unknown Server CommonName\n", cbuf );
}
}
#endif
int SockClose(int sock)
-/* close a socket (someday we may do other cleanup here) */
+/* close a socket gracefully */
{
+ char ch;
#ifdef SSL_ENABLE
SSL *ssl;
_ssl_context[sock] = NULL;
}
#endif
- return(close(sock));
+
+#ifdef __UNUSED__
+ /*
+ * This hangs in RedHat 6.2 after fetchmail runs for a while a
+ * FIN_WAIT2 comes up in netstat and fetchmail never returns from
+ * the recv system call. (Reported from jtnews
+ * <jtnews@bellatlantic.net>, Wed, 24 May 2000 21:26:02.)
+ *
+ * Half-close the connection first so the other end gets notified.
+ *
+ * This stops sends but allows receives (effectively, it sends a
+ * TCP <FIN>). */
+ if (shutdown(sock, 1) == 0) {
+ /* If there is any data still waiting in the queue, discard it.
+ * Call recv() until either it returns 0 (meaning we received a FIN)
+ * or any error occurs. This makes sure all data sent by the other
+ * side is acknowledged at the TCP level.
+ */
+ if (fm_peek(sock, &ch, 1) > 0)
+ while (fm_read(sock, &ch, 1) > 0)
+ continue;
+ }
+#endif /* __UNUSED__ */
+
+ /* if there's an error closing at this point, not much we can do */
+ return(fm_close(sock)); /* this is guarded */
}
#ifdef MAIN
/*
* Use the chargen service to test input buffering directly.
* You may have to uncomment the `chargen' service description in your
- * inetd.conf (and then SIGHUP inetd) for this to work.
- */
+ * inetd.conf (and then SIGHUP inetd) for this to work. */
main()
{
int sock = SockOpen("localhost", 19, NULL);