libkiconv: Remove unneeded SHLIBDIR in the Makefile.
[dragonfly.git] / lib / libbluetooth / bluetooth.c
1 /* $NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
2
3 /*
4  * bluetooth.c
5  *
6  * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $
31  * $FreeBSD: src/lib/libbluetooth/bluetooth.c,v 1.2 2004/03/05 08:10:17 markm Exp $
32  */
33
34 #include <bluetooth.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #define _PATH_BT_HOSTS          "/etc/bluetooth/hosts"
40 #define _PATH_BT_PROTOCOLS      "/etc/bluetooth/protocols"
41 #define MAXALIASES               35
42
43 static FILE             *hostf = NULL;
44 static int               host_stayopen = 0;
45 static struct hostent    host;
46 static bdaddr_t          host_addr;
47 static char             *host_addr_ptrs[2];
48 static char             *host_aliases[MAXALIASES];
49
50 static FILE             *protof = NULL;
51 static int               proto_stayopen = 0;
52 static struct protoent   proto;
53 static char             *proto_aliases[MAXALIASES];
54
55 static char              buf[BUFSIZ + 1];
56
57 static int bt_hex_byte   (char const *str);
58 static int bt_hex_nibble (char nibble);
59
60 struct hostent *
61 bt_gethostbyname(char const *name)
62 {
63         struct hostent  *p;
64         char            **cp;
65
66         bt_sethostent(host_stayopen);
67         while ((p = bt_gethostent()) != NULL) {
68                 if (strcasecmp(p->h_name, name) == 0)
69                         break;
70                 for (cp = p->h_aliases; *cp != NULL; cp++)
71                         if (strcasecmp(*cp, name) == 0)
72                                 goto found;
73         }
74 found:
75         bt_endhostent();
76
77         return (p);
78 }
79
80 struct hostent *
81 bt_gethostbyaddr(void const *addr, socklen_t len, int type)
82 {
83         struct hostent  *p;
84
85         if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
86                 h_errno = NO_RECOVERY;
87                 return (NULL);
88         }
89
90         bt_sethostent(host_stayopen);
91         while ((p = bt_gethostent()) != NULL)
92                 if (p->h_addrtype == type && memcmp(p->h_addr, addr, len) == 0)
93                         break;
94         bt_endhostent();
95
96         return (p);
97 }
98
99 struct hostent *
100 bt_gethostent(void)
101 {
102         char    *p, *cp, **q;
103
104         if (hostf == NULL)
105                 hostf = fopen(_PATH_BT_HOSTS, "r");
106
107         if (hostf == NULL) {
108                 h_errno = NETDB_INTERNAL;
109                 return (NULL);
110         }
111 again:
112         if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
113                 h_errno = HOST_NOT_FOUND;
114                 return (NULL);
115         }
116         if (*p == '#')
117                 goto again;
118         if ((cp = strpbrk(p, "#\n")) == NULL)
119                 goto again;
120         *cp = 0;
121         if ((cp = strpbrk(p, " \t")) == NULL)
122                 goto again;
123         *cp++ = 0;
124         if (bt_aton(p, &host_addr) == 0)
125                 goto again;
126         host_addr_ptrs[0] = (char *) &host_addr;
127         host_addr_ptrs[1] = NULL;
128         host.h_addr_list = host_addr_ptrs;
129         host.h_length = sizeof(host_addr);
130         host.h_addrtype = AF_BLUETOOTH;
131         while (*cp == ' ' || *cp == '\t')
132                 cp++;
133         host.h_name = cp;
134         q = host.h_aliases = host_aliases;
135         if ((cp = strpbrk(cp, " \t")) != NULL)
136                 *cp++ = 0;
137         while (cp != NULL && *cp != 0) {
138                 if (*cp == ' ' || *cp == '\t') {
139                         cp++;
140                         continue;
141                 }
142                 if (q < &host_aliases[MAXALIASES - 1])
143                         *q++ = cp;
144                 if ((cp = strpbrk(cp, " \t")) != NULL)
145                         *cp++ = 0;
146         }
147         *q = NULL;
148         h_errno = NETDB_SUCCESS;
149
150         return (&host);
151 }
152
153 void
154 bt_sethostent(int stayopen)
155 {
156         if (hostf == NULL)
157                 hostf = fopen(_PATH_BT_HOSTS, "r");
158         else
159                 rewind(hostf);
160
161         host_stayopen = stayopen;
162 }
163
164 void
165 bt_endhostent(void)
166 {
167         if (hostf != NULL && host_stayopen == 0) {
168                 (void) fclose(hostf);
169                 hostf = NULL;
170         }
171 }
172
173 struct protoent *
174 bt_getprotobyname(char const *name)
175 {
176         struct protoent  *p;
177         char            **cp;
178
179         bt_setprotoent(proto_stayopen);
180         while ((p = bt_getprotoent()) != NULL) {
181                 if (strcmp(p->p_name, name) == 0)
182                         break;
183                 for (cp = p->p_aliases; *cp != NULL; cp++)
184                         if (strcmp(*cp, name) == 0)
185                                 goto found;
186         }
187 found:
188         bt_endprotoent();
189
190         return (p);
191 }
192
193 struct protoent *
194 bt_getprotobynumber(int num)
195 {
196         struct protoent *p;
197
198         bt_setprotoent(proto_stayopen);
199         while ((p = bt_getprotoent()) != NULL)
200                 if (p->p_proto == num)
201                         break;
202         bt_endprotoent();
203
204         return (p);
205 }
206
207 struct protoent *
208 bt_getprotoent(void)
209 {
210         char    *p, *cp, **q;
211
212         if (protof == NULL)
213                 protof = fopen(_PATH_BT_PROTOCOLS, "r");
214
215         if (protof == NULL)
216                 return (NULL);
217 again:
218         if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
219                 return (NULL);
220         if (*p == '#')
221                 goto again;
222         if ((cp = strpbrk(p, "#\n")) == NULL)
223                 goto again;
224         *cp = '\0';
225         proto.p_name = p;
226         if ((cp = strpbrk(p, " \t")) == NULL)
227                 goto again;
228         *cp++ = '\0';
229         while (*cp == ' ' || *cp == '\t')
230                 cp++;
231         if ((p = strpbrk(cp, " \t")) != NULL)
232                 *p++ = '\0';
233         proto.p_proto = (int)strtol(cp, NULL, 0);
234         q = proto.p_aliases = proto_aliases;
235         if (p != NULL) {
236                 cp = p;
237                 while (cp != NULL && *cp != 0) {
238                         if (*cp == ' ' || *cp == '\t') {
239                                 cp++;
240                                 continue;
241                         }
242                         if (q < &proto_aliases[MAXALIASES - 1])
243                                 *q++ = cp;
244                         if ((cp = strpbrk(cp, " \t")) != NULL)
245                                 *cp++ = '\0';
246                 }
247         }
248         *q = NULL;
249
250         return (&proto);
251 }
252
253 void
254 bt_setprotoent(int stayopen)
255 {
256         if (protof == NULL)
257                 protof = fopen(_PATH_BT_PROTOCOLS, "r");
258         else
259                 rewind(protof);
260
261         proto_stayopen = stayopen;
262 }
263
264 void
265 bt_endprotoent(void)
266 {
267         if (protof != NULL) {
268                 (void) fclose(protof);
269                 protof = NULL;
270         }
271 }
272
273 char const *
274 bt_ntoa(bdaddr_t const *ba, char *str)
275 {
276         static char     buffer[24];
277
278         if (str == NULL)
279                 str = buffer;
280
281         sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
282                 ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
283
284         return (str);
285 }
286
287 int
288 bt_aton(char const *str, bdaddr_t *ba)
289 {
290         int      i, b;
291         char    *end = NULL;
292
293         memset(ba, 0, sizeof(*ba));
294
295         for (i = 5, end = strchr(str, ':');
296              i > 0 && *str != '\0' && end != NULL;
297              i --, str = end + 1, end = strchr(str, ':')) {
298                 switch (end - str) {
299                 case 1:
300                         b = bt_hex_nibble(str[0]);
301                         break;
302
303                 case 2:
304                         b = bt_hex_byte(str);
305                         break;
306
307                 default:
308                         b = -1;
309                         break;
310                 }
311
312                 if (b < 0)
313                         return (0);
314
315                 ba->b[i] = b;
316         }
317
318         if (i != 0 || end != NULL || *str == 0)
319                 return (0);
320
321         switch (strlen(str)) {
322         case 1:
323                 b = bt_hex_nibble(str[0]);
324                 break;
325
326         case 2:
327                 b = bt_hex_byte(str);
328                 break;
329
330         default:
331                 b = -1;
332                 break;
333         }
334
335         if (b < 0)
336                 return (0);
337
338         ba->b[i] = b;
339
340         return (1);
341 }
342
343 static int
344 bt_hex_byte(char const *str)
345 {
346         int     n1, n2;
347
348         if ((n1 = bt_hex_nibble(str[0])) < 0)
349                 return (-1);
350
351         if ((n2 = bt_hex_nibble(str[1])) < 0)
352                 return (-1);
353
354         return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
355 }
356
357 static int
358 bt_hex_nibble(char nibble)
359 {
360         if ('0' <= nibble && nibble <= '9')
361                 return (nibble - '0');
362
363         if ('a' <= nibble && nibble <= 'f')
364                 return (nibble - 'a' + 0xa);
365
366         if ('A' <= nibble && nibble <= 'F')
367                 return (nibble - 'A' + 0xa);
368
369         return (-1);
370 }