#include "nntp.h"
#include "paths.h"
+/*
+** store an error message in buff like libinn(3) says NNTPconnect does
+*/
+static void store_error(char *buff, const char *string1, const char *string2) {
+ /* we put these in [...] to make it easier to tell them apart
+ * from messages sent by the server */
+ snprintf(buff, NNTP_STRLEN, "[%s%s]", string1, string2);
+ buff[NNTP_STRLEN-1] = 0;
+}
+
/*
** Open a connection to an NNTP server and create stdio FILE's for talking
** to it. Return -1 on error.
int i = -1;
int j;
int oerrno;
+ int gai_r;
FILE *F;
#ifdef HAVE_INET6
struct addrinfo hints, *ressave, *addr;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
sprintf(portbuf, "%d", port);
- if (getaddrinfo(host, portbuf, &hints, &addr) != 0)
+ if ((gai_r = getaddrinfo(host, portbuf, &hints, &addr)) != 0) {
+ store_error(buff, "getaddrinfo failed: ", gai_strerror(gai_r));
+ errno = 0;
return -1;
+ }
for (ressave = addr; addr; addr = addr->ai_next) {
if ((i = socket(addr->ai_family, addr->ai_socktype,
/* all connect(2) calls failed or some other error has occurred */
oerrno = errno;
close(i);
+ store_error(buff, "connect(s) failed: ", strerror(oerrno));
errno = oerrno;
return -1;
}
}
else if ((hp = gethostbyname(host)) != NULL)
ap = hp->h_addr_list;
- else
+ else {
/* Not a host name. */
+ store_error(buff, "gethostbyname failed: ", hstrerror(h_errno));
+ errno = 0;
return -1;
+ }
/* Set up the socket address. */
memset(&server, 0, sizeof server);
client.sin_len = sizeof( struct sockaddr_in );
#endif
if (innconf->sourceaddress) {
- if (!inet_aton(innconf->sourceaddress, &client.sin_addr))
+ if (!inet_aton(innconf->sourceaddress, &client.sin_addr)) {
+ store_error(buff, "inet_aton failed on innconf's"
+ " source address: ", innconf->sourceaddress);
+ errno = EINVAL;
return -1;
+ }
} else
client.sin_addr.s_addr = htonl(INADDR_ANY);
-
+
/* Loop through the address list, trying to connect. */
for (; ap && *ap; ap++) {
/* Make a socket and try to connect. */
- if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
+ if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
+ if (!buff[0]) {
+ oerrno = errno;
+ store_error(buff, "create socket failed: ", strerror(oerrno));
+ errno = oerrno;
+ }
break;
+ }
/* Bind to the source address we want. */
if (bind(i, (struct sockaddr *)&client, sizeof client) < 0) {
oerrno = errno;
close(i);
+ store_error(buff, "bind failed: ", strerror(oerrno));
errno = oerrno;
continue;
}
if (connect(i, (struct sockaddr *)&server, sizeof server) < 0) {
oerrno = errno;
close(i);
+ store_error(buff, "connect failed: ", strerror(oerrno));
errno = oerrno;
continue;
}
oerrno = errno;
close(i);
errno = oerrno;
+ store_error(buff, "fdopen failed: ", strerror(oerrno));
+ errno = EINVAL;
return -1;
}
if (fgets(buff, sizeof mybuff, F) == NULL) {
+ if (!ferror(F)) store_error(buff, "peer closed connection","");
+ else store_error(buff, "fgets failed: ", strerror(errno));
oerrno = errno;
fclose(F);
errno = oerrno;
if ((*ToServerp = fdopen(dup(i), "w")) == NULL) {
oerrno = errno;
fclose(F);
+ store_error(buff, "fdopen/dup failed: ", strerror(oerrno));
errno = oerrno;
return -1;
}
return 0;
}
+ if (!buff[0])
+ store_error(buff, "no address(es) for host","");
+
return -1;
}