summaryrefslogtreecommitdiff
path: root/agent/mibgroup/mibII/system_mib.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/mibII/system_mib.c')
-rw-r--r--agent/mibgroup/mibII/system_mib.c765
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, &registeredOwnerSz) == 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 */
+