~peter-pearse/ubuntu/natty/guile-1.8/prop001

« back to all changes in this revision

Viewing changes to libguile/win32-socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schepler
  • Date: 2006-11-09 03:11:16 UTC
  • Revision ID: james.westby@ubuntu.com-20061109031116-hu0q1jxqg12y6yeg
Tags: upstream-1.8.1+1
ImportĀ upstreamĀ versionĀ 1.8.1+1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
 
2
 * 
 
3
 * This library is free software; you can redistribute it and/or
 
4
 * modify it under the terms of the GNU Lesser General Public
 
5
 * License as published by the Free Software Foundation; either
 
6
 * version 2.1 of the License, or (at your option) any later version.
 
7
 *
 
8
 * This library 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 GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public
 
14
 * License along with this library; if not, write to the Free Software
 
15
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 */
 
17
 
 
18
 
 
19
 
 
20
 
 
21
#if HAVE_CONFIG_H
 
22
#  include <config.h>
 
23
#endif
 
24
 
 
25
#include "libguile/__scm.h"
 
26
#include "libguile/modules.h"
 
27
#include "libguile/numbers.h"
 
28
 
 
29
#include <stdio.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <ctype.h>
 
33
#include <errno.h>
 
34
#include <limits.h>
 
35
 
 
36
#ifndef PATH_MAX
 
37
#define PATH_MAX 255
 
38
#endif
 
39
 
 
40
#include "win32-socket.h"
 
41
 
 
42
/* Winsock API error description structure.  The error description is 
 
43
   necessary because there is no error list available.  */
 
44
typedef struct
 
45
{
 
46
  int error;         /* Error code.  */
 
47
  char *str;         /* Error description.  */
 
48
  int replace;       /* Possible error code replacement.  */
 
49
  char *replace_str; /* Replacement symbol.  */
 
50
  char *correct_str; /* Original symbol.  */
 
51
}
 
52
socket_error_t;
 
53
 
 
54
#define FILE_ETC_SERVICES     "services"
 
55
#define ENVIRON_ETC_SERVICES  "SERVICES"
 
56
#define FILE_ETC_NETWORKS     "networks"
 
57
#define ENVIRON_ETC_NETWORKS  "NETWORKS"
 
58
#define FILE_ETC_PROTOCOLS    "protocol"
 
59
#define ENVIRON_ETC_PROTOCOLS "PROTOCOLS"
 
60
#define MAX_NAMLEN  256
 
61
#define MAX_ALIASES 4
 
62
 
 
63
/* Internal structure for a thread's M$-Windows servent interface.  */
 
64
typedef struct
 
65
{
 
66
  FILE *fd;                            /* Current file.  */
 
67
  char file[PATH_MAX];                 /* File name.  */
 
68
  struct servent ent;                  /* Return value.  */
 
69
  char name[MAX_NAMLEN];               /* Service name.  */
 
70
  char proto[MAX_NAMLEN];              /* Protocol name.  */
 
71
  char alias[MAX_ALIASES][MAX_NAMLEN]; /* All aliases.  */
 
72
  char *aliases[MAX_ALIASES];          /* Alias pointers.  */
 
73
  int port;                            /* Network port.  */
 
74
}
 
75
scm_i_servent_t;
 
76
 
 
77
static scm_i_servent_t scm_i_servent;
 
78
 
 
79
/* Internal structure for a thread's M$-Windows protoent interface.  */
 
80
typedef struct
 
81
{
 
82
  FILE *fd;                            /* Current file.  */
 
83
  char file[PATH_MAX];                 /* File name.  */
 
84
  struct protoent ent;                 /* Return value.  */
 
85
  char name[MAX_NAMLEN];               /* Protocol name.  */
 
86
  char alias[MAX_ALIASES][MAX_NAMLEN]; /* All aliases.  */
 
87
  char *aliases[MAX_ALIASES];          /* Alias pointers.  */
 
88
  int proto;                           /* Protocol number.  */
 
89
}
 
90
scm_i_protoent_t;
 
91
 
 
92
static scm_i_protoent_t scm_i_protoent;
 
93
 
 
94
/* Define replacement symbols for most of the WSA* error codes.  */
 
95
#ifndef EWOULDBLOCK
 
96
# define EWOULDBLOCK     WSAEWOULDBLOCK
 
97
#endif
 
98
#ifndef EINPROGRESS
 
