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