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