common.c revision 40975
1/*-
2 * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer
10 *    in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 *	$Id: common.c,v 1.1 1998/11/05 19:48:16 des Exp $
29 */
30
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34
35#include <com_err.h>
36#include <errno.h>
37#include <netdb.h>
38#include <string.h>
39#include <unistd.h>
40
41#include "fetch.h"
42#include "common.h"
43
44
45/*** Local data **************************************************************/
46
47/*
48 * Error messages for resolver errors
49 */
50static struct fetcherr _netdb_errlist[] = {
51    { HOST_NOT_FOUND,	FETCH_RESOLV,	"Host not found" },
52    { TRY_AGAIN,	FETCH_RESOLV,	"Transient resolver failure" },
53    { NO_RECOVERY,	FETCH_RESOLV,	"Non-recoverable resolver failure" },
54    { NO_DATA,		FETCH_RESOLV,	"No address record" },
55    { -1,		FETCH_UNKNOWN,	"Unknown resolver error" }
56};
57
58static int com_err_initialized;
59
60/*** Error-reporting functions ***********************************************/
61
62/*
63 * Initialize the common error library
64 */
65static void
66_fetch_init_com_err(void)
67{
68    initialize_ftch_error_table();
69    com_err_initialized = 1;
70}
71
72/*
73 * Map error code to string
74 */
75static int
76_fetch_finderr(struct fetcherr *p, int e)
77{
78    int i;
79    for (i = 0; p[i].num != -1; i++)
80	if (p[i].num == e)
81	    break;
82    return i;
83}
84
85/*
86 * Set error code
87 */
88void
89_fetch_seterr(struct fetcherr *p, int e)
90{
91    int n;
92
93    if (!com_err_initialized)
94	_fetch_init_com_err();
95
96    n = _fetch_finderr(p, e);
97    com_err("libfetch", p[n].cat, "(%d %s)", e, p[n].string);
98}
99
100/*
101 * Set error code according to errno
102 */
103void
104_fetch_syserr(void)
105{
106    int cat;
107
108    if (!com_err_initialized)
109	_fetch_init_com_err();
110
111    switch (errno) {
112    case 0:
113	cat = FETCH_OK;
114	break;
115    case EPERM:
116    case EACCES:
117    case EROFS:
118    case EAUTH:
119    case ENEEDAUTH:
120	cat = FETCH_AUTH;
121	break;
122    case ENOENT:
123    case EISDIR: /* XXX */
124	cat = FETCH_UNAVAIL;
125	break;
126    case ENOMEM:
127	cat = FETCH_MEMORY;
128	break;
129    case EBUSY:
130    case EAGAIN:
131	cat = FETCH_TEMP;
132	break;
133    case EEXIST:
134	cat = FETCH_EXISTS;
135	break;
136    case ENOSPC:
137	cat = FETCH_FULL;
138	break;
139    case EADDRINUSE:
140    case EADDRNOTAVAIL:
141    case ENETDOWN:
142    case ENETUNREACH:
143    case ENETRESET:
144    case EHOSTUNREACH:
145	cat = FETCH_NETWORK;
146	break;
147    case ECONNABORTED:
148    case ECONNRESET:
149	cat = FETCH_ABORT;
150	break;
151    case ETIMEDOUT:
152	cat = FETCH_TIMEOUT;
153	break;
154    case ECONNREFUSED:
155    case EHOSTDOWN:
156	cat = FETCH_DOWN;
157	break;
158    default:
159	cat = FETCH_UNKNOWN;
160    }
161    com_err("libfetch", cat, "(%02d %s)", errno, strerror(errno));
162}
163
164
165/*** Network-related utility functions ***************************************/
166
167/*
168 * Establish a TCP connection to the specified port on the specified host.
169 */
170int
171fetchConnect(char *host, int port)
172{
173    struct sockaddr_in sin;
174    struct hostent *he;
175    int sd;
176
177#ifndef NDEBUG
178    fprintf(stderr, "\033[1m---> %s:%d\033[m\n", host, port);
179#endif
180
181    /* look up host name */
182    if ((he = gethostbyname(host)) == NULL) {
183	_netdb_seterr(h_errno);
184	return -1;
185    }
186
187    /* set up socket address structure */
188    bzero(&sin, sizeof(sin));
189    bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
190    sin.sin_family = he->h_addrtype;
191    sin.sin_port = htons(port);
192
193    /* try to connect */
194    if ((sd = socket(sin.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
195	_fetch_syserr();
196	return -1;
197    }
198    if (connect(sd, (struct sockaddr *)&sin, sizeof sin) == -1) {
199	_fetch_syserr();
200	close(sd);
201	return -1;
202    }
203
204    return sd;
205}
206