99
# define EINPROGRESS     WSAEINPROGRESS
 
100
#endif
 
101
#ifndef EALREADY
 
102
# define EALREADY        WSAEALREADY
 
103
#endif
 
104
#ifndef EDESTADDRREQ
 
105
# define EDESTADDRREQ    WSAEDESTADDRREQ
 
106
#endif
 
107
#ifndef EMSGSIZE
 
108
# define EMSGSIZE        WSAEMSGSIZE
 
109
#endif
 
110
#ifndef EPROTOTYPE
 
111
# define EPROTOTYPE      WSAEPROTOTYPE
 
112
#endif
 
113
#ifndef ENOTSOCK
 
114
# define ENOTSOCK        WSAENOTSOCK
 
115
#endif
 
116
#ifndef ENOPROTOOPT
 
117
# define ENOPROTOOPT     WSAENOPROTOOPT
 
118
#endif
 
119
#ifndef EPROTONOSUPPORT
 
120
# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
 
121
#endif
 
122
#ifndef ESOCKTNOSUPPORT
 
123
# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
 
124
#endif
 
125
#ifndef EOPNOTSUPP
 
126
# define EOPNOTSUPP      WSAEOPNOTSUPP
 
127
#endif
 
128
#ifndef EPFNOSUPPORT
 
129
# define EPFNOSUPPORT    WSAEPFNOSUPPORT
 
130
#endif
 
131
#ifndef EAFNOSUPPORT
 
132
# define EAFNOSUPPORT    WSAEAFNOSUPPORT
 
133
#endif
 
134
#ifndef EADDRINUSE
 
135
# define EADDRINUSE      WSAEADDRINUSE
 
136
#endif
 
137
#ifndef EADDRNOTAVAIL
 
138
# define EADDRNOTAVAIL   WSAEADDRNOTAVAIL
 
139
#endif
 
140
#ifndef ENETDOWN
 
141
# define ENETDOWN        WSAENETDOWN
 
142
#endif
 
143
#ifndef ENETUNREACH
 
144
# define ENETUNREACH     WSAENETUNREACH
 
145
#endif
 
146
#ifndef ENETRESET
 
147
# define ENETRESET       WSAENETRESET
 
148
#endif
 
149
#ifndef ECONNABORTED
 
150
# define ECONNABORTED    WSAECONNABORTED
 
151
#endif
 
152
#ifndef ECONNRESET
 
153
# define ECONNRESET      WSAECONNRESET
 
154
#endif
 
155
#ifndef ENOBUFS
 
156
# define ENOBUFS         WSAENOBUFS
 
157
#endif
 
158
#ifndef EISCONN
 
159
# define EISCONN         WSAEISCONN
 
160
#endif
 
161
#ifndef ENOTCONN
 
162
# define ENOTCONN        WSAENOTCONN
 
163
#endif
 
164
#ifndef ESHUTDOWN
 
165
# define ESHUTDOWN       WSAESHUTDOWN
 
166
#endif
 
167
#ifndef ETOOMANYREFS
 
168
# define ETOOMANYREFS    WSAETOOMANYREFS
 
169
#endif
 
170
#ifndef ETIMEDOUT
 
171
# define ETIMEDOUT       WSAETIMEDOUT
 
172
#endif
 
173
#ifndef ECONNREFUSED
 
174
# define ECONNREFUSED    WSAECONNREFUSED
 
175
#endif
 
176
#ifndef ELOOP
 
177
# define ELOOP           WSAELOOP
 
178
#endif
 
179
#ifndef EHOSTDOWN
 
180
# define EHOSTDOWN       WSAEHOSTDOWN
 
181
#endif
 
182
#ifndef EHOSTUNREACH
 
183
# define EHOSTUNREACH    WSAEHOSTUNREACH
 
184
#endif
 
185
#ifndef EPROCLIM
 
186
# define EPROCLIM        WSAEPROCLIM
 
187
#endif
 
188
#ifndef EUSERS
 
189
# define EUSERS          WSAEUSERS
 
190
#endif
 
191
#ifndef EDQUOT
 
192
# define EDQUOT          WSAEDQUOT
 
193
#endif
 
194
#ifndef ESTALE
 
195
# define ESTALE          WSAESTALE
 
196
#endif
 
197
#ifndef EREMOTE
 
198
# define EREMOTE         WSAEREMOTE
 
