win32-socket.c 20 KB

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