common.c revision 40975
140939Sdes/*-
240939Sdes * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav
340939Sdes * All rights reserved.
440939Sdes *
540939Sdes * Redistribution and use in source and binary forms, with or without
640939Sdes * modification, are permitted provided that the following conditions
740939Sdes * are met:
840939Sdes * 1. Redistributions of source code must retain the above copyright
940939Sdes *    notice, this list of conditions and the following disclaimer
1040939Sdes *    in this position and unchanged.
1140939Sdes * 2. Redistributions in binary form must reproduce the above copyright
1240939Sdes *    notice, this list of conditions and the following disclaimer in the
1340939Sdes *    documentation and/or other materials provided with the distribution.
1440939Sdes * 3. The name of the author may not be used to endorse or promote products
1540939Sdes *    derived from this software without specific prior written permission
1640939Sdes *
1740939Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1840939Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1940939Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2040939Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2140939Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2240939Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2340939Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2440939Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2540939Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2640939Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2740939Sdes *
2840975Sdes *	$Id: common.c,v 1.1 1998/11/05 19:48:16 des Exp $
2940939Sdes */
3040939Sdes
3140939Sdes#include <sys/types.h>
3240939Sdes#include <sys/socket.h>
3340939Sdes#include <netinet/in.h>
3440939Sdes
3540975Sdes#include <com_err.h>
3640939Sdes#include <errno.h>
3740939Sdes#include <netdb.h>
3840939Sdes#include <string.h>
3940939Sdes#include <unistd.h>
4040939Sdes
4140939Sdes#include "fetch.h"
4240939Sdes#include "common.h"
4340939Sdes
4440975Sdes
4540939Sdes/*** Local data **************************************************************/
4640939Sdes
4740939Sdes/*
4840939Sdes * Error messages for resolver errors
4940939Sdes */
5040939Sdesstatic struct fetcherr _netdb_errlist[] = {
5140975Sdes    { HOST_NOT_FOUND,	FETCH_RESOLV,	"Host not found" },
5240975Sdes    { TRY_AGAIN,	FETCH_RESOLV,	"Transient resolver failure" },
5340975Sdes    { NO_RECOVERY,	FETCH_RESOLV,	"Non-recoverable resolver failure" },
5440975Sdes    { NO_DATA,		FETCH_RESOLV,	"No address record" },
5540975Sdes    { -1,		FETCH_UNKNOWN,	"Unknown resolver error" }
5640939Sdes};
5740939Sdes
5840975Sdesstatic int com_err_initialized;
5940939Sdes
6040939Sdes/*** Error-reporting functions ***********************************************/
6140939Sdes
6240939Sdes/*
6340975Sdes * Initialize the common error library
6440975Sdes */
6540975Sdesstatic void
6640975Sdes_fetch_init_com_err(void)
6740975Sdes{
6840975Sdes    initialize_ftch_error_table();
6940975Sdes    com_err_initialized = 1;
7040975Sdes}
7140975Sdes
7240975Sdes/*
7340939Sdes * Map error code to string
7440939Sdes */
7540975Sdesstatic int
7640975Sdes_fetch_finderr(struct fetcherr *p, int e)
7740939Sdes{
7840975Sdes    int i;
7940975Sdes    for (i = 0; p[i].num != -1; i++)
8040975Sdes	if (p[i].num == e)
8140975Sdes	    break;
8240975Sdes    return i;
8340939Sdes}
8440939Sdes
8540939Sdes/*
8640939Sdes * Set error code
8740939Sdes */
8840939Sdesvoid
8940939Sdes_fetch_seterr(struct fetcherr *p, int e)
9040939Sdes{
9140975Sdes    int n;
9240975Sdes
9340975Sdes    if (!com_err_initialized)
9440975Sdes	_fetch_init_com_err();
9540975Sdes
9640975Sdes    n = _fetch_finderr(p, e);
9740975Sdes    com_err("libfetch", p[n].cat, "(%d %s)", e, p[n].string);
9840939Sdes}
9940939Sdes
10040939Sdes/*
10140939Sdes * Set error code according to errno
10240939Sdes */
10340939Sdesvoid
10440939Sdes_fetch_syserr(void)
10540939Sdes{
10640975Sdes    int cat;
10740975Sdes
10840975Sdes    if (!com_err_initialized)
10940975Sdes	_fetch_init_com_err();
11040975Sdes
11140975Sdes    switch (errno) {
11240975Sdes    case 0:
11340975Sdes	cat = FETCH_OK;
11440975Sdes	break;
11540975Sdes    case EPERM:
11640975Sdes    case EACCES:
11740975Sdes    case EROFS:
11840975Sdes    case EAUTH:
11940975Sdes    case ENEEDAUTH:
12040975Sdes	cat = FETCH_AUTH;
12140975Sdes	break;
12240975Sdes    case ENOENT:
12340975Sdes    case EISDIR: /* XXX */
12440975Sdes	cat = FETCH_UNAVAIL;
12540975Sdes	break;
12640975Sdes    case ENOMEM:
12740975Sdes	cat = FETCH_MEMORY;
12840975Sdes	break;
12940975Sdes    case EBUSY:
13040975Sdes    case EAGAIN:
13140975Sdes	cat = FETCH_TEMP;
13240975Sdes	break;
13340975Sdes    case EEXIST:
13440975Sdes	cat = FETCH_EXISTS;
13540975Sdes	break;
13640975Sdes    case ENOSPC:
13740975Sdes	cat = FETCH_FULL;
13840975Sdes	break;
13940975Sdes    case EADDRINUSE:
14040975Sdes    case EADDRNOTAVAIL:
14140975Sdes    case ENETDOWN:
14240975Sdes    case ENETUNREACH:
14340975Sdes    case ENETRESET:
14440975Sdes    case EHOSTUNREACH:
14540975Sdes	cat = FETCH_NETWORK;
14640975Sdes	break;
14740975Sdes    case ECONNABORTED:
14840975Sdes    case ECONNRESET:
14940975Sdes	cat = FETCH_ABORT;
15040975Sdes	break;
15140975Sdes    case ETIMEDOUT:
15240975Sdes	cat = FETCH_TIMEOUT;
15340975Sdes	break;
15440975Sdes    case ECONNREFUSED:
15540975Sdes    case EHOSTDOWN:
15640975Sdes	cat = FETCH_DOWN;
15740975Sdes	break;
15840975Sdes    default:
15940975Sdes	cat = FETCH_UNKNOWN;
16040975Sdes    }
16140975Sdes    com_err("libfetch", cat, "(%02d %s)", errno, strerror(errno));
16240939Sdes}
16340939Sdes
16440939Sdes
16540939Sdes/*** Network-related utility functions ***************************************/
16640939Sdes
16740939Sdes/*
16840939Sdes * Establish a TCP connection to the specified port on the specified host.
16940939Sdes */
17040939Sdesint
17140939SdesfetchConnect(char *host, int port)
17240939Sdes{
17340939Sdes    struct sockaddr_in sin;
17440939Sdes    struct hostent *he;
17540939Sdes    int sd;
17640939Sdes
17740939Sdes#ifndef NDEBUG
17840939Sdes    fprintf(stderr, "\033[1m---> %s:%d\033[m\n", host, port);
17940939Sdes#endif
18040939Sdes
18140939Sdes    /* look up host name */
18240939Sdes    if ((he = gethostbyname(host)) == NULL) {
18340939Sdes	_netdb_seterr(h_errno);
18440939Sdes	return -1;
18540939Sdes    }
18640939Sdes
18740939Sdes    /* set up socket address structure */
18840939Sdes    bzero(&sin, sizeof(sin));
18940939Sdes    bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
19040939Sdes    sin.sin_family = he->h_addrtype;
19140939Sdes    sin.sin_port = htons(port);
19240939Sdes
19340939Sdes    /* try to connect */
19440939Sdes    if ((sd = socket(sin.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
19540939Sdes	_fetch_syserr();
19640939Sdes	return -1;
19740939Sdes    }
19840939Sdes    if (connect(sd, (struct sockaddr *)&sin, sizeof sin) == -1) {
19940939Sdes	_fetch_syserr();
20040939Sdes	close(sd);
20140939Sdes	return -1;
20240939Sdes    }
20340939Sdes
20440939Sdes    return sd;
20540939Sdes}
206