diff options
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 |