1 /*
2  * libstatgrab
3  * https://libstatgrab.org
4  * Copyright (C) 2003-2004 Peter Saunders
5  * Copyright (C) 2003-2019 Tim Bishop
6  * Copyright (C) 2003-2013 Adam Sampson
7  * Copyright (C) 2012-2019 Jens Rehsack
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301, USA.
23  */
24 
25 #include "tools.h"
26 
27 /**
28  * Note: values must be sorted, search will be done using bsearch
29  */
30 #if defined(SOLARIS)
31 #define GET_BITWIDTH_BY_ARCH_NAME
32 static const char *isa32[] = { "i386", "sparc" };
33 static const char *isa64[] = { "amd64", "sparcv9" };
34 #elif defined(CTL_HW) && (defined(HW_MACHINE_ARCH)||defined(HW_MACHINE))
35 #define GET_BITWIDTH_BY_ARCH_NAME
36 static const char *isa32[] = { "arm", "armeb", "hppa", "i386", "m68000", "m68k", "mips", "powerpc", "sh3el", "sh3eb", "sparc", "vax" };
37 static const char *isa64[] = { "alpha", "amd64", "hppa64", "ia64", "mips64", "mips64el", "sparc64", "x86_64" };
38 #endif
39 
40 #ifdef WIN32
41 #include <lm.h>
42 #define WINDOWS2000 "Windows 2000"
43 #define WINDOWSXP "Windows XP"
44 #define WINDOWS2003 "Windows Server 2003"
45 #define BUFSIZE 12
46 
47 static int
home_or_pro(const OSVERSIONINFOEX osinfo,char ** name)48 home_or_pro(const OSVERSIONINFOEX osinfo, char **name)
49 {
50 	int r;
51 
52 	if (osinfo.wSuiteMask & VER_SUITE_PERSONAL) {
53 		r = sg_concat_string(name, " Home Edition");
54 	} else {
55 		r = sg_concat_string(name, " Professional");
56 	}
57 	return r;
58 }
59 
60 static char *
get_os_name(const OSVERSIONINFOEX osinfo,SYSTEM_INFO sysinfo)61 get_os_name(const OSVERSIONINFOEX osinfo, SYSTEM_INFO sysinfo)
62 {
63 	char *name;
64 	char tmp[10];
65 	int r = 0;
66 
67 	/* we only compile on 2k or newer, which is version 5
68 	 * Covers 2000, XP and 2003 */
69 	if (osinfo.dwMajorVersion != 5) {
70 		return "Unknown";
71 	}
72 	switch(osinfo.dwMinorVersion) {
73 		case 0: /* Windows 2000 */
74 			name = strdup(WINDOWS2000);
75 			if(name == NULL) {
76 				goto out;
77 			}
78 			if (osinfo.wProductType == VER_NT_WORKSTATION) {
79 				r = home_or_pro(osinfo, &name);
80 			} else if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) {
81 				r = sg_concat_string(&name, " Datacenter Server");
82 			} else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) {
83 				r = sg_concat_string(&name, " Advanced Server");
84 			} else {
85 				r = sg_concat_string(&name, " Server");
86 			}
87 			break;
88 		case 1: /* Windows XP */
89 			name = strdup(WINDOWSXP);
90 			if(name == NULL) {
91 				goto out;
92 			}
93 			r = home_or_pro(osinfo, &name);
94 			break;
95 		case 2: /* Windows 2003 */
96 			/* XXX complete detection using http://msdn.microsoft.com/en-us/library/ms724833%28VS.85%29.aspx */
97 			if( (osinfo.wProductType == VER_NT_WORKSTATION) &&
98 			    (sysinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) ) {
99 				name = strdup(WINDOWSXP);
100 				r = home_or_pro(osinfo, &name);
101 				r = sg_concat_string(&name, " x64 Edition");
102 			}
103 			else {
104 				name = strdup(WINDOWS2003);
105 			}
106 
107 			if(name == NULL) {
108 				goto out;
109 			}
110 			if (osinfo.wSuiteMask & VER_SUITE_DATACENTER) {
111 				r = sg_concat_string(&name, " Datacenter Edition");
112 			} else if (osinfo.wSuiteMask & VER_SUITE_ENTERPRISE) {
113 				r = sg_concat_string(&name, " Enterprise Edition");
114 			} else if (osinfo.wSuiteMask & VER_SUITE_BLADE) {
115 				r = sg_concat_string(&name, " Web Edition");
116 			} else {
117 				r = sg_concat_string(&name, " Standard Edition");
118 			}
119 			break;
120 		default:
121 			name = strdup("Windows 2000 based");
122 			break;
123 	}
124 	if(r != 0) {
125 		free (name);
126 		return NULL;
127 	}
128 	/* Add on service pack version */
129 	if (osinfo.wServicePackMajor != 0) {
130 		if(osinfo.wServicePackMinor == 0) {
131 			if(snprintf(tmp, sizeof(tmp), " SP%d", osinfo.wServicePackMajor) != -1) {
132 				r = sg_concat_string(&name, tmp);
133 			}
134 		} else {
135 			if(snprintf(tmp, sizeof(tmp), " SP%d.%d", osinfo.wServicePackMajor,
136 					osinfo.wServicePackMinor) != -1) {
137 				r = sg_concat_string(&name, tmp);
138 			}
139 		}
140 		if(r) {
141 			free(name);
142 			return NULL;
143 		}
144 	}
145 	return name;
146 
147 out:
148 	/* strdup failed */
149 	SET_ERROR_WITH_ERRNO("os", SG_ERROR_MALLOC, "get_os_name: strdup() failed");
150 	return NULL;
151 }
152 #endif
153 
154 #ifdef GET_BITWIDTH_BY_ARCH_NAME
155 static int
cmp_arch_name(const void * va,const void * vb)156 cmp_arch_name(const void *va, const void *vb) {
157 	const char *a = * (char * const *)va;
158 	const char *b = * (char * const *)vb;
159 	size_t len, len_b;
160 
161 	assert(a);
162 	assert(b);
163 
164 	len = strlen(a);
165 	len_b = strlen(b);
166 	if( len_b < len )
167 		len = len_b;
168 
169 	return strncmp(a, b, len);
170 }
171 
172 static unsigned
get_bitwidth_by_arch_name(const char * arch_name)173 get_bitwidth_by_arch_name(const char *arch_name) {
174 	char *m = bsearch( &arch_name, &isa64, lengthof(isa64), sizeof(isa64[0]), cmp_arch_name);
175 	if( m != NULL )
176 		return 64;
177 	m = bsearch( &arch_name, &isa32, lengthof(isa32), sizeof(isa32[0]), cmp_arch_name);
178 	if( m != NULL )
179 		return 32;
180 	return 0;
181 }
182 #endif
183 
184 static sg_error
sg_get_host_info_int(sg_host_info * host_info_buf)185 sg_get_host_info_int(sg_host_info *host_info_buf) {
186 
187 #ifdef WIN32
188 	unsigned long nameln;
189 	char *name;
190 	long long result;
191 	OSVERSIONINFOEX osinfo;
192 	SYSTEM_INFO sysinfo;
193 	char *tmp_name;
194 	char tmp[10];
195 #else
196 	struct utsname os;
197 # if defined(HPUX)
198 	struct pst_static pstat_static;
199 	struct pst_dynamic pstat_dynamic;
200 	time_t currtime;
201 	long boottime;
202 # elif defined(SOLARIS)
203 	time_t boottime, curtime;
204 	kstat_ctl_t *kc;
205 	kstat_t *ksp;
206 	kstat_named_t *kn;
207 	char *isainfo = NULL;
208 	long isabufsz, rc;
209 # elif defined(LINUX) || defined(CYGWIN)
210 	FILE *f;
211 # elif defined(ALLBSD)
212 	int mib[2];
213 	struct timeval boottime;
214 	time_t curtime;
215 	size_t size;
216 	int ncpus;
217 #  if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE)
218 	char arch_name[16];
219 #  endif
220 # elif defined(AIX)
221 	static perfstat_cpu_total_t cpu_total;
222 	sg_error rc;
223 #  if defined(HAVE_GETUTXENT)
224 	struct utmpx *ut;
225 #  else
226 	struct utmp *ut;
227 #  endif
228 # endif
229 #endif
230 
231 	host_info_buf->ncpus = 0;
232 	host_info_buf->maxcpus = 0;
233 	host_info_buf->bitwidth = 0;
234 	host_info_buf->host_state = sg_unknown_configuration;
235 	host_info_buf->uptime = 0;
236 	host_info_buf->systime = 0;
237 
238 #ifdef WIN32
239 	/* these settings are static after boot, so why get them
240 	 * constantly?
241 	 *
242 	 * Because we want to know some changes anyway - at least
243 	 * when the hostname (DNS?) changes
244 	 */
245 
246 	/* get system name */
247 	nameln = MAX_COMPUTERNAME_LENGTH + 1;
248 	name = sg_malloc(nameln);
249 	if(name == NULL) {
250 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
251 	}
252 
253 	/*
254 	 * XXX probably GetComputerNameEx() is a better entry point ...
255 	 */
256 	if( GetComputerName(name, &nameln) == 0 ) {
257 		free(name);
258 		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName");
259 	}
260 
261 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) {
262 		free(name);
263 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
264 	}
265 	free(name);
266 
267 	/* get OS name, version and build */
268 	ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
269 	osinfo.dwOSVersionInfoSize = sizeof(osinfo);
270 	if(!GetVersionEx(&osinfo)) {
271 		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx");
272 	}
273 	GetSystemInfo(&sysinfo);
274 
275 	/* Release - single number */
276 	if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
277 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL);
278 	}
279 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) {
280 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
281 	}
282 
283 	/* Version */
284 	/* usually a single digit . single digit, eg 5.0 */
285 	if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
286 				osinfo.dwMinorVersion) == -1) {
287 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
288 	}
289 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) {
290 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
291 	}
292 
293 	/* OS name */
294 	tmp_name = get_os_name(osinfo, sysinfo);
295 	if(tmp_name == NULL) {
296 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
297 	}
298 
299 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) {
300 		free(tmp_name);
301 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
302 	}
303 	free(tmp_name);
304 
305 	/* Platform */
306 	switch(sysinfo.wProcessorArchitecture) {
307 		case PROCESSOR_ARCHITECTURE_INTEL:
308 			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
309 						"Intel")) {
310 				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
311 			}
312 			break;
313 		case PROCESSOR_ARCHITECTURE_IA64:
314 			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
315 						"IA64")) {
316 				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
317 			}
318 			break;
319 		case PROCESSOR_ARCHITECTURE_AMD64:
320 			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
321 						"AMD64")) {
322 				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
323 			}
324 			break;
325 		default:
326 			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
327 						"Unknown")){
328 				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
329 			}
330 			break;
331 	}
332 
333 	if(read_counter_large(SG_WIN32_UPTIME, &result)) {
334 		RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME);
335 	}
336 
337 	host_info_buf->uptime = (time_t) result;
338 #else
339 	if((uname(&os)) < 0) {
340 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL);
341 	}
342 
343 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) {
344 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
345 	}
346 
347 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) {
348 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
349 	}
350 
351 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) {
352 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
353 	}
354 
355 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) {
356 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
357 	}
358 
359 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) {
360 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
361 	}
362 
363 	/* get uptime */
364 #ifdef HPUX
365 	if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) {
366 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static");
367 	}
368 
369 	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
370 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic");
371 	}
372 
373 	currtime = time(NULL);
374 
375 	boottime = pstat_static.boot_time;
376 
377 	host_info_buf->uptime = currtime - boottime;
378 	host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt;
379 	host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt;
380 	host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS);
381 
382 	/*
383 	 * TODO: getting virtualization state
384 	 *       1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so)
385 	 *       2) get function addresses for
386 	 *          a) HPVM_boolean hpvm_api_server_check()
387 	 *          b) HPVM_boolean hpvm_api_virtmach_check()
388 	 *
389 	 * Seems to be hardware virtualization ...
390 	 * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3))
391 	 *      http://jreypo.wordpress.com/tag/hpvm/
392 	 *      http://jreypo.wordpress.com/category/hp-ux/page/3/
393 	 *      http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html
394 	 */
395 
396 #elif defined(SOLARIS)
397 	if ((kc = kstat_open()) == NULL) {
398 		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL);
399 	}
400 
401 	if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){
402 		kstat_close(kc);
403 		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
404 	}
405 	if (kstat_read(kc, ksp, 0) == -1) {
406 		kstat_close(kc);
407 		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL);
408 	}
409 	if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){
410 		kstat_close(kc);
411 		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
412 	}
413 	/* XXX verify on Solaris 10 if it's still ui32 */
414 	boottime = (kn->value.ui32);
415 
416 	kstat_close(kc);
417 
418 	time(&curtime);
419 	host_info_buf->uptime = curtime - boottime;
420 
421 	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
422 	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
423 	isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) );
424 	if( NULL == isainfo ) {
425 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
426 	}
427 # define MKSTR(x) #x
428 # if defined(SI_ARCHITECTURE_K)
429 #  define SYSINFO_CMD SI_ARCHITECTURE_K
430 # elif defined(SI_ISALIST)
431 #  define SYSINFO_CMD SI_ISALIST
432 # else
433 #  define SYSINFO_CMD SI_ARCHITECTURE
434 # endif
435 sysinfo_again:
436 	if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) {
437 		free(isainfo);
438 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) );
439 	}
440 	else if( rc > isabufsz ) {
441 		char *tmp = sg_realloc(isainfo, rc);
442 		if( NULL == tmp ) {
443 			free(isainfo);
444 			RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
445 		}
446 		isabufsz = rc;
447 		isainfo = tmp;
448 		goto sysinfo_again;
449 	}
450 
451 	host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo);
452 	free(isainfo);
453 	host_info_buf->host_state = sg_unknown_configuration;
454 
455 #elif defined(LINUX) || defined(CYGWIN)
456 	if ((f=fopen("/proc/uptime", "r")) == NULL) {
457 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime");
458 	}
459 
460 #define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" )
461 	if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){
462 		fclose(f);
463 		RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL);
464 	}
465 	fclose(f);
466 
467 # if defined(LINUX)
468 	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
469 	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
470 	if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 ||
471 	    access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) {
472 		host_info_buf->bitwidth = 64;
473 	}
474 	else {
475 #  if defined(_SC_LONG_BIT)
476 		host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O
477 #  else
478 		host_info_buf->bitwidth = sysconf(LONG_BIT);
479 #  endif
480 	}
481 	host_info_buf->host_state = sg_unknown_configuration;
482 # endif
483 
484 #elif defined(ALLBSD)
485 	mib[0] = CTL_KERN;
486 	mib[1] = KERN_BOOTTIME;
487 	size = sizeof(boottime);
488 	if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
489 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME");
490 	}
491 	time(&curtime);
492 	host_info_buf->uptime= curtime - boottime.tv_sec;
493 
494 # if defined(HW_NCPU)
495 	mib[0] = CTL_HW;
496 	mib[1] = HW_NCPU;
497 	size = sizeof(int);
498 	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
499 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" );
500 	}
501 # endif
502 # if defined(HW_MACHINE_ARCH)
503 	mib[0] = CTL_HW;
504 	mib[1] = HW_MACHINE_ARCH;
505 	size = sizeof(arch_name);
506 	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
507 		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
508 	}
509 	else {
510 # endif
511 # if defined(HW_MACHINE)
512 	mib[0] = CTL_HW;
513 	mib[1] = HW_MACHINE;
514 	size = sizeof(arch_name);
515 	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
516 		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
517 	}
518 	else {
519 		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" );
520 	}
521 # elif defined(HW_MACHINE_ARCH)
522 		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" );
523 # endif
524 # if defined(HW_MACHINE_ARCH)
525 	}
526 # endif
527 	host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */
528 	host_info_buf->maxcpus = (unsigned)ncpus;
529 # if defined(HW_NCPUONLINE)
530 	/* use knowledge about number of cpu's online, when available instead of assuming all of them */
531 	mib[0] = CTL_HW;
532 	mib[1] = HW_NCPUONLINE;
533 	size = sizeof(int);
534 	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
535 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" );
536 	}
537 # endif
538 	host_info_buf->ncpus = (unsigned)ncpus;
539 
540 #elif defined(AIX)
541 	if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) {
542 		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total");
543 	}
544 
545 	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) {
546 		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
547 	}
548 
549 	host_info_buf->ncpus = cpu_total.ncpus;
550 	host_info_buf->maxcpus = cpu_total.ncpus_cfg;
551 	host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE);
552 	if( sysconf(_SC_LPAR_ENABLED) > 0 ) {
553 		host_info_buf->host_state = sg_hardware_virtualized;
554 	}
555 	else {
556 		host_info_buf->host_state = sg_physical_host;
557 	}
558 
559 #ifdef ENABLE_THREADS
560 	if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) {
561 		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
562 	}
563 #endif
564 # if defined(HAVE_GETUTXENT)
565 #  define UTENTFN getutxent
566 #  define UTENTTM ut->ut_tv.tv_sec
567 	setutxent();
568 # else
569 #  define UTENTFN getutent
570 #  define UTENTTM ut->ut_time
571 	setutent();
572 # endif
573 	while( NULL != ( ut = UTENTFN() ) ) {
574 		if( ut->ut_type == BOOT_TIME ) {
575 			host_info_buf->uptime = time(NULL) - UTENTTM;
576 			break;
577 		}
578 	}
579 # if defined(HAVE_GETUTXENT)
580 	endutxent();
581 # else
582 	endutent();
583 # endif
584 #ifdef ENABLE_THREADS
585 	if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) {
586 		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
587 	}
588 #endif
589 #else
590 	RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE);
591 #endif
592 #endif /* WIN32 */
593 
594 	host_info_buf->systime = time(NULL);
595 
596 	return SG_ERROR_NONE;
597 }
598 
599 #ifdef AIX
600 EASY_COMP_SETUP(os,1,"utmp",NULL);
601 #else
602 EASY_COMP_SETUP(os,1,NULL);
603 #endif
604 
605 typedef sg_host_info sg_os_stats;
606 
607 static void
sg_os_stats_item_init(sg_os_stats * d)608 sg_os_stats_item_init(sg_os_stats *d) {
609 
610 	memset( d, 0, sizeof(*d) );
611 }
612 
613 #if 0
614 #else
615 #define sg_os_stats_item_copy NULL
616 #define sg_os_stats_item_compute_diff NULL
617 #define sg_os_stats_item_compare NULL
618 #endif
619 
620 static void
sg_os_stats_item_destroy(sg_os_stats * d)621 sg_os_stats_item_destroy(sg_os_stats *d) {
622 
623 	free(d->os_name);
624 	free(d->os_release);
625 	free(d->os_version);
626 	free(d->platform);
627 	free(d->hostname);
628 	memset( d, 0, sizeof(*d) );
629 }
630 
631 VECTOR_INIT_INFO_FULL_INIT(sg_os_stats);
632 
633 #define SG_OS_CUR_IDX 0
634 
635 EASY_COMP_ACCESS(sg_get_host_info,os,os,SG_OS_CUR_IDX)
636