Let me add support for sethostname() on Windows platforms. Unlike on Unix, the hostname change becomes effective (outside the Control Panel) only after a reboot.
2011-12-04 Bruno Haible <br...@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(). --- lib/sethostname.c.orig Mon Dec 5 03:43:38 2011 +++ lib/sethostname.c Mon Dec 5 03:34:51 2011 @@ -19,6 +19,7 @@ #include <config.h> +#if !((defined _WIN32 || defined __WIN32__) || defined __CYGWIN__) /* Unix API. */ /* Specification. */ @@ -82,3 +83,80 @@ 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 --- tests/test-sethostname2.c.orig Mon Dec 5 03:43:38 2011 +++ tests/test-sethostname2.c Mon Dec 5 03:43:33 2011 @@ -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 @@ "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 @@ { 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 @@ fprintf (stderr, "set/get comparison failed.\n"); return 1; } +#endif } /* glibc does allow setting a zero length name, so the lower bound -- In memoriam Fred Hampton <http://en.wikipedia.org/wiki/Fred_Hampton>