summaryrefslogtreecommitdiff
path: root/libfetch/common.c
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2012-07-12 20:56:38 +0200
committerAndreas Baumann <abaumann@yahoo.com>2012-07-12 20:56:38 +0200
commitd255a7489b6a64b1e972f5f7bd0f91a6684ff3b1 (patch)
tree36148265294ee2a407fca5b86a7090805c20aa36 /libfetch/common.c
parentb1e647baf2e1724838e34d25339a3672caf09e14 (diff)
downloadcrawler-d255a7489b6a64b1e972f5f7bd0f91a6684ff3b1.tar.gz
crawler-d255a7489b6a64b1e972f5f7bd0f91a6684ff3b1.tar.bz2
-
Diffstat (limited to 'libfetch/common.c')
-rw-r--r--libfetch/common.c907
1 files changed, 0 insertions, 907 deletions
diff --git a/libfetch/common.c b/libfetch/common.c
deleted file mode 100644
index 425b6de..0000000
--- a/libfetch/common.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*-
- * Copyright (c) 1998-2011 Dag-Erling Smørgrav
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-
-#include <netinet/in.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "fetch.h"
-#include "common.h"
-
-
-/*** Local data **************************************************************/
-
-/*
- * Error messages for resolver errors
- */
-static struct fetcherr netdb_errlist[] = {
-#ifdef EAI_NODATA
- { EAI_NODATA, FETCH_RESOLV, "Host not found" },
-#endif
- { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" },
- { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" },
- { EAI_NONAME, FETCH_RESOLV, "No address record" },
- { -1, FETCH_UNKNOWN, "Unknown resolver error" }
-};
-
-/* End-of-Line */
-static const char ENDL[2] = "\r\n";
-
-
-/*** Error-reporting functions ***********************************************/
-
-/*
- * Map error code to string
- */
-static struct fetcherr *
-fetch_finderr(struct fetcherr *p, int e)
-{
- while (p->num != -1 && p->num != e)
- p++;
- return (p);
-}
-
-/*
- * Set error code
- */
-void
-fetch_seterr(struct fetcherr *p, int e)
-{
- p = fetch_finderr(p, e);
- fetchLastErrCode = p->cat;
- snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string);
-}
-
-/*
- * Set error code according to errno
- */
-void
-fetch_syserr(void)
-{
- switch (errno) {
- case 0:
- fetchLastErrCode = FETCH_OK;
- break;
- case EPERM:
- case EACCES:
- case EROFS:
- case EAUTH:
- case ENEEDAUTH:
- fetchLastErrCode = FETCH_AUTH;
- break;
- case ENOENT:
- case EISDIR: /* XXX */
- fetchLastErrCode = FETCH_UNAVAIL;
- break;
- case ENOMEM:
- fetchLastErrCode = FETCH_MEMORY;
- break;
- case EBUSY:
- case EAGAIN:
- fetchLastErrCode = FETCH_TEMP;
- break;
- case EEXIST:
- fetchLastErrCode = FETCH_EXISTS;
- break;
- case ENOSPC:
- fetchLastErrCode = FETCH_FULL;
- break;
- case EADDRINUSE:
- case EADDRNOTAVAIL:
- case ENETDOWN:
- case ENETUNREACH:
- case ENETRESET:
- case EHOSTUNREACH:
- fetchLastErrCode = FETCH_NETWORK;
- break;
- case ECONNABORTED:
- case ECONNRESET:
- fetchLastErrCode = FETCH_ABORT;
- break;
- case ETIMEDOUT:
- fetchLastErrCode = FETCH_TIMEOUT;
- break;
- case ECONNREFUSED:
- case EHOSTDOWN:
- fetchLastErrCode = FETCH_DOWN;
- break;
-default:
- fetchLastErrCode = FETCH_UNKNOWN;
- }
- snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
-}
-
-
-/*
- * Emit status message
- */
-void
-fetch_info(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fputc('\n', stderr);
-}
-
-
-/*** Network-related utility functions ***************************************/
-
-/*
- * Return the default port for a scheme
- */
-int
-fetch_default_port(const char *scheme)
-{
- struct servent *se;
-
- if ((se = getservbyname(scheme, "tcp")) != NULL)
- return (ntohs(se->s_port));
- if (strcasecmp(scheme, SCHEME_FTP) == 0)
- return (FTP_DEFAULT_PORT);
- if (strcasecmp(scheme, SCHEME_HTTP) == 0)
- return (HTTP_DEFAULT_PORT);
- return (0);
-}
-
-/*
- * Return the default proxy port for a scheme
- */
-int
-fetch_default_proxy_port(const char *scheme)
-{
- if (strcasecmp(scheme, SCHEME_FTP) == 0)
- return (FTP_DEFAULT_PROXY_PORT);
- if (strcasecmp(scheme, SCHEME_HTTP) == 0)
- return (HTTP_DEFAULT_PROXY_PORT);
- return (0);
-}
-
-
-/*
- * Create a connection for an existing descriptor.
- */
-conn_t *
-fetch_reopen(int sd)
-{
- conn_t *conn;
- int opt = 1;
-
- /* allocate and fill connection structure */
- if ((conn = calloc(1, sizeof(*conn))) == NULL)
- return (NULL);
- fcntl(sd, F_SETFD, FD_CLOEXEC);
- setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
- conn->sd = sd;
- ++conn->ref;
- return (conn);
-}
-
-
-/*
- * Bump a connection's reference count.
- */
-conn_t *
-fetch_ref(conn_t *conn)
-{
-
- ++conn->ref;
- return (conn);
-}
-
-
-/*
- * Bind a socket to a specific local address
- */
-int
-fetch_bind(int sd, int af, const char *addr)
-{
- struct addrinfo hints, *res, *res0;
- int err;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- if ((err = getaddrinfo(addr, NULL, &hints, &res0)) != 0)
- return (-1);
- for (res = res0; res; res = res->ai_next)
- if (bind(sd, res->ai_addr, res->ai_addrlen) == 0)
- return (0);
- return (-1);
-}
-
-
-/*
- * Establish a TCP connection to the specified port on the specified host.
- */
-conn_t *
-fetch_connect(const char *host, int port, int af, int verbose)
-{
- conn_t *conn;
- char pbuf[10];
- const char *bindaddr;
- struct addrinfo hints, *res, *res0;
- int sd, err;
-
- DEBUG(fprintf(stderr, "---> %s:%d\n", host, port));
-
- if (verbose)
- fetch_info("looking up %s", host);
-
- /* look up host name and set up socket address structure */
- snprintf(pbuf, sizeof(pbuf), "%d", port);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) {
- netdb_seterr(err);
- return (NULL);
- }
- bindaddr = getenv("FETCH_BIND_ADDRESS");
-
- if (verbose)
- fetch_info("connecting to %s:%d", host, port);
-
- /* try to connect */
- for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
- if ((sd = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) == -1)
- continue;
- if (bindaddr != NULL && *bindaddr != '\0' &&
- fetch_bind(sd, res->ai_family, bindaddr) != 0) {
- fetch_info("failed to bind to '%s'", bindaddr);
- close(sd);
- continue;
- }
- if (connect(sd, res->ai_addr, res->ai_addrlen) == 0 &&
- fcntl(sd, F_SETFL, O_NONBLOCK) == 0)
- break;
- close(sd);
- }
- freeaddrinfo(res0);
- if (sd == -1) {
- fetch_syserr();
- return (NULL);
- }
-
- if ((conn = fetch_reopen(sd)) == NULL) {
- fetch_syserr();
- close(sd);
- }
- return (conn);
-}
-
-
-/*
- * Enable SSL on a connection.
- */
-int
-fetch_ssl(conn_t *conn, int verbose)
-{
-#ifdef WITH_SSL
- int ret, ssl_err;
-
- /* Init the SSL library and context */
- if (!SSL_library_init()){
- fprintf(stderr, "SSL library init failed\n");
- return (-1);
- }
-
- SSL_load_error_strings();
-
- conn->ssl_meth = SSLv23_client_method();
- conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth);
- SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY);
-
- conn->ssl = SSL_new(conn->ssl_ctx);
- if (conn->ssl == NULL){
- fprintf(stderr, "SSL context creation failed\n");
- return (-1);
- }
- SSL_set_fd(conn->ssl, conn->sd);
- while ((ret = SSL_connect(conn->ssl)) == -1) {
- ssl_err = SSL_get_error(conn->ssl, ret);
- if (ssl_err != SSL_ERROR_WANT_READ &&
- ssl_err != SSL_ERROR_WANT_WRITE) {
- ERR_print_errors_fp(stderr);
- return (-1);
- }
- }
-
- if (verbose) {
- X509_NAME *name;
- char *str;
-
- fprintf(stderr, "SSL connection established using %s\n",
- SSL_get_cipher(conn->ssl));
- conn->ssl_cert = SSL_get_peer_certificate(conn->ssl);
- name = X509_get_subject_name(conn->ssl_cert);
- str = X509_NAME_oneline(name, 0, 0);
- printf("Certificate subject: %s\n", str);
- free(str);
- name = X509_get_issuer_name(conn->ssl_cert);
- str = X509_NAME_oneline(name, 0, 0);
- printf("Certificate issuer: %s\n", str);
- free(str);
- }
-
- return (0);
-#else
- (void)conn;
- (void)verbose;
- fprintf(stderr, "SSL support disabled\n");
- return (-1);
-#endif
-}
-
-#define FETCH_READ_WAIT -2
-#define FETCH_READ_ERROR -1
-#define FETCH_READ_DONE 0
-
-#ifdef WITH_SSL
-static ssize_t
-fetch_ssl_read(SSL *ssl, char *buf, size_t len)
-{
- ssize_t rlen;
- int ssl_err;
-
- rlen = SSL_read(ssl, buf, len);
- if (rlen < 0) {
- ssl_err = SSL_get_error(ssl, rlen);
- if (ssl_err == SSL_ERROR_WANT_READ ||
- ssl_err == SSL_ERROR_WANT_WRITE) {
- return (FETCH_READ_WAIT);
- } else {
- ERR_print_errors_fp(stderr);
- return (FETCH_READ_ERROR);
- }
- }
- return (rlen);
-}
-#endif
-
-/*
- * Cache some data that was read from a socket but cannot be immediately
- * returned because of an interrupted system call.
- */
-static int
-fetch_cache_data(conn_t *conn, char *src, size_t nbytes)
-{
- char *tmp;
-
- if (conn->cache.size < nbytes) {
- tmp = realloc(conn->cache.buf, nbytes);
- if (tmp == NULL) {
- fetch_syserr();
- return (-1);
- }
- conn->cache.buf = tmp;
- conn->cache.size = nbytes;
- }
-
- memcpy(conn->cache.buf, src, nbytes);
- conn->cache.len = nbytes;
- conn->cache.pos = 0;
-
- return (0);
-}
-
-
-static ssize_t
-fetch_socket_read(int sd, char *buf, size_t len)
-{
- ssize_t rlen;
-
- rlen = read(sd, buf, len);
- if (rlen < 0) {
- if (errno == EAGAIN || (errno == EINTR && fetchRestartCalls))
- return (FETCH_READ_WAIT);
- else
- return (FETCH_READ_ERROR);
- }
- return (rlen);
-}
-
-/*
- * Read a character from a connection w/ timeout
- */
-ssize_t
-fetch_read(conn_t *conn, char *buf, size_t len)
-{
- struct timeval now, timeout, delta;
- fd_set readfds;
- ssize_t rlen, total;
- char *start;
-
- if (fetchTimeout > 0) {
- gettimeofday(&timeout, NULL);
- timeout.tv_sec += fetchTimeout;
- }
-
- total = 0;
- start = buf;
-
- if (conn->cache.len > 0) {
- /*
- * The last invocation of fetch_read was interrupted by a
- * signal after some data had been read from the socket. Copy
- * the cached data into the supplied buffer before trying to
- * read from the socket again.
- */
- total = (conn->cache.len < len) ? conn->cache.len : len;
- memcpy(buf, conn->cache.buf, total);
-
- conn->cache.len -= total;
- conn->cache.pos += total;
- len -= total;
- buf += total;
- }
-
- while (len > 0) {
- /*
- * The socket is non-blocking. Instead of the canonical
- * select() -> read(), we do the following:
- *
- * 1) call read() or SSL_read().
- * 2) if an error occurred, return -1.
- * 3) if we received data but we still expect more,
- * update our counters and loop.
- * 4) if read() or SSL_read() signaled EOF, return.
- * 5) if we did not receive any data but we're not at EOF,
- * call select().
- *
- * In the SSL case, this is necessary because if we
- * receive a close notification, we have to call
- * SSL_read() one additional time after we've read
- * everything we received.
- *
- * In the non-SSL case, it may improve performance (very
- * slightly) when reading small amounts of data.
- */
-#ifdef WITH_SSL
- if (conn->ssl != NULL)
- rlen = fetch_ssl_read(conn->ssl, buf, len);
- else
-#endif
- rlen = fetch_socket_read(conn->sd, buf, len);
- if (rlen == 0) {
- break;
- } else if (rlen > 0) {
- len -= rlen;
- buf += rlen;
- total += rlen;
- continue;
- } else if (rlen == FETCH_READ_ERROR) {
- if (errno == EINTR)
- fetch_cache_data(conn, start, total);
- return (-1);
- }
- // assert(rlen == FETCH_READ_WAIT);
- FD_ZERO(&readfds);
- while (!FD_ISSET(conn->sd, &readfds)) {
- FD_SET(conn->sd, &readfds);
- if (fetchTimeout > 0) {
- gettimeofday(&now, NULL);
- if (!timercmp(&timeout, &now, >)) {
- errno = ETIMEDOUT;
- fetch_syserr();
- return (-1);
- }
- timersub(&timeout, &now, &delta);
- }
- errno = 0;
- if (select(conn->sd + 1, &readfds, NULL, NULL,
- fetchTimeout > 0 ? &delta : NULL) < 0) {
- if (errno == EINTR) {
- if (fetchRestartCalls)
- continue;
- /* Save anything that was read. */
- fetch_cache_data(conn, start, total);
- }
- fetch_syserr();
- return (-1);
- }
- }
- }
- return (total);
-}
-
-
-/*
- * Read a line of text from a connection w/ timeout
- */
-#define MIN_BUF_SIZE 1024
-
-int
-fetch_getln(conn_t *conn)
-{
- char *tmp;
- size_t tmpsize;
- ssize_t len;
- char c;
-
- if (conn->buf == NULL) {
- if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
- errno = ENOMEM;
- return (-1);
- }
- conn->bufsize = MIN_BUF_SIZE;
- }
-
- conn->buf[0] = '\0';
- conn->buflen = 0;
-
- do {
- len = fetch_read(conn, &c, 1);
- if (len == -1)
- return (-1);
- if (len == 0)
- break;
- conn->buf[conn->buflen++] = c;
- if (conn->buflen == conn->bufsize) {
- tmp = conn->buf;
- tmpsize = conn->bufsize * 2 + 1;
- if ((tmp = realloc(tmp, tmpsize)) == NULL) {
- errno = ENOMEM;
- return (-1);
- }
- conn->buf = tmp;
- conn->bufsize = tmpsize;
- }
- } while (c != '\n');
-
- conn->buf[conn->buflen] = '\0';
- DEBUG(fprintf(stderr, "<<< %s", conn->buf));
- return (0);
-}
-
-
-/*
- * Write to a connection w/ timeout
- */
-ssize_t
-fetch_write(conn_t *conn, const char *buf, size_t len)
-{
- struct iovec iov;
-
- iov.iov_base = __DECONST(char *, buf);
- iov.iov_len = len;
- return fetch_writev(conn, &iov, 1);
-}
-
-/*
- * Write a vector to a connection w/ timeout
- * Note: can modify the iovec.
- */
-ssize_t
-fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
-{
- struct timeval now, timeout, delta;
- fd_set writefds;
- ssize_t wlen, total;
- int r;
-
- if (fetchTimeout) {
- FD_ZERO(&writefds);
- gettimeofday(&timeout, NULL);
- timeout.tv_sec += fetchTimeout;
- }
-
- total = 0;
- while (iovcnt > 0) {
- while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) {
- FD_SET(conn->sd, &writefds);
- gettimeofday(&now, NULL);
- delta.tv_sec = timeout.tv_sec - now.tv_sec;
- delta.tv_usec = timeout.tv_usec - now.tv_usec;
- if (delta.tv_usec < 0) {
- delta.tv_usec += 1000000;
- delta.tv_sec--;
- }
- if (delta.tv_sec < 0) {
- errno = ETIMEDOUT;
- fetch_syserr();
- return (-1);
- }
- errno = 0;
- r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
- if (r == -1) {
- if (errno == EINTR && fetchRestartCalls)
- continue;
- return (-1);
- }
- }
- errno = 0;
-#ifdef WITH_SSL
- if (conn->ssl != NULL)
- wlen = SSL_write(conn->ssl,
- iov->iov_base, iov->iov_len);
- else
-#endif
- wlen = writev(conn->sd, iov, iovcnt);
- if (wlen == 0) {
- /* we consider a short write a failure */
- /* XXX perhaps we shouldn't in the SSL case */
- errno = EPIPE;
- fetch_syserr();
- return (-1);
- }
- if (wlen < 0) {
- if (errno == EINTR && fetchRestartCalls)
- continue;
- return (-1);
- }
- total += wlen;
- while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) {
- wlen -= iov->iov_len;
- iov++;
- iovcnt--;
- }
- if (iovcnt > 0) {
- iov->iov_len -= wlen;
- iov->iov_base = __DECONST(char *, iov->iov_base) + wlen;
- }
- }
- return (total);
-}
-
-
-/*
- * Write a line of text to a connection w/ timeout
- */
-int
-fetch_putln(conn_t *conn, const char *str, size_t len)
-{
- struct iovec iov[2];
- int ret;
-
- DEBUG(fprintf(stderr, ">>> %s\n", str));
- iov[0].iov_base = __DECONST(char *, str);
- iov[0].iov_len = len;
- iov[1].iov_base = __DECONST(char *, ENDL);
- iov[1].iov_len = sizeof(ENDL);
- if (len == 0)
- ret = fetch_writev(conn, &iov[1], 1);
- else
- ret = fetch_writev(conn, iov, 2);
- if (ret == -1)
- return (-1);
- return (0);
-}
-
-
-/*
- * Close connection
- */
-int
-fetch_close(conn_t *conn)
-{
- int ret;
-
- if (--conn->ref > 0)
- return (0);
- ret = close(conn->sd);
- free(conn->cache.buf);
- free(conn->buf);
- free(conn);
- return (ret);
-}
-
-
-/*** Directory-related utility functions *************************************/
-
-int
-fetch_add_entry(struct url_ent **p, int *size, int *len,
- const char *name, struct url_stat *us)
-{
- struct url_ent *tmp;
-
- if (*p == NULL) {
- *size = 0;
- *len = 0;
- }
-
- if (*len >= *size - 1) {
- tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p));
- if (tmp == NULL) {
- errno = ENOMEM;
- fetch_syserr();
- return (-1);
- }
- *size = (*size * 2 + 1);
- *p = tmp;
- }
-
- tmp = *p + *len;
- snprintf(tmp->name, PATH_MAX, "%s", name);
- memcpy(&tmp->stat, us, sizeof(*us));
-
- (*len)++;
- (++tmp)->name[0] = 0;
-
- return (0);
-}
-
-
-/*** Authentication-related utility functions ********************************/
-
-static const char *
-fetch_read_word(FILE *f)
-{
- static char word[1024];
-
- if (fscanf(f, " %1023s ", word) != 1)
- return (NULL);
- return (word);
-}
-
-/*
- * Get authentication data for a URL from .netrc
- */
-int
-fetch_netrc_auth(struct url *url)
-{
- char fn[PATH_MAX];
- const char *word;
- char *p;
- FILE *f;
-
- if ((p = getenv("NETRC")) != NULL) {
- if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
- fetch_info("$NETRC specifies a file name "
- "longer than PATH_MAX");
- return (-1);
- }
- } else {
- if ((p = getenv("HOME")) != NULL) {
- struct passwd *pwd;
-
- if ((pwd = getpwuid(getuid())) == NULL ||
- (p = pwd->pw_dir) == NULL)
- return (-1);
- }
- if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn))
- return (-1);
- }
-
- if ((f = fopen(fn, "r")) == NULL)
- return (-1);
- while ((word = fetch_read_word(f)) != NULL) {
- if (strcmp(word, "default") == 0) {
- DEBUG(fetch_info("Using default .netrc settings"));
- break;
- }
- if (strcmp(word, "machine") == 0 &&
- (word = fetch_read_word(f)) != NULL &&
- strcasecmp(word, url->host) == 0) {
- DEBUG(fetch_info("Using .netrc settings for %s", word));
- break;
- }
- }
- if (word == NULL)
- goto ferr;
- while ((word = fetch_read_word(f)) != NULL) {
- if (strcmp(word, "login") == 0) {
- if ((word = fetch_read_word(f)) == NULL)
- goto ferr;
- if (snprintf(url->user, sizeof(url->user),
- "%s", word) > (int)sizeof(url->user)) {
- fetch_info("login name in .netrc is too long");
- url->user[0] = '\0';
- }
- } else if (strcmp(word, "password") == 0) {
- if ((word = fetch_read_word(f)) == NULL)
- goto ferr;
- if (snprintf(url->pwd, sizeof(url->pwd),
- "%s", word) > (int)sizeof(url->pwd)) {
- fetch_info("password in .netrc is too long");
- url->pwd[0] = '\0';
- }
- } else if (strcmp(word, "account") == 0) {
- if ((word = fetch_read_word(f)) == NULL)
- goto ferr;
- /* XXX not supported! */
- } else {
- break;
- }
- }
- fclose(f);
- return (0);
- ferr:
- fclose(f);
- return (-1);
-}
-
-/*
- * The no_proxy environment variable specifies a set of domains for
- * which the proxy should not be consulted; the contents is a comma-,
- * or space-separated list of domain names. A single asterisk will
- * override all proxy variables and no transactions will be proxied
- * (for compatability with lynx and curl, see the discussion at
- * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
- */
-int
-fetch_no_proxy_match(const char *host)
-{
- const char *no_proxy, *p, *q;
- size_t h_len, d_len;
-
- if ((no_proxy = getenv("NO_PROXY")) == NULL &&
- (no_proxy = getenv("no_proxy")) == NULL)
- return (0);
-
- /* asterisk matches any hostname */
- if (strcmp(no_proxy, "*") == 0)
- return (1);
-
- h_len = strlen(host);
- p = no_proxy;
- do {
- /* position p at the beginning of a domain suffix */
- while (*p == ',' || isspace((unsigned char)*p))
- p++;
-
- /* position q at the first separator character */
- for (q = p; *q; ++q)
- if (*q == ',' || isspace((unsigned char)*q))
- break;
-
- d_len = q - p;
- if (d_len > 0 && h_len >= d_len &&
- strncasecmp(host + h_len - d_len,
- p, d_len) == 0) {
- /* domain name matches */
- return (1);
- }
-
- p = q + 1;
- } while (*q);
-
- return (0);
-}