199
#endif
 
200
 
 
201
/* List of error structures.  */
 
202
static socket_error_t socket_errno [] = {
 
203
  /* 000 */ { 0, NULL, 0, NULL, NULL },
 
204
  /* 001 */ { 0, NULL, 0, NULL, NULL },
 
205
  /* 002 */ { 0, NULL, 0, NULL, NULL },
 
206
  /* 003 */ { 0, NULL, 0, NULL, NULL },
 
207
  /* 004 */ { WSAEINTR, "Interrupted function call", EINTR, NULL, "WSAEINTR" },
 
208
  /* 005 */ { 0, NULL, 0, NULL, NULL },
 
209
  /* 006 */ { 0, NULL, 0, NULL, NULL },
 
210
  /* 007 */ { 0, NULL, 0, NULL, NULL },
 
211
  /* 008 */ { 0, NULL, 0, NULL, NULL },
 
212
  /* 009 */ { WSAEBADF, "Bad file number", EBADF, NULL, "WSAEBADF" },
 
213
  /* 010 */ { 0, NULL, 0, NULL, NULL },
 
214
  /* 011 */ { 0, NULL, 0, NULL, NULL },
 
215
  /* 012 */ { 0, NULL, 0, NULL, NULL },
 
216
  /* 013 */ { WSAEACCES, "Permission denied", EACCES, NULL, "WSAEACCES" },
 
217
  /* 014 */ { WSAEFAULT, "Bad address", EFAULT, NULL, "WSAEFAULT" },
 
218
  /* 015 */ { 0, NULL, 0, NULL, NULL },
 
219
  /* 016 */ { 0, NULL, 0, NULL, NULL },
 
220
  /* 017 */ { 0, NULL, 0, NULL, NULL },
 
221
  /* 018 */ { 0, NULL, 0, NULL, NULL },
 
222
  /* 019 */ { 0, NULL, 0, NULL, NULL },
 
223
  /* 020 */ { 0, NULL, 0, NULL, NULL },
 
224
  /* 021 */ { 0, NULL, 0, NULL, NULL },
 
225
  /* 022 */ { WSAEINVAL, "Invalid argument", EINVAL, NULL, "WSAEINVAL" },
 
226
  /* 023 */ { 0, NULL, 0, NULL, NULL },
 
227
  /* 024 */ { WSAEMFILE, "Too many open files", EMFILE, NULL, "WSAEMFILE" },
 
228
  /* 025 */ { 0, NULL, 0, NULL, NULL },
 
229
  /* 026 */ { 0, NULL, 0, NULL, NULL },
 
230
  /* 027 */ { 0, NULL, 0, NULL, NULL },
 
231
  /* 028 */ { 0, NULL, 0, NULL, NULL },
 
232
  /* 029 */ { 0, NULL, 0, NULL, NULL },
 
233
  /* 030 */ { 0, NULL, 0, NULL, NULL },
 
234
  /* 031 */ { 0, NULL, 0, NULL, NULL },
 
235
  /* 032 */ { 0, NULL, 0, NULL, NULL },
 
236
  /* 033 */ { 0, NULL, 0, NULL, NULL },
 
237
  /* 034 */ { 0, NULL, 0, NULL, NULL },
 
238
  /* 035 */ { WSAEWOULDBLOCK, "Resource temporarily unavailable", 
 
239
              EWOULDBLOCK, "EWOULDBLOCK", "WSAEWOULDBLOCK" },
 
240
  /* 036 */ { WSAEINPROGRESS, "Operation now in progress", 
 
241
              EINPROGRESS, "EINPROGRESS", "WSAEINPROGRESS" },
 
242
  /* 037 */ { WSAEALREADY, "Operation already in progress", 
 
243
              EALREADY, "EALREADY", "WSAEALREADY" },
 
244
  /* 038 */ { WSAENOTSOCK, "Socket operation on non-socket", 
 
245
              ENOTSOCK, "ENOTSOCK", "WSAENOTSOCK"},
 
246
  /* 039 */ { WSAEDESTADDRREQ, "Destination address required", 
 
247
              EDESTADDRREQ, "EDESTADDRREQ", "WSAEDESTADDRREQ" },
 
248
  /* 040 */ { WSAEMSGSIZE, "Message too long", 
 
249
              EMSGSIZE, "EMSGSIZE", "WSAEMSGSIZE" },
 
250
  /* 041 */ { WSAEPROTOTYPE, "Protocol wrong type for socket", 
 
251
              EPROTOTYPE, "EPROTOTYPE", "WSAEPROTOTYPE" },
 
252
  /* 042 */ { WSAENOPROTOOPT, "Bad protocol option", 
 
253
              ENOPROTOOPT, "ENOPROTOOPT", "WSAENOPROTOOPT" },
 
254
  /* 043 */ { WSAEPROTONOSUPPORT, "Protocol not supported", 
 
255
              EPROTONOSUPPORT, "EPROTONOSUPPORT", "WSAEPROTONOSUPPORT" },
 
256
  /* 044 */ { WSAESOCKTNOSUPPORT, "Socket type not supported",
 
257
              ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "WSAESOCKTNOSUPPORT" },
 
258
  /* 045 */ { WSAEOPNOTSUPP, "Operation not supported",
 
259
              EOPNOTSUPP, "EOPNOTSUPP", "WSAEOPNOTSUPP" },
 
260
  /* 046 */ { WSAEPFNOSUPPORT, "Protocol family not supported",
 
261
              EPFNOSUPPORT, "EPFNOSUPPORT", "WSAEPFNOSUPPORT" },
 
262
  /* 047 */ { WSAEAFNOSUPPORT, 
 
263
              "Address family not supported by protocol family", 
 
264
              EAFNOSUPPORT, "EAFNOSUPPORT", "WSAEAFNOSUPPORT" },
 
265
  /* 048 */ { WSAEADDRINUSE, "Address already in use", 
 
266
              EADDRINUSE, "EADDRINUSE", "WSAEADDRINUSE" },
 
267
  /* 049 */ { WSAEADDRNOTAVAIL, "Cannot assign requested address",
 
268
              EADDRNOTAVAIL, "EADDRNOTAVAIL", "WSAEADDRNOTAVAIL" },
 
269
  /* 050 */ { WSAENETDOWN, "Network is down",
 
270
              ENETDOWN, "ENETDOWN", "WSAENETDOWN" },
 
271
  /* 051 */ { WSAENETUNREACH, "Network is unreachable",
 
272
              ENETUNREACH, "ENETUNREACH", "WSAENETUNREACH" },
 
273
  /* 052 */ { WSAENETRESET, "Network dropped connection on reset",
 
274
              ENETRESET, "ENETRESET", "WSAENETRESET" },
 
275
  /* 053 */ { WSAECONNABORTED, "Software caused connection abort",
 
276
              ECONNABORTED, "ECONNABORTED", "WSAECONNABORTED" },
 
277
  /* 054 */ { WSAECONNRESET, "Connection reset by peer",
 
278
              ECONNRESET, "ECONNRESET", "WSAECONNRESET" },
 
279
  /* 055 */ { WSAENOBUFS, "No buffer space available",
 
280
              ENOBUFS, "ENOBUFS", "WSAENOBUFS" },
 
281
  /* 056 */ { WSAEISCONN, "Socket is already connected",
 
282
              EISCONN, "EISCONN", "WSAEISCONN" },
 
283
  /* 057 */ { WSAENOTCONN, "Socket is not connected",
 
284
              ENOTCONN, "ENOTCONN", "WSAENOTCONN" },
 
285
  /* 058 */ { WSAESHUTDOWN, "Cannot send after socket shutdown",
 
286
              ESHUTDOWN, "ESHUTDOWN", "WSAESHUTDOWN" },
 
287
  /* 059 */ { WSAETOOMANYREFS, "Too many references; can't splice",
 
288
              ETOOMANYREFS, "ETOOMANYREFS", "WSAETOOMANYREFS" },
 
289
  /* 060 */ { WSAETIMEDOUT, "Connection timed out",
 
290
              ETIMEDOUT, "ETIMEDOUT", "WSAETIMEDOUT" },
 
291
  /* 061 */ { WSAECONNREFUSED, "Connection refused",
 
292
              ECONNREFUSED, "ECONNREFUSED", "WSAECONNREFUSED" },
 
293
  /* 062 */ { WSAELOOP, "Too many levels of symbolic links",
 
294
              ELOOP, "ELOOP", "WSAELOOP" },
 
295
  /* 063 */ { WSAENAMETOOLONG, "File name too long",
 
296
              ENAMETOOLONG, NULL, "WSAENAMETOOLONG" },
 
297
  /* 064 */ { WSAEHOSTDOWN, "Host is down",
 
298
              EHOSTDOWN, "EHOSTDOWN", "WSAEHOSTDOWN" },
 
299
  /* 065 */ { WSAEHOSTUNREACH, "No route to host",
 
300
              EHOSTUNREACH, "EHOSTUNREACH", "WSAEHOSTUNREACH" },
 
301
  /* 066 */ { WSAENOTEMPTY, "Directory not empty",
 
302
              ENOTEMPTY, NULL, "WSAENOTEMPTY" },
 
303
  /* 067 */ { WSAEPROCLIM, "Too many processes",
 
304
              EPROCLIM, "EPROCLIM", "WSAEPROCLIM" },
 
305
  /* 068 */ { WSAEUSERS, "Too many users",
 
306
              EUSERS, "EUSERS", "WSAEUSERS" },
 
307
  /* 069 */ { WSAEDQUOT, "Disc quota exceeded",
 
308
              EDQUOT, "EDQUOT", "WSAEDQUOT" },
 
309
  /* 070 */ { WSAESTALE, "Stale NFS file handle",
 
310
              ESTALE, "ESTALE", "WSAESTALE" },
 
311
  /* 071 */ { WSAEREMOTE, "Too many levels of remote in path",
 
312
              EREMOTE, "EREMOTE", "WSAEREMOTE" },
 
313
  /* 072 */ { 0, NULL, 0, NULL, NULL },
 
314
  /* 073 */ { 0, NULL, 0, NULL, NULL },
 
315
  /* 074 */ { 0, NULL, 0, NULL, NULL },
 
316
  /* 075 */ { 0, NULL, 0, NULL, NULL },
 
317
  /* 076 */ { 0, NULL, 0, NULL, NULL },
 
318
  /* 077 */ { 0, NULL, 0, NULL, NULL },
 
319
  /* 078 */ { 0, NULL, 0, NULL, NULL },
 
320
  /* 079 */ { 0, NULL, 0, NULL, NULL },
 
321
  /* 080 */ { 0, NULL, 0, NULL, NULL },
 
322
  /* 081 */ { 0, NULL, 0, NULL, NULL },
 
323
  /* 082 */ { 0, NULL, 0, NULL, NULL },
 
324
  /* 083 */ { 0, NULL, 0, NULL, NULL },
 
325
  /* 084 */ { 0, NULL, 0, NULL, NULL },
 
326
  /* 085 */ { 0, NULL, 0, NULL, NULL },
 
327
  /* 086 */ { 0, NULL, 0, NULL, NULL },
 
328
  /* 087 */ { 0, NULL, 0, NULL, NULL },
 
329
  /* 088 */ { 0, NULL, 0, NULL, NULL },
 
330
  /* 089 */ { 0, NULL, 0, NULL, NULL },
 
331
  /* 090 */ { 0, NULL, 0, NULL, NULL },
 
332
  /* 091 */ { WSASYSNOTREADY, "Network subsystem is unavailable",
 
333
              0, NULL, "WSASYSNOTREADY" },
 
334
  /* 092 */ { WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range", 
 
335
              0, NULL, "WSAVERNOTSUPPORTED" },
 
336
  /* 093 */ { WSANOTINITIALISED, "Successful WSAStartup not yet performed", 
 
337
              0, NULL, "WSANOTINITIALISED" },
 
338
  /* 094 */ { 0, NULL, 0, NULL, NULL },
 
339
  /* 095 */ { 0, NULL, 0, NULL, NULL },
 
340
  /* 096 */ { 0, NULL, 0, NULL, NULL },
 
341
  /* 097 */ { 0, NULL, 0, NULL, NULL },
 
342
  /* 098 */ { 0, NULL, 0, NULL, NULL },
 
343
  /* 099 */ { 0, NULL, 0, NULL, NULL },
 
344
  /* 100 */ { 0, NULL, 0, NULL, NULL },
 
345
  /* 101 */ { WSAEDISCON, "Graceful shutdown in progress",
 
346
              0, NULL, "WSAEDISCON" },
 
347
  /* 102 */ { WSAENOMORE, "No more services", 
 
348
              0, NULL, "WSAENOMORE" },
 
349
  /* 103 */ { WSAECANCELLED, "Service lookup cancelled",
 
350
              0, NULL, "WSAECANCELLED" },
 
351
  /* 104 */ { WSAEINVALIDPROCTABLE, "Invalid procedure call table", 
 
352
              0, NULL, "WSAEINVALIDPROCTABLE" },
 
353
  /* 105 */ { WSAEINVALIDPROVIDER, "Invalid service provider",
 
354
              0, NULL, "WSAEINVALIDPROVIDER" },
 
355
  /* 106 */ { WSAEPROVIDERFAILEDINIT, "Service provider failure", 
 
356
              0, NULL, "WSAEPROVIDERFAILEDINIT" },
 
357
  /* 107 */ { WSASYSCALLFAILURE, "System call failed",
 
358
              0, NULL, "WSASYSCALLFAILURE" },
 
359
  /* 108 */ { WSASERVICE_NOT_FOUND, "No such service",
 
360
              0, NULL, "WSASERVICE_NOT_FOUND" },
 
361
  /* 109 */ { WSATYPE_NOT_FOUND, "Class not found", 
 
362
              0, NULL, "WSATYPE_NOT_FOUND" },
 
363
  /* 110 */ { WSA_E_NO_MORE, "No more services",
 
364
              0, NULL, "WSA_E_NO_MORE" },
 
365
  /* 111 */ { WSA_E_CANCELLED, "Service lookup cancelled", 
 
366
              0, NULL, "WSA_E_CANCELLED" },
 
367
  /* 112 */ { WSAEREFUSED, "Database query refused", 
 
368
              0, NULL, "WSAEREFUSED" },
 
369
  /* end */ { -1, NULL, -1, NULL, NULL }
 
370
};
 
