Changes to compile under gnu-win32, from Marcus Daniels:
[bpt/guile.git] / libguile / net_db.c
CommitLineData
370312ae 1/* "net_db.c" network database support
1e598865 2 * Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
370312ae
GH
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; see the file COPYING. If not, write to
82892bed
JB
16 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307 USA
370312ae
GH
18 *
19 * As a special exception, the Free Software Foundation gives permission
20 * for additional uses of the text contained in its release of GUILE.
21 *
22 * The exception is that, if you link the GUILE library with other files
23 * to produce an executable, this does not by itself cause the
24 * resulting executable to be covered by the GNU General Public License.
25 * Your use of that executable is in no way restricted on account of
26 * linking the GUILE library code into it.
27 *
28 * This exception does not however invalidate any other reasons why
29 * the executable file might be covered by the GNU General Public License.
30 *
31 * This exception applies only to the code released by the
32 * Free Software Foundation under the name GUILE. If you copy
33 * code from other Free Software Foundation releases into a copy of
34 * GUILE, as the General Public License permits, the exception does
35 * not apply to the code that you add in this way. To avoid misleading
36 * anyone as to the status of such modified files, you must delete
37 * this exception notice from them.
38 *
39 * If you write modifications of your own for GUILE, it is your choice
40 * whether to permit this exception to apply to your modifications.
82892bed 41 * If you do not wish that, delete this exception notice. */
370312ae
GH
42
43/* Written in 1994 by Aubrey Jaffer.
44 * Thanks to Hallvard.Tretteberg@si.sintef.no for inspiration and discussion.
45 * Rewritten by Gary Houston to be a closer interface to the C socket library.
46 * Split into net_db.c and socket.c.
47 */
48\f
49
50#include <stdio.h>
51#include "_scm.h"
52#include "feature.h"
53
54#include "net_db.h"
55
56#ifdef HAVE_STRING_H
57#include <string.h>
58#endif
59
60#include <sys/types.h>
cae76441 61#include <sys/socket.h>
370312ae
GH
62#include <netdb.h>
63#include <netinet/in.h>
64#include <arpa/inet.h>
65
7a98cdb9
JB
66/* Some systems do not declare this. It seems unlikely to produce a
67 conflict. */
68extern int h_errno;
69
370312ae
GH
70\f
71
72#ifndef STDC_HEADERS
73int close ();
74#endif /* STDC_HEADERS */
75
76extern int inet_aton ();
77
78SCM_PROC (s_inet_aton, "inet-aton", 1, 0, 0, scm_inet_aton);
79
80SCM
81scm_inet_aton (address)
82 SCM address;
83{
84 struct in_addr soka;
85
86 SCM_ASSERT (SCM_NIMP (address) && SCM_ROSTRINGP (address), address, SCM_ARG1, s_inet_aton);
87 if (SCM_SUBSTRP (address))
88 address = scm_makfromstr (SCM_ROCHARS (address), SCM_ROLENGTH (address), 0);
89 if (inet_aton (SCM_ROCHARS (address), &soka) == 0)
90 scm_syserror (s_inet_aton);
91 return scm_ulong2num (ntohl (soka.s_addr));
92}
93
94
95SCM_PROC (s_inet_ntoa, "inet-ntoa", 1, 0, 0, scm_inet_ntoa);
96
97SCM
98scm_inet_ntoa (inetid)
99 SCM inetid;
100{
101 struct in_addr addr;
102 char *s;
103 SCM answer;
104 addr.s_addr = htonl (scm_num2ulong (inetid, (char *) SCM_ARG1, s_inet_ntoa));
105 SCM_DEFER_INTS;
106 s = inet_ntoa (addr);
107 answer = scm_makfromstr (s, strlen (s), 0);
108 SCM_ALLOW_INTS;
109 return answer;
110}
111
112SCM_PROC (s_inet_netof, "inet-netof", 1, 0, 0, scm_inet_netof);
113
114SCM
115scm_inet_netof (address)
116 SCM address;
117{
118 struct in_addr addr;
119 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_inet_netof));
120 return scm_ulong2num ((unsigned long) inet_netof (addr));
121}
122
03bc4386 123SCM_PROC (s_lnaof, "inet-lnaof", 1, 0, 0, scm_lnaof);
370312ae
GH
124
125SCM
126scm_lnaof (address)
127 SCM address;
128{
129 struct in_addr addr;
130 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_lnaof));
131 return scm_ulong2num ((unsigned long) inet_lnaof (addr));
132}
133
f244dee1 134
370312ae
GH
135SCM_PROC (s_inet_makeaddr, "inet-makeaddr", 2, 0, 0, scm_inet_makeaddr);
136
137SCM
138scm_inet_makeaddr (net, lna)
139 SCM net;
140 SCM lna;
141{
142 struct in_addr addr;
143 unsigned long netnum;
144 unsigned long lnanum;
145
146 netnum = scm_num2ulong (net, (char *) SCM_ARG1, s_inet_makeaddr);
147 lnanum = scm_num2ulong (lna, (char *) SCM_ARG2, s_inet_makeaddr);
148 addr = inet_makeaddr (netnum, lnanum);
149 return scm_ulong2num (ntohl (addr.s_addr));
150}
151
152
153/* !!! Doesn't take address format.
154 * Assumes hostent stream isn't reused.
155 */
156
157SCM_PROC (s_gethost, "gethost", 0, 1, 0, scm_gethost);
158
159SCM
160scm_gethost (name)
161 SCM name;
162{
163 SCM ans = scm_make_vector (SCM_MAKINUM (5), SCM_UNSPECIFIED, SCM_BOOL_F);
164 SCM *ve = SCM_VELTS (ans);
165 SCM lst = SCM_EOL;
166 struct hostent *entry;
167 struct in_addr inad;
168 char **argv;
169 int i = 0;
370312ae
GH
170 if (SCM_UNBNDP (name))
171 {
172 SCM_DEFER_INTS;
cd34a384 173#ifdef HAVE_GETHOSTENT
370312ae 174 entry = gethostent ();
cd34a384
JB
175#else
176 entry = NULL;
177#endif
07513939
JB
178 if (! entry)
179 {
180 /* As far as I can tell, there's no good way to tell whether
181 zero means an error or end-of-file. The trick of
182 clearing errno before calling gethostent and checking it
183 afterwards doesn't cut it, because, on Linux, it seems to
184 try to contact some other server (YP?) and fails, which
185 is a benign failure. */
186 SCM_ALLOW_INTS;
187 return SCM_BOOL_F;
188 }
370312ae 189 }
ef12d978 190 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 191 {
89958ad0 192 SCM_COERCE_SUBSTR (name);
370312ae 193 SCM_DEFER_INTS;
ae2fa5bc 194 entry = gethostbyname (SCM_ROCHARS (name));
370312ae
GH
195 }
196 else
197 {
198 inad.s_addr = htonl (scm_num2ulong (name, (char *) SCM_ARG1, s_gethost));
199 SCM_DEFER_INTS;
200 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
201 }
202 SCM_ALLOW_INTS;
203 if (!entry)
45db98d0
JB
204 {
205 char *errmsg;
206 SCM args;
07513939 207 args = scm_listify (name, SCM_UNDEFINED);
45db98d0
JB
208 switch (h_errno)
209 {
210 case HOST_NOT_FOUND: errmsg = "host %s not found"; break;
211 case TRY_AGAIN: errmsg = "nameserver failure (try later)"; break;
212 case NO_RECOVERY: errmsg = "non-recoverable error"; break;
213 case NO_DATA: errmsg = "no address associated with %s"; break;
214 default: errmsg = "undefined error"; break;
215 }
216 scm_syserror_msg (s_gethost, errmsg, args, h_errno);
217 }
370312ae
GH
218 ve[0] = scm_makfromstr (entry->h_name, (scm_sizet) strlen (entry->h_name), 0);
219 ve[1] = scm_makfromstrs (-1, entry->h_aliases);
220 ve[2] = SCM_MAKINUM (entry->h_addrtype + 0L);
221 ve[3] = SCM_MAKINUM (entry->h_length + 0L);
222 if (sizeof (struct in_addr) != entry->h_length)
223 {
224 ve[4] = SCM_BOOL_F;
225 return ans;
226 }
227 for (argv = entry->h_addr_list; argv[i]; i++);
228 while (i--)
229 {
230 inad = *(struct in_addr *) argv[i];
231 lst = scm_cons (scm_ulong2num (ntohl (inad.s_addr)), lst);
232 }
233 ve[4] = lst;
234 return ans;
235}
236
237
07513939
JB
238/* In all subsequent getMUMBLE functions, when we're called with no
239 arguments, we're supposed to traverse the tables entry by entry.
240 However, there doesn't seem to be any documented way to distinguish
241 between end-of-table and an error; in both cases the functions
242 return zero. Gotta love Unix. For the time being, we clear errno,
243 and if we get a zero and errno is set, we signal an error. This
244 doesn't seem quite right (what if errno gets set as part of healthy
245 operation?), but it seems to work okay. We'll see. */
246
370312ae
GH
247SCM_PROC (s_getnet, "getnet", 0, 1, 0, scm_getnet);
248
249SCM
250scm_getnet (name)
251 SCM name;
252{
253 SCM ans;
254 SCM *ve;
255 struct netent *entry;
256
257 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
258 ve = SCM_VELTS (ans);
259 if (SCM_UNBNDP (name))
260 {
261 SCM_DEFER_INTS;
07513939 262 errno = 0;
370312ae 263 entry = getnetent ();
07513939
JB
264 if (! entry)
265 {
266 SCM_ALLOW_INTS;
267 if (errno)
268 scm_syserror (s_getnet);
269 else
270 return SCM_BOOL_F;
271 }
370312ae 272 }
ae2fa5bc 273 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 274 {
89958ad0 275 SCM_COERCE_SUBSTR (name);
370312ae 276 SCM_DEFER_INTS;
ae2fa5bc 277 entry = getnetbyname (SCM_ROCHARS (name));
370312ae
GH
278 }
279 else
280 {
281 unsigned long netnum;
282 netnum = scm_num2ulong (name, (char *) SCM_ARG1, s_getnet);
283 SCM_DEFER_INTS;
284 entry = getnetbyaddr (netnum, AF_INET);
285 }
286 SCM_ALLOW_INTS;
287 if (!entry)
07513939
JB
288 scm_syserror_msg (s_getnet, "no such network %s",
289 scm_listify (name, SCM_UNDEFINED), errno);
370312ae
GH
290 ve[0] = scm_makfromstr (entry->n_name, (scm_sizet) strlen (entry->n_name), 0);
291 ve[1] = scm_makfromstrs (-1, entry->n_aliases);
292 ve[2] = SCM_MAKINUM (entry->n_addrtype + 0L);
293 ve[3] = scm_ulong2num (entry->n_net + 0L);
294 return ans;
295}
296
297SCM_PROC (s_getproto, "getproto", 0, 1, 0, scm_getproto);
298
299SCM
300scm_getproto (name)
301 SCM name;
302{
303 SCM ans;
304 SCM *ve;
305 struct protoent *entry;
306
307 ans = scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED, SCM_BOOL_F);
308 ve = SCM_VELTS (ans);
309 if (SCM_UNBNDP (name))
310 {
311 SCM_DEFER_INTS;
07513939 312 errno = 0;
370312ae 313 entry = getprotoent ();
07513939
JB
314 if (! entry)
315 {
316 SCM_ALLOW_INTS;
317 if (errno)
318 scm_syserror (s_getproto);
319 else
320 return SCM_BOOL_F;
321 }
370312ae 322 }
ae2fa5bc 323 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 324 {
89958ad0 325 SCM_COERCE_SUBSTR (name);
370312ae 326 SCM_DEFER_INTS;
ae2fa5bc 327 entry = getprotobyname (SCM_ROCHARS (name));
370312ae
GH
328 }
329 else
330 {
331 unsigned long protonum;
332 protonum = scm_num2ulong (name, (char *) SCM_ARG1, s_getproto);
333 SCM_DEFER_INTS;
334 entry = getprotobynumber (protonum);
335 }
336 SCM_ALLOW_INTS;
337 if (!entry)
07513939
JB
338 scm_syserror_msg (s_getproto, "no such protocol %s",
339 scm_listify (name, SCM_UNDEFINED), errno);
370312ae
GH
340 ve[0] = scm_makfromstr (entry->p_name, (scm_sizet) strlen (entry->p_name), 0);
341 ve[1] = scm_makfromstrs (-1, entry->p_aliases);
342 ve[2] = SCM_MAKINUM (entry->p_proto + 0L);
343 return ans;
344}
f244dee1 345
370312ae
GH
346
347static SCM scm_return_entry SCM_P ((struct servent *entry));
348
349static SCM
350scm_return_entry (entry)
351 struct servent *entry;
352{
353 SCM ans;
354 SCM *ve;
355
356 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
357 ve = SCM_VELTS (ans);
358 ve[0] = scm_makfromstr (entry->s_name, (scm_sizet) strlen (entry->s_name), 0);
359 ve[1] = scm_makfromstrs (-1, entry->s_aliases);
360 ve[2] = SCM_MAKINUM (ntohs (entry->s_port) + 0L);
361 ve[3] = scm_makfromstr (entry->s_proto, (scm_sizet) strlen (entry->s_proto), 0);
362 SCM_ALLOW_INTS;
363 return ans;
364}
365
366SCM_PROC (s_getserv, "getserv", 0, 2, 0, scm_getserv);
367
368SCM
369scm_getserv (name, proto)
370 SCM name;
371 SCM proto;
372{
373 struct servent *entry;
374 if (SCM_UNBNDP (name))
375 {
376 SCM_DEFER_INTS;
07513939 377 errno = 0;
370312ae 378 entry = getservent ();
65b376c7 379 SCM_ALLOW_INTS;
07513939
JB
380 if (!entry)
381 {
382 if (errno)
383 scm_syserror (s_getserv);
384 else
385 return SCM_BOOL_F;
386 }
370312ae
GH
387 return scm_return_entry (entry);
388 }
ae2fa5bc 389 SCM_ASSERT (SCM_NIMP (proto) && SCM_ROSTRINGP (proto), proto, SCM_ARG2, s_getserv);
89958ad0 390 SCM_COERCE_SUBSTR (proto);
ae2fa5bc 391 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 392 {
89958ad0 393 SCM_COERCE_SUBSTR (name);
370312ae 394 SCM_DEFER_INTS;
ae2fa5bc 395 entry = getservbyname (SCM_ROCHARS (name), SCM_ROCHARS (proto));
370312ae
GH
396 }
397 else
398 {
399 SCM_ASSERT (SCM_INUMP (name), name, SCM_ARG1, s_getserv);
400 SCM_DEFER_INTS;
ae2fa5bc 401 entry = getservbyport (htons (SCM_INUM (name)), SCM_ROCHARS (proto));
370312ae
GH
402 }
403 if (!entry)
45db98d0
JB
404 scm_syserror_msg (s_getserv, "no such service %s",
405 scm_listify (name, SCM_UNDEFINED), errno);
65b376c7 406 SCM_ALLOW_INTS;
370312ae
GH
407 return scm_return_entry (entry);
408}
409
410SCM_PROC (s_sethost, "sethost", 0, 1, 0, scm_sethost);
411
412SCM
413scm_sethost (arg)
414 SCM arg;
415{
416 if (SCM_UNBNDP (arg))
417 endhostent ();
418 else
419 sethostent (SCM_NFALSEP (arg));
420 return SCM_UNSPECIFIED;
421}
422
423SCM_PROC (s_setnet, "setnet", 0, 1, 0, scm_setnet);
424
425SCM
426scm_setnet (arg)
427 SCM arg;
428{
429 if (SCM_UNBNDP (arg))
430 endnetent ();
431 else
432 setnetent (SCM_NFALSEP (arg));
433 return SCM_UNSPECIFIED;
434}
435
436SCM_PROC (s_setproto, "setproto", 0, 1, 0, scm_setproto);
437
438SCM
439scm_setproto (arg)
440 SCM arg;
441{
442 if (SCM_UNBNDP (arg))
443 endprotoent ();
444 else
445 setprotoent (SCM_NFALSEP (arg));
446 return SCM_UNSPECIFIED;
447}
448
449SCM_PROC (s_setserv, "setserv", 0, 1, 0, scm_setserv);
450
451SCM
452scm_setserv (arg)
453 SCM arg;
454{
455 if (SCM_UNBNDP (arg))
456 endservent ();
457 else
458 setservent (SCM_NFALSEP (arg));
459 return SCM_UNSPECIFIED;
460}
461
462
463void
464scm_init_net_db ()
465{
466#ifdef INADDR_ANY
467 scm_sysintern ("INADDR_ANY", scm_ulong2num (INADDR_ANY));
468#endif
469#ifdef INADDR_BROADCAST
470 scm_sysintern ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST));
471#endif
472#ifdef INADDR_NONE
473 scm_sysintern ("INADDR_NONE", scm_ulong2num (INADDR_NONE));
474#endif
475#ifdef INADDR_LOOPBACK
476 scm_sysintern ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK));
477#endif
478
479 scm_add_feature ("net-db");
480#include "net_db.x"
481}