common.c revision 1.1 1 1.1 agc /*-
2 1.1 agc * Copyright (c) 1998-2004 Dag-Erling Codan Smrgrav
3 1.1 agc * All rights reserved.
4 1.1 agc *
5 1.1 agc * Redistribution and use in source and binary forms, with or without
6 1.1 agc * modification, are permitted provided that the following conditions
7 1.1 agc * are met:
8 1.1 agc * 1. Redistributions of source code must retain the above copyright
9 1.1 agc * notice, this list of conditions and the following disclaimer
10 1.1 agc * in this position and unchanged.
11 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 agc * notice, this list of conditions and the following disclaimer in the
13 1.1 agc * documentation and/or other materials provided with the distribution.
14 1.1 agc * 3. The name of the author may not be used to endorse or promote products
15 1.1 agc * derived from this software without specific prior written permission
16 1.1 agc *
17 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 1.1 agc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 1.1 agc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.1 agc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 1.1 agc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 1.1 agc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 1.1 agc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 1.1 agc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 1.1 agc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 1.1 agc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.1 agc */
28 1.1 agc
29 1.1 agc #include "free2net.h"
30 1.1 agc
31 1.1 agc #include <sys/cdefs.h>
32 1.1 agc __FBSDID("$FreeBSD: src/lib/libfetch/common.c,v 1.48.4.2 2006/11/11 00:16:07 des Exp $");
33 1.1 agc
34 1.1 agc #include <sys/param.h>
35 1.1 agc #include <sys/socket.h>
36 1.1 agc #include <sys/time.h>
37 1.1 agc #include <sys/uio.h>
38 1.1 agc #include <netinet/in.h>
39 1.1 agc
40 1.1 agc #include <errno.h>
41 1.1 agc #include <netdb.h>
42 1.1 agc #include <pwd.h>
43 1.1 agc #include <stdarg.h>
44 1.1 agc #include <stdlib.h>
45 1.1 agc #include <stdio.h>
46 1.1 agc #include <string.h>
47 1.1 agc #include <unistd.h>
48 1.1 agc
49 1.1 agc #include "fetch.h"
50 1.1 agc #include "common.h"
51 1.1 agc
52 1.1 agc
53 1.1 agc /*** Local data **************************************************************/
54 1.1 agc
55 1.1 agc /*
56 1.1 agc * Error messages for resolver errors
57 1.1 agc */
58 1.1 agc static struct fetcherr _netdb_errlist[] = {
59 1.1 agc #ifdef EAI_NODATA
60 1.1 agc { EAI_NODATA, FETCH_RESOLV, "Host not found" },
61 1.1 agc #endif
62 1.1 agc { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" },
63 1.1 agc { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" },
64 1.1 agc { EAI_NONAME, FETCH_RESOLV, "No address record" },
65 1.1 agc { -1, FETCH_UNKNOWN, "Unknown resolver error" }
66 1.1 agc };
67 1.1 agc
68 1.1 agc /* End-of-Line */
69 1.1 agc static const char ENDL[2] = "\r\n";
70 1.1 agc
71 1.1 agc
72 1.1 agc /*** Error-reporting functions ***********************************************/
73 1.1 agc
74 1.1 agc /*
75 1.1 agc * Map error code to string
76 1.1 agc */
77 1.1 agc static struct fetcherr *
78 1.1 agc _fetch_finderr(struct fetcherr *p, int e)
79 1.1 agc {
80 1.1 agc while (p->num != -1 && p->num != e)
81 1.1 agc p++;
82 1.1 agc return (p);
83 1.1 agc }
84 1.1 agc
85 1.1 agc /*
86 1.1 agc * Set error code
87 1.1 agc */
88 1.1 agc void
89 1.1 agc _fetch_seterr(struct fetcherr *p, int e)
90 1.1 agc {
91 1.1 agc p = _fetch_finderr(p, e);
92 1.1 agc fetchLastErrCode = p->cat;
93 1.1 agc snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string);
94 1.1 agc }
95 1.1 agc
96 1.1 agc /*
97 1.1 agc * Set error code according to errno
98 1.1 agc */
99 1.1 agc void
100 1.1 agc _fetch_syserr(void)
101 1.1 agc {
102 1.1 agc switch (errno) {
103 1.1 agc case 0:
104 1.1 agc fetchLastErrCode = FETCH_OK;
105 1.1 agc break;
106 1.1 agc case EPERM:
107 1.1 agc case EACCES:
108 1.1 agc case EROFS:
109 1.1 agc case EAUTH:
110 1.1 agc case ENEEDAUTH:
111 1.1 agc fetchLastErrCode = FETCH_AUTH;
112 1.1 agc break;
113 1.1 agc case ENOENT:
114 1.1 agc case EISDIR: /* XXX */
115 1.1 agc fetchLastErrCode = FETCH_UNAVAIL;
116 1.1 agc break;
117 1.1 agc case ENOMEM:
118 1.1 agc fetchLastErrCode = FETCH_MEMORY;
119 1.1 agc break;
120 1.1 agc case EBUSY:
121 1.1 agc case EAGAIN:
122 1.1 agc fetchLastErrCode = FETCH_TEMP;
123 1.1 agc break;
124 1.1 agc case EEXIST:
125 1.1 agc fetchLastErrCode = FETCH_EXISTS;
126 1.1 agc break;
127 1.1 agc case ENOSPC:
128 1.1 agc fetchLastErrCode = FETCH_FULL;
129 1.1 agc break;
130 1.1 agc case EADDRINUSE:
131 1.1 agc case EADDRNOTAVAIL:
132 1.1 agc case ENETDOWN:
133 1.1 agc case ENETUNREACH:
134 1.1 agc case ENETRESET:
135 1.1 agc case EHOSTUNREACH:
136 1.1 agc fetchLastErrCode = FETCH_NETWORK;
137 1.1 agc break;
138 1.1 agc case ECONNABORTED:
139 1.1 agc case ECONNRESET:
140 1.1 agc fetchLastErrCode = FETCH_ABORT;
141 1.1 agc break;
142 1.1 agc case ETIMEDOUT:
143 1.1 agc fetchLastErrCode = FETCH_TIMEOUT;
144 1.1 agc break;
145 1.1 agc case ECONNREFUSED:
146 1.1 agc case EHOSTDOWN:
147 1.1 agc fetchLastErrCode = FETCH_DOWN;
148 1.1 agc break;
149 1.1 agc default:
150 1.1 agc fetchLastErrCode = FETCH_UNKNOWN;
151 1.1 agc }
152 1.1 agc snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
153 1.1 agc }
154 1.1 agc
155 1.1 agc
156 1.1 agc /*
157 1.1 agc * Emit status message
158 1.1 agc */
159 1.1 agc void
160 1.1 agc _fetch_info(const char *fmt, ...)
161 1.1 agc {
162 1.1 agc va_list ap;
163 1.1 agc
164 1.1 agc va_start(ap, fmt);
165 1.1 agc vfprintf(stderr, fmt, ap);
166 1.1 agc va_end(ap);
167 1.1 agc fputc('\n', stderr);
168 1.1 agc }
169 1.1 agc
170 1.1 agc
171 1.1 agc /*** Network-related utility functions ***************************************/
172 1.1 agc
173 1.1 agc /*
174 1.1 agc * Return the default port for a scheme
175 1.1 agc */
176 1.1 agc int
177 1.1 agc _fetch_default_port(const char *scheme)
178 1.1 agc {
179 1.1 agc struct servent *se;
180 1.1 agc
181 1.1 agc if ((se = getservbyname(scheme, "tcp")) != NULL)
182 1.1 agc return (ntohs(se->s_port));
183 1.1 agc if (strcasecmp(scheme, SCHEME_FTP) == 0)
184 1.1 agc return (FTP_DEFAULT_PORT);
185 1.1 agc if (strcasecmp(scheme, SCHEME_HTTP) == 0)
186 1.1 agc return (HTTP_DEFAULT_PORT);
187 1.1 agc return (0);
188 1.1 agc }
189 1.1 agc
190 1.1 agc /*
191 1.1 agc * Return the default proxy port for a scheme
192 1.1 agc */
193 1.1 agc int
194 1.1 agc _fetch_default_proxy_port(const char *scheme)
195 1.1 agc {
196 1.1 agc if (strcasecmp(scheme, SCHEME_FTP) == 0)
197 1.1 agc return (FTP_DEFAULT_PROXY_PORT);
198 1.1 agc if (strcasecmp(scheme, SCHEME_HTTP) == 0)
199 1.1 agc return (HTTP_DEFAULT_PROXY_PORT);
200 1.1 agc return (0);
201 1.1 agc }
202 1.1 agc
203 1.1 agc
204 1.1 agc /*
205 1.1 agc * Create a connection for an existing descriptor.
206 1.1 agc */
207 1.1 agc conn_t *
208 1.1 agc _fetch_reopen(int sd)
209 1.1 agc {
210 1.1 agc conn_t *conn;
211 1.1 agc
212 1.1 agc /* allocate and fill connection structure */
213 1.1 agc if ((conn = calloc(1, sizeof(*conn))) == NULL)
214 1.1 agc return (NULL);
215 1.1 agc conn->sd = sd;
216 1.1 agc ++conn->ref;
217 1.1 agc return (conn);
218 1.1 agc }
219 1.1 agc
220 1.1 agc
221 1.1 agc /*
222 1.1 agc * Bump a connection's reference count.
223 1.1 agc */
224 1.1 agc conn_t *
225 1.1 agc _fetch_ref(conn_t *conn)
226 1.1 agc {
227 1.1 agc
228 1.1 agc ++conn->ref;
229 1.1 agc return (conn);
230 1.1 agc }
231 1.1 agc
232 1.1 agc
233 1.1 agc /*
234 1.1 agc * Bind a socket to a specific local address
235 1.1 agc */
236 1.1 agc int
237 1.1 agc _fetch_bind(int sd, int af, const char *addr)
238 1.1 agc {
239 1.1 agc struct addrinfo hints, *res, *res0;
240 1.1 agc
241 1.1 agc memset(&hints, 0, sizeof(hints));
242 1.1 agc hints.ai_family = af;
243 1.1 agc hints.ai_socktype = SOCK_STREAM;
244 1.1 agc hints.ai_protocol = 0;
245 1.1 agc if (getaddrinfo(addr, NULL, &hints, &res0) != 0)
246 1.1 agc return (-1);
247 1.1 agc for (res = res0; res; res = res->ai_next)
248 1.1 agc if (bind(sd, res->ai_addr, res->ai_addrlen) == 0)
249 1.1 agc return (0);
250 1.1 agc return (-1);
251 1.1 agc }
252 1.1 agc
253 1.1 agc
254 1.1 agc /*
255 1.1 agc * Establish a TCP connection to the specified port on the specified host.
256 1.1 agc */
257 1.1 agc conn_t *
258 1.1 agc _fetch_connect(const char *host, int port, int af, int verbose)
259 1.1 agc {
260 1.1 agc conn_t *conn;
261 1.1 agc char pbuf[10];
262 1.1 agc const char *bindaddr;
263 1.1 agc struct addrinfo hints, *res, *res0;
264 1.1 agc int sd, err;
265 1.1 agc
266 1.1 agc DEBUG(fprintf(stderr, "---> %s:%d\n", host, port));
267 1.1 agc
268 1.1 agc if (verbose)
269 1.1 agc _fetch_info("looking up %s", host);
270 1.1 agc
271 1.1 agc /* look up host name and set up socket address structure */
272 1.1 agc snprintf(pbuf, sizeof(pbuf), "%d", port);
273 1.1 agc memset(&hints, 0, sizeof(hints));
274 1.1 agc hints.ai_family = af;
275 1.1 agc hints.ai_socktype = SOCK_STREAM;
276 1.1 agc hints.ai_protocol = 0;
277 1.1 agc if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) {
278 1.1 agc _netdb_seterr(err);
279 1.1 agc return (NULL);
280 1.1 agc }
281 1.1 agc bindaddr = getenv("FETCH_BIND_ADDRESS");
282 1.1 agc
283 1.1 agc if (verbose)
284 1.1 agc _fetch_info("connecting to %s:%d", host, port);
285 1.1 agc
286 1.1 agc /* try to connect */
287 1.1 agc for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
288 1.1 agc if ((sd = socket(res->ai_family, res->ai_socktype,
289 1.1 agc res->ai_protocol)) == -1)
290 1.1 agc continue;
291 1.1 agc if (bindaddr != NULL && *bindaddr != '\0' &&
292 1.1 agc _fetch_bind(sd, res->ai_family, bindaddr) != 0) {
293 1.1 agc _fetch_info("failed to bind to '%s'", bindaddr);
294 1.1 agc close(sd);
295 1.1 agc continue;
296 1.1 agc }
297 1.1 agc if (connect(sd, res->ai_addr, res->ai_addrlen) == 0)
298 1.1 agc break;
299 1.1 agc close(sd);
300 1.1 agc }
301 1.1 agc freeaddrinfo(res0);
302 1.1 agc if (sd == -1) {
303 1.1 agc _fetch_syserr();
304 1.1 agc return (NULL);
305 1.1 agc }
306 1.1 agc
307 1.1 agc if ((conn = _fetch_reopen(sd)) == NULL) {
308 1.1 agc _fetch_syserr();
309 1.1 agc close(sd);
310 1.1 agc }
311 1.1 agc return (conn);
312 1.1 agc }
313 1.1 agc
314 1.1 agc
315 1.1 agc /*
316 1.1 agc * Enable SSL on a connection.
317 1.1 agc */
318 1.1 agc int
319 1.1 agc _fetch_ssl(conn_t *conn, int verbose)
320 1.1 agc {
321 1.1 agc
322 1.1 agc #ifdef WITH_SSL
323 1.1 agc /* Init the SSL library and context */
324 1.1 agc if (!SSL_library_init()){
325 1.1 agc fprintf(stderr, "SSL library init failed\n");
326 1.1 agc return (-1);
327 1.1 agc }
328 1.1 agc
329 1.1 agc SSL_load_error_strings();
330 1.1 agc
331 1.1 agc conn->ssl_meth = SSLv23_client_method();
332 1.1 agc conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth);
333 1.1 agc SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY);
334 1.1 agc
335 1.1 agc conn->ssl = SSL_new(conn->ssl_ctx);
336 1.1 agc if (conn->ssl == NULL){
337 1.1 agc fprintf(stderr, "SSL context creation failed\n");
338 1.1 agc return (-1);
339 1.1 agc }
340 1.1 agc SSL_set_fd(conn->ssl, conn->sd);
341 1.1 agc if (SSL_connect(conn->ssl) == -1){
342 1.1 agc ERR_print_errors_fp(stderr);
343 1.1 agc return (-1);
344 1.1 agc }
345 1.1 agc
346 1.1 agc if (verbose) {
347 1.1 agc X509_NAME *name;
348 1.1 agc char *str;
349 1.1 agc
350 1.1 agc fprintf(stderr, "SSL connection established using %s\n",
351 1.1 agc SSL_get_cipher(conn->ssl));
352 1.1 agc conn->ssl_cert = SSL_get_peer_certificate(conn->ssl);
353 1.1 agc name = X509_get_subject_name(conn->ssl_cert);
354 1.1 agc str = X509_NAME_oneline(name, 0, 0);
355 1.1 agc printf("Certificate subject: %s\n", str);
356 1.1 agc free(str);
357 1.1 agc name = X509_get_issuer_name(conn->ssl_cert);
358 1.1 agc str = X509_NAME_oneline(name, 0, 0);
359 1.1 agc printf("Certificate issuer: %s\n", str);
360 1.1 agc free(str);
361 1.1 agc }
362 1.1 agc
363 1.1 agc return (0);
364 1.1 agc #else
365 1.1 agc /* LINTED */
366 1.1 agc (void)conn;
367 1.1 agc /* LINTED */
368 1.1 agc (void)verbose;
369 1.1 agc fprintf(stderr, "SSL support disabled\n");
370 1.1 agc return (-1);
371 1.1 agc #endif
372 1.1 agc }
373 1.1 agc
374 1.1 agc
375 1.1 agc /*
376 1.1 agc * Read a character from a connection w/ timeout
377 1.1 agc */
378 1.1 agc ssize_t
379 1.1 agc _fetch_read(conn_t *conn, char *buf, size_t len)
380 1.1 agc {
381 1.1 agc struct timeval now, timeout, wait;
382 1.1 agc fd_set readfds;
383 1.1 agc ssize_t rlen, total;
384 1.1 agc int r;
385 1.1 agc
386 1.1 agc if (fetchTimeout) {
387 1.1 agc FD_ZERO(&readfds);
388 1.1 agc gettimeofday(&timeout, NULL);
389 1.1 agc timeout.tv_sec += fetchTimeout;
390 1.1 agc }
391 1.1 agc
392 1.1 agc total = 0;
393 1.1 agc while (len > 0) {
394 1.1 agc while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
395 1.1 agc FD_SET(conn->sd, &readfds);
396 1.1 agc gettimeofday(&now, NULL);
397 1.1 agc wait.tv_sec = timeout.tv_sec - now.tv_sec;
398 1.1 agc wait.tv_usec = timeout.tv_usec - now.tv_usec;
399 1.1 agc if (wait.tv_usec < 0) {
400 1.1 agc wait.tv_usec += 1000000;
401 1.1 agc wait.tv_sec--;
402 1.1 agc }
403 1.1 agc if (wait.tv_sec < 0) {
404 1.1 agc errno = ETIMEDOUT;
405 1.1 agc _fetch_syserr();
406 1.1 agc return (-1);
407 1.1 agc }
408 1.1 agc errno = 0;
409 1.1 agc r = select(conn->sd + 1, &readfds, NULL, NULL, &wait);
410 1.1 agc if (r == -1) {
411 1.1 agc if (errno == EINTR && fetchRestartCalls)
412 1.1 agc continue;
413 1.1 agc _fetch_syserr();
414 1.1 agc return (-1);
415 1.1 agc }
416 1.1 agc }
417 1.1 agc #ifdef WITH_SSL
418 1.1 agc if (conn->ssl != NULL)
419 1.1 agc rlen = SSL_read(conn->ssl, buf, len);
420 1.1 agc else
421 1.1 agc #endif
422 1.1 agc rlen = read(conn->sd, buf, len);
423 1.1 agc if (rlen == 0)
424 1.1 agc break;
425 1.1 agc if (rlen < 0) {
426 1.1 agc if (errno == EINTR && fetchRestartCalls)
427 1.1 agc continue;
428 1.1 agc return (-1);
429 1.1 agc }
430 1.1 agc len -= rlen;
431 1.1 agc buf += rlen;
432 1.1 agc total += rlen;
433 1.1 agc }
434 1.1 agc return (total);
435 1.1 agc }
436 1.1 agc
437 1.1 agc
438 1.1 agc /*
439 1.1 agc * Read a line of text from a connection w/ timeout
440 1.1 agc */
441 1.1 agc #define MIN_BUF_SIZE 1024
442 1.1 agc
443 1.1 agc int
444 1.1 agc _fetch_getln(conn_t *conn)
445 1.1 agc {
446 1.1 agc char *tmp;
447 1.1 agc size_t tmpsize;
448 1.1 agc ssize_t len;
449 1.1 agc char c;
450 1.1 agc
451 1.1 agc if (conn->buf == NULL) {
452 1.1 agc if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
453 1.1 agc errno = ENOMEM;
454 1.1 agc return (-1);
455 1.1 agc }
456 1.1 agc conn->bufsize = MIN_BUF_SIZE;
457 1.1 agc }
458 1.1 agc
459 1.1 agc conn->buf[0] = '\0';
460 1.1 agc conn->buflen = 0;
461 1.1 agc
462 1.1 agc do {
463 1.1 agc len = _fetch_read(conn, &c, 1);
464 1.1 agc if (len == -1)
465 1.1 agc return (-1);
466 1.1 agc if (len == 0)
467 1.1 agc break;
468 1.1 agc conn->buf[conn->buflen++] = c;
469 1.1 agc if (conn->buflen == conn->bufsize) {
470 1.1 agc tmp = conn->buf;
471 1.1 agc tmpsize = conn->bufsize * 2 + 1;
472 1.1 agc if ((tmp = realloc(tmp, tmpsize)) == NULL) {
473 1.1 agc errno = ENOMEM;
474 1.1 agc return (-1);
475 1.1 agc }
476 1.1 agc conn->buf = tmp;
477 1.1 agc conn->bufsize = tmpsize;
478 1.1 agc }
479 1.1 agc } while (c != '\n');
480 1.1 agc
481 1.1 agc conn->buf[conn->buflen] = '\0';
482 1.1 agc DEBUG(fprintf(stderr, "<<< %s", conn->buf));
483 1.1 agc return (0);
484 1.1 agc }
485 1.1 agc
486 1.1 agc
487 1.1 agc /*
488 1.1 agc * Write to a connection w/ timeout
489 1.1 agc */
490 1.1 agc ssize_t
491 1.1 agc _fetch_write(conn_t *conn, const char *buf, size_t len)
492 1.1 agc {
493 1.1 agc struct iovec iov;
494 1.1 agc
495 1.1 agc iov.iov_base = __DECONST(char *, buf);
496 1.1 agc iov.iov_len = len;
497 1.1 agc return _fetch_writev(conn, &iov, 1);
498 1.1 agc }
499 1.1 agc
500 1.1 agc /*
501 1.1 agc * Write a vector to a connection w/ timeout
502 1.1 agc * Note: can modify the iovec.
503 1.1 agc */
504 1.1 agc ssize_t
505 1.1 agc _fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
506 1.1 agc {
507 1.1 agc struct timeval now, timeout, wait;
508 1.1 agc fd_set writefds;
509 1.1 agc ssize_t wlen, total;
510 1.1 agc int r;
511 1.1 agc
512 1.1 agc if (fetchTimeout) {
513 1.1 agc FD_ZERO(&writefds);
514 1.1 agc gettimeofday(&timeout, NULL);
515 1.1 agc timeout.tv_sec += fetchTimeout;
516 1.1 agc }
517 1.1 agc
518 1.1 agc total = 0;
519 1.1 agc while (iovcnt > 0) {
520 1.1 agc while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) {
521 1.1 agc FD_SET(conn->sd, &writefds);
522 1.1 agc gettimeofday(&now, NULL);
523 1.1 agc wait.tv_sec = timeout.tv_sec - now.tv_sec;
524 1.1 agc wait.tv_usec = timeout.tv_usec - now.tv_usec;
525 1.1 agc if (wait.tv_usec < 0) {
526 1.1 agc wait.tv_usec += 1000000;
527 1.1 agc wait.tv_sec--;
528 1.1 agc }
529 1.1 agc if (wait.tv_sec < 0) {
530 1.1 agc errno = ETIMEDOUT;
531 1.1 agc _fetch_syserr();
532 1.1 agc return (-1);
533 1.1 agc }
534 1.1 agc errno = 0;
535 1.1 agc r = select(conn->sd + 1, NULL, &writefds, NULL, &wait);
536 1.1 agc if (r == -1) {
537 1.1 agc if (errno == EINTR && fetchRestartCalls)
538 1.1 agc continue;
539 1.1 agc return (-1);
540 1.1 agc }
541 1.1 agc }
542 1.1 agc errno = 0;
543 1.1 agc #ifdef WITH_SSL
544 1.1 agc if (conn->ssl != NULL)
545 1.1 agc wlen = SSL_write(conn->ssl,
546 1.1 agc iov->iov_base, iov->iov_len);
547 1.1 agc else
548 1.1 agc #endif
549 1.1 agc wlen = writev(conn->sd, iov, iovcnt);
550 1.1 agc if (wlen == 0) {
551 1.1 agc /* we consider a short write a failure */
552 1.1 agc errno = EPIPE;
553 1.1 agc _fetch_syserr();
554 1.1 agc return (-1);
555 1.1 agc }
556 1.1 agc if (wlen < 0) {
557 1.1 agc if (errno == EINTR && fetchRestartCalls)
558 1.1 agc continue;
559 1.1 agc return (-1);
560 1.1 agc }
561 1.1 agc total += wlen;
562 1.1 agc while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) {
563 1.1 agc wlen -= iov->iov_len;
564 1.1 agc iov++;
565 1.1 agc iovcnt--;
566 1.1 agc }
567 1.1 agc if (iovcnt > 0) {
568 1.1 agc iov->iov_len -= wlen;
569 1.1 agc iov->iov_base = (char *)(__DECONST(char *, iov->iov_base)) + wlen;
570 1.1 agc }
571 1.1 agc }
572 1.1 agc return (total);
573 1.1 agc }
574 1.1 agc
575 1.1 agc
576 1.1 agc /*
577 1.1 agc * Write a line of text to a connection w/ timeout
578 1.1 agc */
579 1.1 agc int
580 1.1 agc _fetch_putln(conn_t *conn, const char *str, size_t len)
581 1.1 agc {
582 1.1 agc struct iovec iov[2];
583 1.1 agc int ret;
584 1.1 agc
585 1.1 agc DEBUG(fprintf(stderr, ">>> %s\n", str));
586 1.1 agc iov[0].iov_base = __DECONST(char *, str);
587 1.1 agc iov[0].iov_len = len;
588 1.1 agc iov[1].iov_base = __DECONST(char *, ENDL);
589 1.1 agc iov[1].iov_len = sizeof(ENDL);
590 1.1 agc if (len == 0)
591 1.1 agc ret = _fetch_writev(conn, &iov[1], 1);
592 1.1 agc else
593 1.1 agc ret = _fetch_writev(conn, iov, 2);
594 1.1 agc if (ret == -1)
595 1.1 agc return (-1);
596 1.1 agc return (0);
597 1.1 agc }
598 1.1 agc
599 1.1 agc
600 1.1 agc /*
601 1.1 agc * Close connection
602 1.1 agc */
603 1.1 agc int
604 1.1 agc _fetch_close(conn_t *conn)
605 1.1 agc {
606 1.1 agc int ret;
607 1.1 agc
608 1.1 agc if (--conn->ref > 0)
609 1.1 agc return (0);
610 1.1 agc ret = close(conn->sd);
611 1.1 agc free(conn->buf);
612 1.1 agc free(conn);
613 1.1 agc return (ret);
614 1.1 agc }
615 1.1 agc
616 1.1 agc
617 1.1 agc /*** Directory-related utility functions *************************************/
618 1.1 agc
619 1.1 agc int
620 1.1 agc _fetch_add_entry(struct url_ent **p, int *size, int *len,
621 1.1 agc const char *name, struct url_stat *us)
622 1.1 agc {
623 1.1 agc struct url_ent *tmp;
624 1.1 agc
625 1.1 agc if (*p == NULL) {
626 1.1 agc *size = 0;
627 1.1 agc *len = 0;
628 1.1 agc }
629 1.1 agc
630 1.1 agc if (*len >= *size - 1) {
631 1.1 agc tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p));
632 1.1 agc if (tmp == NULL) {
633 1.1 agc errno = ENOMEM;
634 1.1 agc _fetch_syserr();
635 1.1 agc return (-1);
636 1.1 agc }
637 1.1 agc *size = (*size * 2 + 1);
638 1.1 agc *p = tmp;
639 1.1 agc }
640 1.1 agc
641 1.1 agc tmp = *p + *len;
642 1.1 agc snprintf(tmp->name, PATH_MAX, "%s", name);
643 1.1 agc bcopy(us, &tmp->stat, sizeof(*us));
644 1.1 agc
645 1.1 agc (*len)++;
646 1.1 agc (++tmp)->name[0] = 0;
647 1.1 agc
648 1.1 agc return (0);
649 1.1 agc }
650 1.1 agc
651 1.1 agc
652 1.1 agc /*** Authentication-related utility functions ********************************/
653 1.1 agc
654 1.1 agc static const char *
655 1.1 agc _fetch_read_word(FILE *f)
656 1.1 agc {
657 1.1 agc static char word[1024];
658 1.1 agc
659 1.1 agc if (fscanf(f, " %1024s ", word) != 1)
660 1.1 agc return (NULL);
661 1.1 agc return (word);
662 1.1 agc }
663 1.1 agc
664 1.1 agc /*
665 1.1 agc * Get authentication data for a URL from .netrc
666 1.1 agc */
667 1.1 agc int
668 1.1 agc _fetch_netrc_auth(struct url *url)
669 1.1 agc {
670 1.1 agc char fn[PATH_MAX];
671 1.1 agc const char *word;
672 1.1 agc char *p;
673 1.1 agc FILE *f;
674 1.1 agc
675 1.1 agc if ((p = getenv("NETRC")) != NULL) {
676 1.1 agc if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
677 1.1 agc _fetch_info("$NETRC specifies a file name "
678 1.1 agc "longer than PATH_MAX");
679 1.1 agc return (-1);
680 1.1 agc }
681 1.1 agc } else {
682 1.1 agc if ((p = getenv("HOME")) != NULL) {
683 1.1 agc struct passwd *pwd;
684 1.1 agc
685 1.1 agc if ((pwd = getpwuid(getuid())) == NULL ||
686 1.1 agc (p = pwd->pw_dir) == NULL)
687 1.1 agc return (-1);
688 1.1 agc }
689 1.1 agc if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn))
690 1.1 agc return (-1);
691 1.1 agc }
692 1.1 agc
693 1.1 agc if ((f = fopen(fn, "r")) == NULL)
694 1.1 agc return (-1);
695 1.1 agc while ((word = _fetch_read_word(f)) != NULL) {
696 1.1 agc if (strcmp(word, "default") == 0) {
697 1.1 agc DEBUG(_fetch_info("Using default .netrc settings"));
698 1.1 agc break;
699 1.1 agc }
700 1.1 agc if (strcmp(word, "machine") == 0 &&
701 1.1 agc (word = _fetch_read_word(f)) != NULL &&
702 1.1 agc strcasecmp(word, url->host) == 0) {
703 1.1 agc DEBUG(_fetch_info("Using .netrc settings for %s", word));
704 1.1 agc break;
705 1.1 agc }
706 1.1 agc }
707 1.1 agc if (word == NULL)
708 1.1 agc goto ferr;
709 1.1 agc while ((word = _fetch_read_word(f)) != NULL) {
710 1.1 agc if (strcmp(word, "login") == 0) {
711 1.1 agc if ((word = _fetch_read_word(f)) == NULL)
712 1.1 agc goto ferr;
713 1.1 agc if (snprintf(url->user, sizeof(url->user),
714 1.1 agc "%s", word) > (int)sizeof(url->user)) {
715 1.1 agc _fetch_info("login name in .netrc is too long");
716 1.1 agc url->user[0] = '\0';
717 1.1 agc }
718 1.1 agc } else if (strcmp(word, "password") == 0) {
719 1.1 agc if ((word = _fetch_read_word(f)) == NULL)
720 1.1 agc goto ferr;
721 1.1 agc if (snprintf(url->pwd, sizeof(url->pwd),
722 1.1 agc "%s", word) > (int)sizeof(url->pwd)) {
723 1.1 agc _fetch_info("password in .netrc is too long");
724 1.1 agc url->pwd[0] = '\0';
725 1.1 agc }
726 1.1 agc } else if (strcmp(word, "account") == 0) {
727 1.1 agc if ((word = _fetch_read_word(f)) == NULL)
728 1.1 agc goto ferr;
729 1.1 agc /* XXX not supported! */
730 1.1 agc } else {
731 1.1 agc break;
732 1.1 agc }
733 1.1 agc }
734 1.1 agc fclose(f);
735 1.1 agc return (0);
736 1.1 agc ferr:
737 1.1 agc fclose(f);
738 1.1 agc return (-1);
739 1.1 agc }
740