371
 
 
372
/* Extended list of error structures.  */
 
373
static socket_error_t socket_h_errno [] = {
 
374
  /* 000 */ { 0, NULL, 0, NULL, NULL },
 
375
  /* 001 */ { WSAHOST_NOT_FOUND, "Host not found",
 
376
              HOST_NOT_FOUND, "HOST_NOT_FOUND", "WSAHOST_NOT_FOUND" },
 
377
  /* 002 */ { WSATRY_AGAIN, "Non-authoritative host not found",
 
378
              TRY_AGAIN, "TRY_AGAIN", "WSATRY_AGAIN" },
 
379
  /* 003 */ { WSANO_RECOVERY, "This is a non-recoverable error", 
 
380
              NO_RECOVERY, "NO_RECOVERY", "WSANO_RECOVERY" },
 
381
  /* 004 */ { WSANO_DATA, "Valid name, no data record of requested type",
 
382
              NO_DATA, "NO_DATA", "WSANO_DATA" },
 
383
  /* 005 */ { WSANO_ADDRESS, "No address, look for MX record",
 
384
              NO_ADDRESS, "NO_ADDRESS", "WSANO_ADDRESS" },
 
385
  /* end */ { -1, NULL, -1, NULL, NULL }
 
386
};
 
387
 
 
388
/* Returns the result of @code{WSAGetLastError()}.  */
 
