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