master
c 161 lines 4.81 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "libnetdata/libnetdata.h"
4
5 #if defined(OS_WINDOWS)
6 bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root __maybe_unused) {
7 WCHAR wbuf[HOST_NAME_MAX * 4 + 1];
8 char buf[HOST_NAME_MAX * 4 + 1];
9 DWORD size = _countof(wbuf);
10 bool success = false;
11
12 // First try DNS hostname
13 if (GetComputerNameExW(ComputerNameDnsHostname, wbuf, &size)) {
14 success = true;
15 }
16 // Then try NetBIOS name
17 else {
18 size = _countof(wbuf);
19 if (GetComputerNameW(wbuf, &size)) {
20 success = true;
21 }
22 }
23
24 if (success) {
25 // Convert UTF-16 to UTF-8
26 int utf8_size = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
27 if (utf8_size > 0 && utf8_size <= (int)sizeof(buf)) {
28 WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, utf8_size, NULL, NULL);
29 }
30 else {
31 success = false;
32 }
33 }
34
35 if (!success) {
36 // Try getting the machine GUID first
37 HKEY hKey;
38 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
39 WCHAR guidW[64];
40 DWORD guidSize = sizeof(guidW);
41 DWORD type = REG_SZ;
42
43 if (RegQueryValueExW(hKey, L"MachineGuid", NULL, &type, (LPBYTE)guidW, &guidSize) == ERROR_SUCCESS) {
44 // Convert GUID to UTF-8
45 if (WideCharToMultiByte(CP_UTF8, 0, guidW, -1, buf, sizeof(buf), NULL, NULL) > 0) {
46 success = true;
47 }
48 }
49 RegCloseKey(hKey);
50 }
51
52 if (!success) {
53 // If machine GUID fails, try getting volume serial number of C: drive
54 WCHAR rootPath[] = L"C:\\";
55 DWORD serialNumber;
56 if (GetVolumeInformationW(rootPath, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) {
57 snprintf(buf, sizeof(buf), "host%08lx", (long unsigned)serialNumber);
58 success = true;
59 }
60 else {
61 // Last resort: use process ID
62 snprintf(buf, sizeof(buf), "host%lu", (long unsigned)GetCurrentProcessId());
63 }
64 }
65 }
66
67 char *hostname = trim(buf);
68 rrdlabels_sanitize_value(dst, hostname, dst_size);
69 return *dst != '\0';
70 }
71 #else // !OS_WINDOWS
72
73 #ifdef HAVE_LIBICONV
74 #include <iconv.h>
75
76 static const char *get_current_locale(void) {
77 const char *locale = getenv("LC_ALL"); // LC_ALL overrides all other locale settings
78
79 if (!locale || !*locale) {
80 locale = getenv("LC_CTYPE"); // Check LC_CTYPE for character encoding
81
82 if (!locale || !*locale)
83 locale = getenv("LANG"); // Fallback to LANG
84 }
85
86 return locale;
87 }
88
89 static const char *get_encoding_from_locale(const char *locale) {
90 if(!locale || !*locale)
91 return NULL;
92
93 const char *dot = strchr(locale, '.');
94 if (dot)
95 return dot + 1;
96
97 return locale;
98 }
99
100 // Function to convert from a source encoding to UTF-8
101 static bool iconv_convert_to_utf8(const char *input, const char *src_encoding, char *output, size_t output_size) {
102 iconv_t cd = iconv_open("UTF-8", src_encoding);
103 if (cd == (iconv_t)-1) {
104 int i = errno;
105 return false;
106 }
107
108 char *input_ptr = (char *)input; // iconv() may modify this pointer
109 char *output_ptr = output; // iconv() modifies this pointer
110 size_t input_len = strlen(input);
111 size_t output_len = output_size;
112
113 // Perform the conversion
114 if (iconv(cd, &input_ptr, &input_len, &output_ptr, &output_len) == (size_t)-1) {
115 iconv_close(cd);
116 return false;
117 }
118
119 // Null-terminate the output string
120 *output_ptr = '\0';
121
122 iconv_close(cd);
123 return true;
124 }
125 #endif
126
127 bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root) {
128 *dst = '\0';
129
130 char buf[HOST_NAME_MAX * 4 + 1];
131 *buf = '\0';
132
133 if (filesystem_root && *filesystem_root) {
134 char filename[FILENAME_MAX + 1];
135 snprintfz(filename, FILENAME_MAX, "%s/etc/hostname", netdata_configured_host_prefix);
136
137 if (read_txt_file(filename, buf, sizeof(buf)))
138 *buf = '\0';
139 }
140
141 if(!*buf && gethostname(buf, sizeof(buf)) != 0)
142 snprintf(buf, sizeof(buf), "host%ld", gethostid());
143
144 char *original_hostname = trim(buf);
145
146 #ifdef HAVE_LIBICONV
147 const char *locale = get_current_locale();
148 if (locale && *locale) {
149 char utf8_output[HOST_NAME_MAX * 4 + 1] = "";
150 if(iconv_convert_to_utf8(original_hostname, get_encoding_from_locale(locale), utf8_output, sizeof(utf8_output))) {
151 rrdlabels_sanitize_value(dst, trim(utf8_output), dst_size);
152 return *dst != '\0';
153 }
154 }
155 #endif
156
157 rrdlabels_sanitize_value(dst, original_hostname, dst_size);
158 return *dst != '\0';
159 }
160
161 #endif // !OS_WINDOWS