389
int
 
390
scm_i_socket_errno (void)
 
391
{
 
392
  return WSAGetLastError ();
 
393
}
 
394
 
 
395
/* Returns a valid error message for Winsock-API error codes obtained via
 
396
   @code{WSAGetLastError()} or NULL otherwise.  */
 
397
char *
 
398
scm_i_socket_strerror (int error)
 
399
{
 
400
  if (error >= WSABASEERR && error <= (WSABASEERR + 112))
 
401
    return socket_errno[error - WSABASEERR].str;
 
402
  else if (error >= (WSABASEERR + 1000) && error <= (WSABASEERR + 1005))
 
403
    return socket_h_errno[error - (WSABASEERR + 1000)].str;
 
404
  return NULL;
 
405
}
 
406
 
 
407
/* Constructs a valid filename for the given file @var{file} in the M$-Windows
 
408
   directory.  This is usually the default location for the network files.  */
 
409
char *
 
410
scm_i_socket_filename (char *file)
 
411
{
 
412
  static char dir[PATH_MAX];
 
413
  int len = PATH_MAX;
 
414
 
 
415
  len = GetWindowsDirectory (dir, len);
 
416
  if (dir[len - 1] != '\\')
 
417
    strcat (dir, "\\");
 
418
  strcat (dir, file);
 
419
  return dir;
 
420
}
 
