1414#include "fossil/sys/hostinfo.h"
1515#include <stdio.h>
1616#include <string.h>
17+ #include <stdlib.h>
1718
1819#ifdef _WIN32
1920 #include <windows.h>
2021#elif defined(__APPLE__ )
22+ #define _DARWIN_C_SOURCE
2123 #include <sys/utsname.h>
22- #include <sys/types.h>
2324 #include <unistd.h>
25+ #include <sys/types.h>
2426 #include <sys/sysctl.h>
2527#else
2628 #include <sys/utsname.h>
2729 #include <sys/sysinfo.h>
2830 #include <sys/types.h>
2931 #include <unistd.h>
32+ #include <netdb.h> // for gethostname
3033#endif
3134
3235int fossil_sys_hostinfo_get_system (fossil_sys_hostinfo_system_t * info ) {
@@ -38,19 +41,228 @@ int fossil_sys_hostinfo_get_system(fossil_sys_hostinfo_system_t *info) {
3841 snprintf (info -> os_name , sizeof (info -> os_name ), "Windows" );
3942 snprintf (info -> os_version , sizeof (info -> os_version ), "%lu.%lu" , osvi .dwMajorVersion , osvi .dwMinorVersion );
4043 snprintf (info -> kernel_version , sizeof (info -> kernel_version ), "%lu" , osvi .dwBuildNumber );
44+
45+ DWORD size = sizeof (info -> hostname );
46+ GetComputerNameA (info -> hostname , & size );
47+
48+ size = sizeof (info -> username );
49+ GetUserNameA (info -> username , & size );
50+
51+ // Domain name
52+ size = sizeof (info -> domain_name );
53+ if (!GetEnvironmentVariableA ("USERDOMAIN" , info -> domain_name , size )) {
54+ strncpy (info -> domain_name , "Unknown" , sizeof (info -> domain_name ) - 1 );
55+ info -> domain_name [sizeof (info -> domain_name ) - 1 ] = '\0' ;
56+ }
57+
58+ SYSTEM_INFO sysinfo ;
59+ GetSystemInfo (& sysinfo );
60+ snprintf (info -> machine_type , sizeof (info -> machine_type ), "%u" , sysinfo .wProcessorArchitecture );
61+ snprintf (info -> platform , sizeof (info -> platform ), "Win32" );
62+
4163#elif defined(__APPLE__ )
4264 struct utsname sysinfo ;
4365 if (uname (& sysinfo ) != 0 ) return -1 ;
4466 strncpy (info -> os_name , sysinfo .sysname , sizeof (info -> os_name ) - 1 );
67+ info -> os_name [sizeof (info -> os_name ) - 1 ] = '\0' ;
4568 strncpy (info -> os_version , sysinfo .version , sizeof (info -> os_version ) - 1 );
69+ info -> os_version [sizeof (info -> os_version ) - 1 ] = '\0' ;
4670 strncpy (info -> kernel_version , sysinfo .release , sizeof (info -> kernel_version ) - 1 );
71+ info -> kernel_version [sizeof (info -> kernel_version ) - 1 ] = '\0' ;
72+
73+ if (gethostname (info -> hostname , sizeof (info -> hostname )) != 0 )
74+ strncpy (info -> hostname , "Unknown" , sizeof (info -> hostname ) - 1 );
75+ info -> hostname [sizeof (info -> hostname ) - 1 ] = '\0' ;
76+
77+ const char * user = getenv ("USER" );
78+ if (user )
79+ strncpy (info -> username , user , sizeof (info -> username ) - 1 );
80+ else
81+ strncpy (info -> username , "Unknown" , sizeof (info -> username ) - 1 );
82+ info -> username [sizeof (info -> username ) - 1 ] = '\0' ;
83+
84+ strncpy (info -> domain_name , "Unknown" , sizeof (info -> domain_name ) - 1 );
85+ info -> domain_name [sizeof (info -> domain_name ) - 1 ] = '\0' ;
86+
87+ strncpy (info -> machine_type , sysinfo .machine , sizeof (info -> machine_type ) - 1 );
88+ info -> machine_type [sizeof (info -> machine_type ) - 1 ] = '\0' ;
89+
90+ strncpy (info -> platform , "Apple" , sizeof (info -> platform ) - 1 );
91+ info -> platform [sizeof (info -> platform ) - 1 ] = '\0' ;
92+
4793#else
4894 struct utsname sysinfo ;
4995 if (uname (& sysinfo ) != 0 ) return -1 ;
5096 strncpy (info -> os_name , sysinfo .sysname , sizeof (info -> os_name ) - 1 );
97+ info -> os_name [sizeof (info -> os_name ) - 1 ] = '\0' ;
5198 strncpy (info -> os_version , sysinfo .version , sizeof (info -> os_version ) - 1 );
99+ info -> os_version [sizeof (info -> os_version ) - 1 ] = '\0' ;
52100 strncpy (info -> kernel_version , sysinfo .release , sizeof (info -> kernel_version ) - 1 );
101+ info -> kernel_version [sizeof (info -> kernel_version ) - 1 ] = '\0' ;
102+
103+ if (gethostname (info -> hostname , sizeof (info -> hostname )) != 0 )
104+ strncpy (info -> hostname , "Unknown" , sizeof (info -> hostname ) - 1 );
105+ info -> hostname [sizeof (info -> hostname ) - 1 ] = '\0' ;
106+
107+ const char * user = getenv ("USER" );
108+ if (user )
109+ strncpy (info -> username , user , sizeof (info -> username ) - 1 );
110+ else
111+ strncpy (info -> username , "Unknown" , sizeof (info -> username ) - 1 );
112+ info -> username [sizeof (info -> username ) - 1 ] = '\0' ;
113+
114+ const char * domain = getenv ("DOMAINNAME" );
115+ if (domain )
116+ strncpy (info -> domain_name , domain , sizeof (info -> domain_name ) - 1 );
117+ else
118+ strncpy (info -> domain_name , "Unknown" , sizeof (info -> domain_name ) - 1 );
119+ info -> domain_name [sizeof (info -> domain_name ) - 1 ] = '\0' ;
120+
121+ strncpy (info -> machine_type , sysinfo .machine , sizeof (info -> machine_type ) - 1 );
122+ info -> machine_type [sizeof (info -> machine_type ) - 1 ] = '\0' ;
123+
124+ strncpy (info -> platform , "Unix" , sizeof (info -> platform ) - 1 );
125+ info -> platform [sizeof (info -> platform ) - 1 ] = '\0' ;
126+
127+ #endif
128+ return 0 ;
129+ }
130+
131+ int fossil_sys_hostinfo_get_architecture (fossil_sys_hostinfo_architecture_t * info ) {
132+ if (!info ) return -1 ;
133+
134+ #ifdef _WIN32
135+ SYSTEM_INFO sysinfo ;
136+ GetSystemInfo (& sysinfo );
137+
138+ // Architecture
139+ switch (sysinfo .wProcessorArchitecture ) {
140+ case PROCESSOR_ARCHITECTURE_AMD64 :
141+ strncpy (info -> architecture , "x86_64" , sizeof (info -> architecture ) - 1 );
142+ break ;
143+ case PROCESSOR_ARCHITECTURE_INTEL :
144+ strncpy (info -> architecture , "x86" , sizeof (info -> architecture ) - 1 );
145+ break ;
146+ case PROCESSOR_ARCHITECTURE_ARM :
147+ strncpy (info -> architecture , "ARM" , sizeof (info -> architecture ) - 1 );
148+ break ;
149+ default :
150+ strncpy (info -> architecture , "Unknown" , sizeof (info -> architecture ) - 1 );
151+ break ;
152+ }
153+ info -> architecture [sizeof (info -> architecture ) - 1 ] = '\0' ;
154+
155+ // CPU info (limited on Windows)
156+ strncpy (info -> cpu , "Unknown" , sizeof (info -> cpu ) - 1 );
157+ info -> cpu [sizeof (info -> cpu ) - 1 ] = '\0' ;
158+
159+ snprintf (info -> cpu_cores , sizeof (info -> cpu_cores ), "%lu" , sysinfo .dwNumberOfProcessors );
160+ strncpy (info -> cpu_threads , "Unknown" , sizeof (info -> cpu_threads ) - 1 );
161+ info -> cpu_threads [sizeof (info -> cpu_threads ) - 1 ] = '\0' ;
162+ strncpy (info -> cpu_frequency , "Unknown" , sizeof (info -> cpu_frequency ) - 1 );
163+ info -> cpu_frequency [sizeof (info -> cpu_frequency ) - 1 ] = '\0' ;
164+ strncpy (info -> cpu_architecture , info -> architecture , sizeof (info -> cpu_architecture ) - 1 );
165+ info -> cpu_architecture [sizeof (info -> cpu_architecture ) - 1 ] = '\0' ;
166+
167+ #elif defined(__APPLE__ )
168+ size_t size = sizeof (info -> architecture );
169+ if (sysctlbyname ("hw.machine" , info -> architecture , & size , NULL , 0 ) != 0 )
170+ strncpy (info -> architecture , "Unknown" , sizeof (info -> architecture ) - 1 );
171+ info -> architecture [sizeof (info -> architecture ) - 1 ] = '\0' ;
172+
173+ size = sizeof (info -> cpu );
174+ if (sysctlbyname ("machdep.cpu.brand_string" , info -> cpu , & size , NULL , 0 ) != 0 )
175+ strncpy (info -> cpu , "Unknown" , sizeof (info -> cpu ) - 1 );
176+ info -> cpu [sizeof (info -> cpu ) - 1 ] = '\0' ;
177+
178+ int cores = 0 ;
179+ size = sizeof (cores );
180+ if (sysctlbyname ("hw.physicalcpu" , & cores , & size , NULL , 0 ) == 0 )
181+ snprintf (info -> cpu_cores , sizeof (info -> cpu_cores ), "%d" , cores );
182+ else
183+ strncpy (info -> cpu_cores , "Unknown" , sizeof (info -> cpu_cores ) - 1 );
184+ info -> cpu_cores [sizeof (info -> cpu_cores ) - 1 ] = '\0' ;
185+
186+ int threads = 0 ;
187+ size = sizeof (threads );
188+ if (sysctlbyname ("hw.logicalcpu" , & threads , & size , NULL , 0 ) == 0 )
189+ snprintf (info -> cpu_threads , sizeof (info -> cpu_threads ), "%d" , threads );
190+ else
191+ strncpy (info -> cpu_threads , "Unknown" , sizeof (info -> cpu_threads ) - 1 );
192+ info -> cpu_threads [sizeof (info -> cpu_threads ) - 1 ] = '\0' ;
193+
194+ uint64_t freq = 0 ;
195+ size = sizeof (freq );
196+ if (sysctlbyname ("hw.cpufrequency" , & freq , & size , NULL , 0 ) == 0 )
197+ snprintf (info -> cpu_frequency , sizeof (info -> cpu_frequency ), "%llu" , (unsigned long long )freq );
198+ else
199+ strncpy (info -> cpu_frequency , "Unknown" , sizeof (info -> cpu_frequency ) - 1 );
200+ info -> cpu_frequency [sizeof (info -> cpu_frequency ) - 1 ] = '\0' ;
201+
202+ strncpy (info -> cpu_architecture , info -> architecture , sizeof (info -> cpu_architecture ) - 1 );
203+ info -> cpu_architecture [sizeof (info -> cpu_architecture ) - 1 ] = '\0' ;
204+
205+ #else
206+ struct utsname sysinfo ;
207+ if (uname (& sysinfo ) != 0 ) return -1 ;
208+
209+ strncpy (info -> architecture , sysinfo .machine , sizeof (info -> architecture ) - 1 );
210+ info -> architecture [sizeof (info -> architecture ) - 1 ] = '\0' ;
211+
212+ FILE * fp = fopen ("/proc/cpuinfo" , "r" );
213+ if (fp ) {
214+ char line [256 ];
215+ while (fgets (line , sizeof (line ), fp )) {
216+ if (strncmp (line , "model name" , 10 ) == 0 ) {
217+ char * colon = strchr (line , ':' );
218+ if (colon ) {
219+ colon ++ ;
220+ while (* colon == ' ' ) colon ++ ;
221+ strncpy (info -> cpu , colon , sizeof (info -> cpu ) - 1 );
222+ info -> cpu [sizeof (info -> cpu ) - 1 ] = '\0' ;
223+ }
224+ } else if (strncmp (line , "cpu cores" , 9 ) == 0 ) {
225+ char * colon = strchr (line , ':' );
226+ if (colon ) {
227+ colon ++ ;
228+ while (* colon == ' ' ) colon ++ ;
229+ strncpy (info -> cpu_cores , colon , sizeof (info -> cpu_cores ) - 1 );
230+ info -> cpu_cores [sizeof (info -> cpu_cores ) - 1 ] = '\0' ;
231+ }
232+ } else if (strncmp (line , "siblings" , 8 ) == 0 ) {
233+ char * colon = strchr (line , ':' );
234+ if (colon ) {
235+ colon ++ ;
236+ while (* colon == ' ' ) colon ++ ;
237+ strncpy (info -> cpu_threads , colon , sizeof (info -> cpu_threads ) - 1 );
238+ info -> cpu_threads [sizeof (info -> cpu_threads ) - 1 ] = '\0' ;
239+ }
240+ } else if (strncmp (line , "cpu MHz" , 7 ) == 0 ) {
241+ char * colon = strchr (line , ':' );
242+ if (colon ) {
243+ colon ++ ;
244+ while (* colon == ' ' ) colon ++ ;
245+ strncpy (info -> cpu_frequency , colon , sizeof (info -> cpu_frequency ) - 1 );
246+ info -> cpu_frequency [sizeof (info -> cpu_frequency ) - 1 ] = '\0' ;
247+ }
248+ }
249+ }
250+ fclose (fp );
251+ } else {
252+ strncpy (info -> cpu , "Unknown" , sizeof (info -> cpu ) - 1 );
253+ info -> cpu [sizeof (info -> cpu ) - 1 ] = '\0' ;
254+ strncpy (info -> cpu_cores , "Unknown" , sizeof (info -> cpu_cores ) - 1 );
255+ info -> cpu_cores [sizeof (info -> cpu_cores ) - 1 ] = '\0' ;
256+ strncpy (info -> cpu_threads , "Unknown" , sizeof (info -> cpu_threads ) - 1 );
257+ info -> cpu_threads [sizeof (info -> cpu_threads ) - 1 ] = '\0' ;
258+ strncpy (info -> cpu_frequency , "Unknown" , sizeof (info -> cpu_frequency ) - 1 );
259+ info -> cpu_frequency [sizeof (info -> cpu_frequency ) - 1 ] = '\0' ;
260+ }
261+
262+ strncpy (info -> cpu_architecture , info -> architecture , sizeof (info -> cpu_architecture ) - 1 );
263+ info -> cpu_architecture [sizeof (info -> cpu_architecture ) - 1 ] = '\0' ;
53264#endif
265+
54266 return 0 ;
55267}
56268
@@ -62,17 +274,32 @@ int fossil_sys_hostinfo_get_memory(fossil_sys_hostinfo_memory_t *info) {
62274 if (!GlobalMemoryStatusEx (& statex )) return -1 ;
63275 info -> total_memory = statex .ullTotalPhys ;
64276 info -> free_memory = statex .ullAvailPhys ;
277+ info -> used_memory = statex .ullTotalPhys - statex .ullAvailPhys ;
278+ info -> available_memory = statex .ullAvailPhys ;
279+ info -> total_swap = statex .ullTotalPageFile ;
280+ info -> free_swap = statex .ullAvailPageFile ;
281+ info -> used_swap = statex .ullTotalPageFile - statex .ullAvailPageFile ;
65282#elif defined(__APPLE__ )
66283 int64_t memsize ;
67284 size_t len = sizeof (memsize );
68285 if (sysctlbyname ("hw.memsize" , & memsize , & len , NULL , 0 ) != 0 ) return -1 ;
69286 info -> total_memory = memsize ;
70287 info -> free_memory = 0 ; // macOS does not provide free memory info in the same way
288+ info -> used_memory = 0 ;
289+ info -> available_memory = 0 ;
290+ info -> total_swap = 0 ;
291+ info -> free_swap = 0 ;
292+ info -> used_swap = 0 ;
71293#else
72294 struct sysinfo sys_info ;
73295 if (sysinfo (& sys_info ) != 0 ) return -1 ;
74- info -> total_memory = sys_info .totalram ;
75- info -> free_memory = sys_info .freeram ;
296+ info -> total_memory = sys_info .totalram * sys_info .mem_unit ;
297+ info -> free_memory = sys_info .freeram * sys_info .mem_unit ;
298+ info -> used_memory = (sys_info .totalram - sys_info .freeram ) * sys_info .mem_unit ;
299+ info -> available_memory = sys_info .freeram * sys_info .mem_unit ;
300+ info -> total_swap = sys_info .totalswap * sys_info .mem_unit ;
301+ info -> free_swap = sys_info .freeswap * sys_info .mem_unit ;
302+ info -> used_swap = (sys_info .totalswap - sys_info .freeswap ) * sys_info .mem_unit ;
76303#endif
77304 return 0 ;
78305}
0 commit comments