]> diplodocus.org Git - nmh/blob - sbr/client.c
pending-release-notes: add mhshow's "-prefer", and mh-format's %(kibi/kilo)
[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
18 #define MAXARGS 1000
19
20 /*
21 * static prototypes
22 */
23
24 /* client's own static version of several nmh subroutines */
25 static char **client_brkstring (char *, char *, char *);
26 static int client_brkany (char, char *);
27 static char **client_copyip (char **, char **, int);
28 static char *client_getcpy (char *);
29 static void client_freelist(char **);
30
31
32 int
33 client (char *args, char *service, char *response, int len_response, int debug)
34 {
35 int sd, rc;
36 char **ap, *arguments[MAXARGS];
37 struct addrinfo hints, *res, *ai;
38
39 ap = arguments;
40 if (args != NULL && *args != 0) {
41 ap = client_copyip (client_brkstring (client_getcpy (args), " ", "\n"),
42 ap, MAXARGS);
43 } else {
44 if (servers != NULL && *servers != 0)
45 ap = client_copyip (client_brkstring (client_getcpy (servers), " ", "\n"),
46 ap, MAXARGS);
47 }
48 if (ap == arguments) {
49 *ap++ = client_getcpy ("localhost");
50 *ap = NULL;
51 }
52
53 memset(&hints, 0, sizeof(hints));
54 #ifdef AI_ADDRCONFIG
55 hints.ai_flags = AI_ADDRCONFIG;
56 #endif
57 hints.ai_family = PF_UNSPEC;
58 hints.ai_socktype = SOCK_STREAM;
59
60 for (ap = arguments; *ap; ap++) {
61
62 if (debug) {
63 fprintf(stderr, "Trying to connect to \"%s\" ...\n", *ap);
64 }
65
66 rc = getaddrinfo(*ap, service, &hints, &res);
67
68 if (rc) {
69 if (debug) {
70 fprintf(stderr, "Lookup of \"%s\" failed: %s\n", *ap,
71 gai_strerror(rc));
72 }
73 continue;
74 }
75
76 for (ai = res; ai != NULL; ai = ai->ai_next) {
77 if (debug) {
78 char address[NI_MAXHOST];
79 char port[NI_MAXSERV];
80
81 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
82 sizeof(address), port, sizeof port,
83 NI_NUMERICHOST | NI_NUMERICSERV);
84
85 fprintf(stderr, "Connecting to %s:%s...\n",
86 rc ? "unknown" : address,
87 rc ? "--" : port);
88 }
89
90 sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
91
92 if (sd < 0) {
93 if (debug)
94 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
95 continue;
96 }
97
98 if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
99 freeaddrinfo(res);
100 client_freelist(arguments);
101 return sd;
102 }
103
104 if (debug) {
105 fprintf(stderr, "Connection failed: %s\n", strerror(errno));
106 }
107
108 close(sd);
109 }
110
111 freeaddrinfo(res);
112 }
113
114 client_freelist(arguments);
115 strncpy (response, "no servers available", len_response);
116 return NOTOK;
117 }
118
119
120 /*
121 * Free a list of strings
122 */
123
124 static void
125 client_freelist(char **list)
126 {
127 free(*list);
128 }
129
130
131 /*
132 * static copies of three nmh subroutines
133 */
134
135 static char *broken[MAXARGS + 1];
136
137 static char **
138 client_brkstring (char *strg, char *brksep, char *brkterm)
139 {
140 register int bi;
141 register char c, *sp;
142
143 sp = strg;
144
145 for (bi = 0; bi < MAXARGS; bi++) {
146 while (client_brkany (c = *sp, brksep))
147 *sp++ = 0;
148 if (!c || client_brkany (c, brkterm)) {
149 *sp = 0;
150 broken[bi] = 0;
151 return broken;
152 }
153
154 broken[bi] = sp;
155 while ((c = *++sp) && !client_brkany (c, brksep) && !client_brkany (c, brkterm))
156 continue;
157 }
158 broken[MAXARGS] = 0;
159
160 return broken;
161 }
162
163
164 /*
165 * returns 1 if chr in strg, 0 otherwise
166 */
167 static int
168 client_brkany (char chr, char *strg)
169 {
170 register char *sp;
171
172 if (strg)
173 for (sp = strg; *sp; sp++)
174 if (chr == *sp)
175 return 1;
176 return 0;
177 }
178
179
180 /*
181 * copy a string array and return pointer to end
182 */
183 static char **
184 client_copyip (char **p, char **q, int len_q)
185 {
186 while (*p && --len_q > 0)
187 *q++ = *p++;
188
189 *q = NULL;
190
191 return q;
192 }
193
194
195 static char *
196 client_getcpy (char *str)
197 {
198 char *cp;
199 size_t len;
200
201 len = strlen(str) + 1;
202 cp = mh_xmalloc(len);
203
204 memcpy (cp, str, len);
205 return cp;
206 }