diff options
Diffstat (limited to 'agent/mibgroup/mibII/system_mib.c')
-rw-r--r-- | agent/mibgroup/mibII/system_mib.c | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/system_mib.c b/agent/mibgroup/mibII/system_mib.c new file mode 100644 index 0000000..f902cb8 --- /dev/null +++ b/agent/mibgroup/mibII/system_mib.c @@ -0,0 +1,765 @@ +/* + * System MIB group implementation - system.c + * + */ +/* Portions of this file are subject to the following copyright(s). See + * the Net-SNMP's COPYING file for more details and other copyrights + * that may apply: + */ +/* + * Portions of this file are copyrighted by: + * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms specified in the COPYING file + * distributed with the Net-SNMP package. + */ + +#include <net-snmp/net-snmp-config.h> + +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#include <sys/types.h> +#if HAVE_WINSOCK_H +#include <winsock.h> +#endif + +#if !defined(mingw32) && defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#endif + +#include <ctype.h> +#if HAVE_UTSNAME_H +#include <utsname.h> +#else +#if HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "util_funcs.h" +#include "system_mib.h" +#include "struct.h" +#include "sysORTable.h" + + + /********************* + * + * Kernel & interface information, + * and internal forward declarations + * + *********************/ + +#define SYS_STRING_LEN 256 +char version_descr[SYS_STRING_LEN] = NETSNMP_VERS_DESC; +char sysContact[SYS_STRING_LEN] = NETSNMP_SYS_CONTACT; +char sysName[SYS_STRING_LEN] = NETSNMP_SYS_NAME; +char sysLocation[SYS_STRING_LEN] = NETSNMP_SYS_LOC; +oid sysObjectID[MAX_OID_LEN]; +size_t sysObjectIDLength; + +extern oid version_sysoid[]; +extern int version_sysoid_len; + +char oldversion_descr[SYS_STRING_LEN]; +char oldsysContact[SYS_STRING_LEN]; +char oldsysName[SYS_STRING_LEN]; +char oldsysLocation[SYS_STRING_LEN]; + +int sysServices = 72; +int sysServicesConfiged = 0; + +extern oid version_id[]; +extern int version_id_len; + +static int sysContactSet = 0, sysLocationSet = 0, sysNameSet = 0; + +WriteMethod writeSystem; +int header_system(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); + +#if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) +static void windowsOSVersionString(char [], size_t); +#endif + + /********************* + * + * snmpd.conf config parsing + * + *********************/ + +void +system_parse_config_sysdescr(const char *token, char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) >= sizeof(version_descr)) { + snprintf(tmpbuf, + sizeof(tmpbuf), + "sysdescr token too long (must be < %lu):\n\t%s", + (unsigned long)sizeof(version_descr), + cptr); + config_perror(tmpbuf); + } else if (strcmp(cptr, "\"\"") == 0) { + version_descr[0] = '\0'; + } else { + strcpy(version_descr, cptr); + } +} + +void +system_parse_config_sysloc(const char *token, char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) >= sizeof(sysLocation)) { + snprintf(tmpbuf, 1024, + "syslocation token too long (must be < %lu):\n\t%s", + (unsigned long)sizeof(sysLocation), cptr); + config_perror(tmpbuf); + } + + if (strcmp(token, "psyslocation") == 0) { + if (sysLocationSet < 0) { + /* + * This is bogus (and shouldn't happen anyway) -- the sysLocation + * is already configured read-only. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysLocation.0\n"); + return; + } else { + sysLocationSet++; + } + } else { + if (sysLocationSet > 0) { + /* + * This is bogus (and shouldn't happen anyway) -- we already read a + * persistent value of sysLocation, which we should ignore in + * favour of this one. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysLocation.0\n"); + /* + * Fall through and copy in this value. + */ + } + sysLocationSet = -1; + } + + if (strcmp(cptr, "\"\"") == 0) { + sysLocation[0] = '\0'; + } else if (strlen(cptr) < sizeof(sysLocation)) { + strcpy(sysLocation, cptr); + } +} + +void +system_parse_config_syscon(const char *token, char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) >= sizeof(sysContact)) { + snprintf(tmpbuf, 1024, + "syscontact token too long (must be < %lu):\n\t%s", + (unsigned long)sizeof(sysContact), cptr); + config_perror(tmpbuf); + } + + if (strcmp(token, "psyscontact") == 0) { + if (sysContactSet < 0) { + /* + * This is bogus (and shouldn't happen anyway) -- the sysContact + * is already configured read-only. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysContact.0\n"); + return; + } else { + sysContactSet++; + } + } else { + if (sysContactSet > 0) { + /* + * This is bogus (and shouldn't happen anyway) -- we already read a + * persistent value of sysContact, which we should ignore in favour + * of this one. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysContact.0\n"); + /* + * Fall through and copy in this value. + */ + } + sysContactSet = -1; + } + + if (strcmp(cptr, "\"\"") == 0) { + sysContact[0] = '\0'; + } else if (strlen(cptr) < sizeof(sysContact)) { + strcpy(sysContact, cptr); + } +} + +void +system_parse_config_sysname(const char *token, char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) >= sizeof(sysName)) { + snprintf(tmpbuf, 1024, + "sysname token too long (must be < %lu):\n\t%s", + (unsigned long)sizeof(sysName), cptr); + config_perror(tmpbuf); + } + + if (strcmp(token, "psysname") == 0) { + if (sysNameSet < 0) { + /* + * This is bogus (and shouldn't happen anyway) -- the sysName + * is already configured read-only. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysName.0\n"); + return; + } else { + sysNameSet++; + } + } else { + if (sysNameSet > 0) { + /* + * This is bogus (and shouldn't happen anyway) -- we already read a + * persistent value of sysName, which we should ignore in favour + * of this one. + */ + snmp_log(LOG_WARNING, + "ignoring attempted override of read-only sysName.0\n"); + /* + * Fall through and copy in this value. + */ + } + sysNameSet = -1; + } + + if (strcmp(cptr, "\"\"") == 0) { + sysName[0] = '\0'; + } else if (strlen(cptr) < sizeof(sysName)) { + strcpy(sysName, cptr); + } +} + +void +system_parse_config_sysServices(const char *token, char *cptr) +{ + sysServices = atoi(cptr); + sysServicesConfiged = 1; +} + +void system_parse_config_sysObjectID(const char *token, char *cptr) +{ + char tmpbuf[1024]; + + sysObjectIDLength = MAX_OID_LEN; + if (!read_objid(cptr, sysObjectID, &sysObjectIDLength)) { + snprintf(tmpbuf, + sizeof(tmpbuf), + "sysobjectid token not a parsable OID:\n\t%s", + cptr); + config_perror(tmpbuf); + memcpy(sysObjectID, version_sysoid, version_sysoid_len * sizeof(oid)); + sysObjectIDLength = version_sysoid_len; + } +} + + + /********************* + * + * Initialisation & common implementation functions + * + *********************/ + +/* + * define the structure we're going to ask the agent to register our + * information at + */ +struct variable1 system_variables[] = { + {VERSION_DESCR, ASN_OCTET_STR, RONLY, var_system, 1, {1}}, + {VERSIONID, ASN_OBJECT_ID, RONLY, var_system, 1, {2}}, + {UPTIME, ASN_TIMETICKS, RONLY, var_system, 1, {3}}, + {SYSCONTACT, ASN_OCTET_STR, RWRITE, var_system, 1, {4}}, + {SYSTEMNAME, ASN_OCTET_STR, RWRITE, var_system, 1, {5}}, + {SYSLOCATION, ASN_OCTET_STR, RWRITE, var_system, 1, {6}}, + {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}}, + {SYSORLASTCHANGE, ASN_TIMETICKS, RONLY, var_system, 1, {8}} +}; +/* + * Define the OID pointer to the top of the mib tree that we're + * registering underneath + */ +oid system_variables_oid[] = { SNMP_OID_MIB2, 1 }; +oid system_module_oid[] = { SNMP_OID_SNMPMODULES, 1 }; +int system_module_oid_len = + sizeof(system_module_oid) / sizeof(oid); +int system_module_count = 0; + +static int +system_store(int a, int b, void *c, void *d) +{ + char line[SNMP_MAXBUF_SMALL]; + + if (sysLocationSet > 0) { + snprintf(line, SNMP_MAXBUF_SMALL, "psyslocation %s", sysLocation); + snmpd_store_config(line); + } + if (sysContactSet > 0) { + snprintf(line, SNMP_MAXBUF_SMALL, "psyscontact %s", sysContact); + snmpd_store_config(line); + } + if (sysNameSet > 0) { + snprintf(line, SNMP_MAXBUF_SMALL, "psysname %s", sysName); + snmpd_store_config(line); + } + + return 0; +} + +void +init_system_mib(void) +{ + +#ifdef HAVE_UNAME + struct utsname utsName; + + uname(&utsName); + snprintf(version_descr, sizeof(version_descr), + "%s %s %s %s %s", utsName.sysname, + utsName.nodename, utsName.release, utsName.version, + utsName.machine); + version_descr[ sizeof(version_descr)-1 ] = 0; +#else +#if HAVE_EXECV + struct extensible extmp; + + /* + * set default values of system stuff + */ + sprintf(extmp.command, "%s -a", UNAMEPROG); + /* + * setup defaults + */ + extmp.type = EXECPROC; + extmp.next = NULL; + exec_command(&extmp); + strncpy(version_descr, extmp.output, sizeof(version_descr)); + version_descr[sizeof(version_descr) - 1] = 0; + version_descr[strlen(version_descr) - 1] = 0; /* chomp new line */ +#else +#if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) + windowsOSVersionString(version_descr, sizeof(version_descr)); +#else + strcpy(version_descr, "unknown"); +#endif +#endif +#endif + +#ifdef HAVE_GETHOSTNAME + gethostname(sysName, sizeof(sysName)); +#else +#ifdef HAVE_UNAME + strncpy(sysName, utsName.nodename, sizeof(sysName)); +#else +#if defined (HAVE_EXECV) && !defined (mingw32) + sprintf(extmp.command, "%s -n", UNAMEPROG); + /* + * setup defaults + */ + extmp.type = EXECPROC; + extmp.next = NULL; + exec_command(&extmp); + strncpy(sysName, extmp.output, sizeof(sysName)); + sysName[strlen(sysName) - 1] = 0; /* chomp new line */ +#else + strcpy(sysName, "unknown"); +#endif /* HAVE_EXECV */ +#endif /* HAVE_UNAME */ +#endif /* HAVE_GETHOSTNAME */ + +#if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) + { + HKEY hKey; + /* Default sysContact is the registered windows user */ + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { + char registeredOwner[256] = ""; + DWORD registeredOwnerSz = 256; + if (RegQueryValueEx(hKey, "RegisteredOwner", NULL, NULL, (LPBYTE)registeredOwner, ®isteredOwnerSz) == ERROR_SUCCESS) { + strcpy(sysContact, registeredOwner); + } + RegCloseKey(hKey); + } + } +#endif + + /* default sysObjectID */ + memcpy(sysObjectID, version_sysoid, version_sysoid_len * sizeof(oid)); + sysObjectIDLength = version_sysoid_len; + + /* + * register ourselves with the agent to handle our mib tree + */ + REGISTER_MIB("mibII/system", system_variables, variable1, + system_variables_oid); + + if (++system_module_count == 3) + REGISTER_SYSOR_ENTRY(system_module_oid, + "The MIB module for SNMPv2 entities"); + + sysContactSet = sysLocationSet = sysNameSet = 0; + + /* + * register our config handlers + */ + snmpd_register_config_handler("sysdescr", + system_parse_config_sysdescr, NULL, + "description"); + snmpd_register_config_handler("syslocation", + system_parse_config_sysloc, NULL, + "location"); + snmpd_register_config_handler("syscontact", system_parse_config_syscon, + NULL, "contact-name"); + snmpd_register_config_handler("sysname", system_parse_config_sysname, + NULL, "node-name"); + snmpd_register_config_handler("psyslocation", + system_parse_config_sysloc, NULL, NULL); + snmpd_register_config_handler("psyscontact", + system_parse_config_syscon, NULL, NULL); + snmpd_register_config_handler("psysname", system_parse_config_sysname, + NULL, NULL); + snmpd_register_config_handler("sysservices", + system_parse_config_sysServices, NULL, + "NUMBER"); + snmpd_register_config_handler("sysobjectid", + system_parse_config_sysObjectID, NULL, + "OID"); + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, + system_store, NULL); + +} + + + /********************* + * + * System specific implementation functions + * + *********************/ + +#ifdef USING_MIBII_SYSORTABLE_MODULE +extern struct timeval sysOR_lastchange; +#endif + +u_char * +var_system(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ + static u_long ulret; + + if (header_generic(vp, name, length, exact, var_len, write_method) == + MATCH_FAILED) + return NULL; + + switch (vp->magic) { + case VERSION_DESCR: + *var_len = strlen(version_descr); + return (u_char *) version_descr; + case VERSIONID: + *var_len = sysObjectIDLength * sizeof(sysObjectID[0]); + return (u_char *)sysObjectID; + case UPTIME: + ulret = netsnmp_get_agent_uptime(); + return ((u_char *) & ulret); + case SYSCONTACT: + *var_len = strlen(sysContact); + *write_method = writeSystem; + return (u_char *) sysContact; + case SYSTEMNAME: + *var_len = strlen(sysName); + *write_method = writeSystem; + return (u_char *) sysName; + case SYSLOCATION: + *var_len = strlen(sysLocation); + *write_method = writeSystem; + return (u_char *) sysLocation; + case SYSSERVICES: +#if NETSNMP_NO_DUMMY_VALUES + if (!sysServicesConfiged) + return NULL; +#endif + long_return = sysServices; + return (u_char *) & long_return; + +#ifdef USING_MIBII_SYSORTABLE_MODULE + case SYSORLASTCHANGE: + ulret = netsnmp_timeval_uptime(&sysOR_lastchange); + return ((u_char *) & ulret); +#endif + + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n", + vp->magic)); + } + return NULL; +} + + + +int +writeSystem(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + u_char *cp; + char *buf = NULL, *oldbuf = NULL; + int count, *setvar = NULL; + + switch ((char) name[7]) { + case VERSION_DESCR: + case VERSIONID: + case UPTIME: + snmp_log(LOG_ERR, "Attempt to write to R/O OID\n"); + return SNMP_ERR_NOTWRITABLE; + case SYSCONTACT: + buf = sysContact; + oldbuf = oldsysContact; + setvar = &sysContactSet; + break; + case SYSTEMNAME: + buf = sysName; + oldbuf = oldsysName; + setvar = &sysNameSet; + break; + case SYSLOCATION: + buf = sysLocation; + oldbuf = oldsysLocation; + setvar = &sysLocationSet; + break; + case SYSSERVICES: + case SYSORLASTCHANGE: + snmp_log(LOG_ERR, "Attempt to write to R/O OID\n"); + return SNMP_ERR_NOTWRITABLE; + default: + return SNMP_ERR_GENERR; /* ??? */ + } + + switch (action) { + case RESERVE1: /* Check values for acceptability */ + if (var_val_type != ASN_OCTET_STR) { + snmp_log(LOG_ERR, "not string\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(sysLocation) - 1) { + snmp_log(LOG_ERR, "bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + + for (cp = var_val, count = 0; count < (int) var_val_len; + count++, cp++) { + if (!isprint(*cp)) { + snmp_log(LOG_ERR, "not print %x\n", *cp); + return SNMP_ERR_WRONGVALUE; + } + } + if (setvar != NULL && *setvar < 0) { + /* + * The object is set in a read-only configuration file. + */ + return SNMP_ERR_NOTWRITABLE; + } + break; + + case RESERVE2: /* Allocate memory and similar resources */ + + /* + * Using static strings, so nothing needs to be done + */ + break; + + case ACTION: /* Perform the SET action (if reversible) */ + + /* + * Save the old value, in case of UNDO + */ + strcpy(oldbuf, buf); + memcpy(buf, var_val, var_val_len); + buf[var_val_len] = 0; + break; + + case UNDO: /* Reverse the SET action and free resources */ + + strcpy(buf, oldbuf); + oldbuf[0] = 0; + break; + + case COMMIT: + if (setvar != NULL) { + *setvar = 1; + } + snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); + (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, + SNMP_CALLBACK_STORE_DATA, NULL); + snmp_clean_persistent(netsnmp_ds_get_string + (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); + + case FREE: /* Free any resources allocated */ + + /* + * No resources have been allocated, but "empty" the 'oldbuf' + */ + oldbuf[0] = 0; + break; + } + return SNMP_ERR_NOERROR; +} /* end of writeSystem */ + + /********************* + * + * Internal implementation functions - None + * + *********************/ + +#if (defined (WIN32) && defined (HAVE_WIN32_PLATFORM_SDK)) || defined (mingw32) +static void +windowsOSVersionString(char stringbuf[], size_t stringbuflen) +{ + /* copy OS version to string buffer in 'uname -a' format */ + OSVERSIONINFOEX osVersionInfo; + BOOL gotOsVersionInfoEx; + char windowsVersion[256] = ""; + char hostname[256] = ""; + char identifier[256] = ""; + DWORD identifierSz = 256; + HKEY hKey; + + ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX)); + osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + gotOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osVersionInfo); + if (gotOsVersionInfoEx == FALSE) { + GetVersionEx((OSVERSIONINFO *)&osVersionInfo); + } + + switch (osVersionInfo.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + if ((osVersionInfo.dwMajorVersion == 5) && (osVersionInfo.dwMinorVersion == 2)) { + strcat(windowsVersion, "Server 2003"); + } else if ((osVersionInfo.dwMajorVersion == 5) && (osVersionInfo.dwMinorVersion == 1)) { + strcat(windowsVersion, "XP"); + } else if ((osVersionInfo.dwMajorVersion == 5) && (osVersionInfo.dwMinorVersion == 0)) { + strcat(windowsVersion, "2000"); + } else if (osVersionInfo.dwMajorVersion <= 4) { + strcat(windowsVersion, "NT"); + } + if (gotOsVersionInfoEx == TRUE) { + if (osVersionInfo.wProductType == VER_NT_WORKSTATION) { + if (osVersionInfo.dwMajorVersion == 4) { + strcat(windowsVersion, " Workstation 4.0"); + } else if (osVersionInfo.wSuiteMask & VER_SUITE_PERSONAL) { + strcat(windowsVersion, " Home Edition"); + } else { + strcat(windowsVersion, " Professional"); + } + } else if (osVersionInfo.wProductType == VER_NT_SERVER) { + if ((osVersionInfo.dwMajorVersion == 5) && (osVersionInfo.dwMinorVersion == 2)) { + if (osVersionInfo.wSuiteMask & VER_SUITE_DATACENTER) { + strcat(windowsVersion, " Datacenter Edition"); + } else if (osVersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE) { + strcat(windowsVersion, " Enterprise Edition"); + } else if (osVersionInfo.wSuiteMask == VER_SUITE_BLADE) { + strcat(windowsVersion, " Web Edition"); + } else { + strcat(windowsVersion, " Standard Edition"); + } + } else if ((osVersionInfo.dwMajorVersion == 5) && (osVersionInfo.dwMinorVersion == 0)) { + if (osVersionInfo.wSuiteMask & VER_SUITE_DATACENTER) { + strcat(windowsVersion, " Datacenter Server"); + } else if (osVersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE) { + strcat(windowsVersion, " Advanced Server"); + } else { + strcat(windowsVersion, " Server"); + } + } else { + if (osVersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE) { + strcat(windowsVersion, " Server 4.0, Enterprise Edition"); + } else { + strcat(windowsVersion, " Server 4.0"); + } + } + } + } else { + char productType[80]; + DWORD productTypeSz = 80; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueEx(hKey, "ProductType", NULL, NULL, (LPBYTE) productType, &productTypeSz) == ERROR_SUCCESS) { + char versionStr[10]; + if (strcmpi("WINNT", productType) == 0) { + strcat(windowsVersion, " Workstation"); + } else if (strcmpi("LANMANNT", productType) == 0) { + strcat(windowsVersion, " Server"); + } else if (strcmpi("SERVERNT", productType) == 0) { + strcat(windowsVersion, " Advanced Server"); + } + sprintf(versionStr, " %d.%d", (int)osVersionInfo.dwMajorVersion, (int)osVersionInfo.dwMinorVersion); + strcat(windowsVersion, versionStr); + } + RegCloseKey(hKey); + } + } + break; + case VER_PLATFORM_WIN32_WINDOWS: + if ((osVersionInfo.dwMajorVersion == 4) && (osVersionInfo.dwMinorVersion == 90)) { + strcat(windowsVersion, "ME"); + } else if ((osVersionInfo.dwMajorVersion == 4) && (osVersionInfo.dwMinorVersion == 10)) { + strcat(windowsVersion, "98"); + if (osVersionInfo.szCSDVersion[1] == 'A') { + strcat(windowsVersion, " SE"); + } + } else if ((osVersionInfo.dwMajorVersion == 4) && (osVersionInfo.dwMinorVersion == 0)) { + strcat(windowsVersion, "95"); + if ((osVersionInfo.szCSDVersion[1] == 'C') || (osVersionInfo.szCSDVersion[1] == 'B')) { + strcat(windowsVersion, " OSR2"); + } + } + break; + } + + gethostname(hostname, sizeof(hostname)); + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { + RegQueryValueEx(hKey, "Identifier", NULL, NULL, (LPBYTE)&identifier, &identifierSz); + RegCloseKey(hKey); + } + + /* Output is made to look like results from uname -a */ + snprintf(stringbuf, stringbuflen, + "Windows %s %d.%d.%d %s %s %s", hostname, + (int)osVersionInfo.dwMajorVersion, (int)osVersionInfo.dwMinorVersion, + (int)osVersionInfo.dwBuildNumber, osVersionInfo.szCSDVersion, + windowsVersion, identifier); +} +#endif /* WIN32 and HAVE_WIN32_PLATFORM_SDK or mingw32 */ + |