diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/agent/mibgroup/host/data_access/swinst.c APPLE/agent/mibgroup/host/data_access/swinst.c
--- SVN/agent/mibgroup/host/data_access/swinst.c
+++ APPLE/agent/mibgroup/host/data_access/swinst.c
@@ -0,0 +1,211 @@
+/*
+ * swinst.c : hrSWInstalledTable data access
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/data_access/swinst.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* ---------------------------------------------------------------------
+ */
+
+static void netsnmp_swinst_entry_free_cb(netsnmp_swinst_entry *, void *);
+
+extern void netsnmp_swinst_arch_init(void);
+extern void netsnmp_swinst_arch_shutdown(void);
+extern int netsnmp_swinst_arch_load(netsnmp_container *, u_int);
+
+void init_swinst( void )
+{
+ static int initialized = 0;
+
+ DEBUGMSGTL(("swinst", "init called\n"));
+
+ if (initialized)
+ return; /* already initialized */
+
+
+ /*
+ * call arch init code
+ */
+ netsnmp_swinst_arch_init();
+}
+
+void shutdown_swinst( void )
+{
+ DEBUGMSGTL(("swinst", "shutdown called\n"));
+
+ netsnmp_swinst_arch_shutdown();
+}
+
+/* ---------------------------------------------------------------------
+ */
+
+/*
+ * load a container with installed software. If user_container is NULL,
+ * a new container will be allocated and returned, and the caller
+ * is responsible for releasing the allocated memory when done.
+ *
+ * if flags contains NETSNMP_SWINST_ALL_OR_NONE and any error occurs,
+ * the container will be completely cleared.
+ */
+netsnmp_container *
+netsnmp_swinst_container_load( netsnmp_container *user_container, int flags )
+{
+ netsnmp_container *container = user_container;
+ int arch_rc;
+
+ DEBUGMSGTL(("swinst:container", "load\n"));
+
+ /*
+ * create the container, if needed
+ */
+ if (NULL == container) {
+ container = netsnmp_container_find("swinst:table_container");
+ if (NULL == container)
+ return NULL;
+ }
+ if (NULL == container->container_name)
+ container->container_name = strdup("swinst container");
+
+ /*
+ * call the arch specific code to load the container
+ */
+ arch_rc = netsnmp_swinst_arch_load( container, flags );
+ if (arch_rc && (flags & NETSNMP_SWINST_ALL_OR_NONE)) {
+ /*
+ * caller does not want a partial load, so empty the container.
+ * if we created the container, destroy it.
+ */
+ netsnmp_swinst_container_free_items(container);
+ if (container != user_container) {
+ netsnmp_swinst_container_free(container, flags);
+ }
+ }
+
+ return container;
+}
+
+void
+netsnmp_swinst_container_free(netsnmp_container *container, u_int free_flags)
+{
+ DEBUGMSGTL(("swinst:container", "free\n"));
+
+ if (NULL == container) {
+ snmp_log(LOG_ERR,
+ "invalid container for netsnmp_swinst_container_free\n");
+ return;
+ }
+
+ if(! (free_flags & NETSNMP_SWINST_DONT_FREE_ITEMS))
+ netsnmp_swinst_container_free_items(container);
+
+ CONTAINER_FREE(container);
+}
+
+/*
+ * free a swinst container
+ */
+void netsnmp_swinst_container_free_items(netsnmp_container *container)
+{
+ DEBUGMSGTL(("swinst:container", "free_items\n"));
+
+ if (NULL == container) {
+ snmp_log(LOG_ERR,
+ "invalid container for netsnmp_swinst_container_free_items\n");
+ return;
+ }
+
+ /*
+ * free all items.
+ */
+ CONTAINER_CLEAR(container,
+ (netsnmp_container_obj_func*)netsnmp_swinst_entry_free_cb,
+ NULL);
+}
+
+
+/* ---------------------------------------------------------------------
+ */
+
+/*
+ * create a new row in the table
+ */
+netsnmp_swinst_entry *
+netsnmp_swinst_entry_create(int32_t swIndex)
+{
+ netsnmp_swinst_entry *entry;
+
+ entry = SNMP_MALLOC_TYPEDEF(netsnmp_swinst_entry);
+ if (!entry)
+ return NULL;
+
+ entry->swIndex = swIndex;
+ entry->oid_index.len = 1;
+ entry->oid_index.oids = &entry->swIndex;
+
+ entry->swType = HRSWINSTALLEDTYPE_APPLICATION;
+
+ return entry;
+}
+
+/*
+ * free a row
+ */
+void
+netsnmp_swinst_entry_free(netsnmp_swinst_entry *entry)
+{
+ DEBUGMSGTL(("swinst:entry:free", "index %d\n",entry->swIndex));
+
+ free(entry);
+}
+
+/*
+ * free a row
+ */
+static void
+netsnmp_swinst_entry_free_cb(netsnmp_swinst_entry *entry, void *context)
+{
+ free(entry);
+}
+
+/*
+ * remove a row from the table
+ */
+void
+netsnmp_swinst_entry_remove(netsnmp_container * container,
+ netsnmp_swinst_entry *entry)
+{
+ DEBUGMSGTL(("swinst:container", "remove\n"));
+ if (!entry)
+ return; /* Nothing to remove */
+ CONTAINER_REMOVE(container, entry);
+}
+
+/* ---------------------------------------------------------------------
+ */
+
+#ifdef TEST
+int main(int argc, char *argv[])
+{
+ const char *tokens = getenv("SNMP_DEBUG");
+
+ netsnmp_container_init_list();
+
+ /** swinst,verbose:swinst */
+ if (tokens)
+ debug_register_tokens(tokens);
+ else
+ debug_register_tokens("swinst");
+ snmp_set_do_debugging(1);
+
+ init_swinst();
+ netsnmp_swinst_container_load(NULL, 0);
+ shutdown_swinst();
+
+ return 0;
+}
+#endif
diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/agent/mibgroup/host/data_access/swinst.h APPLE/agent/mibgroup/host/data_access/swinst.h
--- SVN/agent/mibgroup/host/data_access/swinst.h
+++ APPLE/agent/mibgroup/host/data_access/swinst.h
@@ -0,0 +1,46 @@
+/*
+ * swinst data access header
+ *
+ * $Id: swinst.patch,v 1.3 2007/08/16 22:09:13 randall Exp $
+ */
+#ifndef NETSNMP_ACCESS_SWINST_CONFIG_H
+#define NETSNMP_ACCESS_SWINST_CONFIG_H
+
+/*
+ * all platforms use this generic code
+ */
+config_require(host/data_access/swinst)
+
+/**---------------------------------------------------------------------*/
+/*
+ * configure required files
+ *
+ * Notes:
+ *
+ * 1) prefer functionality over platform, where possible. If a method
+ * is available for multiple platforms, test that first. That way
+ * when a new platform is ported, it won't need a new test here.
+ *
+ * 2) don't do detail requirements here. If, for example,
+ * HPUX11 had different reuirements than other HPUX, that should
+ * be handled in the *_hpux.h header file.
+ */
+
+#ifdef NETSNMP_INCLUDE_HRSWINST_REWRITES
+
+config_exclude(host/hr_swinst)
+
+# if defined( darwin )
+
+ config_require(host/data_access/swinst_darwin)
+
+# else
+
+ config_error(This platform does not yet support hrSWInstalledTable rewrites)
+
+# endif
+#else
+# define NETSNMP_ACCESS_SWINST_NOARCH 1
+#endif
+
+#endif /* NETSNMP_ACCESS_SWINST_CONFIG_H */
diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/agent/mibgroup/host/data_access/swinst_darwin.c APPLE/agent/mibgroup/host/data_access/swinst_darwin.c
--- SVN/agent/mibgroup/host/data_access/swinst_darwin.c
+++ APPLE/agent/mibgroup/host/data_access/swinst_darwin.c
@@ -0,0 +1,385 @@
+/*
+ * swinst.c : hrSWInstalledTable data access
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/library/container.h>
+#include <net-snmp/library/dir_utils.h>
+#include <net-snmp/library/snmp_debug.h>
+#include <net-snmp/data_access/swinst.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#define __APPLE_API_EVOLVING 1
+#include <sys/acl.h> /* or else CoreFoundation.h barfs */
+#undef __APPLE_API_EVOLVING
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+/* ---------------------------------------------------------------------
+ */
+static int _add_applications_in_dir(netsnmp_container *, const char* path);
+static int32_t _index;
+static int _check_bundled_app(CFURLRef currentURL, CFStringRef *name,
+ CFStringRef *info, const char* path);
+static int _check_classic_app(CFURLRef currentURL, CFStringRef *name,
+ CFStringRef *info, const char* path);
+static netsnmp_container *dirs = NULL;
+
+/* ---------------------------------------------------------------------
+ */
+void
+netsnmp_swinst_arch_init( void )
+{
+ struct stat stat_buf;
+ const char *default_dirs[] = {
+ "/Applications",
+ "/Applications (Mac OS 9)",
+ "/System/Library/CoreServices",
+ "/System/Library/Extensions",
+ "/System/Library/Services"
+#ifdef TEST
+ , "/Developer/Applications"
+ , "/Volumes/audX/Applications (Mac OS 9)"
+#endif
+ };
+ int i, count = sizeof(default_dirs)/sizeof(default_dirs[0]);
+
+ /*
+ * create the container, if needed
+ */
+ if (NULL == dirs) {
+ dirs = netsnmp_container_find("directory_container:cstring");
+ if (NULL == dirs) {
+ snmp_log(LOG_ERR, "couldn't allocate container for dir list\n");
+ return;
+ }
+ dirs->container_name = strdup("directory search list");
+ netsnmp_binary_array_options_set(dirs, 1, CONTAINER_KEY_UNSORTED);
+ }
+
+ /*
+ * add dirs
+ */
+ for(i = 0; i < count; ++i) {
+ char * tmp;
+ /** xxx: get/save the last mod date? */
+ if(-1 == stat(default_dirs[i], &stat_buf)) {
+ DEBUGMSGTL(("swinst:arch:darwin", "skipping dir %s\n",
+ default_dirs[i]));
+ continue;
+ }
+ DEBUGMSGTL(("swinst:arch:darwin", "adding dir %s\n",
+ default_dirs[i]));
+ tmp = strdup(default_dirs[i]);
+ if (NULL == tmp) {
+ snmp_log(LOG_ERR,"strdup failed\n");
+ break;
+ }
+ CONTAINER_INSERT(dirs, tmp);
+ }
+}
+
+void
+netsnmp_swinst_arch_shutdown( void )
+{
+ netsnmp_directory_container_free(dirs);
+}
+
+/* ---------------------------------------------------------------------
+ */
+
+int
+netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags )
+{
+ netsnmp_iterator *it;
+ const char *dir;
+ int rc;
+
+ DEBUGMSGTL(("swinst:arch:darwin", "load\n"));
+
+ if (NULL == dirs) {
+ DEBUGMSGTL(("swinst:arch:darwin", "no dirs to scan!\n"));
+ return -1;
+ }
+
+ _index = 0;
+
+ it = CONTAINER_ITERATOR(dirs);
+ for (dir = ITERATOR_FIRST(it); dir; dir = ITERATOR_NEXT(it)) {
+ rc = _add_applications_in_dir(container, dir);
+ }
+ ITERATOR_RELEASE(it);
+ DEBUGMSGTL(("swinst:arch:darwin", "loaded %d apps\n",_index));
+
+ return 0;
+}
+
+void _dump_flags(u_long flags)
+{
+ static struct {
+ const char*name;
+ u_long bits;
+ } names[] = {
+ { "kLSItemInfoIsPlainFile", 0x00000001 },
+ { "kLSItemInfoIsPackage", 0x00000002 },
+ { "kLSItemInfoIsApplication", 0x00000004 },
+ { "kLSItemInfoIsContainer", 0x00000008 },
+ { "kLSItemInfoIsAliasFile", 0x00000010 },
+ { "kLSItemInfoIsSymlink", 0x00000020 },
+ { "kLSItemInfoIsInvisible", 0x00000040 },
+ { "kLSItemInfoIsNativeApp", 0x00000080 },
+ { "kLSItemInfoIsClassicApp", 0x00000100 },
+ { "kLSItemInfoAppPrefersNative", 0x00000200 },
+ { "kLSItemInfoAppPrefersClassic", 0x00000400 },
+ { "kLSItemInfoAppIsScriptable", 0x00000800 },
+ { "kLSItemInfoIsVolume", 0x00001000 },
+ { "kLSItemInfoExtensionIsHidden", 0x00100000 }
+ };
+ int i, count = sizeof(names)/sizeof(names[0]);
+
+ for(i = 0; i < count; ++i) {
+ if (flags & names[i].bits) {
+ DEBUGMSGTL(("swinst:arch:darwin:flags", "\t%s\n",
+ names[i].name));
+ }
+ }
+}
+
+static int
+_add_applications_in_dir(netsnmp_container *container, const char* path)
+{
+ netsnmp_container *files;
+ netsnmp_iterator *it;
+ const char *file;
+ netsnmp_swinst_entry *entry = NULL;
+ struct stat stat_buf;
+ size_t date_len;
+ u_char *date_buf;
+ int rc = 0;
+
+ CFStringRef currentPath = NULL;
+ CFURLRef currentURL = NULL;
+ LSItemInfoRecord itemInfoRecord;
+ CFStringRef prodName = NULL;
+ CFStringRef version = NULL;
+
+ DEBUGMSGTL(("swinst:arch:darwin", " adding files from %s\n", path));
+ files = netsnmp_directory_container_read(NULL, path, 0);
+ if (NULL == files) {
+ snmp_log(LOG_ERR, "swinst: could not read directory %s\n", path);
+ return -1;
+ }
+
+ it = CONTAINER_ITERATOR(files);
+ if (NULL == it) {
+ snmp_log(LOG_ERR, "could not get iterator\n");
+ netsnmp_directory_container_free(files);
+ return -1;
+ }
+ for (file = ITERATOR_FIRST(it);
+ file;
+ file = ITERATOR_NEXT(it),
+ CFRelease(currentPath),
+ CFRelease(currentURL)) {
+
+ int rc2 = 0;
+
+ currentPath =
+ CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, file,
+ kCFStringEncodingUTF8,
+ kCFAllocatorNull);
+ currentURL =
+ CFURLCreateWithFileSystemPath(kCFAllocatorDefault, currentPath,
+ kCFURLPOSIXPathStyle, true);
+ LSCopyItemInfoForURL(currentURL,
+ kLSRequestBasicFlagsOnly|kLSRequestAppTypeFlags,
+ &itemInfoRecord);
+ if((0 == itemInfoRecord.flags) ||
+ (kLSItemInfoIsPlainFile == itemInfoRecord.flags) ||
+ (itemInfoRecord.flags & kLSItemInfoIsInvisible) ||
+ (itemInfoRecord.flags & kLSItemInfoIsAliasFile)) {
+ continue;
+ }
+ /** recurse on non-application containers (i.e. directory) */
+ if ((itemInfoRecord.flags & kLSItemInfoIsContainer) &&
+ (!(itemInfoRecord.flags & kLSItemInfoIsApplication))) {
+ netsnmp_directory_container_read(files, file, 0);
+ continue;
+ }
+
+ /** skip any other non-application files */
+ if (!(itemInfoRecord.flags & kLSItemInfoIsApplication)) {
+ continue;
+ }
+
+ if ((itemInfoRecord.flags & kLSItemInfoIsPackage) ||
+ (itemInfoRecord.flags & kLSItemInfoIsContainer)) {
+ rc2 = _check_bundled_app(currentURL, &prodName, &version, file);
+ }
+ else if ((itemInfoRecord.flags & kLSItemInfoIsClassicApp) ||
+ (itemInfoRecord.flags & kLSItemInfoIsPlainFile)) {
+ rc2 = _check_classic_app(currentURL, &prodName, &version, file);
+ } else {
+ snmp_log(LOG_ERR,"swinst shouldn't get here: %s\n", file);
+ _dump_flags(itemInfoRecord.flags);
+ continue;
+ }
+ if (rc2) { /* not an app. if directory, recurse; else continue */
+ _dump_flags(itemInfoRecord.flags);
+ if (1 == rc2)
+ netsnmp_directory_container_read(files, file, 0);
+ continue;
+ }
+
+ /*
+ * allocate entry
+ */
+ entry = netsnmp_swinst_entry_create(++_index);
+ if (NULL == entry) {
+ snmp_log(LOG_ERR, "error creating swinst entry\n");
+ rc = -1;
+ SNMP_CFRelease(prodName);
+ SNMP_CFRelease(version);
+ break;
+ }
+
+ entry->swName_len =
+ snprintf(entry->swName, sizeof(entry->swName),
+ "%s %s", CFStringGetCStringPtr(prodName,0),
+ CFStringGetCStringPtr(version,0));
+
+ DEBUGMSGTL(("swinst:arch:darwin", "\t%s %s\n", file, entry->swName));
+
+ /** get the last mod date */
+ if(stat(file, &stat_buf) != -1) {
+ date_buf = date_n_time(&stat_buf.st_mtime, &date_len);
+ entry->swDate_len = date_len;
+ memcpy(entry->swDate, date_buf, entry->swDate_len);
+ }
+
+ CONTAINER_INSERT(container, entry);
+ entry = NULL;
+ SNMP_CFRelease(prodName);
+ SNMP_CFRelease(version);
+ }
+ ITERATOR_RELEASE(it);
+ netsnmp_directory_container_free(files);
+
+ return rc;
+}
+
+int
+_check_bundled_app(CFURLRef currentURL, CFStringRef *prodName,
+ CFStringRef *version, const char* file)
+{
+ CFBundleRef theBundle = NULL;
+ CFDictionaryRef infoDict = NULL;
+
+ if ((NULL == prodName) || (NULL == version))
+ return -1;
+
+ theBundle = CFBundleCreate (kCFAllocatorDefault, currentURL);
+ if(theBundle == NULL)
+ return -1; /* not a bundle */
+
+ infoDict = CFBundleGetInfoDictionary(theBundle);
+ if(0 == CFDictionaryGetCount(infoDict)) {
+ SNMP_CFRelease(theBundle);
+ return 1; /* directory */
+ }
+
+ *prodName = (CFStringRef)
+ CFDictionaryGetValue (infoDict, CFSTR("CFBundleName"));
+ if (NULL == *prodName) {
+ *prodName = (CFStringRef)
+ CFDictionaryGetValue (infoDict, CFSTR("CFBundleDisplayName"));
+ if (NULL == *prodName) {
+ *prodName = (CFStringRef) CFDictionaryGetValue (infoDict,
+ CFSTR("CFBundleExecutable"));
+ }
+ }
+ if(NULL == *prodName) {
+ DEBUGMSGTL(("swinst:arch:darwin", "\tmissing name: %s\n",file));
+ /*CFShow(infoDict);*/
+ SNMP_CFRelease(theBundle);
+ return -1;
+ }
+
+ *version = (CFStringRef)
+ CFDictionaryGetValue (infoDict, CFSTR("CFBundleShortVersionString"));
+ if(NULL == *version) {
+ *version = (CFStringRef)
+ CFDictionaryGetValue (infoDict, CFSTR("CFBundleVersion"));
+ if (*version == NULL)
+ *version = (CFStringRef) CFDictionaryGetValue (infoDict,
+ CFSTR("CFBundleGetInfoString"));
+ }
+ if(NULL == *version) {
+ DEBUGMSGTL(("swinst:arch:darwin", "\tmissing version: %s\n",file));
+ /*CFShow(infoDict);*/
+ SNMP_CFRelease(theBundle);
+ return -1;
+ }
+
+ if(theBundle != NULL) {
+ CFRetain(*prodName);
+ CFRetain(*version);
+ SNMP_CFRelease(theBundle);
+ }
+ return 0;
+}
+
+static int
+_check_classic_app(CFURLRef currentURL, CFStringRef *prodName,
+ CFStringRef *version, const char* file)
+{
+ /*
+ * get info for classic or single-file apps
+ */
+ FSRef theFSRef;
+ int theResFile;
+
+ if ((NULL == prodName) || (NULL == version))
+ return -1;
+
+ *prodName = CFURLCopyLastPathComponent(currentURL);
+ if (! CFURLGetFSRef(currentURL, &theFSRef)) {
+ DEBUGMSGTL(("swinst:arch:darwin", "GetFSRef failed: %s\n", file));
+ SNMP_CFRelease(*prodName);
+ return -1;
+ }
+ theResFile = FSOpenResFile(&theFSRef, fsRdPerm);
+ if (ResError() != noErr) {
+ DEBUGMSGTL(("swinst:arch:darwin", "FSOpenResFile failed: %s\n", file));
+ SNMP_CFRelease(*prodName);
+ return -1;
+ }
+ VersRecHndl versHandle = (VersRecHndl)Get1IndResource('vers', 1);
+ if (versHandle != NULL) {
+ *version = CFStringCreateWithPascalString(kCFAllocatorDefault,
+ (**versHandle).shortVersion, kCFStringEncodingMacRoman);
+ if (*version == NULL) {
+ StringPtr longVersionPtr = (**versHandle).shortVersion;
+ longVersionPtr = (StringPtr)(((Ptr) longVersionPtr) +
+ 1 + ((unsigned char) *longVersionPtr));
+ *version = CFStringCreateWithPascalString(kCFAllocatorDefault,
+ longVersionPtr, kCFStringEncodingMacRoman);
+ }
+ ReleaseResource((Handle)versHandle);
+ }
+ CloseResFile(theResFile);
+ if(*version == NULL) {
+ DEBUGMSGTL(("swinst:arch:darwin",
+ "\tmissing classic/file version: %s\n", file));
+ SNMP_CFRelease(*prodName);
+ return -1;
+ }
+
+ return 0;
+}
diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/agent/mibgroup/host/hrSWInstalledTable.c APPLE/agent/mibgroup/host/hrSWInstalledTable.c
--- SVN/agent/mibgroup/host/hrSWInstalledTable.c
+++ APPLE/agent/mibgroup/host/hrSWInstalledTable.c
@@ -0,0 +1,261 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.container.conf,v 1.8 2006/07/26 15:58:26 dts12 Exp $
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/table_container.h>
+#include <net-snmp/data_access/swinst.h>
+#include <net-snmp/agent/cache_handler.h>
+#include "hrSWInstalledTable.h"
+
+#define MYTABLE "hrSWInstalledTable"
+
+static void _cache_free(netsnmp_cache * cache, void *magic);
+static int _cache_load(netsnmp_cache * cache, void *magic);
+
+/** Initializes the hrSWInstalledTable module */
+void
+init_hrSWInstalledTable(void)
+{
+ /*
+ * here we initialize all the tables we're planning on supporting
+ */
+ initialize_table_hrSWInstalledTable();
+}
+
+/** Initialize the hrSWInstalledTable table by defining its contents and how it's structured */
+void
+initialize_table_hrSWInstalledTable(void)
+{
+ static oid hrSWInstalledTable_oid[] =
+ { 1, 3, 6, 1, 2, 1, 25, 6, 3 };
+ size_t hrSWInstalledTable_oid_len =
+ OID_LENGTH(hrSWInstalledTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_mib_handler *handler;
+ netsnmp_container *container;
+ netsnmp_cache *cache;
+ netsnmp_table_registration_info *table_info;
+
+ DEBUGMSGTL(("hrSWInstalled", "initialize\n"));
+
+ reg =
+ netsnmp_create_handler_registration("hrSWInstalledTable",
+ hrSWInstalledTable_handler,
+ hrSWInstalledTable_oid,
+ hrSWInstalledTable_oid_len,
+ HANDLER_CAN_RONLY);
+ if (NULL == reg) {
+ snmp_log(LOG_ERR,"error creating handler registration for "
+ MYTABLE "\n");
+ goto bail;
+ }
+
+ container = netsnmp_container_find("hrSWInstalledTable:table_container");
+ if (NULL == container) {
+ snmp_log(LOG_ERR,"error creating container for "
+ MYTABLE "\n");
+ goto bail;
+ }
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ if (NULL == table_info) {
+ snmp_log(LOG_ERR,"error allocating table registration for "
+ MYTABLE "\n");
+ goto bail;
+ }
+
+ netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: hrSWInstalledIndex */
+ 0);
+ table_info->min_column = COLUMN_HRSWINSTALLEDINDEX;
+ table_info->max_column = COLUMN_HRSWINSTALLEDDATE;
+
+ /*************************************************
+ *
+ * inject container_table helper
+ */
+ handler = netsnmp_container_table_handler_get(table_info, container,
+ TABLE_CONTAINER_KEY_NETSNMP_INDEX);
+ if (NULL == handler) {
+ snmp_log(LOG_ERR,"error allocating table registration for "
+ MYTABLE "\n");
+ goto bail;
+ }
+ if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
+ snmp_log(LOG_ERR,"error injecting container_table handler for "
+ MYTABLE "\n");
+ goto bail;
+ }
+ handler = NULL; /* reg has it, will reuse below */
+
+ /*************************************************
+ *
+ * inject cache helper
+ */
+ cache = netsnmp_cache_create(30, /* timeout in seconds */
+ _cache_load, _cache_free,
+ hrSWInstalledTable_oid,
+ hrSWInstalledTable_oid_len);
+
+ if (NULL == cache) {
+ snmp_log(LOG_ERR, "error creating cache for "
+ MYTABLE "\n");
+ goto bail;
+ }
+ cache->magic = container;
+
+ handler = netsnmp_cache_handler_get(cache);
+ if (NULL == handler) {
+ snmp_log(LOG_ERR, "error creating cache handler for "
+ MYTABLE "\n");
+ goto bail;
+ }
+ if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
+ snmp_log(LOG_ERR,"error injecting cache handler for "
+ MYTABLE "\n");
+ goto bail;
+ }
+ handler = NULL; /* reg has it*/
+
+ if (SNMPERR_SUCCESS != netsnmp_register_table(reg, table_info)) {
+ snmp_log(LOG_ERR,"error registering table handler for "
+ MYTABLE "\n");
+ goto bail;
+ }
+
+ return; /* ok */
+
+
+ bail: /* not ok */
+
+ if (handler)
+ netsnmp_handler_free(handler);
+
+ if (cache)
+ netsnmp_cache_free(cache);
+
+ if (table_info)
+ netsnmp_table_registration_info_free(table_info);
+
+ if (container)
+ CONTAINER_FREE(container);
+
+ if (reg)
+ netsnmp_handler_registration_free(reg);
+
+}
+
+/** handles requests for the hrSWInstalledTable table */
+int
+hrSWInstalledTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *table_info;
+ netsnmp_swinst_entry *table_entry;
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+ table_entry = (netsnmp_swinst_entry *)
+ netsnmp_container_table_extract_context(request);
+ table_info = netsnmp_extract_table_info(request);
+ if ((NULL == table_entry) || (NULL == table_info)) {
+ snmp_log(LOG_ERR, "could not extract table entry or info for "
+ MYTABLE "\n");
+ snmp_set_var_typed_value(request->requestvb,
+ SNMP_ERR_GENERR, NULL, 0);
+ continue;
+ }
+
+ switch (table_info->colnum) {
+ case COLUMN_HRSWINSTALLEDINDEX:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ table_entry->swIndex);
+ break;
+ case COLUMN_HRSWINSTALLEDNAME: {
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) table_entry->swName,
+ table_entry->swName_len);
+ } break;
+ case COLUMN_HRSWINSTALLEDID:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) &nullOid, nullOidLen);
+ break;
+ case COLUMN_HRSWINSTALLEDTYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ table_entry->swType);
+ break;
+ case COLUMN_HRSWINSTALLEDDATE:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) table_entry->swDate,
+ table_entry->swDate_len);
+ break;
+ default:
+ /*
+ * An unsupported/unreadable column (if applicable)
+ */
+ snmp_set_var_typed_value(request->requestvb,
+ SNMP_NOSUCHOBJECT, NULL, 0);
+ }
+ }
+ break;
+
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+/***********************************************************************
+ *
+ * DATA ACCESS
+ *
+ * The data access mechanism here is rather simple: let newsnmp_swinst_*
+ * take care of it.
+ ***********************************************************************/
+/**
+ * @internal
+ */
+static int
+_cache_load(netsnmp_cache * cache, void *vmagic)
+{
+ DEBUGMSGTL(("hrSWInstalledTable:cache", "load\n"));
+
+ if ((NULL == cache) || (NULL == cache->magic)) {
+ snmp_log(LOG_ERR, "invalid cache for hrSWInstalledTable_cache_load\n");
+ return -1;
+ }
+
+ /** should only be called for an invalid or expired cache */
+ netsnmp_assert((0 == cache->valid) || (1 == cache->expired));
+
+ cache->magic =
+ netsnmp_swinst_container_load((netsnmp_container *) cache->magic, 0);
+
+ return 0;
+} /* _cache_load */
+
+/**
+ * @internal
+ */
+static void
+_cache_free(netsnmp_cache * cache, void *magic)
+{
+ if ((NULL == cache) || (NULL == cache->magic)) {
+ snmp_log(LOG_ERR, "invalid cache in hrSWInstalledTable_cache_free\n");
+ return;
+ }
+ DEBUGMSGTL(("hrSWInstalledTable:cache", "free\n"));
+
+ netsnmp_swinst_container_free_items((netsnmp_container *) cache->magic);
+} /* _cache_free */
diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/agent/mibgroup/host/hrSWInstalledTable.h APPLE/agent/mibgroup/host/hrSWInstalledTable.h
--- SVN/agent/mibgroup/host/hrSWInstalledTable.h
+++ APPLE/agent/mibgroup/host/hrSWInstalledTable.h
@@ -0,0 +1,25 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.container.conf,v 1.8 2006/07/26 15:58:26 dts12 Exp $
+ */
+#ifndef HRSWINSTALLEDTABLE_H
+#define HRSWINSTALLEDTABLE_H
+
+config_require(host/data_access/swinst)
+
+/*
+ * function declarations
+ */
+void init_hrSWInstalledTable(void);
+void initialize_table_hrSWInstalledTable(void);
+Netsnmp_Node_Handler hrSWInstalledTable_handler;
+
+/*
+ * column number definitions for table hrSWInstalledTable
+ */
+#define COLUMN_HRSWINSTALLEDINDEX 1
+#define COLUMN_HRSWINSTALLEDNAME 2
+#define COLUMN_HRSWINSTALLEDID 3
+#define COLUMN_HRSWINSTALLEDTYPE 4
+#define COLUMN_HRSWINSTALLEDDATE 5
+#endif /* HRSWINSTALLEDTABLE_H */
diff -I '\$Id: ' -u -r -b -w -p -d --new-file --exclude-from=/Users/rstory/.rcfiles/diff-ignore SVN/include/net-snmp/data_access/swinst.h APPLE/include/net-snmp/data_access/swinst.h
--- SVN/include/net-snmp/data_access/swinst.h
+++ APPLE/include/net-snmp/data_access/swinst.h
@@ -0,0 +1,67 @@
+#ifndef NETSNMP_SWINST_H
+#define NETSNMP_SWINST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /*
+ * Data structure for a swinst entry
+ */
+ typedef struct hrSWInstalledTable_entry {
+ netsnmp_index oid_index;
+
+ /*
+ * Index values; MIB type is int32, but we use oid so this
+ * structure can be used directly with a table_container.
+ */
+ oid swIndex;
+
+ /*
+ * Column values
+ */
+ char swName[64];
+ char swDate[11];
+#ifdef NETSNMP_HAVE_SWID
+ oid *swID;
+ u_char swID_len;
+#endif
+ u_char swType;
+ u_char swName_len;
+ u_char swDate_len;
+ } netsnmp_swinst_entry;
+
+#define HRSWINSTALLEDTYPE_UNKNOWN 1
+#define HRSWINSTALLEDTYPE_OPERATINGSYSTEM 2
+#define HRSWINSTALLEDTYPE_DEVICEDRIVER 3
+#define HRSWINSTALLEDTYPE_APPLICATION 4
+
+
+#define NETSNMP_SWINST_NOFLAGS 0x00000000
+
+#define NETSNMP_SWINST_ALL_OR_NONE 0x00000001
+#define NETSNMP_SWINST_DONT_FREE_ITEMS 0x00000002
+
+ netsnmp_container *
+ netsnmp_swinst_container_load(netsnmp_container *container, int flags );
+
+ void netsnmp_swinst_container_free(netsnmp_container *container,
+ u_int flags);
+ void netsnmp_swinst_container_free_items(netsnmp_container *container);
+
+ void netsnmp_swinst_entry_remove(netsnmp_container * container,
+ netsnmp_swinst_entry *entry);
+
+ netsnmp_swinst_entry * netsnmp_swinst_entry_create(int32_t index);
+ void netsnmp_swinst_entry_free(netsnmp_swinst_entry *entry);
+
+ int32_t netsnmp_swinst_add_name(const char *name);
+ int32_t netsnmp_swinst_get_id(const char *name);
+ const char * netsnmp_swinst_get_name(int32_t id);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* NETSNMP_SWINST_H */