421
 
 
422
/* Removes comments and white spaces at end of line and returns a pointer
 
423
   to the end of the line.  */
 
424
static char *
 
425
scm_i_socket_uncomment (char *line)
 
426
{
 
427
  char *end;
 
428
 
 
429
  if ((end = strchr (line, '#')) != NULL)
 
430
    *end-- = '\0';
 
431
  else
 
432
    {
 
433
      end = line + strlen (line) - 1;
 
434
      while (end > line && (*end == '\r' || *end == '\n'))
 
435
        *end-- = '\0';
 
436
    }
 
437
  while (end > line && isspace (*end))
 
438
    *end-- = '\0';
 
439
 
 
440
  return end;
 
441
}
 
442
 
 
443
/* The getservent() function reads the next line from the file `/etc/services'
 
444
   and returns a structure servent containing the broken out fields from the
 
445
   line.  The `/etc/services' file is opened if necessary. */
 
446
struct servent *
 
447
getservent (void)
 
448
{
 
449
  char line[MAX_NAMLEN], *end, *p;
 
450
  int done = 0, i, n, a;
 
451
  struct servent *e = NULL;
 
452
 
 
453
  /* Ensure a open file.  */
 
454
  if (scm_i_servent.fd == NULL || feof (scm_i_servent.fd))
 
455
    {
 
456
      setservent (1);
 
457
      if (scm_i_servent.fd == NULL)
 
458
        return NULL;
 
459
    }
 
460
 
 
461
  while (!done)
 
462
    {
 
463
      /* Get new line.  */
 
464
      if (fgets (line, MAX_NAMLEN, scm_i_servent.fd) != NULL)
 
465
        {
 
466
          end = scm_i_socket_uncomment (line);
 
467
 
 
468
          /* Scan the line.  */
 
469
          if ((i = sscanf (line, "%s %d/%s%n", 
 
470
                           scm_i_servent.name,
 
471
                           &scm_i_servent.port, 
 
472
                           scm_i_servent.proto, &n)) != 3)
 
473
            continue;
 
474
 
 
475
          /* Scan the remaining aliases.  */
 
476
          p = line + n;
 
477
          for (a = 0; a < MAX_ALIASES && p < end && i != -1 && n > 1; 
 
478
               a++, p += n)
 
479
            i = sscanf (p, "%s%n", scm_i_servent.alias[a], &n);
 
480
 
 
481
          /* Prepare the return value.  */
 
482
          e = &scm_i_servent.ent;
 
483
          e->s_name = scm_i_servent.name;
 
484
          e->s_port = htons (scm_i_servent.port);
 
485
          e->s_proto = scm_i_servent.proto;
 
486
          e->s_aliases = scm_i_servent.aliases;
 
487
          scm_i_servent.aliases[a] = NULL;
 
488
          while (a--)
 
489
            scm_i_servent.aliases[a] = scm_i_servent.alias[a];
 
490
          done = 1;
 
491
        }
 
492
      else
 
493
        break;
 
494
    }
 
495
  return done ? e : NULL;
 
496
}
 
