* root.h: Added "fluids" member to scm_root_state.
[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
0e958795 112#ifdef HAVE_INET_NETOF
370312ae
GH
113SCM_PROC (s_inet_netof, "inet-netof", 1, 0, 0, scm_inet_netof);
114
115SCM
116scm_inet_netof (address)
117 SCM address;
118{
119 struct in_addr addr;
120 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_inet_netof));
121 return scm_ulong2num ((unsigned long) inet_netof (addr));
122}
0e958795 123#endif
370312ae 124
0e958795 125#ifdef HAVE_INET_LNAOF
03bc4386 126SCM_PROC (s_lnaof, "inet-lnaof", 1, 0, 0, scm_lnaof);
370312ae
GH
127
128SCM
129scm_lnaof (address)
130 SCM address;
131{
132 struct in_addr addr;
133 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_lnaof));
134 return scm_ulong2num ((unsigned long) inet_lnaof (addr));
135}
0e958795 136#endif
370312ae 137
0e958795 138#ifdef HAVE_INET_MAKEADDR
370312ae
GH
139SCM_PROC (s_inet_makeaddr, "inet-makeaddr", 2, 0, 0, scm_inet_makeaddr);
140
141SCM
142scm_inet_makeaddr (net, lna)
143 SCM net;
144 SCM lna;
145{
146 struct in_addr addr;
147 unsigned long netnum;
148 unsigned long lnanum;
149
150 netnum = scm_num2ulong (net, (char *) SCM_ARG1, s_inet_makeaddr);
151 lnanum = scm_num2ulong (lna, (char *) SCM_ARG2, s_inet_makeaddr);
152 addr = inet_makeaddr (netnum, lnanum);
153 return scm_ulong2num (ntohl (addr.s_addr));
154}
0e958795 155#endif
370312ae
GH
156
157
158/* !!! Doesn't take address format.
159 * Assumes hostent stream isn't reused.
160 */
161
162SCM_PROC (s_gethost, "gethost", 0, 1, 0, scm_gethost);
163
164SCM
165scm_gethost (name)
166 SCM name;
167{
168 SCM ans = scm_make_vector (SCM_MAKINUM (5), SCM_UNSPECIFIED, SCM_BOOL_F);
169 SCM *ve = SCM_VELTS (ans);
170 SCM lst = SCM_EOL;
171 struct hostent *entry;
172 struct in_addr inad;
173 char **argv;
174 int i = 0;
370312ae
GH
175 if (SCM_UNBNDP (name))
176 {
177 SCM_DEFER_INTS;
cd34a384 178#ifdef HAVE_GETHOSTENT
370312ae 179 entry = gethostent ();
cd34a384
JB
180#else
181 entry = NULL;
182#endif
07513939
JB
183 if (! entry)
184 {
185 /* As far as I can tell, there's no good way to tell whether
186 zero means an error or end-of-file. The trick of
187 clearing errno before calling gethostent and checking it
188 afterwards doesn't cut it, because, on Linux, it seems to
189 try to contact some other server (YP?) and fails, which
190 is a benign failure. */
191 SCM_ALLOW_INTS;
192 return SCM_BOOL_F;
193 }
370312ae 194 }
ef12d978 195 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 196 {
89958ad0 197 SCM_COERCE_SUBSTR (name);
370312ae 198 SCM_DEFER_INTS;
ae2fa5bc 199 entry = gethostbyname (SCM_ROCHARS (name));
370312ae
GH
200 }
201 else
202 {
203 inad.s_addr = htonl (scm_num2ulong (name, (char *) SCM_ARG1, s_gethost));
204 SCM_DEFER_INTS;
205 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
206 }
207 SCM_ALLOW_INTS;
208 if (!entry)
45db98d0
JB
209 {
210 char *errmsg;
211 SCM args;
07513939 212 args = scm_listify (name, SCM_UNDEFINED);
45db98d0
JB
213 switch (h_errno)
214 {
215 case HOST_NOT_FOUND: errmsg = "host %s not found"; break;
216 case TRY_AGAIN: errmsg = "nameserver failure (try later)"; break;
217 case NO_RECOVERY: errmsg = "non-recoverable error"; break;
218 case NO_DATA: errmsg = "no address associated with %s"; break;
219 default: errmsg = "undefined error"; break;
220 }
221 scm_syserror_msg (s_gethost, errmsg, args, h_errno);
222 }
370312ae
GH
223 ve[0] = scm_makfromstr (entry->h_name, (scm_sizet) strlen (entry->h_name), 0);
224 ve[1] = scm_makfromstrs (-1, entry->h_aliases);
225 ve[2] = SCM_MAKINUM (entry->h_addrtype + 0L);
226 ve[3] = SCM_MAKINUM (entry->h_length + 0L);
227 if (sizeof (struct in_addr) != entry->h_length)
228 {
229 ve[4] = SCM_BOOL_F;
230 return ans;
231 }
232 for (argv = entry->h_addr_list; argv[i]; i++);
233 while (i--)
234 {
235 inad = *(struct in_addr *) argv[i];
236 lst = scm_cons (scm_ulong2num (ntohl (inad.s_addr)), lst);
237 }
238 ve[4] = lst;
239 return ans;
240}
241
242
07513939
JB
243/* In all subsequent getMUMBLE functions, when we're called with no
244 arguments, we're supposed to traverse the tables entry by entry.
245 However, there doesn't seem to be any documented way to distinguish
246 between end-of-table and an error; in both cases the functions
247 return zero. Gotta love Unix. For the time being, we clear errno,
248 and if we get a zero and errno is set, we signal an error. This
249 doesn't seem quite right (what if errno gets set as part of healthy
250 operation?), but it seems to work okay. We'll see. */
251
0e958795 252#if defined(HAVE_GETNETENT) && defined(HAVE_GETNETBYNAME) && defined(HAVE_GETNETBYADDR)
370312ae
GH
253SCM_PROC (s_getnet, "getnet", 0, 1, 0, scm_getnet);
254
255SCM
256scm_getnet (name)
257 SCM name;
258{
259 SCM ans;
260 SCM *ve;
261 struct netent *entry;
262
263 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
264 ve = SCM_VELTS (ans);
265 if (SCM_UNBNDP (name))
266 {
267 SCM_DEFER_INTS;
07513939 268 errno = 0;
370312ae 269 entry = getnetent ();
07513939
JB
270 if (! entry)
271 {
272 SCM_ALLOW_INTS;
273 if (errno)
274 scm_syserror (s_getnet);
275 else
276 return SCM_BOOL_F;
277 }
370312ae 278 }
ae2fa5bc 279 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 280 {
89958ad0 281 SCM_COERCE_SUBSTR (name);
370312ae 282 SCM_DEFER_INTS;
ae2fa5bc 283 entry = getnetbyname (SCM_ROCHARS (name));
370312ae
GH
284 }
285 else
286 {
287 unsigned long netnum;
288 netnum = scm_num2ulong (name, (char *) SCM_ARG1, s_getnet);
289 SCM_DEFER_INTS;
290 entry = getnetbyaddr (netnum, AF_INET);
291 }
292 SCM_ALLOW_INTS;
293 if (!entry)
07513939
JB
294 scm_syserror_msg (s_getnet, "no such network %s",
295 scm_listify (name, SCM_UNDEFINED), errno);
370312ae
GH
296 ve[0] = scm_makfromstr (entry->n_name, (scm_sizet) strlen (entry->n_name), 0);
297 ve[1] = scm_makfromstrs (-1, entry->n_aliases);
298 ve[2] = SCM_MAKINUM (entry->n_addrtype + 0L);
299 ve[3] = scm_ulong2num (entry->n_net + 0L);
300 return ans;
301}
0e958795 302#endif
370312ae 303
0e958795 304#ifdef HAVE_GETPROTOENT
370312ae
GH
305SCM_PROC (s_getproto, "getproto", 0, 1, 0, scm_getproto);
306
307SCM
308scm_getproto (name)
309 SCM name;
310{
311 SCM ans;
312 SCM *ve;
313 struct protoent *entry;
314
315 ans = scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED, SCM_BOOL_F);
316 ve = SCM_VELTS (ans);
317 if (SCM_UNBNDP (name))
318 {
319 SCM_DEFER_INTS;
07513939 320 errno = 0;
370312ae 321 entry = getprotoent ();
07513939
JB
322 if (! entry)
323 {
324 SCM_ALLOW_INTS;
325 if (errno)
326 scm_syserror (s_getproto);
327 else
328 return SCM_BOOL_F;
329 }
370312ae 330 }
ae2fa5bc 331 else if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 332 {
89958ad0 333 SCM_COERCE_SUBSTR (name);
370312ae 334 SCM_DEFER_INTS;
ae2fa5bc 335 entry = getprotobyname (SCM_ROCHARS (name));
370312ae
GH
336 }
337 else
338 {
339 unsigned long protonum;
340 protonum = scm_num2ulong (name, (char *) SCM_ARG1, s_getproto);
341 SCM_DEFER_INTS;
342 entry = getprotobynumber (protonum);
343 }
344 SCM_ALLOW_INTS;
345 if (!entry)
07513939
JB
346 scm_syserror_msg (s_getproto, "no such protocol %s",
347 scm_listify (name, SCM_UNDEFINED), errno);
370312ae
GH
348 ve[0] = scm_makfromstr (entry->p_name, (scm_sizet) strlen (entry->p_name), 0);
349 ve[1] = scm_makfromstrs (-1, entry->p_aliases);
350 ve[2] = SCM_MAKINUM (entry->p_proto + 0L);
351 return ans;
352}
0e958795 353#endif
370312ae
GH
354
355static SCM scm_return_entry SCM_P ((struct servent *entry));
356
357static SCM
358scm_return_entry (entry)
359 struct servent *entry;
360{
361 SCM ans;
362 SCM *ve;
363
364 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
365 ve = SCM_VELTS (ans);
366 ve[0] = scm_makfromstr (entry->s_name, (scm_sizet) strlen (entry->s_name), 0);
367 ve[1] = scm_makfromstrs (-1, entry->s_aliases);
368 ve[2] = SCM_MAKINUM (ntohs (entry->s_port) + 0L);
369 ve[3] = scm_makfromstr (entry->s_proto, (scm_sizet) strlen (entry->s_proto), 0);
370 SCM_ALLOW_INTS;
371 return ans;
372}
373
0e958795 374#ifdef HAVE_GETSERVENT
370312ae
GH
375SCM_PROC (s_getserv, "getserv", 0, 2, 0, scm_getserv);
376
377SCM
378scm_getserv (name, proto)
379 SCM name;
380 SCM proto;
381{
382 struct servent *entry;
383 if (SCM_UNBNDP (name))
384 {
385 SCM_DEFER_INTS;
07513939 386 errno = 0;
370312ae 387 entry = getservent ();
65b376c7 388 SCM_ALLOW_INTS;
07513939
JB
389 if (!entry)
390 {
391 if (errno)
392 scm_syserror (s_getserv);
393 else
394 return SCM_BOOL_F;
395 }
370312ae
GH
396 return scm_return_entry (entry);
397 }
ae2fa5bc 398 SCM_ASSERT (SCM_NIMP (proto) && SCM_ROSTRINGP (proto), proto, SCM_ARG2, s_getserv);
89958ad0 399 SCM_COERCE_SUBSTR (proto);
ae2fa5bc 400 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
370312ae 401 {
89958ad0 402 SCM_COERCE_SUBSTR (name);
370312ae 403 SCM_DEFER_INTS;
ae2fa5bc 404 entry = getservbyname (SCM_ROCHARS (name), SCM_ROCHARS (proto));
370312ae
GH
405 }
406 else
407 {
408 SCM_ASSERT (SCM_INUMP (name), name, SCM_ARG1, s_getserv);
409 SCM_DEFER_INTS;
ae2fa5bc 410 entry = getservbyport (htons (SCM_INUM (name)), SCM_ROCHARS (proto));
370312ae
GH
411 }
412 if (!entry)
45db98d0
JB
413 scm_syserror_msg (s_getserv, "no such service %s",
414 scm_listify (name, SCM_UNDEFINED), errno);
65b376c7 415 SCM_ALLOW_INTS;
370312ae
GH
416 return scm_return_entry (entry);
417}
0e958795 418#endif
370312ae 419
0e958795 420#if defined(HAVE_SETHOSTENT) && defined(HAVE_ENDHOSTENT)
370312ae
GH
421SCM_PROC (s_sethost, "sethost", 0, 1, 0, scm_sethost);
422
423SCM
424scm_sethost (arg)
425 SCM arg;
426{
427 if (SCM_UNBNDP (arg))
428 endhostent ();
429 else
430 sethostent (SCM_NFALSEP (arg));
431 return SCM_UNSPECIFIED;
432}
0e958795 433#endif
370312ae 434
0e958795 435#if defined(HAVE_SETNETENT) && defined(HAVE_ENDNETENT)
370312ae
GH
436SCM_PROC (s_setnet, "setnet", 0, 1, 0, scm_setnet);
437
438SCM
439scm_setnet (arg)
440 SCM arg;
441{
442 if (SCM_UNBNDP (arg))
443 endnetent ();
444 else
445 setnetent (SCM_NFALSEP (arg));
446 return SCM_UNSPECIFIED;
447}
0e958795 448#endif
370312ae 449
0e958795 450#if defined(HAVE_SETPROTOENT) && defined(HAVE_ENDPROTOENT)
370312ae
GH
451SCM_PROC (s_setproto, "setproto", 0, 1, 0, scm_setproto);
452
453SCM
454scm_setproto (arg)
455 SCM arg;
456{
457 if (SCM_UNBNDP (arg))
458 endprotoent ();
459 else
460 setprotoent (SCM_NFALSEP (arg));
461 return SCM_UNSPECIFIED;
462}
0e958795 463#endif
370312ae 464
0e958795 465#if defined(HAVE_SETSERVENT) && defined(HAVE_ENDSERVENT)
370312ae
GH
466SCM_PROC (s_setserv, "setserv", 0, 1, 0, scm_setserv);
467
468SCM
469scm_setserv (arg)
470 SCM arg;
471{
472 if (SCM_UNBNDP (arg))
473 endservent ();
474 else
475 setservent (SCM_NFALSEP (arg));
476 return SCM_UNSPECIFIED;
477}
0e958795 478#endif
370312ae
GH
479
480
481void
482scm_init_net_db ()
483{
484#ifdef INADDR_ANY
485 scm_sysintern ("INADDR_ANY", scm_ulong2num (INADDR_ANY));
486#endif
487#ifdef INADDR_BROADCAST
488 scm_sysintern ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST));
489#endif
490#ifdef INADDR_NONE
491 scm_sysintern ("INADDR_NONE", scm_ulong2num (INADDR_NONE));
492#endif
493#ifdef INADDR_LOOPBACK
494 scm_sysintern ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK));
495#endif
496
497 scm_add_feature ("net-db");
498#include "net_db.x"
499}