Пример #1
0
static sg_error
sg_get_user_stats_int(sg_vector **user_stats_vector_ptr) {
	size_t num_users = 0;
	sg_user_stats *user_ptr;
	time_t now = time(NULL);

#if defined (WIN32)
	LPWKSTA_USER_INFO_0 buf = NULL;
	LPWKSTA_USER_INFO_0 tmp_buf;
	unsigned long entries_read = 0;
	unsigned long entries_tot = 0;
	unsigned long resumehandle = 0;
	NET_API_STATUS nStatus;
	int i;
	char name[256];

#undef VECTOR_UPDATE_ERROR_CLEANUP
#define VECTOR_UPDATE_ERROR_CLEANUP if (buf != NULL) NetApiBufferFree(buf);

	do {
		nStatus = NetWkstaUserEnum(NULL, 0, (LPBYTE*)&buf,
				MAX_PREFERRED_LENGTH, &entries_read,
				&entries_tot, &resumehandle);
		if((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
			if((tmp_buf = buf) == NULL)
				continue;

			for( i = 0; i < entries_read; ++i ) {
				/* assert(tmp_buf != NULL); */
				if( tmp_buf == NULL ) {
					sg_set_error(SG_ERROR_PERMISSION, "User list");
					ERROR_LOG("user", "Permission denied fetching user details");
					break; /* XXX break and not return? */
				}
				/* It's in unicode. We are not. Convert */
				WideCharToMultiByte(CP_ACP, 0, tmp_buf->wkui0_username, -1, name, sizeof(name), NULL, NULL);

				VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);
				if( SG_ERROR_NONE != sg_update_string( &user_ptr[num_users].login_name, name ) ) {
					VECTOR_UPDATE_ERROR_CLEANUP
					RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
				}

				user_ptr[num_users].systime = now;

				++tmp_buf;
				++num_users;
			}
		}
		else {
			RETURN_WITH_SET_ERROR("user", SG_ERROR_PERMISSION, "User enum");
		}

		if (buf != NULL) {
			NetApiBufferFree(buf);
			buf=NULL;
		}
	} while (nStatus == ERROR_MORE_DATA);

	if (buf != NULL)
		NetApiBufferFree(buf);
#elif defined(CAN_USE_UTMPX) || defined(CAN_USE_UTMP)

#define SG_LUPDATE_IF(tgt,obj,memb) \
	(((void *)(&(obj->memb))) == ((void *)(&(obj->memb[0])))) \
	? sg_lupdate_string(tgt, obj->memb, sizeof(obj->memb))\
	: sg_update_string(tgt, obj->memb)

#define UTMP_MUTEX_NAME "utmp"

#undef VECTOR_UPDATE_ERROR_CLEANUP
# if defined(CAN_USE_UTMPX)
	struct utmpx *utx;
# endif
# if defined(CAN_USE_UTMP)
	struct utmp *ut;
# endif

	/* following block contains code for utmpx */
# if defined(CAN_USE_UTMPX)
#  ifdef ENABLE_THREADS
#   define VECTOR_UPDATE_ERROR_CLEANUP endutxent(); sg_unlock_mutex(UTMP_MUTEX_NAME);
	sg_lock_mutex(UTMP_MUTEX_NAME);
#  else
#   define VECTOR_UPDATE_ERROR_CLEANUP endutxent();
#  endif
	setutxent();
	while( NULL != (utx = getutxent()) ) {
		if( USER_PROCESS != utx->ut_type )
			continue;

		VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

		if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, utx, ut_user ) ) ||
#  if defined(HAVE_UTMPX_HOST)
#   if defined(HAVE_UTMPX_SYSLEN)
		    ( SG_ERROR_NONE != sg_lupdate_string( &user_ptr[num_users].hostname, utx->ut_host, utx->ut_syslen + 1 ) ) ||
#   else
		    ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, utx, ut_host ) ) ||
