mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 21:30:29 +02:00
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.
This commit is contained in:
parent
351982f656
commit
6063dc1ddd
5 changed files with 289 additions and 4 deletions
|
@ -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>
|
2001-11-20 Marius Vollmer <mvo@zagadka.ping.de>
|
||||||
|
|
||||||
* modules.c (scm_c_export): Do nothing when the first argument is
|
* modules.c (scm_c_export): Do nothing when the first argument is
|
||||||
|
|
|
@ -74,6 +74,10 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#include "win32-socket.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined (HAVE_H_ERRNO) && !defined (__MINGW32__) && !defined (__CYGWIN__)
|
#if !defined (HAVE_H_ERRNO) && !defined (__MINGW32__) && !defined (__CYGWIN__)
|
||||||
/* h_errno not found in netdb.h, maybe this will help. */
|
/* h_errno not found in netdb.h, maybe this will help. */
|
||||||
extern int h_errno;
|
extern int h_errno;
|
||||||
|
@ -266,7 +270,7 @@ SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETPROTOENT
|
#if defined (HAVE_GETPROTOENT) || defined (__MINGW32__)
|
||||||
SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
|
SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
|
||||||
(SCM protocol),
|
(SCM protocol),
|
||||||
"@deffnx {Scheme Procedure} getprotobyname name\n"
|
"@deffnx {Scheme Procedure} getprotobyname name\n"
|
||||||
|
@ -314,7 +318,7 @@ SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETSERVENT
|
#if defined (HAVE_GETSERVENT) || defined (__MINGW32__)
|
||||||
static SCM
|
static SCM
|
||||||
scm_return_entry (struct servent *entry)
|
scm_return_entry (struct servent *entry)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +409,7 @@ SCM_DEFINE (scm_setnet, "setnet", 0, 1, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#endif
|
#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_DEFINE (scm_setproto, "setproto", 0, 1, 0,
|
||||||
(SCM stayopen),
|
(SCM stayopen),
|
||||||
"If @var{stayopen} is omitted, this is equivalent to @code{endprotoent}.\n"
|
"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
|
#undef FUNC_NAME
|
||||||
#endif
|
#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_DEFINE (scm_setserv, "setserv", 0, 1, 0,
|
||||||
(SCM stayopen),
|
(SCM stayopen),
|
||||||
"If @var{stayopen} is omitted, this is equivalent to @code{endservent}.\n"
|
"If @var{stayopen} is omitted, this is equivalent to @code{endservent}.\n"
|
||||||
|
|
|
@ -4390,6 +4390,17 @@ scm_i_big2dbl (SCM b)
|
||||||
|
|
||||||
#ifdef GUILE_DEBUG
|
#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) \
|
#define CHECK(type, v) \
|
||||||
do { \
|
do { \
|
||||||
if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
|
if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
|
||||||
|
|
|
@ -46,7 +46,16 @@
|
||||||
#include "libguile/modules.h"
|
#include "libguile/modules.h"
|
||||||
#include "libguile/numbers.h"
|
#include "libguile/numbers.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 255
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "win32-socket.h"
|
#include "win32-socket.h"
|
||||||
|
|
||||||
|
@ -62,6 +71,46 @@ typedef struct
|
||||||
}
|
}
|
||||||
socket_error_t;
|
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. */
|
/* Define replacement symbols for most of the WSA* error codes. */
|
||||||
#ifndef EWOULDBLOCK
|
#ifndef EWOULDBLOCK
|
||||||
# define EWOULDBLOCK WSAEWOULDBLOCK
|
# define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
|
@ -375,6 +424,205 @@ scm_i_socket_strerror (int error)
|
||||||
return NULL;
|
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
|
/* Define both the original and replacement error symbol is possible. Thus
|
||||||
the user is able to check symbolic errors after unsuccessful networking
|
the user is able to check symbolic errors after unsuccessful networking
|
||||||
function calls. */
|
function calls. */
|
||||||
|
|
|
@ -52,5 +52,13 @@
|
||||||
int scm_i_socket_errno (void);
|
int scm_i_socket_errno (void);
|
||||||
char * scm_i_socket_strerror (int error);
|
char * scm_i_socket_strerror (int error);
|
||||||
void scm_i_init_socket_Win32 (void);
|
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 */
|
#endif /* SCM_WIN32_SOCKET_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue