* __scm.h, alist.c, alist.h, append.c, append.h, appinit.c,
[bpt/guile.git] / libguile / socket.c
CommitLineData
0f2d19dd 1/* "socket.c" internet socket support for client/server in SCM
86667910
JB
2 * Copyright (C) 1995,1996 Free Software Foundation, Inc.
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
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice.
41 */
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 */
0f2d19dd
JB
47\f
48
49#include <stdio.h>
0f2d19dd 50#include "_scm.h"
20e6290e
JB
51#include "feature.h"
52
53#include "socket.h"
95b88819
GH
54
55#ifdef HAVE_STRING_H
56#include <string.h>
57#endif
58
0f2d19dd
JB
59#include <sys/types.h>
60#include <sys/socket.h>
61#include <sys/un.h>
62#include <netinet/in.h>
63#include <netdb.h>
64#include <arpa/inet.h>
65
66\f
67
68#ifndef STDC_HEADERS
69int close P ((int fd));
70#endif /* STDC_HEADERS */
71
82ddea4e 72extern int inet_aton ();
82ddea4e 73
02b754d3 74SCM_PROC (s_sys_inet_aton, "inet-aton", 1, 0, 0, scm_sys_inet_aton);
0f2d19dd
JB
75#ifdef __STDC__
76SCM
77scm_sys_inet_aton (SCM address)
78#else
79SCM
80scm_sys_inet_aton (address)
81 SCM address;
82#endif
83{
84 struct in_addr soka;
2e18892a 85
0f2d19dd
JB
86 SCM_ASSERT (SCM_NIMP (address) && SCM_ROSTRINGP (address), address, SCM_ARG1, s_sys_inet_aton);
87 if (SCM_SUBSTRP (address))
88 address = scm_makfromstr (SCM_ROCHARS (address), SCM_ROLENGTH (address), 0);
02b754d3 89 if (inet_aton (SCM_ROCHARS (address), &soka) == 0)
52859adf 90 scm_syserror (s_sys_inet_aton);
02b754d3 91 return scm_ulong2num (ntohl (soka.s_addr));
0f2d19dd
JB
92}
93
94
95SCM_PROC (s_inet_ntoa, "inet-ntoa", 1, 0, 0, scm_inet_ntoa);
96#ifdef __STDC__
97SCM
98scm_inet_ntoa (SCM inetid)
99#else
100SCM
101scm_inet_ntoa (inetid)
102 SCM inetid;
103#endif
104{
105 struct in_addr addr;
106 char *s;
107 SCM answer;
108 addr.s_addr = htonl (scm_num2ulong (inetid, (char *) SCM_ARG1, s_inet_ntoa));
109 SCM_DEFER_INTS;
110 s = inet_ntoa (addr);
111 answer = scm_makfromstr (s, strlen (s), 0);
112 SCM_ALLOW_INTS;
113 return answer;
114}
115
116SCM_PROC (s_inet_netof, "inet-netof", 1, 0, 0, scm_inet_netof);
117#ifdef __STDC__
118SCM
119scm_inet_netof (SCM address)
120#else
121SCM
122scm_inet_netof (address)
123 SCM address;
124#endif
125{
126 struct in_addr addr;
127 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_inet_netof));
128 return scm_ulong2num ((unsigned long) inet_netof (addr));
129}
130
131SCM_PROC (s_lnaof, "lnaof", 1, 0, 0, scm_lnaof);
132#ifdef __STDC__
133SCM
134scm_lnaof (SCM address)
135#else
136SCM
137scm_lnaof (address)
138 SCM address;
139#endif
140{
141 struct in_addr addr;
142 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_lnaof));
143 return scm_ulong2num ((unsigned long) inet_lnaof (addr));
144}
145
146
147SCM_PROC (s_inet_makeaddr, "inet-makeaddr", 2, 0, 0, scm_inet_makeaddr);
148#ifdef __STDC__
149SCM
150scm_inet_makeaddr (SCM net, SCM lna)
151#else
152SCM
153scm_inet_makeaddr (net, lna)
154 SCM net;
155 SCM lna;
156#endif
157{
158 struct in_addr addr;
159 unsigned long netnum;
160 unsigned long lnanum;
161
162 netnum = scm_num2ulong (net, (char *) SCM_ARG1, s_inet_makeaddr);
163 lnanum = scm_num2ulong (lna, (char *) SCM_ARG2, s_inet_makeaddr);
164 addr = inet_makeaddr (netnum, lnanum);
165 return scm_ulong2num (ntohl (addr.s_addr));
166}
167
168
169/* !!! Doesn't take address format.
170 * Assumes hostent stream isn't reused.
171 */
172
02b754d3 173SCM_PROC (s_sys_gethost, "gethost", 0, 1, 0, scm_sys_gethost);
0f2d19dd
JB
174#ifdef __STDC__
175SCM
176scm_sys_gethost (SCM name)
177#else
178SCM
179scm_sys_gethost (name)
180 SCM name;
181#endif
182{
183 SCM ans = scm_make_vector (SCM_MAKINUM (5), SCM_UNSPECIFIED, SCM_BOOL_F);
184 SCM *ve = SCM_VELTS (ans);
185 SCM lst = SCM_EOL;
186 struct hostent *entry;
187 struct in_addr inad;
188 char **argv;
189 int i = 0;
190#ifdef HAVE_GETHOSTENT
191 if (SCM_UNBNDP (name))
192 {
193 SCM_DEFER_INTS;
194 entry = gethostent ();
195 }
196 else
197#endif
198 if (SCM_NIMP (name) && SCM_STRINGP (name))
199 {
200 SCM_DEFER_INTS;
201 entry = gethostbyname (SCM_CHARS (name));
202 }
203 else
204 {
205 inad.s_addr = htonl (scm_num2ulong (name, (char *) SCM_ARG1, s_sys_gethost));
206 SCM_DEFER_INTS;
207 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
208 }
209 SCM_ALLOW_INTS;
210 if (!entry)
52859adf 211 scm_syserror (s_sys_gethost);
0f2d19dd
JB
212 ve[0] = scm_makfromstr (entry->h_name, (scm_sizet) strlen (entry->h_name), 0);
213 ve[1] = scm_makfromstrs (-1, entry->h_aliases);
214 ve[2] = SCM_MAKINUM (entry->h_addrtype + 0L);
215 ve[3] = SCM_MAKINUM (entry->h_length + 0L);
216 if (sizeof (struct in_addr) != entry->h_length)
217 {
218 ve[4] = SCM_BOOL_F;
219 return ans;
220 }
221 for (argv = entry->h_addr_list; argv[i]; i++);
222 while (i--)
223 {
224 inad = *(struct in_addr *) argv[i];
225 lst = scm_cons (scm_ulong2num (ntohl (inad.s_addr)), lst);
226 }
227 ve[4] = lst;
228 return ans;
229}
230
231
02b754d3 232SCM_PROC (s_sys_getnet, "getnet", 0, 1, 0, scm_sys_getnet);
0f2d19dd
JB
233#ifdef __STDC__
234SCM
235scm_sys_getnet (SCM name)
236#else
237SCM
238scm_sys_getnet (name)
239 SCM name;
240#endif
241{
242 SCM ans;
243 SCM *ve;
244 struct netent *entry;
245
246 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
247 ve = SCM_VELTS (ans);
248 if (SCM_UNBNDP (name))
249 {
250 SCM_DEFER_INTS;
251 entry = getnetent ();
252 }
253 else if (SCM_NIMP (name) && SCM_STRINGP (name))
254 {
255 SCM_DEFER_INTS;
256 entry = getnetbyname (SCM_CHARS (name));
257 }
258 else
259 {
260 unsigned long netnum;
261 netnum = scm_num2ulong (name, (char *) SCM_ARG1, s_sys_getnet);
262 SCM_DEFER_INTS;
263 entry = getnetbyaddr (netnum, AF_INET);
264 }
265 SCM_ALLOW_INTS;
266 if (!entry)
52859adf 267 scm_syserror (s_sys_getnet);
0f2d19dd
JB
268 ve[0] = scm_makfromstr (entry->n_name, (scm_sizet) strlen (entry->n_name), 0);
269 ve[1] = scm_makfromstrs (-1, entry->n_aliases);
270 ve[2] = SCM_MAKINUM (entry->n_addrtype + 0L);
271 ve[3] = scm_ulong2num (entry->n_net + 0L);
272 return ans;
273}
274
02b754d3 275SCM_PROC (s_sys_getproto, "getproto", 0, 1, 0, scm_sys_getproto);
0f2d19dd
JB
276#ifdef __STDC__
277SCM
278scm_sys_getproto (SCM name)
279#else
280SCM
281scm_sys_getproto (name)
282 SCM name;
283#endif
284{
285 SCM ans;
286 SCM *ve;
287 struct protoent *entry;
288
289 ans = scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED, SCM_BOOL_F);
290 ve = SCM_VELTS (ans);
291 if (SCM_UNBNDP (name))
292 {
293 SCM_DEFER_INTS;
294 entry = getprotoent ();
295 }
296 else if (SCM_NIMP (name) && SCM_STRINGP (name))
297 {
298 SCM_DEFER_INTS;
299 entry = getprotobyname (SCM_CHARS (name));
300 }
301 else
302 {
303 unsigned long protonum;
304 protonum = scm_num2ulong (name, (char *) SCM_ARG1, s_sys_getproto);
305 SCM_DEFER_INTS;
306 entry = getprotobynumber (protonum);
307 }
308 SCM_ALLOW_INTS;
309 if (!entry)
52859adf 310 scm_syserror (s_sys_getproto);
0f2d19dd
JB
311 ve[0] = scm_makfromstr (entry->p_name, (scm_sizet) strlen (entry->p_name), 0);
312 ve[1] = scm_makfromstrs (-1, entry->p_aliases);
313 ve[2] = SCM_MAKINUM (entry->p_proto + 0L);
314 return ans;
315}
316
317#ifdef __STDC__
318static SCM
319scm_return_entry (struct servent *entry)
320#else
321static SCM
322scm_return_entry (entry)
323 struct servent *entry;
324#endif
325{
326 SCM ans;
327 SCM *ve;
328
329 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
330 ve = SCM_VELTS (ans);
0f2d19dd
JB
331 ve[0] = scm_makfromstr (entry->s_name, (scm_sizet) strlen (entry->s_name), 0);
332 ve[1] = scm_makfromstrs (-1, entry->s_aliases);
333 ve[2] = SCM_MAKINUM (ntohs (entry->s_port) + 0L);
334 ve[3] = scm_makfromstr (entry->s_proto, (scm_sizet) strlen (entry->s_proto), 0);
335 SCM_ALLOW_INTS;
336 return ans;
337}
338
02b754d3 339SCM_PROC (s_sys_getserv, "getserv", 0, 2, 0, scm_sys_getserv);
0f2d19dd
JB
340#ifdef __STDC__
341SCM
342scm_sys_getserv (SCM name, SCM proto)
343#else
344SCM
345scm_sys_getserv (name, proto)
346 SCM name;
347 SCM proto;
348#endif
349{
350 struct servent *entry;
351 if (SCM_UNBNDP (name))
352 {
353 SCM_DEFER_INTS;
354 entry = getservent ();
02b754d3 355 if (!entry)
52859adf 356 scm_syserror (s_sys_getserv);
0f2d19dd
JB
357 return scm_return_entry (entry);
358 }
359 SCM_ASSERT (SCM_NIMP (proto) && SCM_STRINGP (proto), proto, SCM_ARG2, s_sys_getserv);
360 if (SCM_NIMP (name) && SCM_STRINGP (name))
361 {
362 SCM_DEFER_INTS;
363 entry = getservbyname (SCM_CHARS (name), SCM_CHARS (proto));
364 }
365 else
366 {
367 SCM_ASSERT (SCM_INUMP (name), name, SCM_ARG1, s_sys_getserv);
368 SCM_DEFER_INTS;
369 entry = getservbyport (SCM_INUM (name), SCM_CHARS (proto));
370 }
02b754d3 371 if (!entry)
52859adf 372 scm_syserror (s_sys_getserv);
0f2d19dd
JB
373 return scm_return_entry (entry);
374}
375
376SCM_PROC (s_sethost, "sethost", 0, 1, 0, scm_sethost);
377#ifdef __STDC__
378SCM
379scm_sethost (SCM arg)
380#else
381SCM
382scm_sethost (arg)
383 SCM arg;
384#endif
385{
386 if (SCM_UNBNDP (arg))
387 endhostent ();
388 else
389 sethostent (SCM_NFALSEP (arg));
390 return SCM_UNSPECIFIED;
391}
392
393SCM_PROC (s_setnet, "setnet", 0, 1, 0, scm_setnet);
394#ifdef __STDC__
395SCM
396scm_setnet (SCM arg)
397#else
398SCM
399scm_setnet (arg)
400 SCM arg;
401#endif
402{
403 if (SCM_UNBNDP (arg))
404 endnetent ();
405 else
406 setnetent (SCM_NFALSEP (arg));
407 return SCM_UNSPECIFIED;
408}
409
410SCM_PROC (s_setproto, "setproto", 0, 1, 0, scm_setproto);
411#ifdef __STDC__
412SCM
413scm_setproto (SCM arg)
414#else
415SCM
416scm_setproto (arg)
417 SCM arg;
418#endif
419{
420 if (SCM_UNBNDP (arg))
421 endprotoent ();
422 else
423 setprotoent (SCM_NFALSEP (arg));
424 return SCM_UNSPECIFIED;
425}
426
427SCM_PROC (s_setserv, "setserv", 0, 1, 0, scm_setserv);
428#ifdef __STDC__
429SCM
430scm_setserv (SCM arg)
431#else
432SCM
433scm_setserv (arg)
434 SCM arg;
435#endif
436{
437 if (SCM_UNBNDP (arg))
438 endservent ();
439 else
440 setservent (SCM_NFALSEP (arg));
441 return SCM_UNSPECIFIED;
442}
443
444#ifdef __STDC__
445void
446scm_init_socket (void)
447#else
448void
449scm_init_socket ()
450#endif
451{
452 scm_add_feature ("socket");
453#include "socket.x"
454}
455
456