*-map tests: Fix compilation error.
[gnulib.git] / lib / sethostname.c
blob676fde2305a14e6823a08ec0b672117c0099f790
1 /* sethostname emulation for glibc compliance.
3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Ben Walton <bwalton@artsci.utoronto.ca> */
20 #include <config.h>
22 #if !(defined _WIN32 || defined __CYGWIN__)
23 /* Unix API. */
25 /* Specification. */
26 #include <unistd.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <limits.h>
32 /* Set up to LEN chars of NAME as system hostname.
33 Return 0 if ok, set errno and return -1 on error. */
35 int
36 sethostname (const char *name, size_t len)
38 /* Ensure the string isn't too long. glibc does allow setting an
39 empty hostname so no point in enforcing a lower bound. */
40 if (len > HOST_NAME_MAX)
42 errno = EINVAL;
43 return -1;
46 #ifdef __minix /* Minix */
48 FILE *hostf;
49 int r = 0;
51 /* glibc returns EFAULT, EINVAL, and EPERM on error. None of
52 these are appropriate for us to set, even if they may match the
53 situation, during failed open/write/close operations, so we
54 leave errno alone and rely on what the system sets up. */
55 hostf = fopen ("/etc/hostname.file", "w");
56 if (hostf == NULL)
57 r = -1;
58 else
60 fprintf (hostf, "%.*s\n", (int) len, name);
61 if (ferror (hostf))
63 /* Close hostf, preserving the errno from the fprintf call. */
64 int saved_errno = errno;
65 fclose (hostf);
66 errno = saved_errno;
67 r = -1;
69 else
71 if (fclose (hostf))
72 /* fclose sets errno on failure. */
73 r = -1;
77 return r;
79 #else
80 /* For platforms that we don't have a better option for, simply bail
81 out. */
82 errno = ENOSYS;
83 return -1;
84 #endif
87 #else
88 /* Native Windows API. Also used on Cygwin. */
90 /* Ensure that <windows.h> declares SetComputerNameEx. */
91 #undef _WIN32_WINNT
92 #define _WIN32_WINNT _WIN32_WINNT_WIN2K
94 #define WIN32_LEAN_AND_MEAN
96 /* Specification. */
97 #include <unistd.h>
99 #include <errno.h>
100 #include <limits.h>
101 #include <string.h>
103 #include <windows.h>
104 /* The mingw header files don't define GetComputerNameEx, SetComputerNameEx. */
105 #ifndef GetComputerNameEx
106 # define GetComputerNameEx GetComputerNameExA
107 #endif
108 #ifndef SetComputerNameEx
109 # define SetComputerNameEx SetComputerNameExA
110 #endif
112 /* Set up to LEN chars of NAME as system hostname.
113 Return 0 if ok, set errno and return -1 on error. */
116 sethostname (const char *name, size_t len)
118 char name_asciz[HOST_NAME_MAX + 1];
119 char old_name[HOST_NAME_MAX + 1];
120 DWORD old_name_len;
122 /* Ensure the string isn't too long. glibc does allow setting an
123 empty hostname so no point in enforcing a lower bound. */
124 if (len > HOST_NAME_MAX)
126 errno = EINVAL;
127 return -1;
130 /* Prepare a NUL-terminated copy of name. */
131 memcpy (name_asciz, name, len);
132 name_asciz[len] = '\0';
134 /* Save the old NetBIOS name. */
135 old_name_len = sizeof (old_name) - 1;
136 if (! GetComputerNameEx (ComputerNamePhysicalNetBIOS,
137 old_name, &old_name_len))
138 old_name_len = 0;
140 /* Set both the NetBIOS and the first part of the IP / DNS name. */
141 if (! SetComputerNameEx (ComputerNamePhysicalNetBIOS, name_asciz))
143 errno = (GetLastError () == ERROR_ACCESS_DENIED ? EPERM : EINVAL);
144 return -1;
146 if (! SetComputerNameEx (ComputerNamePhysicalDnsHostname, name_asciz))
148 errno = (GetLastError () == ERROR_ACCESS_DENIED ? EPERM : EINVAL);
149 /* Restore the old NetBIOS name. */
150 if (old_name_len > 0)
152 old_name[old_name_len] = '\0';
153 SetComputerNameEx (ComputerNamePhysicalNetBIOS, old_name);
155 return -1;
158 /* Note that the new host name becomes effective only after a reboot! */
159 return 0;
162 #endif