1/*
2 * Copyright (C) 2004
3 * 	Hartmut Brandt.
4 * 	All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Begemot: bsnmp/lib/support.c,v 1.1 2004/08/06 08:47:58 brandt Exp $
30 *
31 * Functions that are missing on certain systems.
32 */
33#include <stdio.h>
34#include <stdlib.h>
35#include <stdarg.h>
36#include <errno.h>
37#include <string.h>
38#include "support.h"
39
40#ifndef HAVE_ERR_H
41
42void
43warnx(const char *fmt, ...)
44{
45	va_list ap;
46
47	va_start(ap, fmt);
48	fprintf(stderr, "warning: ");
49	vfprintf(stderr, fmt, ap);
50	fprintf(stderr, "\n");
51	va_end(ap);
52}
53
54void
55warn(const char *fmt, ...)
56{
57	va_list ap;
58	int e = errno;
59
60	va_start(ap, fmt);
61	fprintf(stderr, "warning: ");
62	vfprintf(stderr, fmt, ap);
63	fprintf(stderr, ": %s\n", strerror(e));
64	va_end(ap);
65}
66
67void
68errx(int code, const char *fmt, ...)
69{
70	va_list ap;
71
72	va_start(ap, fmt);
73	fprintf(stderr, "error: ");
74	vfprintf(stderr, fmt, ap);
75	fprintf(stderr, "\n");
76	va_end(ap);
77	exit(code);
78}
79
80void
81err(int code, const char *fmt, ...)
82{
83	va_list ap;
84	int e = errno;
85
86	va_start(ap, fmt);
87	fprintf(stderr, "error: ");
88	vfprintf(stderr, fmt, ap);
89	fprintf(stderr, ": %s\n", strerror(e));
90	va_end(ap);
91	exit(code);
92}
93
94#endif
95
96#ifndef HAVE_STRLCPY
97
98size_t
99strlcpy(char *dst, const char *src, size_t len)
100{
101	size_t ret = strlen(dst);
102
103	while (len > 1) {
104		*dst++ = *src++;
105		len--;
106	}
107	if (len > 0)
108		*dst = '\0';
109	return (ret);
110}
111
112#endif
113
114#ifndef HAVE_GETADDRINFO
115
116#include <sys/types.h>
117#include <sys/socket.h>
118#include <netinet/in.h>
119#include <netdb.h>
120
121extern int h_nerr;
122extern int h_errno;
123extern const char *h_errlist[];
124
125/*
126 * VERY poor man's implementation
127 */
128int
129getaddrinfo(const char *host, const char *port, const struct addrinfo *hints,
130    struct addrinfo **res)
131{
132	struct hostent *hent;
133	struct sockaddr_in *s;
134	struct servent *sent;
135
136	if ((hent = gethostbyname(host)) == NULL)
137		return (h_errno);
138	if (hent->h_addrtype != hints->ai_family)
139		return (HOST_NOT_FOUND);
140	if (hent->h_addrtype != AF_INET)
141		return (HOST_NOT_FOUND);
142
143	if ((*res = malloc(sizeof(**res))) == NULL)
144		return (HOST_NOT_FOUND);
145
146	(*res)->ai_flags = hints->ai_flags;
147	(*res)->ai_family = hints->ai_family;
148	(*res)->ai_socktype = hints->ai_socktype;
149	(*res)->ai_protocol = hints->ai_protocol;
150	(*res)->ai_next = NULL;
151
152	if (((*res)->ai_addr = malloc(sizeof(struct sockaddr_in))) == NULL) {
153		freeaddrinfo(*res);
154		return (HOST_NOT_FOUND);
155	}
156	(*res)->ai_addrlen = sizeof(struct sockaddr_in);
157	s = (struct sockaddr_in *)(*res)->ai_addr;
158	s->sin_family = hints->ai_family;
159	s->sin_len = sizeof(*s);
160	memcpy(&s->sin_addr, hent->h_addr, 4);
161
162	if ((sent = getservbyname(port, NULL)) == NULL) {
163		freeaddrinfo(*res);
164		return (HOST_NOT_FOUND);
165	}
166	s->sin_port = sent->s_port;
167
168	return (0);
169}
170
171const char *
172gai_strerror(int e)
173{
174
175	if (e < 0 || e >= h_nerr)
176		return ("unknown error");
177	return (h_errlist[e]);
178}
179
180void
181freeaddrinfo(struct addrinfo *p)
182{
183	struct addrinfo *next;
184
185	while (p != NULL) {
186		next = p->ai_next;
187		if (p->ai_addr != NULL)
188			free(p->ai_addr);
189		free(p);
190		p = next;
191	}
192}
193
194#endif
195