Rearranged whitespace (and comments) in all the code!
[mmh] / sbr / client.c
1 /*
2  * client.c -- connect to a server
3  *
4  * This code is Copyright (c) 2002, by the authors of nmh.  See the
5  * COPYRIGHT file in the root directory of the nmh distribution for
6  * complete copyright information.
7  */
8
9 #include <h/mh.h>
10 #include <h/mts.h>
11 #include <h/utils.h>
12 #include <errno.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netdb.h>
16
17 #ifdef HAVE_ARPA_INET_H
18 # include <arpa/inet.h>
19 #endif
20
21 #define TRUE 1
22 #define FALSE 0
23
24 #define MAXARGS   1000
25
26 /*
27  * static prototypes
28  */
29
30 /* client's own static version of several nmh subroutines */
31 static char **client_brkstring (char *, char *, char *);
32 static int client_brkany (char, char *);
33 static char **client_copyip (char **, char **, int);
34 static char *client_getcpy (char *);
35 static void client_freelist(char **);
36
37
38 int
39 client (char *args, char *service, char *response, int len_response, int debug)
40 {
41         int sd, rc;
42         char **ap, *arguments[MAXARGS];
43         struct addrinfo hints, *res, *ai;
44
45         ap = arguments;
46         if (args != NULL && *args != 0) {
47                 ap = client_copyip (client_brkstring (client_getcpy (args), " ", "\n"),
48                         ap, MAXARGS);
49         }
50         if (ap == arguments) {
51                 *ap++ = client_getcpy ("localhost");
52                 *ap = NULL;
53         }
54
55         memset(&hints, 0, sizeof(hints));
56 #ifdef AI_ADDRCONFIG
57         hints.ai_flags = AI_ADDRCONFIG;
58 #endif
59         hints.ai_family = PF_UNSPEC;
60         hints.ai_socktype = SOCK_STREAM;
61
62         for (ap = arguments; *ap; ap++) {
63
64                 if (debug) {
65                         fprintf(stderr, "Trying to connect to \"%s\" ...\n", *ap);
66                 }
67
68                 rc = getaddrinfo(*ap, service, &hints, &res);
69
70                 if (rc) {
71                         if (debug) {
72                                 fprintf(stderr, "Lookup of \"%s\" failed: %s\n", *ap,
73                                         gai_strerror(rc));
74                         }
75                         continue;
76                 }
77
78                 for (ai = res; ai != NULL; ai = ai->ai_next) {
79                         if (debug) {
80                                 char address[NI_MAXHOST];
81
82                                 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
83                                          sizeof(address), NULL, 0, NI_NUMERICHOST);
84
85                                 fprintf(stderr, "Connecting to %s...\n",
86                                         rc ? "unknown" : address);
87                         }
88
89                         sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
90
91                         if (sd < 0) {
92                                 if (debug)
93                                         fprintf(stderr, "socket() failed: %s\n", strerror(errno));
94                                 continue;
95                         }
96
97                         if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
98                                 freeaddrinfo(res);
99                                 client_freelist(ap);
100                                 return sd;
101                         }
102
103                         if (debug) {
104                                 fprintf(stderr, "Connection failed: %s\n", strerror(errno));
105                         }
106
107                         close(sd);
108                 }
109
110                 freeaddrinfo(res);
111         }
112
113         client_freelist(ap);
114         strncpy (response, "no servers available", len_response);
115         return NOTOK;
116 }
117
118
119 /*
120  * Free a list of strings
121  */
122
123 static void
124 client_freelist(char **list)
125 {
126         while (*list++ != NULL)
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 }
207