xref: /freebsd/contrib/bsnmp/lib/support.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
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 
42 void
43 warnx(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 
54 void
55 warn(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 
67 void
68 errx(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 
80 void
81 err(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 
98 size_t
99 strlcpy(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 
121 extern int h_nerr;
122 extern int h_errno;
123 extern const char *h_errlist[];
124 
125 /*
126  * VERY poor man's implementation
127  */
128 int
129 getaddrinfo(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 
171 const char *
172 gai_strerror(int e)
173 {
174 
175 	if (e < 0 || e >= h_nerr)
176 		return ("unknown error");
177 	return (h_errlist[e]);
178 }
179 
180 void
181 freeaddrinfo(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