497
 
 
498
/* The setservent() function opens and rewinds the `/etc/services' file.  
 
499
   This file can be set from outside with an environment variable specifying
 
500
   the file name.  */
 
501
void
 
502
setservent (int stayopen)
 
503
{
 
504
  char *file = NULL;
 
505
 
 
506
  endservent ();
 
507
  if ((file = getenv (ENVIRON_ETC_SERVICES)) != NULL)
 
508
    strcpy (scm_i_servent.file, file);
 
509
  else if ((file = scm_i_socket_filename (FILE_ETC_SERVICES)) != NULL)
 
510
    strcpy (scm_i_servent.file, file);
 
511
  scm_i_servent.fd = fopen (scm_i_servent.file, "rt");
 
512
}
 
513
 
 
514
/* The endservent() function closes the `/etc/services' file.  */
 
515
void
 
516
endservent (void)
 
517
{
 
518
  if (scm_i_servent.fd != NULL)
 
519
    {
 
520
      fclose (scm_i_servent.fd);
 
521
      scm_i_servent.fd = NULL;
 
522
    }
 
523
}
 
524
 
 
525
/* The getprotoent() function reads the next line from the file
 
526
   `/etc/protocols' and returns a structure protoent containing the broken
 
527
   out fields from the line. The `/etc/protocols' file is opened if 
 
528
   necessary.  */
 