#   endif
#  endif
		    ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, utx, ut_line ) ) ||
		    ( SG_ERROR_NONE != sg_update_mem( (void *)(&user_ptr[num_users].record_id), utx->ut_id, sizeof(utx->ut_id) ) ) ) {
			    VECTOR_UPDATE_ERROR_CLEANUP
			    RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
		}

		user_ptr[num_users].record_id_size = sizeof(utx->ut_id);
		user_ptr[num_users].pid = utx->ut_pid;
		user_ptr[num_users].login_time = utx->ut_tv.tv_sec;
		user_ptr[num_users].systime = now;

		++num_users;
	}

	endutxent();

	if(!num_users) {
# endif

	/* following block contains code for utmp */
# if defined(CAN_USE_UTMP)

#  undef VECTOR_UPDATE_ERROR_CLEANUP
#  ifdef ENABLE_THREADS
#   define VECTOR_UPDATE_ERROR_CLEANUP endutent(); sg_unlock_mutex(UTMP_MUTEX_NAME);
#  else
#   define VECTOR_UPDATE_ERROR_CLEANUP endutent();
#  endif
	setutent();
	while( NULL != (ut = getutent()) ) {
#  ifdef HAVE_UTMP_TYPE
		if( USER_PROCESS != ut->ut_type )
			continue;
#  elif defined(HAVE_UTMP_NAME)
	    if (ut->ut_name[0] == '\0')
		    continue;
#  elif defined(HAVE_UTMP_USER)
	    if (ut->ut_user[0] == '\0')
		    continue;
#  endif

	    VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

	    if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, ut, ut_line ) )
#  if defined(HAVE_UTMP_USER)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_user ) )
#  elif defined(HAVE_UTMP_NAME)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_name ) )
#  endif
#  if defined(HAVE_UTMP_HOST)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, ut, ut_host ) )
#  endif
#  if defined(HAVE_UTMP_ID)
	     || ( SG_ERROR_NONE != sg_update_mem( (void **)(&user_ptr[num_users].record_id), ut->ut_id, sizeof(ut->ut_id) ) )
#  endif
	    ) {
			VECTOR_UPDATE_ERROR_CLEANUP
			RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
	    }

#  if defined(HAVE_UTMP_ID)
	    user_ptr[num_users].record_id_size = sizeof(ut->ut_id);
#  endif
#  if defined(HAVE_UTMP_PID)
	    user_ptr[num_users].pid = ut->ut_pid;
#  endif
#if defined(HAVE_UTMP_TIME)
	    user_ptr[num_users].login_time = ut->ut_time;
#endif
	    user_ptr[num_users].systime = now;

	    ++num_users;
    }

    endutent();
# endif

# if defined(CAN_USE_UTMPX)
    }
#endif

# ifdef ENABLE_THREADS
    sg_unlock_mutex(UTMP_MUTEX_NAME);
# endif
#elif defined(HAVE_STRUCT_UTMP) && defined(_PATH_UTMP)
    struct utmp entry;
    FILE *f;

    if ((f=fopen(_PATH_UTMP, "r")) == NULL) {
	    RETURN_WITH_SET_ERROR_WITH_ERRNO("user", SG_ERROR_OPEN, _PATH_UTMP);
    }

#ifdef SG_LUPDATE_IF
#undef SG_LUPDATE_IF
#endif

#define SG_LUPDATE_IF(tgt,obj,memb) \
	(((void *)(&(obj.memb))) == ((void *)(&(obj.memb[0])))) \
	? sg_lupdate_string(tgt, obj.memb, sizeof(obj.memb))\
	: sg_update_string(tgt, obj.memb)

#undef VECTOR_UPDATE_ERROR_CLEANUP
#define VECTOR_UPDATE_ERROR_CLEANUP fclose(f);

    while((fread(&entry, sizeof(entry),1,f)) != 0){
#ifdef HAVE_UTMP_TYPE
	    if( USER_PROCESS != ut->ut_type )
		    continue;
#elif defined(HAVE_UTMP_NAME)
	    if (entry.ut_name[0] == '\0')
		    continue;
#elif defined(HAVE_UTMP_USER)
	    if (entry.ut_user[0] == '\0')
		    continue;
#endif

	    VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats);

	    if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, entry, ut_line ) )
#if defined(HAVE_UTMP_USER)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_user ) )
#elif defined(HAVE_UTMP_NAME)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_name ) )
#endif
#if defined(HAVE_UTMP_HOST)
	     || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, entry, ut_host ) )
#endif
#if defined(HAVE_UTMP_ID)
	     || ( SG_ERROR_NONE != sg_update_mem( &user_ptr[num_users].record_id, entry.ut_id, sizeof(entry.ut_id) ) )
#endif
	    ) {
			VECTOR_UPDATE_ERROR_CLEANUP
			RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() );
	    }

#if defined(HAVE_UTMP_ID)
	    user_ptr[num_users].record_id_size = sizeof(entry.ut_id);
#endif
#if defined(HAVE_UTMP_PID)
	    user_ptr[num_users].pid = entry.ut_pid;
#endif
#if defined(HAVE_UTMP_TIME)
	    user_ptr[num_users].login_time = entry.ut_time;
#endif
		user_ptr[num_users].systime = now;

		++num_users;
	}

	fclose(f);
#else
	RETURN_WITH_SET_ERROR("user", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	return SG_ERROR_NONE;
}
Пример #2
0
static sg_error
sg_get_host_info_int(sg_host_info *host_info_buf) {

#ifdef WIN32
	unsigned long nameln;
	char *name;
	long long result;
	OSVERSIONINFOEX osinfo;
	SYSTEM_INFO sysinfo;
	char *tmp_name;
	char tmp[10];
#else
	struct utsname os;
# if defined(HPUX)
	struct pst_static pstat_static;
	struct pst_dynamic pstat_dynamic;
	time_t currtime;
	long boottime;
# elif defined(SOLARIS)
	time_t boottime, curtime;
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
	char *isainfo = NULL;
	long isabufsz, rc;
# elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
# elif defined(ALLBSD)
	int mib[2];
	struct timeval boottime;
	time_t curtime;
	size_t size;
	int ncpus;
#  if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE)
	char arch_name[16];
#  endif
# elif defined(AIX)
	static perfstat_cpu_total_t cpu_total;
	sg_error rc;
#  if defined(HAVE_GETUTXENT)
	struct utmpx *ut;
#  else
	struct utmp *ut;
#  endif
# endif
#endif

	host_info_buf->ncpus = 0;
	host_info_buf->maxcpus = 0;
	host_info_buf->bitwidth = 0;
	host_info_buf->host_state = sg_unknown_configuration;
	host_info_buf->uptime = 0;
	host_info_buf->systime = 0;

#ifdef WIN32
	/* these settings are static after boot, so why get them
	 * constantly?
	 *
	 * Because we want to know some changes anyway - at least
	 * when the hostname (DNS?) changes
	 */

	/* get system name */
	nameln = MAX_COMPUTERNAME_LENGTH + 1;
	name = sg_malloc(nameln);
	if(name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/*
	 * XXX probably GetComputerNameEx() is a better entry point ...
	 */
	if( GetComputerName(name, &nameln) == 0 ) {
		free(name);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) {
		free(name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(name);

	/* get OS name, version and build */
	ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
	osinfo.dwOSVersionInfoSize = sizeof(osinfo);
	if(!GetVersionEx(&osinfo)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx");
	}
	GetSystemInfo(&sysinfo);

	/* Release - single number */
	if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL);
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* Version */
	/* usually a single digit . single digit, eg 5.0 */
	if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
				osinfo.dwMinorVersion) == -1) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* OS name */
	tmp_name = get_os_name(osinfo, sysinfo);
	if(tmp_name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) {
		free(tmp_name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(tmp_name);

	/* Platform */
	switch(sysinfo.wProcessorArchitecture) {
		case PROCESSOR_ARCHITECTURE_INTEL:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Intel")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_IA64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"IA64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_AMD64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"AMD64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		default:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Unknown")){
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
	}

	if(read_counter_large(SG_WIN32_UPTIME, &result)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME);
	}

	host_info_buf->uptime = (time_t) result;
#else
	if((uname(&os)) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL);
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* get uptime */
#ifdef HPUX
	if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static");
	}

	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic");
	}

	currtime = time(NULL);

	boottime = pstat_static.boot_time;

	host_info_buf->uptime = currtime - boottime;
	host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt;
	host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt;
	host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS);

	/*
	 * TODO: getting virtualization state
	 *       1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so)
	 *       2) get function addresses for
	 *          a) HPVM_boolean hpvm_api_server_check()
	 *          b) HPVM_boolean hpvm_api_virtmach_check()
	 *
	 * Seems to be hardware virtualization ...
	 * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3))
	 *      http://jreypo.wordpress.com/tag/hpvm/
	 *      http://jreypo.wordpress.com/category/hp-ux/page/3/
	 *      http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html
	 */

#elif defined(SOLARIS)
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL);
	}

	if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
	}
	if (kstat_read(kc, ksp, 0) == -1) {
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL);
	}
	if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
	}
	/* XXX verify on Solaris 10 if it's still ui32 */
	boottime = (kn->value.ui32);

	kstat_close(kc);

	time(&curtime);
	host_info_buf->uptime = curtime - boottime;

	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) );
	if( NULL == isainfo ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
# define MKSTR(x) #x
# if defined(SI_ARCHITECTURE_K)
#  define SYSINFO_CMD SI_ARCHITECTURE_K
# elif defined(SI_ISALIST)
#  define SYSINFO_CMD SI_ISALIST
# else
#  define SYSINFO_CMD SI_ARCHITECTURE
# endif
sysinfo_again:
	if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) {
		free(isainfo);
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) );
	}
	else if( rc > isabufsz ) {
		char *tmp = sg_realloc(isainfo, rc);
		if( NULL == tmp ) {
			free(isainfo);
			RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
		}
		isabufsz = rc;
		isainfo = tmp;
		goto sysinfo_again;
	}

	host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo);
	free(isainfo);
	host_info_buf->host_state = sg_unknown_configuration;

#elif defined(LINUX) || defined(CYGWIN)
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime");
	}

#define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" )
	if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){
		fclose(f);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL);
	}
	fclose(f);

# if defined(LINUX)
	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 ||
	    access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) {
		host_info_buf->bitwidth = 64;
	}
	else {
		host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O
	}
	host_info_buf->host_state = sg_unknown_configuration;
# endif

#elif defined(ALLBSD)
	mib[0] = CTL_KERN;
	mib[1] = KERN_BOOTTIME;
	size = sizeof(boottime);
	if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME");
	}
	time(&curtime);
	host_info_buf->uptime= curtime - boottime.tv_sec;

# if defined(HW_NCPU)
	mib[0] = CTL_HW;
	mib[1] = HW_NCPU;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" );
	}
# endif
# if defined(HW_MACHINE_ARCH)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE_ARCH;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
# endif
# if defined(HW_MACHINE)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" );
	}
# elif defined(HW_MACHINE_ARCH)
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" );
# endif
# if defined(HW_MACHINE_ARCH)
	}
# endif
	host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */
	host_info_buf->maxcpus = (unsigned)ncpus;
# if defined(HW_NCPUONLINE)
	/* use knowledge about number of cpu's online, when available instead of assuming all of them */
	mib[0] = CTL_HW;
	mib[1] = HW_NCPUONLINE;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" );
	}
# endif
	host_info_buf->ncpus = (unsigned)ncpus;

#elif defined(AIX)
	if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	host_info_buf->ncpus = cpu_total.ncpus;
	host_info_buf->maxcpus = cpu_total.ncpus_cfg;
	host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE);
	if( sysconf(_SC_LPAR_ENABLED) > 0 ) {
		host_info_buf->host_state = sg_hardware_virtualized;
	}
	else {
		host_info_buf->host_state = sg_physical_host;
	}

#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
# if defined(HAVE_GETUTXENT)
#  define UTENTFN getutxent
#  define UTENTTM ut->ut_tv.tv_sec
	setutxent();
# else
#  define UTENTFN getutent
#  define UTENTTM ut->ut_time
	setutent();
# endif
	while( NULL != ( ut = UTENTFN() ) ) {
		if( ut->ut_type == BOOT_TIME ) {
			host_info_buf->uptime = time(NULL) - UTENTTM;
			break;
		}
	}
# if defined(HAVE_GETUTXENT)
	endutxent();
# else
	endutent();
# endif
#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
#else
	RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif
#endif /* WIN32 */

	host_info_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}