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