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