Here is an updated patch to get gethostname working under MinGW. It uses the recent new gnulib module 'sockets'.
The module works like this: If the gethostname function is not found on the system, it pulls in gethostname.c into the gnulib library, and defines gethostname to rpl_gethostname. rpl_gethostname calls the gl_socket_* functions to initialize and shutdown Windows sockets, calls the real Windows gethostname function. It then converts from the Windows error codes to errno, and then shut downs Windows sockets. What do people think about the approach chosen here? There are many choices which are open for discussion: 1) Should we convert from WSA* errors to errno codes? Alternatively, we could return WSA* errors in the errno variable, since the integer values do not seem to overlap, and enhance strerror to be able to print the Windows socket error strings. This may cause problems for code comparing errno values though, which is why I chose not to do this. 2) Should conversion of WSA* error codes happen inside the gethostname.c file, or should it be moved to (e.g.) sockets.{c,h}? It is not clear to me if there is a 1-1 mapping of all relevant error codes. Maybe some Windows function return Windows socket error X which is appropriate to map to errno value Y, while at the same time another Windows function return Windows socket error X which is appropriate (in that context) to map to errno value Z. 3) Is there any chance that the #define gethostname rpl_gethostname and replacement prototype of gethostname in gnulib's unistd.h will cause problems? Consider that gethostname in winsock2.h is declared with PASCAL calling conventions, so the prototype is not the same as the one that gnulib uses. That may cause problems in some weird situations, but I can't see them right now. The self test works fine. 4) Is calling WSAStartup/WSACleanup in each gnulib replacement module a good idea? I could easily argue that it is simpler for everyone if gnulib simply say that if you care about Windows portability, you need to call WSAStartup+WSACleanup yourself. The gnulib module 'sockets' could be used for this, and then the 'gethostname' module may not need to depend directly on the 'sockets' module. 5) Does this result in the right thing on cygwin? I suppose it should detect that gethostname is present and not do anything beyond that. Thanks, /Simon diff --git a/lib/gethostname.c b/lib/gethostname.c index 169dd4e..767afe6 100644 --- a/lib/gethostname.c +++ b/lib/gethostname.c @@ -15,14 +15,24 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* David MacKenzie <[EMAIL PROTECTED]> */ +/* David MacKenzie <[EMAIL PROTECTED]>, + MinGW port by Simon Josefsson <[EMAIL PROTECTED]> */ #include <config.h> +#undef gethostname #ifdef HAVE_UNAME # include <sys/utsname.h> #endif +#ifdef WINDOWS_SOCKETS +# include <errno.h> +# include "sockets.h" +# ifdef HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +#endif + #include <string.h> /* Put up to LEN chars of the host name into NAME. @@ -32,7 +42,7 @@ #include <stddef.h> int -gethostname (char *name, size_t len) +rpl_gethostname (char *name, size_t len) { #ifdef HAVE_UNAME struct utsname uts; @@ -46,6 +56,37 @@ gethostname (char *name, size_t len) len = sizeof (uts.nodename); } strncpy (name, uts.nodename, len); +#elif WINDOWS_SOCKETS + int err; + + if (gl_sockets_startup (SOCKETS_1_1)) + { + errno = ENOSYS; + return -1; + } + + err = gethostname (name, len); + if (err < 0) + { + switch (WSAGetLastError()) + { + case WSAEFAULT: + errno = EFAULT; + break; + + default: + errno = ENOSYS; + break; + } + } + + if (gl_sockets_cleanup ()) + { + errno = ENOSYS; + return -1; + } + + return err; #else strcpy (name, ""); /* Hardcode your system name if you want. */ #endif diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 5400c86..b67e288 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -1,5 +1,5 @@ /* Substitute for and wrapper around <unistd.h>. - Copyright (C) 2004-2007 Free Software Foundation, Inc. + Copyright (C) 2004-2008 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -156,6 +156,18 @@ extern char * getcwd (char *buf, size_t size); getcwd (b, s)) #endif +#if @GNULIB_GETHOSTNAME@ +# if [EMAIL PROTECTED]@ +# include <stddef.h> + extern int gethostname (char *name, size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef gethostname +# define gethostname(n,s) \ + (GL_LINK_WARNING ("gethostname is unportable - " \ + "use gnulib module gethostname for portability"), \ + gethostname (n, s)) +#endif #if @GNULIB_GETLOGIN_R@ /* Copies the user's login name to NAME. diff --git a/m4/gethostname.m4 b/m4/gethostname.m4 index 1e9749d..e272e48 100644 --- a/m4/gethostname.m4 +++ b/m4/gethostname.m4 @@ -1,18 +1,39 @@ -# gethostname.m4 serial 2 -dnl Copyright (C) 2002 Free Software Foundation, Inc. +# gethostname.m4 serial 3 +dnl Copyright (C) 2002, 2008 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_GETHOSTNAME], [ - AC_REPLACE_FUNCS(gethostname) - if test $ac_cv_func_gethostname = no; then + AC_REQUIRE([gl_SOCKETS])dnl for HAVE_SYS_SOCKET_H, HAVE_WINSOCK2_H, -lws2_32 + + AC_CACHE_CHECK([for gethostname], [gl_cv_func_gethostname], [ + AC_TRY_LINK([ +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#include <stddef.h> +], [gethostname("", 0);], + [gl_cv_func_gethostname=yes], + [gl_cv_func_gethostname=no])]) + + if test "$gl_cv_func_gethostname" = no; then + AC_LIBOBJ(gethostname) + AC_DEFINE(gethostname, rpl_gethostname, + [Define to rpl_gethostname if the replacement function should be used.]) gl_PREREQ_GETHOSTNAME + if test $ac_cv_have_decl_gethostname = yes; then + HAVE_DECL_GETHOSTNAME=1 + else + HAVE_DECL_GETHOSTNAME=0 + fi fi ]) # Prerequisites of lib/gethostname.c. AC_DEFUN([gl_PREREQ_GETHOSTNAME], [ AC_CHECK_FUNCS(uname) + AC_CHECK_DECLS_ONCE([gethostname]) ]) diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 index 4b8857c..daf7677 100644 --- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -1,5 +1,5 @@ # unistd_h.m4 serial 10 -dnl Copyright (C) 2006-2007 Free Software Foundation, Inc. +dnl Copyright (C) 2006-2008 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -37,6 +37,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR]) GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) + GNULIB_GETHOSTNAME=0; AC_SUBST([GNULIB_GETHOSTNAME]) GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) @@ -49,6 +50,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], HAVE_GETPAGESIZE=1; AC_SUBST([HAVE_GETPAGESIZE]) HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) + HAVE_DECL_GETHOSTNAME=1;AC_SUBST([HAVE_DECL_GETHOSTNAME]) HAVE_DECL_GETLOGIN_R=1; AC_SUBST([HAVE_DECL_GETLOGIN_R]) HAVE_OS_H=0; AC_SUBST([HAVE_OS_H]) HAVE_SYS_PARAM_H=0; AC_SUBST([HAVE_SYS_PARAM_H]) diff --git a/modules/gethostname b/modules/gethostname index 7c13807..9cb1c23 100644 --- a/modules/gethostname +++ b/modules/gethostname @@ -6,13 +6,17 @@ lib/gethostname.c m4/gethostname.m4 Depends-on: +sockets +unistd configure.ac: gl_FUNC_GETHOSTNAME +gl_UNISTD_MODULE_INDICATOR([gethostname]) Makefile.am: Include: +<unistd.h> License: LGPL diff --git a/modules/unistd b/modules/unistd index 4d16cf3..a47e94b 100644 --- a/modules/unistd +++ b/modules/unistd @@ -28,6 +28,7 @@ unistd.h: unistd.in.h -e 's|@''GNULIB_FCHDIR''@|$(GNULIB_FCHDIR)|g' \ -e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \ -e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \ + -e 's|@''GNULIB_GETHOSTNAME''@|$(GNULIB_GETHOSTNAME)|g' \ -e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \ -e 's|@''GNULIB_GETPAGESIZE''@|$(GNULIB_GETPAGESIZE)|g' \ -e 's|@''GNULIB_LCHOWN''@|$(GNULIB_LCHOWN)|g' \ @@ -39,6 +40,7 @@ unistd.h: unistd.in.h -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_DECL_GETHOSTNAME''@|$(HAVE_DECL_GETHOSTNAME)|g' \ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \