sethostname: Port to Windows platforms.

* lib/sethostname.c: Provide an alternate implementation for Windows
platforms.
* tests/test-sethostname2.c (geteuid): Redefine on Cygwin.
(main): Skip the test if sethostname() fails with EPERM. On Windows
platforms, don't check the result of gethostname().

2011-12-04  Bruno Haible  <bruno@clisp.org>
This commit is contained in:
Bruno Haible
2011-12-05 03:46:40 +01:00
parent c69114d482
commit bb052d4a74
3 changed files with 101 additions and 2 deletions
+9
View File
@@ -1,3 +1,12 @@
2011-12-04 Bruno Haible <bruno@clisp.org>
sethostname: Port to Windows platforms.
* lib/sethostname.c: Provide an alternate implementation for Windows
platforms.
* tests/test-sethostname2.c (geteuid): Redefine on Cygwin.
(main): Skip the test if sethostname() fails with EPERM. On Windows
platforms, don't check the result of gethostname().
2011-12-04 Bruno Haible <bruno@clisp.org>
Jim Meyering <meyering@redhat.com>
+78
View File
@@ -19,6 +19,7 @@
#include <config.h>
#if !((defined _WIN32 || defined __WIN32__) || defined __CYGWIN__)
/* Unix API. */
/* Specification. */
@@ -82,3 +83,80 @@ sethostname (const char *name, size_t len)
return -1;
#endif
}
#else
/* Native Windows API. Also used on Cygwin. */
/* Ensure that <windows.h> declares SetComputerNameEx. */
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x500
#define WIN32_LEAN_AND_MEAN
/* Specification. */
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <windows.h>
/* The mingw header files don't define GetComputerNameEx, SetComputerNameEx. */
#ifndef GetComputerNameEx
# define GetComputerNameEx GetComputerNameExA
#endif
#ifndef SetComputerNameEx
# define SetComputerNameEx SetComputerNameExA
#endif
/* Set up to LEN chars of NAME as system hostname.
Return 0 if ok, set errno and return -1 on error. */
int
sethostname (const char *name, size_t len)
{
char name_asciz[HOST_NAME_MAX + 1];
char old_name[HOST_NAME_MAX + 1];
DWORD old_name_len;
/* Ensure the string isn't too long. glibc does allow setting an
empty hostname so no point in enforcing a lower bound. */
if (len > HOST_NAME_MAX)
{
errno = EINVAL;
return -1;
}
/* Prepare a NUL-terminated copy of name. */
memcpy (name_asciz, name, len);
name_asciz[len] = '\0';
/* Save the old NetBIOS name. */
old_name_len = sizeof (old_name) - 1;
if (! GetComputerNameEx (ComputerNamePhysicalNetBIOS,
old_name, &old_name_len))
old_name_len = 0;
/* Set both the NetBIOS and the first part of the IP / DNS name. */
if (! SetComputerNameEx (ComputerNamePhysicalNetBIOS, name_asciz))
{
errno = (GetLastError () == ERROR_ACCESS_DENIED ? EPERM : EINVAL);
return -1;
}
if (! SetComputerNameEx (ComputerNamePhysicalDnsHostname, name_asciz))
{
errno = (GetLastError () == ERROR_ACCESS_DENIED ? EPERM : EINVAL);
/* Restore the old NetBIOS name. */
if (old_name_len > 0)
{
old_name[old_name_len] = '\0';
SetComputerNameEx (ComputerNamePhysicalNetBIOS, old_name);
}
return -1;
}
/* Note that the new host name becomes effective only after a reboot! */
return 0;
}
#endif
+14 -2
View File
@@ -31,8 +31,10 @@
#define TESTHOSTNAME "gnulib-hostname"
/* mingw and MSVC 9 lack geteuid, so setup a dummy value. */
#if !HAVE_GETEUID
/* mingw and MSVC 9 lack geteuid, so setup a dummy value.
On Cygwin, geteuid() may return non-zero even for user accounts with
administrator privileges, so use a dummy value as well. */
#if !HAVE_GETEUID || defined __CYGWIN__
# define geteuid() 0
#endif
@@ -72,6 +74,11 @@ main (int argc, char *argv[] _GL_UNUSED)
"Skipping test: sethostname is not really implemented.\n");
return 77;
}
else if (rcs == -1 && errno == EPERM)
{
fprintf (stderr, "Skipping test: insufficient permissions.\n");
return 77;
}
else
{
fprintf (stderr, "error setting valid hostname.\n");
@@ -82,6 +89,10 @@ main (int argc, char *argv[] _GL_UNUSED)
{
ASSERT (gethostname (newname, sizeof (newname)) == 0);
/* On Windows, a hostname change becomes effective only after
a reboot. */
#if !((defined _WIN32 || defined __WIN32__) || defined __CYGWIN__)
/* if we don't get back what we put in, there is no need to
restore the original name as we will assume it was not
properly changed. */
@@ -90,6 +101,7 @@ main (int argc, char *argv[] _GL_UNUSED)
fprintf (stderr, "set/get comparison failed.\n");
return 1;
}
#endif
}
/* glibc does allow setting a zero length name, so the lower bound