529
struct protoent *
 
530
getprotoent (void)
 
531
{
 
532
  char line[MAX_NAMLEN], *end, *p;
 
533
  int done = 0, i, n, a;
 
534
  struct protoent *e = NULL;
 
535
 
 
536
  /* Ensure a open file.  */
 
537
  if (scm_i_protoent.fd == NULL || feof (scm_i_protoent.fd))
 
538
    {
 
539
      setprotoent (1);
 
540
      if (scm_i_protoent.fd == NULL)
 
541
        return NULL;
 
542
    }
 
543
 
 
544
  while (!done)
 
545
    {
 
546
      /* Get new line.  */
 
547
      if (fgets (line, MAX_NAMLEN, scm_i_protoent.fd) != NULL)
 
548
        {
 
549
          end = scm_i_socket_uncomment (line);
 
550
 
 
551
          /* Scan the line.  */
 
552
          if ((i = sscanf (line, "%s %d%n", 
 
553
                           scm_i_protoent.name,
 
554
                           &scm_i_protoent.proto, &n)) != 2)
 
555
            continue;
 
556
 
 
557
          /* Scan the remaining aliases.  */
 
558
          p = line + n;
 
559
          for (a = 0; a < MAX_ALIASES && p < end && i != -1 && n > 1; 
 
560
               a++, p += n)
 
561
            i = sscanf (p, "%s%n", scm_i_protoent.alias[a], &n);
 
562
 
 
563
          /* Prepare the return value.  */
 
564
          e = &scm_i_protoent.ent;
 
565
          e->p_name = scm_i_protoent.name;
 
566
          e->p_proto = scm_i_protoent.proto;
 
567
          e->p_aliases = scm_i_protoent.aliases;
 
568
          scm_i_protoent.aliases[a] = NULL;
 
569
          while (a--)
 
570
            scm_i_protoent.aliases[a] = scm_i_protoent.alias[a];
 
571
          done = 1;
 
572
        }
 
573
      else
 
574
        break;
 
575
    }
 
576
  return done ? e : NULL;
 
577
}
 
578
 
 
579
/* The setprotoent() function opens and rewinds the `/etc/protocols' file. 
 
580
   As in setservent() the user can modify the location of the file using
 
581
   an environment variable.  */
 
582
void 
 
583
setprotoent (int stayopen)
 
584
{
 
585
  char *file = NULL;
 
586
 
 
587
  endprotoent ();
 
588
  if ((file = getenv (ENVIRON_ETC_PROTOCOLS)) != NULL)
 
589
    strcpy (scm_i_protoent.file, file);
 
590
  else if ((file = scm_i_socket_filename (FILE_ETC_PROTOCOLS)) != NULL)
 
591
    strcpy (scm_i_protoent.file, file);
 
592
  scm_i_protoent.fd = fopen (scm_i_protoent.file, "rt");
 
593
}
 
594
 
 
595
/* The endprotoent() function closes `/etc/protocols'.  */
 
596
void
 
597
endprotoent (void)
 
598
{
 
599
  if (scm_i_protoent.fd != NULL)
 
600
    {
 
601
      fclose (scm_i_protoent.fd);
 
602
      scm_i_protoent.fd = NULL;
 
603
    }
 
604
}
 
605
 
 
606
/* Define both the original and replacement error symbol is possible.  Thus
 
607
   the user is able to check symbolic errors after unsuccessful networking
 
608
   function calls.  */
 
609
static void
 
610
scm_socket_symbols_Win32 (socket_error_t * e)
 
611
{
 
612
  while (e->error != -1)
 
613
    {
 
614
      if (e->error)
 
615
        {
 
616
          if (e->correct_str)
 
617
            scm_c_define (e->correct_str, scm_from_int (e->error));
 
618
          if (e->replace && e->replace_str)
 
619
            scm_c_define (e->replace_str, scm_from_int (e->replace));
 
620
        }
 
621
      e++;
 
622
    }
 
623
}
 
624
 
 
625
/* Initialize Winsock API under M$-Windows.  */
 
626
void
 
627
scm_i_init_socket_Win32 (void)
 
628
{
 
629
  scm_socket_symbols_Win32 (socket_errno);
 
630
  scm_socket_symbols_Win32 (socket_h_errno);
 
631
}