diff options
author | Bruno Haible <bruno@clisp.org> | 2011-12-05 03:46:40 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2011-12-05 03:46:40 +0100 |
commit | bb052d4a7416accaad0747e84bd2a0accbfcf923 (patch) | |
tree | d076481f6841f2620aaa5ed68eb5110534a1ad2e /lib/sethostname.c | |
parent | c69114d48295481373ee197c72214877b909414e (diff) | |
download | gnulib-bb052d4a7416accaad0747e84bd2a0accbfcf923.tar.gz |
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>
Diffstat (limited to 'lib/sethostname.c')
-rw-r--r-- | lib/sethostname.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/sethostname.c b/lib/sethostname.c index 3c2ec3c0c5..6555921609 100644 --- a/lib/sethostname.c +++ b/lib/sethostname.c @@ -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 |