X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fsethostname.c;h=065c370770d42b165e5d7694da86bb87807fae10;hb=dd5c6076e60de0237ab75d5a3a77070231d6c0fd;hp=e1b7d74db591f0d564a2d89f4b53bfb1887c3ed7;hpb=ab8fbf44bf4633d1c326940ce1d0715fb63936d4;p=gnulib.git diff --git a/lib/sethostname.c b/lib/sethostname.c index e1b7d74db..065c37077 100644 --- a/lib/sethostname.c +++ b/lib/sethostname.c @@ -1,6 +1,6 @@ /* sethostname emulation for glibc compliance. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011-2012 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 @@ -19,6 +19,7 @@ #include +#if !((defined _WIN32 || defined __WIN32__) || defined __CYGWIN__) /* Unix API. */ /* Specification. */ @@ -26,7 +27,6 @@ #include #include -#include #include /* Set up to LEN chars of NAME as system hostname. @@ -43,12 +43,6 @@ sethostname (const char *name, size_t len) return -1; } - /* NAME does not need to be null terminated so leave room to terminate - regardless of input. */ - char hostname[HOST_NAME_MAX + 1]; - memcpy ((void *) hostname, (const void *) name, len); - hostname[len] = '\0'; - #ifdef __minix /* Minix */ { FILE *hostf; @@ -63,25 +57,106 @@ sethostname (const char *name, size_t len) r = -1; else { - fprintf (hostf, "%s\n", hostname); + fprintf (hostf, "%.*s\n", (int) len, name); if (ferror (hostf)) { - clearerr (hostf); + /* Close hostf, preserving the errno from the fprintf call. */ + int saved_errno = errno; + fclose (hostf); + errno = saved_errno; r = -1; } - - /* use return value of fclose for function return value as it - matches our needs. fclose will also set errno on - failure */ - r = fclose (hostf); + else + { + if (fclose (hostf)) + /* fclose sets errno on failure. */ + r = -1; + } } return r; } #else /* For platforms that we don't have a better option for, simply bail - out */ + out. */ errno = ENOSYS; return -1; #endif } + +#else +/* Native Windows API. Also used on Cygwin. */ + +/* Ensure that declares SetComputerNameEx. */ +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x500 + +#define WIN32_LEAN_AND_MEAN + +/* Specification. */ +#include + +#include +#include +#include + +#include +/* 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