* scheme-options.texi, scheme-procedures.texi,
[bpt/guile.git] / libguile / socket.c
CommitLineData
e6e2e95a 1/* Copyright (C) 1996,1997,1998, 2000, 2001 Free Software Foundation, Inc.
86667910
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
86667910
JB
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.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46
e6e2e95a
MD
47#include <errno.h>
48
a0599745
MD
49#include "libguile/_scm.h"
50#include "libguile/unif.h"
51#include "libguile/feature.h"
52#include "libguile/fports.h"
53#include "libguile/strings.h"
54#include "libguile/vectors.h"
20e6290e 55
a0599745
MD
56#include "libguile/validate.h"
57#include "libguile/socket.h"
95b88819
GH
58
59#ifdef HAVE_STRING_H
60#include <string.h>
61#endif
370312ae
GH
62#ifdef HAVE_UNISTD_H
63#include <unistd.h>
64#endif
0f2d19dd
JB
65#include <sys/types.h>
66#include <sys/socket.h>
1ba8c23a 67#ifdef HAVE_UNIX_DOMAIN_SOCKETS
0f2d19dd 68#include <sys/un.h>
0e958795 69#endif
0f2d19dd
JB
70#include <netinet/in.h>
71#include <netdb.h>
72#include <arpa/inet.h>
73
97d0e20b
GH
74#if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
75#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
76 + strlen ((ptr)->sun_path))
77#endif
78
439006bf
GH
79/* we are not currently using socklen_t. it's not defined on all systems,
80 so would need to be checked by configure. in the meantime, plain
81 int is the best alternative. */
82
0f2d19dd
JB
83\f
84
a1ec6916 85SCM_DEFINE (scm_htons, "htons", 1, 0, 0,
1bbd0b84 86 (SCM in),
b380b885
MD
87 "Returns a new integer from @var{value} by converting from host to\n"
88 "network order. @var{value} must be within the range of a C unsigned\n"
89 "short integer.")
1bbd0b84 90#define FUNC_NAME s_scm_htons
5c11cc9d
GH
91{
92 unsigned short c_in;
93
3b3b36dd 94 SCM_VALIDATE_INUM_COPY (1,in,c_in);
5c11cc9d 95 if (c_in != SCM_INUM (in))
1bbd0b84 96 SCM_OUT_OF_RANGE (1,in);
5c11cc9d
GH
97
98 return SCM_MAKINUM (htons (c_in));
99}
1bbd0b84 100#undef FUNC_NAME
5c11cc9d 101
a1ec6916 102SCM_DEFINE (scm_ntohs, "ntohs", 1, 0, 0,
1bbd0b84 103 (SCM in),
b380b885
MD
104 "Returns a new integer from @var{value} by converting from network to\n"
105 "host order. @var{value} must be within the range of a C unsigned short\n"
106 "integer.")
1bbd0b84 107#define FUNC_NAME s_scm_ntohs
5c11cc9d
GH
108{
109 unsigned short c_in;
110
3b3b36dd 111 SCM_VALIDATE_INUM_COPY (1,in,c_in);
5c11cc9d 112 if (c_in != SCM_INUM (in))
1bbd0b84 113 SCM_OUT_OF_RANGE (1,in);
5c11cc9d
GH
114
115 return SCM_MAKINUM (ntohs (c_in));
116}
1bbd0b84 117#undef FUNC_NAME
5c11cc9d 118
a1ec6916 119SCM_DEFINE (scm_htonl, "htonl", 1, 0, 0,
1bbd0b84 120 (SCM in),
b380b885
MD
121 "Returns a new integer from @var{value} by converting from host to\n"
122 "network order. @var{value} must be within the range of a C unsigned\n"
123 "long integer.")
1bbd0b84 124#define FUNC_NAME s_scm_htonl
5c11cc9d 125{
1bbd0b84 126 unsigned long c_in = SCM_NUM2ULONG (1,in);
5c11cc9d
GH
127 return scm_ulong2num (htonl (c_in));
128}
1bbd0b84 129#undef FUNC_NAME
5c11cc9d 130
a1ec6916 131SCM_DEFINE (scm_ntohl, "ntohl", 1, 0, 0,
1bbd0b84 132 (SCM in),
b380b885
MD
133 "Returns a new integer from @var{value} by converting from network to\n"
134 "host order. @var{value} must be within the range of a C unsigned\n"
135 "long integer.")
1bbd0b84 136#define FUNC_NAME s_scm_ntohl
5c11cc9d 137{
1bbd0b84 138 unsigned long c_in = SCM_NUM2ULONG (1,in);
5c11cc9d
GH
139 return scm_ulong2num (ntohl (c_in));
140}
1bbd0b84 141#undef FUNC_NAME
5c11cc9d 142
bc45012d 143SCM_SYMBOL (sym_socket, "socket");
82ddea4e 144
439006bf 145#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
1bbd0b84 146
a1ec6916 147SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
1bbd0b84 148 (SCM family, SCM style, SCM proto),
b380b885
MD
149 "Returns a new socket port of the type specified by @var{family}, @var{style}\n"
150 "and @var{protocol}. All three parameters are integers. Typical values\n"
151 "for @var{family} are the values of @code{AF_UNIX}\n"
152 "and @code{AF_INET}. Typical values for @var{style} are\n"
153 "the values of @code{SOCK_STREAM}, @code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
154 "@var{protocol} can be obtained from a protocol name using\n"
155 "@code{getprotobyname}. A value of\n"
156 "zero specifies the default protocol, which is usually right.\n\n"
157 "A single socket port cannot by used for communication until\n"
158 "it has been connected to another socket.")
1bbd0b84 159#define FUNC_NAME s_scm_socket
0f2d19dd 160{
370312ae 161 int fd;
370312ae 162
439006bf
GH
163 SCM_VALIDATE_INUM (1, family);
164 SCM_VALIDATE_INUM (2, style);
165 SCM_VALIDATE_INUM (3, proto);
370312ae 166 fd = socket (SCM_INUM (family), SCM_INUM (style), SCM_INUM (proto));
439006bf
GH
167 if (fd == -1)
168 SCM_SYSERROR;
169 return SCM_SOCK_FD_TO_PORT (fd);
0f2d19dd 170}
1bbd0b84 171#undef FUNC_NAME
0f2d19dd 172
0e958795 173#ifdef HAVE_SOCKETPAIR
a1ec6916 174SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
1bbd0b84 175 (SCM family, SCM style, SCM proto),
b380b885
MD
176 "Returns a pair of connected (but unnamed) socket ports of the type specified\n"
177 "by @var{family}, @var{style} and @var{protocol}.\n"
178 "Many systems support only\n"
179 "socket pairs of the @code{AF_UNIX} family. Zero is likely to be\n"
180 "the only meaningful value for @var{protocol}.")
1bbd0b84 181#define FUNC_NAME s_scm_socketpair
0f2d19dd 182{
370312ae
GH
183 int fam;
184 int fd[2];
370312ae 185
3b3b36dd
GB
186 SCM_VALIDATE_INUM (1,family);
187 SCM_VALIDATE_INUM (2,style);
188 SCM_VALIDATE_INUM (3,proto);
370312ae
GH
189
190 fam = SCM_INUM (family);
191
370312ae 192 if (socketpair (fam, SCM_INUM (style), SCM_INUM (proto), fd) == -1)
1bbd0b84 193 SCM_SYSERROR;
370312ae 194
439006bf 195 return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
0f2d19dd 196}
1bbd0b84 197#undef FUNC_NAME
0e958795 198#endif
0f2d19dd 199
a1ec6916 200SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
1bbd0b84 201 (SCM sock, SCM level, SCM optname),
b380b885
MD
202 "Returns the value of a particular socket option for the socket\n"
203 "port @var{socket}. @var{level} is an integer code for type of option\n"
204 "being requested, e.g., @code{SOL_SOCKET} for socket-level options.\n"
205 "@var{optname} is an\n"
206 "integer code for the option required and should be specified using one of\n"
207 "the symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n\n"
208 "The returned value is typically an integer but @code{SO_LINGER} returns a\n"
209 "pair of integers.")
1bbd0b84 210#define FUNC_NAME s_scm_getsockopt
0f2d19dd 211{
370312ae 212 int fd;
439006bf 213 /* size of optval is the largest supported option. */
370312ae
GH
214#ifdef HAVE_STRUCT_LINGER
215 char optval[sizeof (struct linger)];
439006bf 216 int optlen = sizeof (struct linger);
370312ae
GH
217#else
218 char optval[sizeof (scm_sizet)];
439006bf 219 int optlen = sizeof (scm_sizet);
370312ae
GH
220#endif
221 int ilevel;
222 int ioptname;
0f2d19dd 223
78446828 224 sock = SCM_COERCE_OUTPORT (sock);
2cf6d014
MD
225 SCM_VALIDATE_OPFPORT (1, sock);
226 SCM_VALIDATE_INUM_COPY (2, level, ilevel);
227 SCM_VALIDATE_INUM_COPY (3, optname, ioptname);
0f2d19dd 228
ee149d03 229 fd = SCM_FPORT_FDES (sock);
370312ae 230 if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
1bbd0b84 231 SCM_SYSERROR;
1cc91f1b 232
439006bf 233 if (ilevel == SOL_SOCKET)
0f2d19dd 234 {
439006bf
GH
235#ifdef SO_LINGER
236 if (ioptname == SO_LINGER)
237 {
370312ae 238#ifdef HAVE_STRUCT_LINGER
439006bf
GH
239 struct linger *ling = (struct linger *) optval;
240
241 return scm_cons (scm_long2num (ling->l_onoff),
242 scm_long2num (ling->l_linger));
370312ae 243#else
439006bf
GH
244 return scm_cons (scm_long2num (*(int *) optval)
245 SCM_MAKINUM (0));
0f2d19dd 246#endif
439006bf
GH
247 }
248 else
370312ae 249#endif
439006bf 250 if (0
370312ae 251#ifdef SO_SNDBUF
439006bf 252 || ioptname == SO_SNDBUF
370312ae
GH
253#endif
254#ifdef SO_RCVBUF
439006bf 255 || ioptname == SO_RCVBUF
370312ae 256#endif
439006bf
GH
257 )
258 {
259 return scm_long2num (*(scm_sizet *) optval);
260 }
261 }
262 return scm_long2num (*(int *) optval);
0f2d19dd 263}
1bbd0b84 264#undef FUNC_NAME
0f2d19dd 265
a1ec6916 266SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
1bbd0b84 267 (SCM sock, SCM level, SCM optname, SCM value),
b380b885
MD
268 "Sets the value of a particular socket option for the socket\n"
269 "port @var{socket}. @var{level} is an integer code for type of option\n"
270 "being set, e.g., @code{SOL_SOCKET} for socket-level options.\n"
271 "@var{optname} is an\n"
272 "integer code for the option to set and should be specified using one of\n"
273 "the symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n"
274 "@var{value} is the value to which the option should be set. For\n"
275 "most options this must be an integer, but for @code{SO_LINGER} it must\n"
276 "be a pair.\n\n"
277 "The return value is unspecified.")
1bbd0b84 278#define FUNC_NAME s_scm_setsockopt
0f2d19dd 279{
370312ae 280 int fd;
439006bf
GH
281 int optlen = -1;
282 /* size of optval is the largest supported option. */
370312ae 283#ifdef HAVE_STRUCT_LINGER
439006bf 284 char optval[sizeof (struct linger)];
370312ae
GH
285#else
286 char optval[sizeof (scm_sizet)];
287#endif
288 int ilevel, ioptname;
439006bf 289
78446828 290 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
291
292 SCM_VALIDATE_OPFPORT (1, sock);
293 SCM_VALIDATE_INUM_COPY (2, level, ilevel);
294 SCM_VALIDATE_INUM_COPY (3, optname, ioptname);
295
ee149d03 296 fd = SCM_FPORT_FDES (sock);
439006bf
GH
297
298 if (ilevel == SOL_SOCKET)
370312ae 299 {
439006bf
GH
300#ifdef SO_LINGER
301 if (ioptname == SO_LINGER)
302 {
370312ae 303#ifdef HAVE_STRUCT_LINGER
439006bf
GH
304 struct linger ling;
305 long lv;
306
307 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
308 lv = SCM_NUM2LONG (4, SCM_CAR (value));
309 ling.l_onoff = (int) lv;
310 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_onoff == lv);
311 lv = SCM_NUM2LONG (4, SCM_CDR (value));
312 ling.l_linger = (int) lv;
313 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_linger == lv);
314 optlen = (int) sizeof (struct linger);
315 memcpy (optval, (void *) &ling, optlen);
370312ae 316#else
439006bf
GH
317 int ling;
318 long lv;
319
320 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
321 /* timeout is ignored, but may as well validate it. */
322 lv = SCM_NUM2LONG (4, SCM_CDR (value));
323 ling = (int) lv;
324 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
325 lv = SCM_NUM2LONG (4, SCM_CAR (value));
326 ling = (int) lv;
327 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
328 optlen = (int) sizeof (int);
329 (*(int *) optval) = ling;
330#endif
331 }
332 else
333#endif
334 if (0
370312ae 335#ifdef SO_SNDBUF
439006bf 336 || ioptname == SO_SNDBUF
370312ae
GH
337#endif
338#ifdef SO_RCVBUF
439006bf 339 || ioptname == SO_RCVBUF
370312ae 340#endif
439006bf
GH
341 )
342 {
343 long lv = SCM_NUM2LONG (4, value);
344
345 optlen = (int) sizeof (scm_sizet);
346 (*(scm_sizet *) optval) = (scm_sizet) lv;
347 }
348 }
349 if (optlen == -1)
0f2d19dd 350 {
439006bf
GH
351 /* Most options take an int. */
352 long lv = SCM_NUM2LONG (4, value);
353 int val = (int) lv;
354
355 SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
370312ae 356 optlen = (int) sizeof (int);
439006bf 357 (*(int *) optval) = val;
0f2d19dd 358 }
370312ae 359 if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
1bbd0b84 360 SCM_SYSERROR;
370312ae 361 return SCM_UNSPECIFIED;
0f2d19dd 362}
1bbd0b84 363#undef FUNC_NAME
0f2d19dd 364
a1ec6916 365SCM_DEFINE (scm_shutdown, "shutdown", 2, 0, 0,
1bbd0b84 366 (SCM sock, SCM how),
b380b885
MD
367 "Sockets can be closed simply by using @code{close-port}. The\n"
368 "@code{shutdown} procedure allows reception or tranmission on a\n"
369 "connection to be shut down individually, according to the parameter\n"
370 "@var{how}:\n\n"
371 "@table @asis\n"
372 "@item 0\n"
373 "Stop receiving data for this socket. If further data arrives, reject it.\n"
374 "@item 1\n"
375 "Stop trying to transmit data from this socket. Discard any\n"
376 "data waiting to be sent. Stop looking for acknowledgement of\n"
377 "data already sent; don't retransmit it if it is lost.\n"
378 "@item 2\n"
379 "Stop both reception and transmission.\n"
380 "@end table\n\n"
381 "The return value is unspecified.")
1bbd0b84 382#define FUNC_NAME s_scm_shutdown
0f2d19dd 383{
370312ae 384 int fd;
78446828 385 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd
GB
386 SCM_VALIDATE_OPFPORT (1,sock);
387 SCM_VALIDATE_INUM (2,how);
1bbd0b84 388 SCM_ASSERT_RANGE(2,how,0 <= SCM_INUM (how) && 2 >= SCM_INUM (how));
ee149d03 389 fd = SCM_FPORT_FDES (sock);
370312ae 390 if (shutdown (fd, SCM_INUM (how)) == -1)
1bbd0b84 391 SCM_SYSERROR;
370312ae
GH
392 return SCM_UNSPECIFIED;
393}
1bbd0b84 394#undef FUNC_NAME
0f2d19dd 395
370312ae
GH
396/* convert fam/address/args into a sockaddr of the appropriate type.
397 args is modified by removing the arguments actually used.
398 which_arg and proc are used when reporting errors:
399 which_arg is the position of address in the original argument list.
400 proc is the name of the original procedure.
401 size returns the size of the structure allocated. */
402
370312ae 403static struct sockaddr *
439006bf
GH
404scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg,
405 const char *proc, int *size)
370312ae
GH
406{
407 switch (fam)
0f2d19dd 408 {
370312ae
GH
409 case AF_INET:
410 {
411 SCM isport;
412 struct sockaddr_in *soka;
413
439006bf
GH
414 SCM_ASSERT (SCM_CONSP (*args), *args,
415 which_arg + 1, proc);
416 isport = SCM_CAR (*args);
417 SCM_ASSERT (SCM_INUMP (isport), isport, which_arg + 1, proc);
418 soka = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in));
419 if (!soka)
420 scm_memory_error (proc);
93a6b6f5
GH
421 /* e.g., for BSDs which don't like invalid sin_len. */
422 memset (soka, 0, sizeof (struct sockaddr_in));
370312ae
GH
423 soka->sin_family = AF_INET;
424 soka->sin_addr.s_addr =
425 htonl (scm_num2ulong (address, (char *) which_arg, proc));
370312ae 426 *args = SCM_CDR (*args);
370312ae
GH
427 soka->sin_port = htons (SCM_INUM (isport));
428 *size = sizeof (struct sockaddr_in);
429 return (struct sockaddr *) soka;
430 }
1ba8c23a 431#ifdef HAVE_UNIX_DOMAIN_SOCKETS
370312ae
GH
432 case AF_UNIX:
433 {
434 struct sockaddr_un *soka;
439006bf 435 int addr_size;
370312ae 436
a6d9e5ab 437 SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
439006bf
GH
438 /* the static buffer size in sockaddr_un seems to be arbitrary
439 and not necessarily a hard limit. e.g., the glibc manual
440 suggests it may be possible to declare it size 0. let's
441 ignore it. if the O/S doesn't like the size it will cause
442 connect/bind etc., to fail. sun_path is always the last
443 member of the structure. */
444 addr_size = sizeof (struct sockaddr_un)
445 + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
446 soka = (struct sockaddr_un *) malloc (addr_size);
447 if (!soka)
448 scm_memory_error (proc);
449 memset (soka, 0, addr_size); /* for sun_len: see sin_len above. */
450 soka->sun_family = AF_UNIX;
34f0f2b8 451 memcpy (soka->sun_path, SCM_STRING_CHARS (address),
439006bf
GH
452 SCM_STRING_LENGTH (address));
453 *size = SUN_LEN (soka);
370312ae
GH
454 return (struct sockaddr *) soka;
455 }
0e958795 456#endif
370312ae
GH
457 default:
458 scm_out_of_range (proc, SCM_MAKINUM (fam));
0f2d19dd 459 }
0f2d19dd 460}
370312ae 461
a1ec6916 462SCM_DEFINE (scm_connect, "connect", 3, 0, 1,
1bbd0b84 463 (SCM sock, SCM fam, SCM address, SCM args),
b380b885
MD
464 "Initiates a connection from @var{socket} to the address\n"
465 "specified by @var{address} and possibly @var{arg @dots{}}. The format\n"
466 "required for @var{address}\n"
467 "and @var{arg} @dots{} depends on the family of the socket.\n\n"
468 "For a socket of family @code{AF_UNIX},\n"
469 "only @code{address} is specified and must be a string with the\n"
470 "filename where the socket is to be created.\n\n"
471 "For a socket of family @code{AF_INET},\n"
472 "@code{address} must be an integer Internet host address and @var{arg} @dots{}\n"
473 "must be a single integer port number.\n\n"
474 "The return value is unspecified.")
1bbd0b84 475#define FUNC_NAME s_scm_connect
0f2d19dd 476{
370312ae
GH
477 int fd;
478 struct sockaddr *soka;
439006bf 479 int size;
0f2d19dd 480
78446828 481 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd
GB
482 SCM_VALIDATE_OPFPORT (1,sock);
483 SCM_VALIDATE_INUM (2,fam);
ee149d03 484 fd = SCM_FPORT_FDES (sock);
439006bf
GH
485 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
486 &size);
370312ae 487 if (connect (fd, soka, size) == -1)
439006bf
GH
488 {
489 int save_errno = errno;
490
491 free (soka);
492 errno = save_errno;
493 SCM_SYSERROR;
494 }
495 free (soka);
370312ae 496 return SCM_UNSPECIFIED;
0f2d19dd 497}
1bbd0b84 498#undef FUNC_NAME
0f2d19dd 499
a1ec6916 500SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
1bbd0b84 501 (SCM sock, SCM fam, SCM address, SCM args),
b380b885
MD
502 "Assigns an address to the socket port @var{socket}.\n"
503 "Generally this only needs to be done for server sockets,\n"
504 "so they know where to look for incoming connections. A socket\n"
505 "without an address will be assigned one automatically when it\n"
506 "starts communicating.\n\n"
507 "The format of @var{address} and @var{ARG} @dots{} depends on the family\n"
508 "of the socket.\n\n"
509 "For a socket of family @code{AF_UNIX}, only @var{address}\n"
510 "is specified and must \n"
511 "be a string with the filename where the socket is to be created.\n\n"
512 "For a socket of family @code{AF_INET}, @var{address} must be an integer\n"
513 "Internet host address and @var{arg} @dots{} must be a single integer\n"
514 "port number.\n\n"
515 "The values of the following variables can also be used for @var{address}:\n\n"
516 "@defvar INADDR_ANY\n"
517 "Allow connections from any address.\n"
518 "@end defvar\n\n"
519 "@defvar INADDR_LOOPBACK\n"
520 "The address of the local host using the loopback device.\n"
521 "@end defvar\n\n"
522 "@defvar INADDR_BROADCAST\n"
523 "The broadcast address on the local network.\n"
524 "@end defvar\n\n"
525 "@defvar INADDR_NONE\n"
526 "No address.\n"
527 "@end defvar\n\n"
528 "The return value is unspecified.")
1bbd0b84 529#define FUNC_NAME s_scm_bind
370312ae 530{
370312ae 531 struct sockaddr *soka;
439006bf 532 int size;
370312ae
GH
533 int fd;
534
78446828 535 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
536 SCM_VALIDATE_OPFPORT (1, sock);
537 SCM_VALIDATE_INUM (2, fam);
538 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
539 &size);
ee149d03 540 fd = SCM_FPORT_FDES (sock);
439006bf
GH
541 if (bind (fd, soka, size) == -1)
542 {
543 int save_errno = errno;
544
545 free (soka);
546 errno = save_errno;
1bbd0b84 547 SCM_SYSERROR;
439006bf
GH
548 }
549 free (soka);
370312ae
GH
550 return SCM_UNSPECIFIED;
551}
1bbd0b84 552#undef FUNC_NAME
370312ae 553
a1ec6916 554SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
1bbd0b84 555 (SCM sock, SCM backlog),
b380b885
MD
556 "This procedure enables @var{socket} to accept connection\n"
557 "requests. @var{backlog} is an integer specifying\n"
558 "the maximum length of the queue for pending connections.\n"
559 "If the queue fills, new clients will fail to connect until the\n"
560 "server calls @code{accept} to accept a connection from the queue.\n\n"
561 "The return value is unspecified.")
1bbd0b84 562#define FUNC_NAME s_scm_listen
370312ae
GH
563{
564 int fd;
78446828 565 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd
GB
566 SCM_VALIDATE_OPFPORT (1,sock);
567 SCM_VALIDATE_INUM (2,backlog);
ee149d03 568 fd = SCM_FPORT_FDES (sock);
370312ae 569 if (listen (fd, SCM_INUM (backlog)) == -1)
1bbd0b84 570 SCM_SYSERROR;
370312ae
GH
571 return SCM_UNSPECIFIED;
572}
1bbd0b84 573#undef FUNC_NAME
370312ae
GH
574
575/* Put the components of a sockaddr into a new SCM vector. */
370312ae 576static SCM
439006bf 577scm_addr_vector (struct sockaddr *address, const char *proc)
0f2d19dd 578{
370312ae
GH
579 short int fam = address->sa_family;
580 SCM result;
581 SCM *ve;
439006bf 582
1ba8c23a 583#ifdef HAVE_UNIX_DOMAIN_SOCKETS
370312ae 584 if (fam == AF_UNIX)
0f2d19dd 585 {
370312ae 586 struct sockaddr_un *nad = (struct sockaddr_un *) address;
439006bf 587
00ffa0e7 588 result = scm_c_make_vector (2, SCM_UNSPECIFIED);
370312ae
GH
589 ve = SCM_VELTS (result);
590 ve[0] = scm_ulong2num ((unsigned long) fam);
591 ve[1] = scm_makfromstr (nad->sun_path,
592 (scm_sizet) strlen (nad->sun_path), 0);
0f2d19dd 593 }
0e958795
JB
594 else
595#endif
596 if (fam == AF_INET)
0f2d19dd 597 {
370312ae 598 struct sockaddr_in *nad = (struct sockaddr_in *) address;
439006bf 599
00ffa0e7 600 result = scm_c_make_vector (3, SCM_UNSPECIFIED);
370312ae
GH
601 ve = SCM_VELTS (result);
602 ve[0] = scm_ulong2num ((unsigned long) fam);
603 ve[1] = scm_ulong2num (ntohl (nad->sin_addr.s_addr));
604 ve[2] = scm_ulong2num ((unsigned long) ntohs (nad->sin_port));
0f2d19dd
JB
605 }
606 else
70d63753 607 scm_misc_error (proc, "Unrecognised address family: ~A",
e0c08f17 608 SCM_LIST1 (SCM_MAKINUM (fam)));
370312ae
GH
609
610 return result;
611}
612
439006bf
GH
613/* calculate the size of a buffer large enough to hold any supported
614 sockaddr type. if the buffer isn't large enough, certain system
615 calls will return a truncated address. */
370312ae 616
439006bf
GH
617#if defined (HAVE_UNIX_DOMAIN_SOCKETS)
618#define MAX_SIZE_UN sizeof (struct sockaddr_un)
0e958795 619#else
439006bf 620#define MAX_SIZE_UN 0
0e958795 621#endif
439006bf
GH
622
623#define MAX_ADDR_SIZE max (sizeof (struct sockaddr_in), MAX_SIZE_UN)
0f2d19dd 624
a1ec6916 625SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
1bbd0b84 626 (SCM sock),
b380b885
MD
627 "Accepts a connection on a bound, listening socket @var{socket}. If there\n"
628 "are no pending connections in the queue, it waits until\n"
629 "one is available unless the non-blocking option has been set on the\n"
630 "socket.\n\n"
631 "The return value is a\n"
632 "pair in which the CAR is a new socket port for the connection and\n"
633 "the CDR is an object with address information about the client which\n"
634 "initiated the connection.\n\n"
635 "If the address is not available then the CDR will be an empty vector.\n\n"
636 "@var{socket} does not become part of the\n"
637 "connection and will continue to accept new requests.")
1bbd0b84 638#define FUNC_NAME s_scm_accept
0f2d19dd 639{
370312ae
GH
640 int fd;
641 int newfd;
642 SCM address;
643 SCM newsock;
439006bf
GH
644 int addr_size = MAX_ADDR_SIZE;
645 char max_addr[MAX_ADDR_SIZE];
646 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 647
78446828 648 sock = SCM_COERCE_OUTPORT (sock);
439006bf 649 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 650 fd = SCM_FPORT_FDES (sock);
439006bf
GH
651 newfd = accept (fd, addr, &addr_size);
652 if (newfd == -1)
653 SCM_SYSERROR;
654 newsock = SCM_SOCK_FD_TO_PORT (newfd);
655 if (addr_size > 0)
656 address = scm_addr_vector (addr, FUNC_NAME);
0f2d19dd 657 else
370312ae
GH
658 address = SCM_BOOL_F;
659
370312ae 660 return scm_cons (newsock, address);
0f2d19dd 661}
1bbd0b84 662#undef FUNC_NAME
0f2d19dd 663
a1ec6916 664SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0,
1bbd0b84 665 (SCM sock),
b380b885
MD
666 "Returns the address of @var{socket}, in the same form as the object\n"
667 "returned by @code{accept}. On many systems the address of a socket\n"
668 "in the @code{AF_FILE} namespace cannot be read.")
1bbd0b84 669#define FUNC_NAME s_scm_getsockname
0f2d19dd 670{
370312ae
GH
671 int fd;
672 SCM result;
439006bf
GH
673 int addr_size = MAX_ADDR_SIZE;
674 char max_addr[MAX_ADDR_SIZE];
675 struct sockaddr *addr = (struct sockaddr *) max_addr;
676
78446828 677 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd 678 SCM_VALIDATE_OPFPORT (1,sock);
ee149d03 679 fd = SCM_FPORT_FDES (sock);
439006bf 680 if (getsockname (fd, addr, &addr_size) == -1)
1bbd0b84 681 SCM_SYSERROR;
439006bf
GH
682 if (addr_size > 0)
683 result = scm_addr_vector (addr, FUNC_NAME);
0f2d19dd 684 else
370312ae 685 result = SCM_BOOL_F;
370312ae 686 return result;
0f2d19dd 687}
1bbd0b84 688#undef FUNC_NAME
0f2d19dd 689
a1ec6916 690SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0,
1bbd0b84 691 (SCM sock),
b380b885
MD
692 "Returns the address of the socket that the socket @var{socket} is connected to,\n"
693 "in the same form as the object\n"
694 "returned by @code{accept}. On many systems the address of a socket\n"
695 "in the @code{AF_FILE} namespace cannot be read.")
1bbd0b84 696#define FUNC_NAME s_scm_getpeername
0f2d19dd 697{
370312ae
GH
698 int fd;
699 SCM result;
439006bf
GH
700 int addr_size = MAX_ADDR_SIZE;
701 char max_addr[MAX_ADDR_SIZE];
702 struct sockaddr *addr = (struct sockaddr *) max_addr;
703
78446828 704 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd 705 SCM_VALIDATE_OPFPORT (1,sock);
ee149d03 706 fd = SCM_FPORT_FDES (sock);
439006bf 707 if (getpeername (fd, addr, &addr_size) == -1)
1bbd0b84 708 SCM_SYSERROR;
439006bf
GH
709 if (addr_size > 0)
710 result = scm_addr_vector (addr, FUNC_NAME);
0f2d19dd 711 else
370312ae 712 result = SCM_BOOL_F;
370312ae 713 return result;
0f2d19dd 714}
1bbd0b84 715#undef FUNC_NAME
0f2d19dd 716
a1ec6916 717SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
1bbd0b84 718 (SCM sock, SCM buf, SCM flags),
b380b885
MD
719 "Receives data from the socket port @var{socket}. @var{socket} must already\n"
720 "be bound to the address from which data is to be received.\n"
721 "@var{buf} is a string into which\n"
722 "the data will be written. The size of @var{buf} limits the amount of\n"
723 "data which can be received: in the case of packet\n"
724 "protocols, if a packet larger than this limit is encountered then some data\n"
725 "will be irrevocably lost.\n\n"
726 "The optional @var{flags} argument is a value or\n"
727 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
728 "The value returned is the number of bytes read from the socket.\n\n"
09831f94
NJ
729 "Note that the data is read directly from the socket file descriptor:\n"
730 "any unread buffered port data is ignored.")
1bbd0b84 731#define FUNC_NAME s_scm_recv
0f2d19dd 732{
370312ae
GH
733 int rv;
734 int fd;
735 int flg;
370312ae 736
3b3b36dd
GB
737 SCM_VALIDATE_OPFPORT (1,sock);
738 SCM_VALIDATE_STRING (2,buf);
739 SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg);
ee149d03 740 fd = SCM_FPORT_FDES (sock);
370312ae 741
bfa974f0 742 SCM_SYSCALL (rv = recv (fd, SCM_STRING_CHARS (buf), SCM_STRING_LENGTH (buf), flg));
370312ae 743 if (rv == -1)
1bbd0b84 744 SCM_SYSERROR;
370312ae 745
1146b6cd 746 return SCM_MAKINUM (rv);
370312ae 747}
1bbd0b84 748#undef FUNC_NAME
370312ae 749
a1ec6916 750SCM_DEFINE (scm_send, "send", 2, 1, 0,
1bbd0b84 751 (SCM sock, SCM message, SCM flags),
b380b885
MD
752 "Transmits the string @var{message} on the socket port @var{socket}. \n"
753 "@var{socket} must already be bound to a destination address. The\n"
754 "value returned is the number of bytes transmitted -- it's possible for\n"
755 "this to be less than the length of @var{message} if the socket is\n"
756 "set to be non-blocking. The optional @var{flags} argument is a value or\n"
757 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
758 "Note that the data is written directly to the socket file descriptor:\n"
759 "any unflushed buffered port data is ignored.")
1bbd0b84 760#define FUNC_NAME s_scm_send
370312ae
GH
761{
762 int rv;
763 int fd;
764 int flg;
765
78446828 766 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd 767 SCM_VALIDATE_OPFPORT (1,sock);
a6d9e5ab 768 SCM_VALIDATE_STRING (2, message);
3b3b36dd 769 SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg);
ee149d03 770 fd = SCM_FPORT_FDES (sock);
370312ae 771
34f0f2b8 772 SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg));
370312ae 773 if (rv == -1)
1bbd0b84 774 SCM_SYSERROR;
370312ae
GH
775 return SCM_MAKINUM (rv);
776}
1bbd0b84 777#undef FUNC_NAME
370312ae 778
a1ec6916 779SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
60d02d09 780 (SCM sock, SCM str, SCM flags, SCM start, SCM end),
b380b885
MD
781 "Returns data from the socket port @var{socket} and also information about\n"
782 "where the data was received from. @var{socket} must already\n"
783 "be bound to the address from which data is to be received.\n"
60d02d09
GH
784 "@code{str}, is a string into which\n"
785 "the data will be written. The size of @var{str} limits the amount of\n"
b380b885
MD
786 "data which can be received: in the case of packet\n"
787 "protocols, if a packet larger than this limit is encountered then some data\n"
788 "will be irrevocably lost.\n\n"
789 "The optional @var{flags} argument is a value or\n"
790 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
791 "The value returned is a pair: the CAR is the number of bytes read from\n"
792 "the socket and the CDR an address object in the same form as returned by\n"
793 "@code{accept}.\n\n"
60d02d09 794 "The @var{start} and @var{end} arguments specify a substring of @var{str}\n"
b380b885
MD
795 "to which the data should be written.\n\n"
796 "Note that the data is read directly from the socket file descriptor:\n"
797 "any unread buffered port data is ignored.")
1bbd0b84 798#define FUNC_NAME s_scm_recvfrom
370312ae
GH
799{
800 int rv;
801 int fd;
802 int flg;
60d02d09
GH
803 char *buf;
804 int offset;
1146b6cd 805 int cend;
370312ae 806 SCM address;
439006bf
GH
807 int addr_size = MAX_ADDR_SIZE;
808 char max_addr[MAX_ADDR_SIZE];
809 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 810
3b3b36dd 811 SCM_VALIDATE_OPFPORT (1,sock);
60d02d09
GH
812 fd = SCM_FPORT_FDES (sock);
813 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 4, start, offset,
814 5, end, cend);
1146b6cd
GH
815 if (SCM_UNBNDP (flags))
816 flg = 0;
370312ae 817 else
60d02d09 818 SCM_VALIDATE_ULONG_COPY (3, flags, flg);
370312ae 819
97d0e20b
GH
820 /* recvfrom will not necessarily return an address. usually nothing
821 is returned for stream sockets. */
439006bf 822 addr->sa_family = AF_UNSPEC;
60d02d09 823 SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
1146b6cd 824 cend - offset, flg,
439006bf 825 addr, &addr_size));
370312ae 826 if (rv == -1)
1bbd0b84 827 SCM_SYSERROR;
439006bf
GH
828 if (addr_size > 0 && addr->sa_family != AF_UNSPEC)
829 address = scm_addr_vector (addr, FUNC_NAME);
370312ae
GH
830 else
831 address = SCM_BOOL_F;
832
1146b6cd 833 return scm_cons (SCM_MAKINUM (rv), address);
0f2d19dd 834}
1bbd0b84 835#undef FUNC_NAME
0f2d19dd 836
a1ec6916 837SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
1bbd0b84 838 (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
b380b885
MD
839 "Transmits the string @var{message} on the socket port @var{socket}. The\n"
840 "destination address is specified using the @var{family}, @var{address} and\n"
841 "@var{arg} arguments, in a similar way to the @code{connect}\n"
842 "procedure. The\n"
843 "value returned is the number of bytes transmitted -- it's possible for\n"
844 "this to be less than the length of @var{message} if the socket is\n"
845 "set to be non-blocking. The optional @var{flags} argument is a value or\n"
846 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
847 "Note that the data is written directly to the socket file descriptor:\n"
848 "any unflushed buffered port data is ignored.")
1bbd0b84 849#define FUNC_NAME s_scm_sendto
370312ae
GH
850{
851 int rv;
852 int fd;
853 int flg;
854 struct sockaddr *soka;
439006bf 855 int size;
370312ae 856
78446828 857 sock = SCM_COERCE_OUTPORT (sock);
3b3b36dd 858 SCM_VALIDATE_FPORT (1,sock);
a6d9e5ab 859 SCM_VALIDATE_STRING (2, message);
3b3b36dd 860 SCM_VALIDATE_INUM (3,fam);
ee149d03 861 fd = SCM_FPORT_FDES (sock);
370312ae 862 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args_and_flags, 4,
1bbd0b84 863 FUNC_NAME, &size);
370312ae
GH
864 if (SCM_NULLP (args_and_flags))
865 flg = 0;
866 else
867 {
3b3b36dd 868 SCM_VALIDATE_CONS (5,args_and_flags);
1bbd0b84 869 flg = SCM_NUM2ULONG (5,SCM_CAR (args_and_flags));
370312ae 870 }
439006bf
GH
871 SCM_SYSCALL (rv = sendto (fd, SCM_STRING_CHARS (message),
872 SCM_STRING_LENGTH (message),
ae2fa5bc 873 flg, soka, size));
370312ae 874 if (rv == -1)
439006bf
GH
875 {
876 int save_errno = errno;
877 free (soka);
878 errno = save_errno;
879 SCM_SYSERROR;
880 }
881 free (soka);
370312ae
GH
882 return SCM_MAKINUM (rv);
883}
1bbd0b84 884#undef FUNC_NAME
370312ae
GH
885\f
886
887
888void
0f2d19dd 889scm_init_socket ()
0f2d19dd 890{
370312ae
GH
891 /* protocol families. */
892#ifdef AF_UNSPEC
893 scm_sysintern ("AF_UNSPEC", SCM_MAKINUM (AF_UNSPEC));
894#endif
895#ifdef AF_UNIX
896 scm_sysintern ("AF_UNIX", SCM_MAKINUM (AF_UNIX));
897#endif
898#ifdef AF_INET
899 scm_sysintern ("AF_INET", SCM_MAKINUM (AF_INET));
900#endif
901
902#ifdef PF_UNSPEC
903 scm_sysintern ("PF_UNSPEC", SCM_MAKINUM (PF_UNSPEC));
904#endif
905#ifdef PF_UNIX
906 scm_sysintern ("PF_UNIX", SCM_MAKINUM (PF_UNIX));
907#endif
908#ifdef PF_INET
909 scm_sysintern ("PF_INET", SCM_MAKINUM (PF_INET));
910#endif
911
912 /* socket types. */
913#ifdef SOCK_STREAM
914 scm_sysintern ("SOCK_STREAM", SCM_MAKINUM (SOCK_STREAM));
915#endif
916#ifdef SOCK_DGRAM
917 scm_sysintern ("SOCK_DGRAM", SCM_MAKINUM (SOCK_DGRAM));
918#endif
919#ifdef SOCK_RAW
920 scm_sysintern ("SOCK_RAW", SCM_MAKINUM (SOCK_RAW));
921#endif
922
923 /* setsockopt level. */
924#ifdef SOL_SOCKET
925 scm_sysintern ("SOL_SOCKET", SCM_MAKINUM (SOL_SOCKET));
926#endif
927#ifdef SOL_IP
928 scm_sysintern ("SOL_IP", SCM_MAKINUM (SOL_IP));
929#endif
930#ifdef SOL_TCP
931 scm_sysintern ("SOL_TCP", SCM_MAKINUM (SOL_TCP));
932#endif
933#ifdef SOL_UDP
934 scm_sysintern ("SOL_UDP", SCM_MAKINUM (SOL_UDP));
935#endif
936
937 /* setsockopt names. */
938#ifdef SO_DEBUG
939 scm_sysintern ("SO_DEBUG", SCM_MAKINUM (SO_DEBUG));
940#endif
941#ifdef SO_REUSEADDR
942 scm_sysintern ("SO_REUSEADDR", SCM_MAKINUM (SO_REUSEADDR));
943#endif
944#ifdef SO_STYLE
945 scm_sysintern ("SO_STYLE", SCM_MAKINUM (SO_STYLE));
946#endif
947#ifdef SO_TYPE
948 scm_sysintern ("SO_TYPE", SCM_MAKINUM (SO_TYPE));
949#endif
950#ifdef SO_ERROR
951 scm_sysintern ("SO_ERROR", SCM_MAKINUM (SO_ERROR));
952#endif
953#ifdef SO_DONTROUTE
954 scm_sysintern ("SO_DONTROUTE", SCM_MAKINUM (SO_DONTROUTE));
955#endif
956#ifdef SO_BROADCAST
957 scm_sysintern ("SO_BROADCAST", SCM_MAKINUM (SO_BROADCAST));
958#endif
959#ifdef SO_SNDBUF
960 scm_sysintern ("SO_SNDBUF", SCM_MAKINUM (SO_SNDBUF));
961#endif
962#ifdef SO_RCVBUF
963 scm_sysintern ("SO_RCVBUF", SCM_MAKINUM (SO_RCVBUF));
964#endif
965#ifdef SO_KEEPALIVE
966 scm_sysintern ("SO_KEEPALIVE", SCM_MAKINUM (SO_KEEPALIVE));
967#endif
968#ifdef SO_OOBINLINE
969 scm_sysintern ("SO_OOBINLINE", SCM_MAKINUM (SO_OOBINLINE));
970#endif
971#ifdef SO_NO_CHECK
972 scm_sysintern ("SO_NO_CHECK", SCM_MAKINUM (SO_NO_CHECK));
973#endif
974#ifdef SO_PRIORITY
975 scm_sysintern ("SO_PRIORITY", SCM_MAKINUM (SO_PRIORITY));
976#endif
977#ifdef SO_LINGER
978 scm_sysintern ("SO_LINGER", SCM_MAKINUM (SO_LINGER));
979#endif
980
981 /* recv/send options. */
982#ifdef MSG_OOB
983 scm_sysintern ("MSG_OOB", SCM_MAKINUM (MSG_OOB));
984#endif
985#ifdef MSG_PEEK
986 scm_sysintern ("MSG_PEEK", SCM_MAKINUM (MSG_PEEK));
987#endif
988#ifdef MSG_DONTROUTE
989 scm_sysintern ("MSG_DONTROUTE", SCM_MAKINUM (MSG_DONTROUTE));
990#endif
991
0f2d19dd 992 scm_add_feature ("socket");
370312ae 993
8dc9439f 994#ifndef SCM_MAGIC_SNARFER
a0599745 995#include "libguile/socket.x"
8dc9439f 996#endif
0f2d19dd
JB
997}
998
89e00824
ML
999
1000/*
1001 Local Variables:
1002 c-file-style: "gnu"
1003 End:
1004*/