C files should #include only the header files they need, not
[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"
95b88819
GH
51
52#ifdef HAVE_STRING_H
53#include <string.h>
54#endif
55
0f2d19dd
JB
56#include <sys/types.h>
57#include <sys/socket.h>
58#include <sys/un.h>
59#include <netinet/in.h>
60#include <netdb.h>
61#include <arpa/inet.h>
62
63\f
64
65#ifndef STDC_HEADERS
66int close P ((int fd));
67#endif /* STDC_HEADERS */
68
82ddea4e 69extern int inet_aton ();
82ddea4e 70
02b754d3 71SCM_PROC (s_sys_inet_aton, "inet-aton", 1, 0, 0, scm_sys_inet_aton);
0f2d19dd
JB
72#ifdef __STDC__
73SCM
74scm_sys_inet_aton (SCM address)
75#else
76SCM
77scm_sys_inet_aton (address)
78 SCM address;
79#endif
80{
81 struct in_addr soka;
2e18892a 82
0f2d19dd
JB
83 SCM_ASSERT (SCM_NIMP (address) && SCM_ROSTRINGP (address), address, SCM_ARG1, s_sys_inet_aton);
84 if (SCM_SUBSTRP (address))
85 address = scm_makfromstr (SCM_ROCHARS (address), SCM_ROLENGTH (address), 0);
02b754d3
GH
86 if (inet_aton (SCM_ROCHARS (address), &soka) == 0)
87 SCM_SYSERROR (s_sys_inet_aton);
88 return scm_ulong2num (ntohl (soka.s_addr));
0f2d19dd
JB
89}
90
91
92SCM_PROC (s_inet_ntoa, "inet-ntoa", 1, 0, 0, scm_inet_ntoa);
93#ifdef __STDC__
94SCM
95scm_inet_ntoa (SCM inetid)
96#else
97SCM
98scm_inet_ntoa (inetid)
99 SCM inetid;
100#endif
101{
102 struct in_addr addr;
103 char *s;
104 SCM answer;
105 addr.s_addr = htonl (scm_num2ulong (inetid, (char *) SCM_ARG1, s_inet_ntoa));
106 SCM_DEFER_INTS;
107 s = inet_ntoa (addr);
108 answer = scm_makfromstr (s, strlen (s), 0);
109 SCM_ALLOW_INTS;
110 return answer;
111}
112
113SCM_PROC (s_inet_netof, "inet-netof", 1, 0, 0, scm_inet_netof);
114#ifdef __STDC__
115SCM
116scm_inet_netof (SCM address)
117#else
118SCM
119scm_inet_netof (address)
120 SCM address;
121#endif
122{
123 struct in_addr addr;
124 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_inet_netof));
125 return scm_ulong2num ((unsigned long) inet_netof (addr));
126}
127
128SCM_PROC (s_lnaof, "lnaof", 1, 0, 0, scm_lnaof);
129#ifdef __STDC__
130SCM
131scm_lnaof (SCM address)
132#else
133SCM
134scm_lnaof (address)
135 SCM address;
136#endif
137{
138 struct in_addr addr;
139 addr.s_addr = htonl (scm_num2ulong (address, (char *) SCM_ARG1, s_lnaof));
140 return scm_ulong2num ((unsigned long) inet_lnaof (addr));
141}
142
143
144SCM_PROC (s_inet_makeaddr, "inet-makeaddr", 2, 0, 0, scm_inet_makeaddr);
145#ifdef __STDC__
146SCM
147scm_inet_makeaddr (SCM net, SCM lna)
148#else
149SCM
150scm_inet_makeaddr (net, lna)
151 SCM net;
152 SCM lna;
153#endif
154{
155 struct in_addr addr;
156 unsigned long netnum;
157 unsigned long lnanum;
158
159 netnum = scm_num2ulong (net, (char *) SCM_ARG1, s_inet_makeaddr);
160 lnanum = scm_num2ulong (lna, (char *) SCM_ARG2, s_inet_makeaddr);
161 addr = inet_makeaddr (netnum, lnanum);
162 return scm_ulong2num (ntohl (addr.s_addr));
163}
164
165
166/* !!! Doesn't take address format.
167 * Assumes hostent stream isn't reused.
168 */
169
02b754d3 170SCM_PROC (s_sys_gethost, "gethost", 0, 1, 0, scm_sys_gethost);
0f2d19dd
JB
171#ifdef __STDC__
172SCM
173scm_sys_gethost (SCM name)
174#else
175SCM
176scm_sys_gethost (name)
177 SCM name;
178#endif
179{
180 SCM ans = scm_make_vector (SCM_MAKINUM (5), SCM_UNSPECIFIED, SCM_BOOL_F);
181 SCM *ve = SCM_VELTS (ans);
182 SCM lst = SCM_EOL;
183 struct hostent *entry;
184 struct in_addr inad;
185 char **argv;
186 int i = 0;
187#ifdef HAVE_GETHOSTENT
188 if (SCM_UNBNDP (name))
189 {
190 SCM_DEFER_INTS;
191 entry = gethostent ();
192 }
193 else
194#endif
195 if (SCM_NIMP (name) && SCM_STRINGP (name))
196 {
197 SCM_DEFER_INTS;
198 entry = gethostbyname (SCM_CHARS (name));
199 }
200 else
201 {
202 inad.s_addr = htonl (scm_num2ulong (name, (char *) SCM_ARG1, s_sys_gethost));
203 SCM_DEFER_INTS;
204 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
205 }
206 SCM_ALLOW_INTS;
207 if (!entry)
02b754d3 208 SCM_SYSERROR (s_sys_gethost);
0f2d19dd
JB
209 ve[0] = scm_makfromstr (entry->h_name, (scm_sizet) strlen (entry->h_name), 0);
210 ve[1] = scm_makfromstrs (-1, entry->h_aliases);
211 ve[2] = SCM_MAKINUM (entry->h_addrtype + 0L);
212 ve[3] = SCM_MAKINUM (entry->h_length + 0L);
213 if (sizeof (struct in_addr) != entry->h_length)
214 {
215 ve[4] = SCM_BOOL_F;
216 return ans;
217 }
218 for (argv = entry->h_addr_list; argv[i]; i++);
219 while (i--)
220 {
221 inad = *(struct in_addr *) argv[i];
222 lst = scm_cons (scm_ulong2num (ntohl (inad.s_addr)), lst);
223 }
224 ve[4] = lst;
225 return ans;
226}
227
228
02b754d3 229SCM_PROC (s_sys_getnet, "getnet", 0, 1, 0, scm_sys_getnet);
0f2d19dd
JB
230#ifdef __STDC__
231SCM
232scm_sys_getnet (SCM name)
233#else
234SCM
235scm_sys_getnet (name)
236 SCM name;
237#endif
238{
239 SCM ans;
240 SCM *ve;
241 struct netent *entry;
242
243 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
244 ve = SCM_VELTS (ans);
245 if (SCM_UNBNDP (name))
246 {
247 SCM_DEFER_INTS;
248 entry = getnetent ();
249 }
250 else if (SCM_NIMP (name) && SCM_STRINGP (name))
251 {
252 SCM_DEFER_INTS;
253 entry = getnetbyname (SCM_CHARS (name));
254 }
255 else
256 {
257 unsigned long netnum;
258 netnum = scm_num2ulong (name, (char *) SCM_ARG1, s_sys_getnet);
259 SCM_DEFER_INTS;
260 entry = getnetbyaddr (netnum, AF_INET);
261 }
262 SCM_ALLOW_INTS;
263 if (!entry)
02b754d3 264 SCM_SYSERROR (s_sys_getnet);
0f2d19dd
JB
265 ve[0] = scm_makfromstr (entry->n_name, (scm_sizet) strlen (entry->n_name), 0);
266 ve[1] = scm_makfromstrs (-1, entry->n_aliases);
267 ve[2] = SCM_MAKINUM (entry->n_addrtype + 0L);
268 ve[3] = scm_ulong2num (entry->n_net + 0L);
269 return ans;
270}
271
02b754d3 272SCM_PROC (s_sys_getproto, "getproto", 0, 1, 0, scm_sys_getproto);
0f2d19dd
JB
273#ifdef __STDC__
274SCM
275scm_sys_getproto (SCM name)
276#else
277SCM
278scm_sys_getproto (name)
279 SCM name;
280#endif
281{
282 SCM ans;
283 SCM *ve;
284 struct protoent *entry;
285
286 ans = scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED, SCM_BOOL_F);
287 ve = SCM_VELTS (ans);
288 if (SCM_UNBNDP (name))
289 {
290 SCM_DEFER_INTS;
291 entry = getprotoent ();
292 }
293 else if (SCM_NIMP (name) && SCM_STRINGP (name))
294 {
295 SCM_DEFER_INTS;
296 entry = getprotobyname (SCM_CHARS (name));
297 }
298 else
299 {
300 unsigned long protonum;
301 protonum = scm_num2ulong (name, (char *) SCM_ARG1, s_sys_getproto);
302 SCM_DEFER_INTS;
303 entry = getprotobynumber (protonum);
304 }
305 SCM_ALLOW_INTS;
306 if (!entry)
02b754d3 307 SCM_SYSERROR (s_sys_getproto);
0f2d19dd
JB
308 ve[0] = scm_makfromstr (entry->p_name, (scm_sizet) strlen (entry->p_name), 0);
309 ve[1] = scm_makfromstrs (-1, entry->p_aliases);
310 ve[2] = SCM_MAKINUM (entry->p_proto + 0L);
311 return ans;
312}
313
314#ifdef __STDC__
315static SCM
316scm_return_entry (struct servent *entry)
317#else
318static SCM
319scm_return_entry (entry)
320 struct servent *entry;
321#endif
322{
323 SCM ans;
324 SCM *ve;
325
326 ans = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED, SCM_BOOL_F);
327 ve = SCM_VELTS (ans);
0f2d19dd
JB
328 ve[0] = scm_makfromstr (entry->s_name, (scm_sizet) strlen (entry->s_name), 0);
329 ve[1] = scm_makfromstrs (-1, entry->s_aliases);
330 ve[2] = SCM_MAKINUM (ntohs (entry->s_port) + 0L);
331 ve[3] = scm_makfromstr (entry->s_proto, (scm_sizet) strlen (entry->s_proto), 0);
332 SCM_ALLOW_INTS;
333 return ans;
334}
335
02b754d3 336SCM_PROC (s_sys_getserv, "getserv", 0, 2, 0, scm_sys_getserv);
0f2d19dd
JB
337#ifdef __STDC__
338SCM
339scm_sys_getserv (SCM name, SCM proto)
340#else
341SCM
342scm_sys_getserv (name, proto)
343 SCM name;
344 SCM proto;
345#endif
346{
347 struct servent *entry;
348 if (SCM_UNBNDP (name))
349 {
350 SCM_DEFER_INTS;
351 entry = getservent ();
02b754d3
GH
352 if (!entry)
353 SCM_SYSERROR (s_sys_getserv);
0f2d19dd
JB
354 return scm_return_entry (entry);
355 }
356 SCM_ASSERT (SCM_NIMP (proto) && SCM_STRINGP (proto), proto, SCM_ARG2, s_sys_getserv);
357 if (SCM_NIMP (name) && SCM_STRINGP (name))
358 {
359 SCM_DEFER_INTS;
360 entry = getservbyname (SCM_CHARS (name), SCM_CHARS (proto));
361 }
362 else
363 {
364 SCM_ASSERT (SCM_INUMP (name), name, SCM_ARG1, s_sys_getserv);
365 SCM_DEFER_INTS;
366 entry = getservbyport (SCM_INUM (name), SCM_CHARS (proto));
367 }
02b754d3
GH
368 if (!entry)
369 SCM_SYSERROR (s_sys_getserv);
0f2d19dd
JB
370 return scm_return_entry (entry);
371}
372
373SCM_PROC (s_sethost, "sethost", 0, 1, 0, scm_sethost);
374#ifdef __STDC__
375SCM
376scm_sethost (SCM arg)
377#else
378SCM
379scm_sethost (arg)
380 SCM arg;
381#endif
382{
383 if (SCM_UNBNDP (arg))
384 endhostent ();
385 else
386 sethostent (SCM_NFALSEP (arg));
387 return SCM_UNSPECIFIED;
388}
389
390SCM_PROC (s_setnet, "setnet", 0, 1, 0, scm_setnet);
391#ifdef __STDC__
392SCM
393scm_setnet (SCM arg)
394#else
395SCM
396scm_setnet (arg)
397 SCM arg;
398#endif
399{
400 if (SCM_UNBNDP (arg))
401 endnetent ();
402 else
403 setnetent (SCM_NFALSEP (arg));
404 return SCM_UNSPECIFIED;
405}
406
407SCM_PROC (s_setproto, "setproto", 0, 1, 0, scm_setproto);
408#ifdef __STDC__
409SCM
410scm_setproto (SCM arg)
411#else
412SCM
413scm_setproto (arg)
414 SCM arg;
415#endif
416{
417 if (SCM_UNBNDP (arg))
418 endprotoent ();
419 else
420 setprotoent (SCM_NFALSEP (arg));
421 return SCM_UNSPECIFIED;
422}
423
424SCM_PROC (s_setserv, "setserv", 0, 1, 0, scm_setserv);
425#ifdef __STDC__
426SCM
427scm_setserv (SCM arg)
428#else
429SCM
430scm_setserv (arg)
431 SCM arg;
432#endif
433{
434 if (SCM_UNBNDP (arg))
435 endservent ();
436 else
437 setservent (SCM_NFALSEP (arg));
438 return SCM_UNSPECIFIED;
439}
440
441#ifdef __STDC__
442void
443scm_init_socket (void)
444#else
445void
446scm_init_socket ()
447#endif
448{
449 scm_add_feature ("socket");
450#include "socket.x"
451}
452
453