summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/ChangeLog14
-rw-r--r--libguile/net_db.c12
-rw-r--r--libguile/numbers.c11
-rw-r--r--libguile/win32-socket.c248
-rw-r--r--libguile/win32-socket.h8
5 files changed, 289 insertions, 4 deletions
diff --git a/libguile/ChangeLog b/libguile/ChangeLog
index 7445c1d9a..93bcc0753 100644
--- a/libguile/ChangeLog
+++ b/libguile/ChangeLog
@@ -1,3 +1,17 @@
+2001-11-21 Stefan Jahn <stefan@lkcc.org>
+
+ * win32-socket.c (getservent, setservent, endservent,
+ getprotoent, setprotoent, endprotoent): New functions.
+ Appropriate replacements for M$-Windows.
+
+ * numbers.c (SIZE_MAX, PTRDIFF_MAX, PTRDIFF_MIN): Reintroduced
+ these definitions for GUILE_DEBUG.
+
+ * net_db.c: Include "win32-socket.h" if compiling with a native
+ M$-Windows compiler. Include some pieces of code (protoent and
+ servent interface) protected by HAVE_* macros when using a
+ native M$-Windows compiler.
+
2001-11-20 Marius Vollmer <mvo@zagadka.ping.de>
* modules.c (scm_c_export): Do nothing when the first argument is
diff --git a/libguile/net_db.c b/libguile/net_db.c
index d32819ee8..fd00a0497 100644
--- a/libguile/net_db.c
+++ b/libguile/net_db.c
@@ -74,6 +74,10 @@
#include <arpa/inet.h>
#endif
+#ifdef __MINGW32__
+#include "win32-socket.h"
+#endif
+
#if !defined (HAVE_H_ERRNO) && !defined (__MINGW32__) && !defined (__CYGWIN__)
/* h_errno not found in netdb.h, maybe this will help. */
extern int h_errno;
@@ -266,7 +270,7 @@ SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
#undef FUNC_NAME
#endif
-#ifdef HAVE_GETPROTOENT
+#if defined (HAVE_GETPROTOENT) || defined (__MINGW32__)
SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
(SCM protocol),
"@deffnx {Scheme Procedure} getprotobyname name\n"
@@ -314,7 +318,7 @@ SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
#undef FUNC_NAME
#endif
-#ifdef HAVE_GETSERVENT
+#if defined (HAVE_GETSERVENT) || defined (__MINGW32__)
static SCM
scm_return_entry (struct servent *entry)
{
@@ -405,7 +409,7 @@ SCM_DEFINE (scm_setnet, "setnet", 0, 1, 0,
#undef FUNC_NAME
#endif
-#if defined(HAVE_SETPROTOENT) && defined(HAVE_ENDPROTOENT)
+#if defined (HAVE_SETPROTOENT) && defined (HAVE_ENDPROTOENT) || defined (__MINGW32__)
SCM_DEFINE (scm_setproto, "setproto", 0, 1, 0,
(SCM stayopen),
"If @var{stayopen} is omitted, this is equivalent to @code{endprotoent}.\n"
@@ -421,7 +425,7 @@ SCM_DEFINE (scm_setproto, "setproto", 0, 1, 0,
#undef FUNC_NAME
#endif
-#if defined(HAVE_SETSERVENT) && defined(HAVE_ENDSERVENT)
+#if defined (HAVE_SETSERVENT) && defined (HAVE_ENDSERVENT) || defined (__MINGW32__)
SCM_DEFINE (scm_setserv, "setserv", 0, 1, 0,
(SCM stayopen),
"If @var{stayopen} is omitted, this is equivalent to @code{endservent}.\n"
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 154974d24..4afc1578b 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -4390,6 +4390,17 @@ scm_i_big2dbl (SCM b)
#ifdef GUILE_DEBUG
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) (-1))
+#endif
+#ifndef PTRDIFF_MIN
+#define PTRDIFF_MIN \
+ ((ptrdiff_t) ((ptrdiff_t) 1 << (sizeof (ptrdiff_t) * 8 - 1)))
+#endif
+#ifndef PTRDIFF_MAX
+#define PTRDIFF_MAX (~ PTRDIFF_MIN)
+#endif
+
#define CHECK(type, v) \
do { \
if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
diff --git a/libguile/win32-socket.c b/libguile/win32-socket.c
index 8456ad321..a2556b6d1 100644
--- a/libguile/win32-socket.c
+++ b/libguile/win32-socket.c
@@ -46,7 +46,16 @@
#include "libguile/modules.h"
#include "libguile/numbers.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
#include <errno.h>
+#include <limits.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 255
+#endif
#include "win32-socket.h"
@@ -62,6 +71,46 @@ typedef struct
}
socket_error_t;
+#define FILE_ETC_SERVICES "services"
+#define ENVIRON_ETC_SERVICES "SERVICES"
+#define FILE_ETC_NETWORKS "networks"
+#define ENVIRON_ETC_NETWORKS "NETWORKS"
+#define FILE_ETC_PROTOCOLS "protocol"
+#define ENVIRON_ETC_PROTOCOLS "PROTOCOLS"
+#define MAX_NAMLEN 256
+#define MAX_ALIASES 4
+
+/* Internal structure for a thread's M$-Windows servent interface. */
+typedef struct
+{
+ FILE *fd; /* Current file. */
+ char file[PATH_MAX]; /* File name. */
+ struct servent ent; /* Return value. */
+ char name[MAX_NAMLEN]; /* Service name. */
+ char proto[MAX_NAMLEN]; /* Protocol name. */
+ char alias[MAX_ALIASES][MAX_NAMLEN]; /* All aliases. */
+ char *aliases[MAX_ALIASES]; /* Alias pointers. */
+ int port; /* Network port. */
+}
+scm_i_servent_t;
+
+static scm_i_servent_t scm_i_servent;
+
+/* Internal structure for a thread's M$-Windows protoent interface. */
+typedef struct
+{
+ FILE *fd; /* Current file. */
+ char file[PATH_MAX]; /* File name. */
+ struct protoent ent; /* Return value. */
+ char name[MAX_NAMLEN]; /* Protocol name. */
+ char alias[MAX_ALIASES][MAX_NAMLEN]; /* All aliases. */
+ char *aliases[MAX_ALIASES]; /* Alias pointers. */
+ int proto; /* Protocol number. */
+}
+scm_i_protoent_t;
+
+static scm_i_protoent_t scm_i_protoent;
+
/* Define replacement symbols for most of the WSA* error codes. */
#ifndef EWOULDBLOCK
# define EWOULDBLOCK WSAEWOULDBLOCK
@@ -375,6 +424,205 @@ scm_i_socket_strerror (int error)
return NULL;
}
+/* Constructs a valid filename for the given file @var{file} in the M$-Windows
+ directory. This is usually the default location for the network files. */
+char *
+scm_i_socket_filename (char *file)
+{
+ static char dir[PATH_MAX];
+ int len = PATH_MAX;
+
+ len = GetWindowsDirectory (dir, len);
+ if (dir[len - 1] != '\\')
+ strcat (dir, "\\");
+ strcat (dir, file);
+ return dir;
+}
+
+/* Removes comments and white spaces at end of line and returns a pointer
+ to the end of the line. */
+static char *
+scm_i_socket_uncomment (char *line)
+{
+ char *end;
+
+ if ((end = strchr (line, '#')) != NULL)
+ *end-- = '\0';
+ else
+ {
+ end = line + strlen (line) - 1;
+ while (end > line && (*end == '\r' || *end == '\n'))
+ *end-- = '\0';
+ }
+ while (end > line && isspace (*end))
+ *end-- = '\0';
+
+ return end;
+}
+
+/* The getservent() function reads the next line from the file `/etc/services'
+ and returns a structure servent containing the broken out fields from the
+ line. The `/etc/services' file is opened if necessary. */
+struct servent *
+getservent (void)
+{
+ char line[MAX_NAMLEN], *end, *p;
+ int done = 0, i, n, a;
+ struct servent *e = NULL;
+
+ /* Ensure a open file. */
+ if (scm_i_servent.fd == NULL || feof (scm_i_servent.fd))
+ {
+ setservent (1);
+ if (scm_i_servent.fd == NULL)
+ return NULL;
+ }
+
+ while (!done)
+ {
+ /* Get new line. */
+ if (fgets (line, MAX_NAMLEN, scm_i_servent.fd) != NULL)
+ {
+ end = scm_i_socket_uncomment (line);
+
+ /* Scan the line. */
+ if ((i = sscanf (line, "%s %d/%s%n",
+ scm_i_servent.name,
+ &scm_i_servent.port,
+ scm_i_servent.proto, &n)) != 3)
+ continue;
+
+ /* Scan the remaining aliases. */
+ p = line + n;
+ for (a = 0; a < MAX_ALIASES && p < end && i != -1 && n > 1;
+ a++, p += n)
+ i = sscanf (p, "%s%n", scm_i_servent.alias[a], &n);
+
+ /* Prepare the return value. */
+ e = &scm_i_servent.ent;
+ e->s_name = scm_i_servent.name;
+ e->s_port = htons (scm_i_servent.port);
+ e->s_proto = scm_i_servent.proto;
+ e->s_aliases = scm_i_servent.aliases;
+ scm_i_servent.aliases[a] = NULL;
+ while (a--)
+ scm_i_servent.aliases[a] = scm_i_servent.alias[a];
+ done = 1;
+ }
+ else
+ break;
+ }
+ return done ? e : NULL;
+}
+
+/* The setservent() function opens and rewinds the `/etc/services' file.
+ This file can be set from outside with an environment variable specifying
+ the file name. */
+void
+setservent (int stayopen)
+{
+ char *file = NULL;
+
+ endservent ();
+ if ((file = getenv (ENVIRON_ETC_SERVICES)) != NULL)
+ strcpy (scm_i_servent.file, file);
+ else if ((file = scm_i_socket_filename (FILE_ETC_SERVICES)) != NULL)
+ strcpy (scm_i_servent.file, file);
+ scm_i_servent.fd = fopen (scm_i_servent.file, "rt");
+}
+
+/* The endservent() function closes the `/etc/services' file. */
+void
+endservent (void)
+{
+ if (scm_i_servent.fd != NULL)
+ {
+ fclose (scm_i_servent.fd);
+ scm_i_servent.fd = NULL;
+ }
+}
+
+/* The getprotoent() function reads the next line from the file
+ `/etc/protocols' and returns a structure protoent containing the broken
+ out fields from the line. The `/etc/protocols' file is opened if
+ necessary. */
+struct protoent *
+getprotoent (void)
+{
+ char line[MAX_NAMLEN], *end, *p;
+ int done = 0, i, n, a;
+ struct protoent *e = NULL;
+
+ /* Ensure a open file. */
+ if (scm_i_protoent.fd == NULL || feof (scm_i_protoent.fd))
+ {
+ setprotoent (1);
+ if (scm_i_protoent.fd == NULL)
+ return NULL;
+ }
+
+ while (!done)
+ {
+ /* Get new line. */
+ if (fgets (line, MAX_NAMLEN, scm_i_protoent.fd) != NULL)
+ {
+ end = scm_i_socket_uncomment (line);
+
+ /* Scan the line. */
+ if ((i = sscanf (line, "%s %d%n",
+ scm_i_protoent.name,
+ &scm_i_protoent.proto, &n)) != 2)
+ continue;
+
+ /* Scan the remaining aliases. */
+ p = line + n;
+ for (a = 0; a < MAX_ALIASES && p < end && i != -1 && n > 1;
+ a++, p += n)
+ i = sscanf (p, "%s%n", scm_i_protoent.alias[a], &n);
+
+ /* Prepare the return value. */
+ e = &scm_i_protoent.ent;
+ e->p_name = scm_i_protoent.name;
+ e->p_proto = scm_i_protoent.proto;
+ e->p_aliases = scm_i_protoent.aliases;
+ scm_i_protoent.aliases[a] = NULL;
+ while (a--)
+ scm_i_protoent.aliases[a] = scm_i_protoent.alias[a];
+ done = 1;
+ }
+ else
+ break;
+ }
+ return done ? e : NULL;
+}
+
+/* The setprotoent() function opens and rewinds the `/etc/protocols' file.
+ As in setservent() the user can modify the location of the file using
+ an environment variable. */
+void
+setprotoent (int stayopen)
+{
+ char *file = NULL;
+
+ endprotoent ();
+ if ((file = getenv (ENVIRON_ETC_PROTOCOLS)) != NULL)
+ strcpy (scm_i_protoent.file, file);
+ else if ((file = scm_i_socket_filename (FILE_ETC_PROTOCOLS)) != NULL)
+ strcpy (scm_i_protoent.file, file);
+ scm_i_protoent.fd = fopen (scm_i_protoent.file, "rt");
+}
+
+/* The endprotoent() function closes `/etc/protocols'. */
+void
+endprotoent (void)
+{
+ if (scm_i_protoent.fd != NULL)
+ {
+ fclose (scm_i_protoent.fd);
+ scm_i_protoent.fd = NULL;
+ }
+}
+
/* Define both the original and replacement error symbol is possible. Thus
the user is able to check symbolic errors after unsuccessful networking
function calls. */
diff --git a/libguile/win32-socket.h b/libguile/win32-socket.h
index 83e1030dd..adbe2c517 100644
--- a/libguile/win32-socket.h
+++ b/libguile/win32-socket.h
@@ -52,5 +52,13 @@
int scm_i_socket_errno (void);
char * scm_i_socket_strerror (int error);
void scm_i_init_socket_Win32 (void);
+char * scm_i_socket_filename (char *file);
+
+struct servent * getservent (void);
+void setservent (int stayopen);
+void endservent (void);
+struct protoent * getprotoent (void);
+void setprotoent (int stayopen);
+void endprotoent (void);
#endif /* SCM_WIN32_SOCKET_H */