]> diplodocus.org Git - nmh/blob - sbr/client.c
sendsbr.c: Move interface to own file.
[nmh] / sbr / client.c
1 /* client.c -- connect to a server
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "client.h"
10 #include "h/mts.h"
11 #include "h/utils.h"
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netdb.h>
15 #include <arpa/inet.h>
16 #include <errno.h>
17
18
19 int
20 client (char *server, char *service, char *response, int len_response,
21 int debug)
22 {
23 int sd, rc;
24 struct addrinfo hints, *res, *ai;
25
26 if (!server || *server == '\0') {
27 snprintf(response, len_response, "Internal error: NULL server name "
28 "passed to client()");
29 return NOTOK;
30 }
31
32 ZERO(&hints);
33 #ifdef AI_ADDRCONFIG
34 hints.ai_flags = AI_ADDRCONFIG;
35 #endif
36 hints.ai_family = PF_UNSPEC;
37 hints.ai_socktype = SOCK_STREAM;
38
39 if (debug) {
40 fprintf(stderr, "Trying to connect to \"%s\" ...\n", server);
41 }
42
43 rc = getaddrinfo(server, service, &hints, &res);
44
45 if (rc) {
46 snprintf(response, len_response, "Lookup of \"%s\" failed: %s",
47 server, gai_strerror(rc));
48 return NOTOK;
49 }
50
51 for (ai = res; ai != NULL; ai = ai->ai_next) {
52 if (debug) {
53 char address[NI_MAXHOST];
54 char port[NI_MAXSERV];
55
56 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
57 sizeof(address), port, sizeof port,
58 NI_NUMERICHOST | NI_NUMERICSERV);
59
60 fprintf(stderr, "Connecting to %s:%s...\n",
61 rc ? "unknown" : address, rc ? "--" : port);
62 }
63
64 sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
65
66 if (sd < 0) {
67 if (debug)
68 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
69 rc = errno;
70 continue;
71 }
72
73 if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
74 freeaddrinfo(res);
75 return sd;
76 }
77
78 rc = errno;
79
80 if (debug) {
81 fprintf(stderr, "Connection failed: %s\n", strerror(errno));
82 }
83
84 close(sd);
85 }
86
87 /*
88 * Improve error handling a bit. If we were given multiple IP addresses
89 * then return the old "no servers available" error, but point the user
90 * to -snoop (hopefully that's universal). Otherwise report a specific
91 * error.
92 */
93
94 if (res->ai_next)
95 snprintf(response, len_response, "no servers available (use -snoop "
96 "for details");
97 else
98 snprintf(response, len_response, "Connection to \"%s\" failed: %s",
99 server, strerror(errno));
100
101 freeaddrinfo(res);
102
103 return NOTOK;
104 }