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