1 /*
2 * guile-api.c - export additional Serveez functionality to Guile
3 *
4 * Copyright (C) 2011-2013 Thien-Thi Nguyen
5 * Copyright (C) 2001, 2002, 2003 Stefan Jahn <stefan@lkcc.org>
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this package. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #if ENABLE_GUILE_SERVER
24
25 #include <string.h>
26 #include <errno.h>
27
28 #ifndef __MINGW32__
29 # include <sys/socket.h>
30 # include <netdb.h>
31 #endif
32
33 #if HAVE_RPC_RPCENT_H
34 # include <rpc/rpcent.h>
35 #endif
36 #if HAVE_RPC_RPC_H
37 # include <rpc/rpc.h>
38 #endif
39 #if HAVE_RPC_CLNT_SOC_H
40 # include <rpc/clnt_soc.h>
41 #endif
42 #if HAVE_RPC_PMAP_CLNT_H
43 # include <rpc/pmap_clnt.h>
44 #endif
45 #if HAVE_RPC_PMAP_PROT_H
46 # include <rpc/pmap_prot.h>
47 #endif
48 #if HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif
51 #if HAVE_IO_H
52 # include <io.h>
53 #endif
54
55 #include <libguile.h>
56 #include "networking-headers.h"
57 #include "libserveez.h"
58 #include "guile-missing.h"
59
60 /* Validate network port range. */
61 #define VALIDATE_NETPORT(port, cell, arg) do { \
62 (port) = gi_scm2long (cell); \
63 if ((port) < 0 || (port) >= 65536) SCM_OUT_OF_RANGE (arg, cell); \
64 } while (0)
65
66
67 /* Converts the given hostname @var{host} into a Internet address in host
68 byte order and stores it into @var{addr}. Returns zero on success. This
69 is a blocking operation. */
70 static int
guile_resolve(char * host,in_addr_t * addr)71 guile_resolve (char *host, in_addr_t *addr)
72 {
73 struct hostent *ent;
74
75 if ((ent = gethostbyname (host)) == NULL)
76 return -1;
77 if (ent->h_addrtype == AF_INET)
78 {
79 memcpy (addr, ent->h_addr_list[0], ent->h_length);
80 return 0;
81 }
82 return -1;
83 }
84
85 SCM_DEFINE
86 (guile_sock_connect,
87 "svz:sock:connect", 2, 1, 0,
88 (SCM host, SCM proto, SCM port),
89 doc: /***********
90 Establish a network connection to the given @var{host} [ :@var{port} ].
91 If @var{proto} equals @code{PROTO_ICMP} the @var{port} argument is
92 ignored. Valid identifiers for @var{proto} are @code{PROTO_TCP},
93 @code{PROTO_UDP} and @code{PROTO_ICMP}. The @var{host} argument must be
94 either a string in dotted decimal form, a valid hostname or an exact number
95 in host byte order. When giving a hostname this operation might block.
96 The @var{port} argument must be an exact number in the range from
97 0 to 65535, also in host byte order. Return a valid @code{#<svz-socket>}
98 or @code{#f} on failure. */)
99 {
100 #define FUNC_NAME s_guile_sock_connect
101 svz_socket_t *sock;
102 in_addr_t v4addr;
103 svz_address_t *xhost;
104 in_port_t xport = 0;
105 long p;
106 int xproto;
107 struct sockaddr_in addr;
108 SCM ret = SCM_BOOL_F;
109
110 SCM_ASSERT_TYPE (gi_exactp (host) || gi_stringp (host),
111 host, SCM_ARG1, FUNC_NAME, "string or exact");
112 ASSERT_EXACT (2, proto);
113
114 /* Extract host to connect to. */
115 if (gi_exactp (host))
116 v4addr = htonl (gi_scm2int (host));
117 else
118 {
119 char str[128];
120
121 GI_GET_XREP (str, host);
122 if (svz_inet_aton (str, &addr) == -1)
123 {
124 if (guile_resolve (str, &v4addr) == -1)
125 {
126 guile_error ("%s: IP in dotted decimals or hostname expected",
127 FUNC_NAME);
128 return ret;
129 }
130 }
131 else
132 v4addr = addr.sin_addr.s_addr;
133 }
134 xhost = svz_address_make (AF_INET, &v4addr);
135
136 /* Extract protocol to use. */
137 xproto = gi_scm2int (proto);
138
139 /* Find out about given port. */
140 if (BOUNDP (port))
141 {
142 ASSERT_EXACT (3, port);
143 VALIDATE_NETPORT (p, port, SCM_ARG3);
144 xport = htons (p);
145 }
146
147 /* Depending on the requested protocol; create different kinds of
148 socket structures. */
149 switch (xproto)
150 {
151 case SVZ_PROTO_TCP:
152 sock = svz_tcp_connect (xhost, xport);
153 break;
154 case SVZ_PROTO_UDP:
155 sock = svz_udp_connect (xhost, xport);
156 break;
157 case SVZ_PROTO_ICMP:
158 sock = svz_icmp_connect (xhost, xport, SVZ_ICMP_SERVEEZ);
159 break;
160 default:
161 SCM_OUT_OF_RANGE (SCM_ARG2, proto);
162 }
163 svz_free (xhost);
164
165 if (sock == NULL)
166 return ret;
167
168 sock->disconnected_socket = guile_func_disconnected_socket;
169 return socket_smob (sock);
170 #undef FUNC_NAME
171 }
172
173 #if GUILE_MISSING_inet_ntoa
174 SCM_DEFINE
175 (guile_svz_inet_ntoa,
176 "inet-ntoa", 1, 0, 0,
177 (SCM address),
178 doc: /***********
179 Convert the Internet host address
180 @var{address} given in network byte order to a string in standard
181 numbers-and-dots notation. */)
182 {
183 #define FUNC_NAME s_guile_svz_inet_ntoa
184 char *str;
185 ASSERT_EXACT (1, address);
186 str = svz_inet_ntoa (gi_scm2ulong (address));
187 return gi_string2scm (str);
188 #undef FUNC_NAME
189 }
190 #endif /* GUILE_MISSING_inet_ntoa */
191
192 #if GUILE_MISSING_inet_aton
193 SCM_DEFINE
194 (guile_svz_inet_aton,
195 "inet-aton", 1, 0, 0,
196 (SCM address),
197 doc: /***********
198 Convert the Internet host address @var{address} from the standard
199 numbers-and-dots notation into binary data in network byte order.
200 Return @code{#f} if the address is invalid. */)
201 {
202 #define FUNC_NAME s_guile_svz_inet_aton
203 struct sockaddr_in addr;
204 char str[48];
205
206 ASSERT_STRING (1, address);
207 GI_GET_XREP (str, address);
208 if (svz_inet_aton (str, &addr) == -1)
209 {
210 guile_error ("%s: IP address in dotted decimals expected", FUNC_NAME);
211 return SCM_BOOL_F;
212 }
213 return gi_nnint2scm (addr.sin_addr.s_addr);
214 #undef FUNC_NAME
215 }
216 #endif /* GUILE_MISSING_inet_aton */
217
218 #if GUILE_MISSING_ntohl
219 SCM_DEFINE
220 (guile_svz_ntohl,
221 "ntohl", 1, 0, 0,
222 (SCM netlong),
223 doc: /***********
224 Convert the 32 bit long integer
225 @var{netlong} from network byte order to host byte order. */)
226 {
227 #define FUNC_NAME s_guile_svz_ntohl
228 ASSERT_EXACT (1, netlong);
229 return gi_nnint2scm (ntohl (gi_scm2ulong (netlong)));
230 #undef FUNC_NAME
231 }
232 #endif /* GUILE_MISSING_ntohl */
233
234 #if GUILE_MISSING_htonl
235 SCM_DEFINE
236 (guile_svz_htonl,
237 "htonl", 1, 0, 0,
238 (SCM hostlong),
239 doc: /***********
240 Convert the 32 bit long integer
241 @var{hostlong} from host byte order to network byte order. */)
242 {
243 #define FUNC_NAME s_guile_svz_htonl
244 ASSERT_EXACT (1, hostlong);
245 return gi_nnint2scm (htonl (gi_scm2ulong (hostlong)));
246 #undef FUNC_NAME
247 }
248 #endif /* GUILE_MISSING_htonl */
249
250 #if GUILE_MISSING_ntohs
251 SCM_DEFINE
252 (guile_svz_ntohs,
253 "ntohs", 1, 0, 0,
254 (SCM netshort),
255 doc: /***********
256 Convert the 16 bit short integer
257 @var{netshort} from network byte order to host byte order. */)
258 {
259 #define FUNC_NAME s_guile_svz_ntohs
260 long i;
261 ASSERT_EXACT (1, netshort);
262 VALIDATE_NETPORT (i, netshort, SCM_ARG1);
263 return gi_integer2scm (ntohs (i));
264 #undef FUNC_NAME
265 }
266 #endif /* GUILE_MISSING_ntohs */
267
268 #if GUILE_MISSING_htons
269 SCM_DEFINE
270 (guile_svz_htons,
271 "htons", 1, 0, 0,
272 (SCM hostshort),
273 doc: /***********
274 Convert the 16 bit short integer
275 @var{hostshort} from host byte order to network byte order. */)
276 {
277 #define FUNC_NAME s_guile_svz_htons
278 long i;
279 ASSERT_EXACT (1, hostshort);
280 VALIDATE_NETPORT (i, hostshort, SCM_ARG1);
281 return gi_integer2scm (htons (i));
282 #undef FUNC_NAME
283 }
284 #endif /* GUILE_MISSING_htons */
285
286 SCM_DEFINE
287 (guile_sock_receive_buffer,
288 "svz:sock:receive-buffer", 1, 0, 0,
289 (SCM sock),
290 doc: /***********
291 Return the receive buffer of the
292 socket @var{sock} as a binary smob. */)
293 {
294 #define FUNC_NAME s_guile_sock_receive_buffer
295 svz_socket_t *xsock;
296 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
297 return guile_data_to_bin (xsock->recv_buffer, xsock->recv_buffer_fill);
298 #undef FUNC_NAME
299 }
300
301 SCM_DEFINE
302 (guile_sock_receive_buffer_size,
303 "svz:sock:receive-buffer-size", 1, 1, 0,
304 (SCM sock, SCM size),
305 doc: /***********
306 Return the current receive buffers size and fill status in bytes of
307 the socket @var{sock} as a pair of exact numbers. If the optional
308 argument @var{size} is given, set the receive buffer to the
309 specified size in bytes. */)
310 {
311 #define FUNC_NAME s_guile_sock_receive_buffer_size
312 svz_socket_t *xsock;
313 int len;
314
315 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
316 if (BOUNDP (size))
317 {
318 ASSERT_EXACT (2, size);
319 len = gi_scm2int (size);
320 svz_sock_resize_buffers (xsock, xsock->send_buffer_size, len);
321 }
322 return scm_cons (gi_integer2scm (xsock->recv_buffer_size),
323 gi_integer2scm (xsock->recv_buffer_fill));
324 #undef FUNC_NAME
325 }
326
327 SCM_DEFINE
328 (guile_sock_send_buffer,
329 "svz:sock:send-buffer", 1, 0, 0,
330 (SCM sock),
331 doc: /***********
332 Return the send buffer of the
333 socket @var{sock} as a binary smob. */)
334 {
335 #define FUNC_NAME s_guile_sock_send_buffer
336 svz_socket_t *xsock;
337 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
338 return guile_data_to_bin (xsock->send_buffer, xsock->send_buffer_fill);
339 #undef FUNC_NAME
340 }
341
342 SCM_DEFINE
343 (guile_sock_send_buffer_size,
344 "svz:sock:send-buffer-size", 1, 1, 0,
345 (SCM sock, SCM size),
346 doc: /***********
347 Return the current send buffer size and fill status in
348 bytes of the socket @var{sock} as a pair of exact numbers. If the
349 optional argument @var{size} is given, set the send buffer to
350 the specified size in bytes. */)
351 {
352 #define FUNC_NAME s_guile_sock_send_buffer_size
353 svz_socket_t *xsock;
354 int len;
355
356 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
357 if (BOUNDP (size))
358 {
359 ASSERT_EXACT (2, size);
360 len = gi_scm2int (size);
361 svz_sock_resize_buffers (xsock, len, xsock->recv_buffer_size);
362 }
363 return scm_cons (gi_integer2scm (xsock->send_buffer_size),
364 gi_integer2scm (xsock->send_buffer_fill));
365 #undef FUNC_NAME
366 }
367
368 SCM_DEFINE
369 (guile_sock_receive_buffer_reduce,
370 "svz:sock:receive-buffer-reduce", 1, 1, 0,
371 (SCM sock, SCM length),
372 doc: /***********
373 Dequeue @var{length} bytes from the receive buffer of the
374 socket @var{sock}, or all bytes if @var{length} is omitted.
375 Return the number of bytes actually shuffled away. */)
376 {
377 #define FUNC_NAME s_guile_sock_receive_buffer_reduce
378 svz_socket_t *xsock;
379 int len;
380
381 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
382
383 /* Check if second length argument is given. */
384 if (BOUNDP (length))
385 {
386 ASSERT_EXACT (2, length);
387 len = gi_scm2int (length);
388 if (len < 0 || len > xsock->recv_buffer_fill)
389 SCM_OUT_OF_RANGE (SCM_ARG2, length);
390 }
391 else
392 {
393 len = xsock->recv_buffer_fill;
394 }
395 svz_sock_reduce_recv (xsock, len);
396 return gi_integer2scm (len);
397 #undef FUNC_NAME
398 }
399
400 SCM_DEFINE
401 (guile_sock_remote_address,
402 "svz:sock:remote-address", 1, 1, 0,
403 (SCM sock, SCM address),
404 doc: /***********
405 Return the current remote address as a pair like
406 @code{(host . port)} with both entries in network byte order. If you pass
407 the optional argument @var{address}, you can set the remote address of
408 the socket @var{sock}. */)
409 {
410 #define FUNC_NAME s_guile_sock_remote_address
411 svz_socket_t *xsock;
412 in_addr_t v4addr;
413 long port;
414 SCM pair;
415
416 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
417 svz_address_to (&v4addr, xsock->remote_addr);
418 pair = scm_cons (gi_nnint2scm (v4addr),
419 gi_integer2scm ((int) xsock->remote_port));
420 if (BOUNDP (address))
421 {
422 SCM_ASSERT_TYPE (SCM_PAIRP (address) && gi_exactp (SCM_CAR (address))
423 && gi_exactp (SCM_CDR (address)), address, SCM_ARG2,
424 FUNC_NAME, "pair of exact");
425 VALIDATE_NETPORT (port, SCM_CDR (address), SCM_ARG2);
426 v4addr = gi_scm2ulong (SCM_CAR (address));
427 SVZ_SET_ADDR (xsock->remote_addr, AF_INET, &v4addr);
428 xsock->remote_port = port;
429 }
430 return pair;
431 #undef FUNC_NAME
432 }
433
434 SCM_DEFINE
435 (guile_sock_local_address,
436 "svz:sock:local-address", 1, 1, 0,
437 (SCM sock, SCM address),
438 doc: /***********
439 Return the current local address as a pair like
440 @code{(host . port)} with both entries in network byte order. If you pass
441 the optional argument @var{address}, you can set the local address of
442 the socket @var{sock}. */)
443 {
444 #define FUNC_NAME s_guile_sock_local_address
445 svz_socket_t *xsock;
446 in_addr_t v4addr;
447 long port;
448 SCM pair;
449
450 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
451 svz_address_to (&v4addr, xsock->local_addr);
452 pair = scm_cons (gi_nnint2scm (v4addr),
453 gi_integer2scm ((int) xsock->local_port));
454 if (BOUNDP (address))
455 {
456 SCM_ASSERT_TYPE (SCM_PAIRP (address) && gi_exactp (SCM_CAR (address))
457 && gi_exactp (SCM_CDR (address)), address, SCM_ARG2,
458 FUNC_NAME, "pair of exact");
459 VALIDATE_NETPORT (port, SCM_CDR (address), SCM_ARG2);
460 v4addr = gi_scm2ulong (SCM_CAR (address));
461 SVZ_SET_ADDR (xsock->local_addr, AF_INET, &v4addr);
462 xsock->local_port = port;
463 }
464 return pair;
465 #undef FUNC_NAME
466 }
467
468 SCM_DEFINE
469 (guile_sock_parent,
470 "svz:sock:parent", 1, 1, 0,
471 (SCM sock, SCM parent),
472 doc: /***********
473 Return the given socket's @var{sock} parent and optionally set it to the
474 socket @var{parent}. Return either a valid
475 @code{#<svz-socket>} object or an empty list. */)
476 {
477 #define FUNC_NAME s_guile_sock_parent
478 SCM oparent = SCM_EOL;
479 svz_socket_t *xsock, *xparent;
480
481 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
482 if ((xparent = svz_sock_getparent (xsock)) != NULL)
483 oparent = socket_smob (xparent);
484 if (BOUNDP (parent))
485 {
486 CHECK_SMOB_ARG (socket, parent, SCM_ARG2, "svz-socket", xparent);
487 svz_sock_setparent (xsock, xparent);
488 }
489 return oparent;
490 #undef FUNC_NAME
491 }
492
493 SCM_DEFINE
494 (guile_sock_referrer,
495 "svz:sock:referrer", 1, 1, 0,
496 (SCM sock, SCM referrer),
497 doc: /***********
498 Return the given socket's @var{sock} referrer and optionally set it to the
499 socket @var{referrer}. Return either a valid
500 @code{#<svz-socket>} or an empty list. */)
501 {
502 #define FUNC_NAME s_guile_sock_referrer
503 SCM oreferrer = SCM_EOL;
504 svz_socket_t *xsock, *xreferrer;
505
506 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
507 if ((xreferrer = svz_sock_getreferrer (xsock)) != NULL)
508 oreferrer = socket_smob (xreferrer);
509 if (BOUNDP (referrer))
510 {
511 CHECK_SMOB_ARG (socket, referrer, SCM_ARG2, "svz-socket", xreferrer);
512 svz_sock_setreferrer (xsock, xreferrer);
513 }
514 return oreferrer;
515 #undef FUNC_NAME
516 }
517
518 SCM_DEFINE
519 (guile_sock_server,
520 "svz:sock:server", 1, 1, 0,
521 (SCM sock, SCM server),
522 doc: /***********
523 Return the @code{#<svz-server>} object associated with the
524 given argument @var{sock}. The optional argument @var{server} can be used
525 to redefine this association and must be a valid @code{#<svz-server>}
526 object. For a usual socket callback like @code{connect-socket} or
527 @code{handle-request}, the association is already in place. But for sockets
528 created by @code{svz:sock:connect}, you can use it in order to make the
529 returned socket object part of a server. */)
530 {
531 #define FUNC_NAME s_guile_sock_server
532 SCM oserver = SCM_EOL;
533 svz_socket_t *xsock;
534 svz_server_t *xserver;
535
536 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
537 if ((xserver = svz_server_find (xsock->cfg)) != NULL)
538 oserver = server_smob (xserver);
539 if (BOUNDP (server))
540 {
541 CHECK_SMOB_ARG (server, server, SCM_ARG2, "svz-server", xserver);
542 xsock->cfg = xserver->cfg;
543 }
544 return oserver;
545 #undef FUNC_NAME
546 }
547
548 SCM_DEFINE
549 (guile_sock_protocol,
550 "svz:sock:protocol", 1, 0, 0,
551 (SCM sock),
552 doc: /***********
553 Return one of the @code{PROTO_TCP}, @code{PROTO_UDP}, @code{PROTO_ICMP},
554 @code{PROTO_RAW} or @code{PROTO_PIPE} constants indicating the type of
555 the socket structure @var{sock}. If there is no protocol information
556 available, return @code{#f}. */)
557 {
558 #define FUNC_NAME s_guile_sock_protocol
559 svz_socket_t *xsock;
560
561 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
562 return gi_integer2scm (xsock->proto);
563 #undef FUNC_NAME
564 }
565
566 SCM_DEFINE
567 (guile_sock_final_print,
568 "svz:sock:final-print", 1, 0, 0,
569 (SCM sock),
570 doc: /***********
571 Schedule the socket @var{sock} for shutdown after all data
572 within the send buffer queue has been sent. You should call this
573 right @strong{before} the last call to @code{svz:sock:print}. */)
574 {
575 #define FUNC_NAME s_guile_sock_final_print
576 svz_socket_t *xsock;
577
578 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
579 xsock->flags |= SVZ_SOFLG_FINAL_WRITE;
580 return SCM_UNSPECIFIED;
581 #undef FUNC_NAME
582 }
583
584 SCM_DEFINE
585 (guile_sock_no_delay,
586 "svz:sock:no-delay", 1, 1, 0,
587 (SCM sock, SCM enable),
588 doc: /***********
589 Turn the Nagle algorithm for the TCP socket @var{sock} on or off depending
590 on the optional @var{enable} argument. Return the previous state of this
591 flag (@code{#f} if Nagle is active, @code{#t} otherwise). By default this
592 flag is switched off. This socket option is useful when dealing with small
593 packet transfer in order to disable unnecessary delays. */)
594 {
595 #define FUNC_NAME s_guile_sock_no_delay
596 svz_socket_t *xsock;
597 int old = 0, set = 0;
598
599 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
600 if (xsock->proto & SVZ_PROTO_TCP)
601 {
602 if (BOUNDP (enable))
603 {
604 SCM_ASSERT_TYPE (SCM_BOOLP (enable) || gi_exactp (enable),
605 enable, SCM_ARG2, FUNC_NAME, "boolean or exact");
606 if ((SCM_BOOLP (enable) && gi_nfalsep (enable) != 0) ||
607 (gi_exactp (enable) && gi_scm2int (enable) != 0))
608 set = 1;
609 }
610 if (svz_tcp_nodelay (xsock->sock_desc, set, &old) < 0)
611 old = 0;
612 else if (!BOUNDP (enable))
613 svz_tcp_nodelay (xsock->sock_desc, old, NULL);
614 }
615 return SCM_BOOL (old);
616 #undef FUNC_NAME
617 }
618
619 SCM_DEFINE
620 (guile_sock_p,
621 "svz:sock?", 1, 0, 0,
622 (SCM sock),
623 doc: /***********
624 Return @code{#t} if the given cell @var{sock} is an instance of a valid
625 @code{#<svz-socket>}, otherwise @code{#f}. */)
626 {
627 #define FUNC_NAME s_guile_sock_p
628 return CHECK_SMOB (socket, sock) ? SCM_BOOL_T : SCM_BOOL_F;
629 #undef FUNC_NAME
630 }
631
632 SCM_DEFINE
633 (guile_server_p,
634 "svz:server?", 1, 0, 0,
635 (SCM server),
636 doc: /***********
637 Return @code{#t} if the given cell @var{server} is an instance of a valid
638 @code{#<svz-server>}, otherwise @code{#f}. */)
639 {
640 #define FUNC_NAME s_guile_server_p
641 return CHECK_SMOB (server, server) ? SCM_BOOL_T : SCM_BOOL_F;
642 #undef FUNC_NAME
643 }
644
645 SCM_DEFINE
646 (guile_sock_disconnected_socket,
647 "svz:sock:disconnected", 1, 1, 0,
648 (SCM sock, SCM proc),
649 doc: /***********
650 Set the @code{disconnected-socket} member of the socket structure
651 @var{sock} to @var{proc}. The given callback
652 runs whenever the socket is lost for some external reason.
653 Return the previously set handler if there is one. */)
654 {
655 #define FUNC_NAME s_guile_sock_disconnected_socket
656 SOCK_CALLBACK_BODY (disconnected_socket, sfn_disconnected);
657 #undef FUNC_NAME
658 }
659
660 SCM_DEFINE
661 (guile_sock_kicked_socket,
662 "svz:sock:kicked", 1, 1, 0,
663 (SCM sock, SCM proc),
664 doc: /***********
665 Set the @code{kicked-socket} callback of the given socket structure
666 @var{sock} to @var{proc} and return any previously
667 set procedure. This callback gets called whenever the socket gets
668 closed by Serveez intentionally. */)
669 {
670 #define FUNC_NAME s_guile_sock_kicked_socket
671 SOCK_CALLBACK_BODY (kicked_socket, sfn_kicked);
672 #undef FUNC_NAME
673 }
674
675 SCM_DEFINE
676 (guile_sock_trigger_cond,
677 "svz:sock:trigger-condition", 1, 1, 0,
678 (SCM sock, SCM proc),
679 doc: /***********
680 Set the @code{trigger-condition} callback for the socket
681 structure @var{sock} to @var{proc}. Return the
682 previously set procedure if available. The callback is run once every
683 server loop indicating whether the @code{trigger} callback should be
684 run or not. */)
685 {
686 #define FUNC_NAME s_guile_sock_trigger_cond
687 SOCK_CALLBACK_BODY (trigger_cond, sfn_trigger_condition);
688 #undef FUNC_NAME
689 }
690
691 SCM_DEFINE
692 (guile_sock_trigger_func,
693 "svz:sock:trigger", 1, 1, 0,
694 (SCM sock, SCM proc),
695 doc: /***********
696 Set the @code{trigger} callback of the socket structure @var{sock} to
697 @var{proc} and return any previously set procedure.
698 The callback is run when the @code{trigger-condition} callback returns
699 @code{#t}. */)
700 {
701 #define FUNC_NAME s_guile_sock_trigger_func
702 SOCK_CALLBACK_BODY (trigger_func, sfn_trigger);
703 #undef FUNC_NAME
704 }
705
706 SCM_DEFINE
707 (guile_sock_idle_func,
708 "svz:sock:idle", 1, 1, 0,
709 (SCM sock, SCM proc),
710 doc: /***********
711 Set the @code{idle} callback of the socket structure
712 @var{sock} to @var{proc}. Return any previously
713 set procedure. The callback is run by the periodic task scheduler when the
714 @code{idle-counter} of the socket structure drops to zero. If this counter
715 is not zero it gets decremented once a second. The @code{idle}
716 callback can reset @code{idle-counter} to some value and thus can
717 re-schedule itself for a later task. */)
718 {
719 #define FUNC_NAME s_guile_sock_idle_func
720 SOCK_CALLBACK_BODY (idle_func, sfn_idle);
721 #undef FUNC_NAME
722 }
723
724 SCM_DEFINE
725 (guile_sock_check_request_oob,
726 "svz:sock:check-oob-request", 1, 1, 0,
727 (SCM sock, SCM proc),
728 doc: /***********
729 Set the @code{check-oob-request} callback of the given socket
730 structure @var{sock} to @var{proc}, returning
731 the previous callback (if there was any set before).
732 The callback is run whenever urgent data (out-of-band)
733 has been detected on the socket. */)
734 {
735 #define FUNC_NAME s_guile_sock_check_request_oob
736 SOCK_CALLBACK_BODY (check_request_oob, sfn_check_oob_request);
737 #undef FUNC_NAME
738 }
739
740 SCM_DEFINE
741 (guile_sock_idle_counter,
742 "svz:sock:idle-counter", 1, 1, 0,
743 (SCM sock, SCM counter),
744 doc: /***********
745 Return the socket structure @var{sock}'s current
746 @code{idle-counter} value. If the optional argument @var{counter} is
747 given, the set the @code{idle-counter}. Please have a look at the
748 @code{svz:sock:idle} procedure for the exact meaning of this value. */)
749 {
750 #define FUNC_NAME s_guile_sock_idle_counter
751 svz_socket_t *xsock;
752 int ocounter;
753
754 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
755 ocounter = xsock->idle_counter;
756 if (BOUNDP (counter))
757 {
758 ASSERT_EXACT (2, counter);
759 xsock->idle_counter = gi_scm2int (counter);
760 }
761 return gi_integer2scm (ocounter);
762 #undef FUNC_NAME
763 }
764
765 static svz_server_t *
named_instance_or_smob(SCM server,const char * FUNC_NAME)766 named_instance_or_smob (SCM server, const char *FUNC_NAME)
767 {
768 char name[64];
769 svz_server_t *rv = NULL;
770
771 if (GI_GET_XREP_MAYBE (name, server))
772 rv = svz_server_get (name);
773 if (! rv)
774 CHECK_SMOB_ARG (server, server, SCM_ARG1, "svz-server or string", rv);
775 return rv;
776 }
777
778 SCM_DEFINE
779 (guile_server_listeners,
780 "svz:server:listeners", 1, 0, 0,
781 (SCM server),
782 doc: /***********
783 Return a list of listening @code{#<svz-socket>} smobs to which the
784 given server instance @var{server} is currently bound, or an empty list
785 if there is no such binding yet. */)
786 {
787 #define FUNC_NAME s_guile_server_listeners
788 svz_server_t *xserver = named_instance_or_smob (server, FUNC_NAME);
789 svz_array_t *listeners;
790 size_t i;
791 SCM list = SCM_EOL;
792
793 /* Create a list of socket smobs for the server. */
794 if ((listeners = svz_server_listeners (xserver)) != NULL)
795 {
796 for (i = 0; i < svz_array_size (listeners); i++)
797 list = scm_cons (socket_smob ((svz_socket_t *)
798 svz_array_get (listeners, i)),
799 list);
800 svz_array_destroy (listeners);
801 }
802 return scm_reverse (list);
803 #undef FUNC_NAME
804 }
805
806 SCM_DEFINE
807 (guile_server_clients,
808 "svz:server:clients", 1, 0, 0,
809 (SCM server),
810 doc: /***********
811 Return a list of @code{#<svz-socket>} client smobs associated with
812 the given server instance @var{server} in arbitrary order, or an
813 empty list if there is no such client. */)
814 {
815 #define FUNC_NAME s_guile_server_clients
816 svz_server_t *xserver = named_instance_or_smob (server, FUNC_NAME);
817 svz_array_t *clients;
818 svz_socket_t *sock;
819 size_t i;
820 SCM list = SCM_EOL;
821
822 /* Create a list of socket smobs for the server. */
823 if ((clients = svz_server_clients (xserver)) != NULL)
824 {
825 svz_array_foreach (clients, sock, i)
826 list = scm_cons (socket_smob (sock), list);
827 svz_array_destroy (clients);
828 }
829 return list;
830 #undef FUNC_NAME
831 }
832
833 #if HAVE_GETRPCENT || HAVE_GETRPCBYNAME || HAVE_GETRPCBYNUMBER
834 static SCM
scm_return_rpcentry(struct rpcent * entry)835 scm_return_rpcentry (struct rpcent *entry)
836 {
837 return scm_vector
838 (gi_list_3 (gi_string2scm (entry->r_name),
839 scm_makfromstrs (-1, entry->r_aliases),
840 gi_integer2scm (entry->r_number)));
841 }
842
843 SCM_DEFINE
844 (scm_getrpc,
845 "getrpc", 0, 1, 0,
846 (SCM arg),
847 doc: /***********
848 Lookup a network rpc service @var{arg} (name or service number),
849 and return a network rpc service object.
850 If given no arguments, it behave like @code{getrpcent}. */)
851 {
852 #define FUNC_NAME s_scm_getrpc
853 struct rpcent *entry = NULL;
854
855 #if HAVE_GETRPCENT
856 if (!BOUNDP (arg))
857 {
858 if ((entry = getrpcent ()) == NULL)
859 return SCM_BOOL_F;
860 return scm_return_rpcentry (entry);
861 }
862 #endif /* HAVE_GETRPCENT */
863 #if HAVE_GETRPCBYNAME
864 if (gi_stringp (arg))
865 {
866 char name[64];
867
868 GI_GET_XREP (name, arg);
869 entry = getrpcbyname (name);
870 }
871 else
872 #endif /* HAVE_GETRPCBYNAME */
873 #if HAVE_GETRPCBYNUMBER
874 {
875 ASSERT_EXACT (1, arg);
876 entry = getrpcbynumber (gi_scm2int (arg));
877 }
878 #endif /* #if HAVE_GETRPCBYNUMBER */
879
880 if (!entry)
881 scm_syserror_msg (FUNC_NAME, "no such rpc service ~A",
882 scm_cons (arg, SCM_EOL), errno);
883 return scm_return_rpcentry (entry);
884 #undef FUNC_NAME
885 }
886 #endif /* HAVE_GETRPCENT || HAVE_GETRPCBYNAME || HAVE_GETRPCBYNUMBER */
887
888 #if !HAVE_DECL_SETRPCENT
889 extern void setrpcent (int);
890 #endif
891 #if !HAVE_DECL_ENDRPCENT
892 extern void endrpcent (void);
893 #endif
894
895 #if HAVE_SETRPCENT && HAVE_ENDRPCENT
896 SCM_DEFINE
897 (scm_setrpc,
898 "setrpc", 0, 1, 0,
899 (SCM stayopen),
900 doc: /***********
901 Open and rewind the file @file{/etc/rpc}.
902 If the @var{stayopen} flag is non-zero, the net data base will not be
903 closed after each call to @code{getrpc}. If @var{stayopen} is omitted,
904 this is equivalent to calling @code{endrpcent}. Otherwise it is
905 equivalent to calling @code{setrpcent} with arg 1. */)
906 {
907 #define FUNC_NAME s_scm_setrpc
908 if (!BOUNDP (stayopen))
909 endrpcent ();
910 else
911 setrpcent (!SCM_FALSEP (stayopen));
912 return SCM_UNSPECIFIED;
913 #undef FUNC_NAME
914 }
915 #endif /* HAVE_SETRPCENT && HAVE_ENDRPCENT */
916
917 #if HAVE_PMAP_GETMAPS
918 SCM_DEFINE
919 (scm_portmap_list,
920 "portmap-list", 0, 1, 0,
921 (SCM address),
922 doc: /***********
923 Return a list of the current RPC program-to-port mappings
924 on the host located at IP address @var{address}, which
925 defaults to the local machine's IP address.
926 Return an empty list if either there is no such list
927 available or an error occurred while fetching the list. */)
928 {
929 #define FUNC_NAME s_scm_portmap_list
930 struct sockaddr_in addr, raddr;
931 struct pmaplist *map;
932 char str[48];
933 SCM list = SCM_EOL, mapping;
934
935 memset (&addr, 0, sizeof (struct sockaddr_in));
936 #if HAVE_GET_MYADDRESS
937 get_myaddress (&addr);
938 #else
939 addr.sin_family = AF_INET;
940 addr.sin_port = htons (PMAPPORT);
941 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
942 #endif
943 if (BOUNDP (address))
944 {
945 ASSERT_STRING (1, address);
946 GI_GET_XREP (str, address);
947 if (svz_inet_aton (str, &raddr) == -1)
948 {
949 guile_error ("%s: IP in dotted decimals expected", FUNC_NAME);
950 return SCM_EOL;
951 }
952 addr.sin_addr.s_addr = raddr.sin_addr.s_addr;
953 }
954
955 if ((map = pmap_getmaps (&addr)) == NULL)
956 return SCM_EOL;
957 do
958 {
959 mapping = gi_list_3 (gi_integer2scm (map->pml_map.pm_vers),
960 gi_integer2scm (map->pml_map.pm_prot),
961 gi_integer2scm (map->pml_map.pm_port));
962 mapping = scm_cons (gi_integer2scm (map->pml_map.pm_prog),
963 mapping);
964 mapping = scm_vector (mapping);
965 list = scm_cons (mapping ,list);
966 }
967 while ((map = map->pml_next) != NULL);
968 return scm_reverse (list);
969 #undef FUNC_NAME
970 }
971 #endif /* HAVE_PMAP_GETMAPS */
972
973 static SCM
errnostring(void)974 errnostring (void)
975 {
976 return scm_strerror (gi_integer2scm (errno));
977 }
978
979 #if HAVE_PMAP_SET && HAVE_PMAP_UNSET
980 SCM_DEFINE
981 (scm_portmap,
982 "portmap", 2, 2, 0,
983 (SCM prognum, SCM versnum, SCM protocol, SCM port),
984 doc: /***********
985 Establish a (portmap service) mapping
986 between the triple [@var{prognum},@var{versnum},@var{protocol}] and
987 @var{port} on the machine's portmap service. The value of @var{protocol}
988 is most likely @code{IPPROTO_UDP} or @code{IPPROTO_TCP}.
989 If instead @var{protocol} and @var{port} are omitted, destroy
990 all mapping between the triple [@var{prognum},@var{versnum},*] and ports
991 on the machine's portmap service. */)
992 {
993 #define FUNC_NAME s_scm_portmap
994 ASSERT_EXACT (1, prognum);
995 ASSERT_EXACT (2, prognum);
996
997 if (!BOUNDP (protocol) && !BOUNDP (port))
998 {
999 if (!pmap_unset (gi_scm2int (prognum), gi_scm2int (versnum)))
1000 scm_syserror_msg (FUNC_NAME, "~A: pmap_unset ~A ~A",
1001 gi_list_3 (errnostring (), prognum, versnum),
1002 errno);
1003 }
1004 else
1005 {
1006 ASSERT_EXACT (3, protocol);
1007 ASSERT_EXACT (4, port);
1008
1009 if (!pmap_set (gi_scm2int (prognum), gi_scm2int (versnum),
1010 gi_scm2int (protocol), gi_scm2int (port)))
1011 scm_syserror_msg (FUNC_NAME, "~A: pmap_set ~A ~A ~A ~A",
1012 gi_list_5 (errnostring (), prognum,
1013 versnum, protocol, port),
1014 errno);
1015 }
1016 return SCM_UNSPECIFIED;
1017 #undef FUNC_NAME
1018 }
1019 #endif /* HAVE_PMAP_SET && HAVE_PMAP_UNSET */
1020
1021 /* Validate @var{callback}; protect it from gc. */
1022 static void
validate_callback(SCM callback,const char * who)1023 validate_callback (SCM callback, const char *who)
1024 {
1025 SCM_ASSERT_TYPE (SCM_PROCEDUREP (callback), callback,
1026 SCM_ARG2, who, "procedure");
1027 /* TODO: Check arity. */
1028
1029 /* Protect callback from garbage collection meanwhile. */
1030 gi_gc_protect (callback);
1031 }
1032
1033 #define VALIDATE_CALLBACK(x) validate_callback (x, FUNC_NAME)
1034
1035 /* Callback wrapper for coserver responses. */
1036 static int
guile_coserver_callback(char * res,void * closure)1037 guile_coserver_callback (char *res, void *closure)
1038 {
1039 SCM callback = (SCM) closure;
1040 int ret = -1;
1041
1042 /* If successfully done, run the given Guile procedure. */
1043 if (res != NULL)
1044 {
1045 guile_call (callback, 1, gi_string2scm (res));
1046 ret = 0;
1047 }
1048
1049 /* Pass the value to garbage collection again. */
1050 gi_gc_unprotect (callback);
1051 return ret;
1052 }
1053
1054 #define ENQ_COSERVER_REQUEST(req,coserver) \
1055 svz_coserver_ ## coserver ## _invoke \
1056 (req, guile_coserver_callback, \
1057 (void *) callback)
1058
1059 SCM_DEFINE
1060 (guile_coserver_dns,
1061 "svz:coserver:dns", 2, 0, 0,
1062 (SCM host, SCM callback),
1063 doc: /***********
1064 Enqueue the @var{host} string argument into the internal
1065 DNS coserver queue. When the coserver responds, the procedure
1066 @var{callback} is run as @code{(callback addr)}. The @var{addr}
1067 argument passed to the callback is a string representing the appropriate
1068 IP address for the given hostname @var{host}. */)
1069 {
1070 #define FUNC_NAME s_guile_coserver_dns
1071 char request[128];
1072
1073 /* Check argument list first. */
1074 ASSERT_STRING (1, host);
1075 VALIDATE_CALLBACK (callback);
1076
1077 /* Convert hostname into C string. */
1078 GI_GET_XREP (request, host);
1079
1080 ENQ_COSERVER_REQUEST (request, dns);
1081 return SCM_UNSPECIFIED;
1082 #undef FUNC_NAME
1083 }
1084
1085 SCM_DEFINE
1086 (guile_coserver_rdns,
1087 "svz:coserver:reverse-dns", 2, 0, 0,
1088 (SCM addr, SCM callback),
1089 doc: /***********
1090 Enqueue the given @var{addr} argument, which must be
1091 an IP address in network byte order, into the internal reverse DNS coserver
1092 queue. When the coserver responds, the procedure @var{callback} is
1093 run as @code{(callback host)} where @var{host} is the hostname of the
1094 requested IP address @var{addr}. */)
1095 {
1096 #define FUNC_NAME s_guile_coserver_rdns
1097 in_addr_t ip;
1098 svz_address_t *a;
1099
1100 /* Check argument list first. */
1101 ASSERT_EXACT (1, addr);
1102 VALIDATE_CALLBACK (callback);
1103
1104 /* Convert IP address into C long value. */
1105 ip = gi_scm2ulong (addr);
1106 a = svz_address_make (AF_INET, &ip);
1107
1108 ENQ_COSERVER_REQUEST (a, rdns);
1109 svz_free (a);
1110 return SCM_UNSPECIFIED;
1111 #undef FUNC_NAME
1112 }
1113
1114 SCM_DEFINE
1115 (guile_coserver_ident,
1116 "svz:coserver:ident", 2, 0, 0,
1117 (SCM sock, SCM callback),
1118 doc: /***********
1119 Enqueue the given @code{#<svz-socket>} @var{sock} into the
1120 internal ident coserver queue. When the coserver responds, it
1121 runs the procedure @var{callback} as @code{(callback user)}, where
1122 @var{user} is the corresponding username for the client connection
1123 @var{sock}. */)
1124 {
1125 #define FUNC_NAME s_guile_coserver_ident
1126 svz_socket_t *xsock;
1127
1128 /* Check argument list first. */
1129 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
1130 VALIDATE_CALLBACK (callback);
1131
1132 ENQ_COSERVER_REQUEST (xsock, ident);
1133 return SCM_UNSPECIFIED;
1134 #undef FUNC_NAME
1135 }
1136
1137 SCM_DEFINE
1138 (guile_sock_find,
1139 "svz:sock:find", 1, 0, 0,
1140 (SCM ident),
1141 doc: /***********
1142 Return the @code{#<svz-socket>} specified by @var{ident},
1143 a pair of integers in the form @code{(identification . version)}.
1144 If that socket no longer exists, return @code{#f}. */)
1145 {
1146 #define FUNC_NAME s_guile_sock_find
1147 int version, id;
1148 svz_socket_t *sock;
1149
1150 SCM_ASSERT_TYPE (SCM_PAIRP (ident) && gi_exactp (SCM_CAR (ident)) &&
1151 gi_exactp (SCM_CDR (ident)), ident, SCM_ARG1,
1152 FUNC_NAME, "pair of exact");
1153 id = gi_scm2int (SCM_CAR (ident));
1154 version = gi_scm2int (SCM_CDR (ident));
1155 if ((sock = svz_sock_find (id, version)) != NULL)
1156 return socket_smob (sock);
1157 return SCM_BOOL_F;
1158 #undef FUNC_NAME
1159 }
1160
1161 SCM_DEFINE
1162 (guile_sock_ident,
1163 "svz:sock:ident", 1, 0, 0,
1164 (SCM sock),
1165 doc: /***********
1166 Return a pair of numbers identifying the given
1167 @code{#<svz-socket>} @var{sock}, which can be passed to
1168 @code{svz:sock:find}. This may be necessary when you are passing
1169 a @code{#<svz-socket>} through coserver callback arguments in order to
1170 verify that the passed @code{#<svz-socket>} is still valid when the
1171 coserver callback runs. */)
1172 {
1173 #define FUNC_NAME s_guile_sock_ident
1174 svz_socket_t *xsock;
1175 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
1176 return scm_cons (gi_integer2scm (xsock->id), gi_integer2scm (xsock->version));
1177 #undef FUNC_NAME
1178 }
1179
1180 SCM_DEFINE
1181 (guile_read_file,
1182 "svz:read-file", 2, 0, 0,
1183 (SCM port, SCM size),
1184 doc: /***********
1185 Return either a binary smob containing a data block read
1186 from the open input port @var{port} with a maximum number of @var{size}
1187 bytes, or the end-of-file object if the underlying ports end has been
1188 reached. The size of the returned binary smob may be less than the
1189 requested size @var{size} if it exceed the current size of the given port
1190 @var{port}. Throw an exception if an error occurred while
1191 reading from the port. */)
1192 {
1193 #define FUNC_NAME s_guile_read_file
1194 int fdes, len, ret;
1195 uint8_t *data;
1196
1197 /* Check argument list. */
1198 SCM_ASSERT_TYPE (SCM_NIMP (port) && SCM_FPORTP (port) &&
1199 SCM_OPINFPORTP (port),
1200 port, SCM_ARG1, FUNC_NAME, "open input port");
1201 ASSERT_EXACT (2, size);
1202
1203 /* Get underlying file descriptor. */
1204 fdes = gi_scm2int (scm_fileno (port));
1205
1206 if ((len = gi_scm2int (size)) <= 0)
1207 SCM_OUT_OF_RANGE (SCM_ARG2, size);
1208
1209 /* Allocate necessary data. */
1210 data = gi_malloc (len, BDATA_WHAT);
1211
1212 /* Read from file descriptor and evaluate return value. */
1213 if ((ret = read (fdes, data, len)) < 0)
1214 {
1215 BFREE (DATA, data, len);
1216 scm_syserror_msg (FUNC_NAME, "~A: read ~A ~A",
1217 gi_list_3 (errnostring (),
1218 gi_integer2scm (fdes),
1219 size),
1220 errno);
1221 }
1222 else if (ret == 0)
1223 {
1224 BFREE (DATA, data, len);
1225 return SCM_EOF_VAL;
1226 }
1227 else if (ret != len)
1228 {
1229 data = gi_realloc (data, len, ret, BDATA_WHAT);
1230 }
1231
1232 /* Finally return binary smob. */
1233 return guile_garbage_to_bin (data, ret);
1234 #undef FUNC_NAME
1235 }
1236
1237 SCM_DEFINE
1238 (guile_sock_send_oob,
1239 "svz:sock:send-oob", 2, 0, 0,
1240 (SCM sock, SCM oob),
1241 doc: /***********
1242 Send byte @var{oob} as urgent (out-of-band) data through the
1243 underlying TCP stream of TCP @var{sock}.
1244 Return @code{#t} on successful completion and otherwise
1245 (either it failed to send the byte or the passed socket is not a TCP
1246 socket) @code{#f}. */)
1247 {
1248 #define FUNC_NAME s_guile_sock_send_oob
1249 svz_socket_t *xsock;
1250 int ret = -1;
1251
1252 /* Check the arguments. */
1253 CHECK_SMOB_ARG (socket, sock, SCM_ARG1, "svz-socket", xsock);
1254 SCM_ASSERT_TYPE (gi_exactp (oob) || SCM_CHARP (oob),
1255 oob, SCM_ARG2, FUNC_NAME, "char or exact");
1256
1257 /* Send the oob byte through TCP sockets only. */
1258 if (xsock->proto & SVZ_PROTO_TCP)
1259 {
1260 xsock->oob = (uint8_t)
1261 (SCM_CHARP (oob) ? SCM_CHAR (oob) :
1262 (uint8_t) gi_scm2int (oob));
1263 ret = svz_tcp_send_oob (xsock);
1264 }
1265 return ((ret < 0) ? SCM_BOOL_F : SCM_BOOL_T);
1266 #undef FUNC_NAME
1267 }
1268
1269 /* Initialize the API procedures supported by Guile. */
1270 void
guile_api_init(void)1271 guile_api_init (void)
1272 {
1273 #if HAVE_PMAP_SET && HAVE_PMAP_UNSET
1274 gi_define ("IPPROTO_UDP", gi_integer2scm (IPPROTO_UDP));
1275 gi_define ("IPPROTO_TCP", gi_integer2scm (IPPROTO_TCP));
1276 #endif
1277
1278 gi_define ("PROTO_TCP", gi_integer2scm (SVZ_PROTO_TCP));
1279 gi_define ("PROTO_UDP", gi_integer2scm (SVZ_PROTO_UDP));
1280 gi_define ("PROTO_ICMP", gi_integer2scm (SVZ_PROTO_ICMP));
1281 gi_define ("PROTO_RAW", gi_integer2scm (SVZ_PROTO_RAW));
1282 gi_define ("PROTO_PIPE", gi_integer2scm (SVZ_PROTO_PIPE));
1283 gi_define ("KICK_FLOOD", gi_integer2scm (0));
1284 gi_define ("KICK_QUEUE", gi_integer2scm (1));
1285 }
1286
1287 /* Finalize the API procedures. */
1288 void
guile_api_finalize(void)1289 guile_api_finalize (void)
1290 {
1291 }
1292
1293 #endif /* ENABLE_GUILE_SERVER */
1294