1diff -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
2--- SVN/agent/mibgroup/host/data_access/swinst.c
3+++ APPLE/agent/mibgroup/host/data_access/swinst.c
4@@ -0,0 +1,211 @@
5+/*
6+ * swinst.c : hrSWInstalledTable data access
7+ */
8+#include <net-snmp/net-snmp-config.h>
9+#include <net-snmp/net-snmp-includes.h>
10+#include <net-snmp/agent/net-snmp-agent-includes.h>
11+#include <net-snmp/data_access/swinst.h>
12+
13+#include <stdlib.h>
14+#include <unistd.h>
15+
16+/* ---------------------------------------------------------------------
17+ */
18+
19+static void netsnmp_swinst_entry_free_cb(netsnmp_swinst_entry *, void *);
20+
21+extern void netsnmp_swinst_arch_init(void);
22+extern void netsnmp_swinst_arch_shutdown(void);
23+extern int netsnmp_swinst_arch_load(netsnmp_container *, u_int);
24+
25+void init_swinst( void )
26+{
27+    static int initialized = 0;
28+
29+    DEBUGMSGTL(("swinst", "init called\n"));
30+
31+    if (initialized)
32+        return; /* already initialized */
33+
34+
35+    /*
36+     * call arch init code
37+     */
38+    netsnmp_swinst_arch_init();
39+}
40+
41+void shutdown_swinst( void )
42+{
43+    DEBUGMSGTL(("swinst", "shutdown called\n"));
44+
45+    netsnmp_swinst_arch_shutdown();
46+}
47+
48+/* ---------------------------------------------------------------------
49+ */
50+
51+/*
52+ * load a container with installed software. If user_container is NULL,
53+ * a new container will be allocated and returned, and the caller
54+ * is responsible for releasing the allocated memory when done.
55+ *
56+ * if flags contains NETSNMP_SWINST_ALL_OR_NONE and any error occurs,
57+ * the container will be completely cleared.
58+ */
59+netsnmp_container *
60+netsnmp_swinst_container_load( netsnmp_container *user_container, int flags )
61+{
62+    netsnmp_container *container = user_container;
63+    int arch_rc;
64+
65+    DEBUGMSGTL(("swinst:container", "load\n"));
66+
67+    /*
68+     * create the container, if needed
69+     */
70+    if (NULL == container) {
71+        container = netsnmp_container_find("swinst:table_container");
72+        if (NULL == container)
73+            return NULL;
74+    }
75+    if (NULL == container->container_name)
76+        container->container_name = strdup("swinst container");
77+
78+    /*
79+     * call the arch specific code to load the container
80+     */
81+    arch_rc = netsnmp_swinst_arch_load( container, flags );
82+    if (arch_rc && (flags & NETSNMP_SWINST_ALL_OR_NONE)) {
83+        /*
84+         * caller does not want a partial load, so empty the container.
85+         * if we created the container, destroy it.
86+         */
87+        netsnmp_swinst_container_free_items(container);
88+        if (container != user_container) {
89+            netsnmp_swinst_container_free(container, flags);
90+        }
91+    }
92+    
93+    return container;
94+}
95+
96+void
97+netsnmp_swinst_container_free(netsnmp_container *container, u_int free_flags)
98+{
99+    DEBUGMSGTL(("swinst:container", "free\n"));
100+
101+    if (NULL == container) {
102+        snmp_log(LOG_ERR,
103+                 "invalid container for netsnmp_swinst_container_free\n");
104+        return;
105+    }
106+
107+    if(! (free_flags & NETSNMP_SWINST_DONT_FREE_ITEMS))
108+        netsnmp_swinst_container_free_items(container);
109+
110+    CONTAINER_FREE(container);
111+}
112+
113+/*
114+ * free a swinst container
115+ */
116+void netsnmp_swinst_container_free_items(netsnmp_container *container)
117+{
118+    DEBUGMSGTL(("swinst:container", "free_items\n"));
119+
120+    if (NULL == container) {
121+        snmp_log(LOG_ERR,
122+                 "invalid container for netsnmp_swinst_container_free_items\n");
123+        return;
124+    }
125+
126+    /*
127+     * free all items.
128+     */
129+    CONTAINER_CLEAR(container,
130+                    (netsnmp_container_obj_func*)netsnmp_swinst_entry_free_cb,
131+                    NULL);
132+}
133+
134+
135+/* ---------------------------------------------------------------------
136+ */
137+
138+/*
139+ * create a new row in the table 
140+ */
141+netsnmp_swinst_entry *
142+netsnmp_swinst_entry_create(int32_t swIndex)
143+{
144+    netsnmp_swinst_entry *entry;
145+
146+    entry = SNMP_MALLOC_TYPEDEF(netsnmp_swinst_entry);
147+    if (!entry)
148+        return NULL;
149+
150+    entry->swIndex = swIndex;
151+    entry->oid_index.len = 1;
152+    entry->oid_index.oids = &entry->swIndex;
153+
154+    entry->swType = HRSWINSTALLEDTYPE_APPLICATION;
155+
156+    return entry;
157+}
158+
159+/*
160+ * free a row
161+ */
162+void
163+netsnmp_swinst_entry_free(netsnmp_swinst_entry *entry)
164+{
165+    DEBUGMSGTL(("swinst:entry:free", "index %d\n",entry->swIndex));
166+
167+    free(entry);
168+}
169+
170+/*
171+ * free a row
172+ */
173+static void
174+netsnmp_swinst_entry_free_cb(netsnmp_swinst_entry *entry, void *context)
175+{
176+    free(entry);
177+}
178+
179+/*
180+ * remove a row from the table 
181+ */
182+void
183+netsnmp_swinst_entry_remove(netsnmp_container * container,
184+                            netsnmp_swinst_entry *entry)
185+{
186+    DEBUGMSGTL(("swinst:container", "remove\n"));
187+    if (!entry)
188+        return;                 /* Nothing to remove */
189+    CONTAINER_REMOVE(container, entry);
190+}
191+
192+/* ---------------------------------------------------------------------
193+ */
194+
195+#ifdef TEST
196+int main(int argc, char *argv[])
197+{
198+    const char *tokens = getenv("SNMP_DEBUG");
199+
200+    netsnmp_container_init_list();
201+
202+    /** swinst,verbose:swinst */
203+    if (tokens)
204+        debug_register_tokens(tokens);
205+    else
206+        debug_register_tokens("swinst");
207+    snmp_set_do_debugging(1);
208+
209+    init_swinst();
210+    netsnmp_swinst_container_load(NULL, 0);
211+    shutdown_swinst();
212+
213+    return 0;
214+}
215+#endif
216diff -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
217--- SVN/agent/mibgroup/host/data_access/swinst.h
218+++ APPLE/agent/mibgroup/host/data_access/swinst.h
219@@ -0,0 +1,46 @@
220+/*
221+ * swinst data access header
222+ *
223+ * $Id: swinst.patch,v 1.3 2007/08/16 22:09:13 randall Exp $
224+ */
225+#ifndef NETSNMP_ACCESS_SWINST_CONFIG_H
226+#define NETSNMP_ACCESS_SWINST_CONFIG_H
227+
228+/*
229+ * all platforms use this generic code
230+ */
231+config_require(host/data_access/swinst)
232+
233+/**---------------------------------------------------------------------*/
234+/*
235+ * configure required files
236+ *
237+ * Notes:
238+ *
239+ * 1) prefer functionality over platform, where possible. If a method
240+ *    is available for multiple platforms, test that first. That way
241+ *    when a new platform is ported, it won't need a new test here.
242+ *
243+ * 2) don't do detail requirements here. If, for example,
244+ *    HPUX11 had different reuirements than other HPUX, that should
245+ *    be handled in the *_hpux.h header file.
246+ */
247+
248+#ifdef NETSNMP_INCLUDE_HRSWINST_REWRITES
249+
250+config_exclude(host/hr_swinst)
251+
252+#   if defined( darwin )
253+
254+    config_require(host/data_access/swinst_darwin)
255+
256+#   else
257+
258+    config_error(This platform does not yet support hrSWInstalledTable rewrites)
259+
260+#   endif
261+#else
262+#   define NETSNMP_ACCESS_SWINST_NOARCH 1
263+#endif
264+
265+#endif /* NETSNMP_ACCESS_SWINST_CONFIG_H */
266diff -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
267--- SVN/agent/mibgroup/host/data_access/swinst_darwin.c
268+++ APPLE/agent/mibgroup/host/data_access/swinst_darwin.c
269@@ -0,0 +1,385 @@
270+/*
271+ * swinst.c : hrSWInstalledTable data access
272+ */
273+#include <net-snmp/net-snmp-config.h>
274+#include <net-snmp/net-snmp-includes.h>
275+#include <net-snmp/agent/net-snmp-agent-includes.h>
276+#include <net-snmp/library/container.h>
277+#include <net-snmp/library/dir_utils.h>
278+#include <net-snmp/library/snmp_debug.h>
279+#include <net-snmp/data_access/swinst.h>
280+
281+#include <stdlib.h>
282+#include <unistd.h>
283+#include <dirent.h>
284+#include <sys/stat.h>
285+
286+#define __APPLE_API_EVOLVING 1
287+#include <sys/acl.h> /* or else CoreFoundation.h barfs */
288+#undef __APPLE_API_EVOLVING 
289+
290+#include <CoreFoundation/CoreFoundation.h>
291+#include <ApplicationServices/ApplicationServices.h>
292+
293+/* ---------------------------------------------------------------------
294+ */
295+static int _add_applications_in_dir(netsnmp_container *, const char* path);
296+static int32_t _index;
297+static int _check_bundled_app(CFURLRef currentURL, CFStringRef *name,
298+                              CFStringRef *info, const char* path);
299+static int _check_classic_app(CFURLRef currentURL, CFStringRef *name,
300+                              CFStringRef *info, const char* path);
301+static netsnmp_container *dirs = NULL;
302+
303+/* ---------------------------------------------------------------------
304+ */
305+void
306+netsnmp_swinst_arch_init( void )
307+{
308+    struct stat stat_buf;
309+    const char *default_dirs[] = {
310+        "/Applications",
311+        "/Applications (Mac OS 9)",
312+        "/System/Library/CoreServices",
313+        "/System/Library/Extensions",
314+        "/System/Library/Services"
315+#ifdef TEST
316+        , "/Developer/Applications"
317+        , "/Volumes/audX/Applications (Mac OS 9)"
318+#endif
319+    };
320+    int i, count = sizeof(default_dirs)/sizeof(default_dirs[0]);
321+
322+    /*
323+     * create the container, if needed
324+     */
325+    if (NULL == dirs) {
326+        dirs = netsnmp_container_find("directory_container:cstring");
327+        if (NULL == dirs) {
328+            snmp_log(LOG_ERR, "couldn't allocate container for dir list\n");
329+            return;
330+        }
331+        dirs->container_name = strdup("directory search list");
332+        netsnmp_binary_array_options_set(dirs, 1, CONTAINER_KEY_UNSORTED);
333+    }
334+
335+    /*
336+     * add dirs
337+     */
338+    for(i = 0; i < count; ++i) {
339+        char *      tmp;
340+        /** xxx: get/save the last mod date? */
341+        if(-1 == stat(default_dirs[i], &stat_buf)) {
342+            DEBUGMSGTL(("swinst:arch:darwin", "skipping dir %s\n",
343+                        default_dirs[i]));
344+            continue;
345+        }
346+        DEBUGMSGTL(("swinst:arch:darwin", "adding dir %s\n",
347+                        default_dirs[i]));
348+        tmp = strdup(default_dirs[i]);
349+        if (NULL == tmp) {
350+            snmp_log(LOG_ERR,"strdup failed\n");
351+            break;
352+        }
353+        CONTAINER_INSERT(dirs, tmp);
354+    }
355+}
356+
357+void
358+netsnmp_swinst_arch_shutdown( void )
359+{
360+    netsnmp_directory_container_free(dirs);
361+}
362+
363+/* ---------------------------------------------------------------------
364+ */
365+
366+int
367+netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags )
368+{
369+    netsnmp_iterator   *it;
370+    const char         *dir;
371+    int                 rc;
372+
373+    DEBUGMSGTL(("swinst:arch:darwin", "load\n"));
374+
375+    if (NULL == dirs) {
376+        DEBUGMSGTL(("swinst:arch:darwin", "no dirs to scan!\n"));
377+        return -1;
378+    }
379+
380+    _index = 0;
381+    
382+    it = CONTAINER_ITERATOR(dirs);
383+    for (dir = ITERATOR_FIRST(it); dir; dir = ITERATOR_NEXT(it)) {
384+        rc = _add_applications_in_dir(container, dir);
385+    }
386+    ITERATOR_RELEASE(it);
387+    DEBUGMSGTL(("swinst:arch:darwin", "loaded %d apps\n",_index));
388+
389+    return 0;
390+}
391+
392+void  _dump_flags(u_long flags)
393+{
394+    static struct {
395+        const char*name;
396+        u_long bits;
397+    } names[] = {
398+        { "kLSItemInfoIsPlainFile", 0x00000001 },
399+        { "kLSItemInfoIsPackage", 0x00000002 },
400+        { "kLSItemInfoIsApplication", 0x00000004 },
401+        { "kLSItemInfoIsContainer", 0x00000008 },
402+        { "kLSItemInfoIsAliasFile", 0x00000010 },
403+        { "kLSItemInfoIsSymlink", 0x00000020 },
404+        { "kLSItemInfoIsInvisible", 0x00000040 },
405+        { "kLSItemInfoIsNativeApp", 0x00000080 },
406+        { "kLSItemInfoIsClassicApp", 0x00000100 },
407+        { "kLSItemInfoAppPrefersNative", 0x00000200 },
408+        { "kLSItemInfoAppPrefersClassic", 0x00000400 },
409+        { "kLSItemInfoAppIsScriptable", 0x00000800 },
410+        { "kLSItemInfoIsVolume", 0x00001000 },
411+        { "kLSItemInfoExtensionIsHidden", 0x00100000 }
412+    };
413+    int i, count = sizeof(names)/sizeof(names[0]);
414+
415+    for(i = 0; i < count; ++i) {
416+        if (flags & names[i].bits) {
417+            DEBUGMSGTL(("swinst:arch:darwin:flags", "\t%s\n",
418+                       names[i].name));
419+        }
420+    }
421+}
422+
423+static int
424+_add_applications_in_dir(netsnmp_container *container, const char* path)
425+{
426+    netsnmp_container  *files;
427+    netsnmp_iterator   *it;
428+    const char         *file;
429+    netsnmp_swinst_entry *entry = NULL;
430+    struct stat	        stat_buf;
431+    size_t              date_len;
432+    u_char             *date_buf;
433+    int                 rc = 0;
434+
435+    CFStringRef         currentPath = NULL;
436+    CFURLRef            currentURL = NULL;
437+    LSItemInfoRecord    itemInfoRecord;
438+    CFStringRef         prodName = NULL;
439+    CFStringRef         version = NULL;
440+    
441+    DEBUGMSGTL(("swinst:arch:darwin", " adding files from %s\n", path));
442+    files = netsnmp_directory_container_read(NULL, path, 0);
443+    if (NULL == files) {
444+        snmp_log(LOG_ERR, "swinst: could not read directory %s\n", path);
445+        return -1;
446+    }
447+
448+    it = CONTAINER_ITERATOR(files);
449+    if (NULL == it) {
450+        snmp_log(LOG_ERR, "could not get iterator\n");
451+        netsnmp_directory_container_free(files);
452+        return -1;
453+    }
454+    for (file = ITERATOR_FIRST(it);
455+         file;
456+         file = ITERATOR_NEXT(it),
457+             CFRelease(currentPath),
458+             CFRelease(currentURL)) {
459+
460+        int                 rc2 = 0;
461+        
462+        currentPath =
463+            CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, file,
464+                                            kCFStringEncodingUTF8,
465+                                            kCFAllocatorNull);
466+        currentURL =
467+            CFURLCreateWithFileSystemPath(kCFAllocatorDefault, currentPath,
468+                                          kCFURLPOSIXPathStyle, true); 
469+        LSCopyItemInfoForURL(currentURL,
470+                             kLSRequestBasicFlagsOnly|kLSRequestAppTypeFlags,
471+                             &itemInfoRecord); 
472+        if((0 == itemInfoRecord.flags) ||
473+           (kLSItemInfoIsPlainFile == itemInfoRecord.flags) ||
474+           (itemInfoRecord.flags & kLSItemInfoIsInvisible) ||
475+           (itemInfoRecord.flags & kLSItemInfoIsAliasFile)) {
476+            continue;
477+        }
478+        /** recurse on non-application containers (i.e. directory) */
479+        if ((itemInfoRecord.flags & kLSItemInfoIsContainer) &&
480+            (!(itemInfoRecord.flags & kLSItemInfoIsApplication))) {
481+            netsnmp_directory_container_read(files, file, 0);
482+            continue;
483+       }
484+
485+        /** skip any other non-application files */
486+        if (!(itemInfoRecord.flags & kLSItemInfoIsApplication)) {
487+            continue;
488+       }
489+
490+        if ((itemInfoRecord.flags & kLSItemInfoIsPackage) ||           
491+            (itemInfoRecord.flags & kLSItemInfoIsContainer)) {
492+            rc2 = _check_bundled_app(currentURL, &prodName, &version, file);
493+        } 
494+        else if ((itemInfoRecord.flags & kLSItemInfoIsClassicApp) ||
495+                 (itemInfoRecord.flags & kLSItemInfoIsPlainFile)) {
496+            rc2 = _check_classic_app(currentURL, &prodName, &version, file);
497+        } else {
498+            snmp_log(LOG_ERR,"swinst shouldn't get here: %s\n", file);
499+            _dump_flags(itemInfoRecord.flags);
500+            continue;
501+        }
502+        if (rc2) { /* not an app. if directory, recurse; else continue */
503+            _dump_flags(itemInfoRecord.flags);
504+            if (1 == rc2)
505+                netsnmp_directory_container_read(files, file, 0);
506+            continue;
507+        }
508+        
509+        /*
510+         * allocate entry
511+         */
512+        entry = netsnmp_swinst_entry_create(++_index);
513+        if (NULL == entry) {
514+            snmp_log(LOG_ERR, "error creating swinst entry\n");
515+            rc = -1;
516+            SNMP_CFRelease(prodName);
517+            SNMP_CFRelease(version);
518+            break;
519+        }
520+
521+        entry->swName_len =
522+            snprintf(entry->swName, sizeof(entry->swName),
523+                     "%s %s", CFStringGetCStringPtr(prodName,0),
524+                     CFStringGetCStringPtr(version,0));
525+
526+        DEBUGMSGTL(("swinst:arch:darwin", "\t%s %s\n", file, entry->swName));
527+
528+        /** get the last mod date */
529+        if(stat(file, &stat_buf) != -1) {
530+            date_buf = date_n_time(&stat_buf.st_mtime, &date_len);
531+            entry->swDate_len = date_len;
532+            memcpy(entry->swDate, date_buf, entry->swDate_len);
533+        }
534+        
535+        CONTAINER_INSERT(container, entry);
536+        entry = NULL;
537+        SNMP_CFRelease(prodName);
538+        SNMP_CFRelease(version);
539+    }
540+    ITERATOR_RELEASE(it);
541+    netsnmp_directory_container_free(files);
542+
543+    return rc;
544+}
545+
546+int
547+_check_bundled_app(CFURLRef currentURL, CFStringRef *prodName,
548+                   CFStringRef *version, const char* file)
549+{
550+    CFBundleRef         theBundle = NULL;
551+    CFDictionaryRef     infoDict = NULL;
552+            
553+    if ((NULL == prodName) || (NULL == version))
554+       return -1;
555+
556+    theBundle = CFBundleCreate (kCFAllocatorDefault, currentURL);
557+    if(theBundle == NULL)
558+        return -1; /* not a bundle */
559+
560+    infoDict = CFBundleGetInfoDictionary(theBundle);
561+    if(0 == CFDictionaryGetCount(infoDict)) {
562+        SNMP_CFRelease(theBundle);
563+        return 1; /* directory */
564+    }
565+
566+    *prodName = (CFStringRef)
567+        CFDictionaryGetValue (infoDict, CFSTR("CFBundleName"));
568+    if (NULL == *prodName) {
569+        *prodName = (CFStringRef)
570+            CFDictionaryGetValue (infoDict, CFSTR("CFBundleDisplayName"));
571+        if (NULL == *prodName) {
572+            *prodName = (CFStringRef) CFDictionaryGetValue (infoDict,
573+                                      CFSTR("CFBundleExecutable"));
574+        }
575+    }
576+    if(NULL == *prodName) {
577+        DEBUGMSGTL(("swinst:arch:darwin", "\tmissing name: %s\n",file));
578+        /*CFShow(infoDict);*/
579+        SNMP_CFRelease(theBundle);
580+        return -1;
581+    }
582+
583+    *version = (CFStringRef)
584+        CFDictionaryGetValue (infoDict, CFSTR("CFBundleShortVersionString"));
585+    if(NULL == *version) {
586+        *version = (CFStringRef)
587+            CFDictionaryGetValue (infoDict, CFSTR("CFBundleVersion"));
588+        if (*version == NULL) 
589+            *version = (CFStringRef) CFDictionaryGetValue (infoDict,
590+                                      CFSTR("CFBundleGetInfoString"));
591+    }
592+    if(NULL == *version) {
593+        DEBUGMSGTL(("swinst:arch:darwin", "\tmissing version: %s\n",file));
594+        /*CFShow(infoDict);*/
595+        SNMP_CFRelease(theBundle);
596+        return -1;
597+    }
598+    
599+    if(theBundle != NULL) {
600+        CFRetain(*prodName);
601+        CFRetain(*version);
602+        SNMP_CFRelease(theBundle);
603+    }
604+    return 0;
605+}
606+
607+static int
608+_check_classic_app(CFURLRef currentURL, CFStringRef *prodName,
609+                   CFStringRef *version, const char* file)
610+{
611+    /*
612+     * get info for classic or single-file apps
613+     */
614+    FSRef theFSRef;
615+    int theResFile;
616+
617+    if ((NULL == prodName) || (NULL == version))
618+       return -1;
619+
620+    *prodName = CFURLCopyLastPathComponent(currentURL);
621+    if (! CFURLGetFSRef(currentURL, &theFSRef)) {
622+        DEBUGMSGTL(("swinst:arch:darwin", "GetFSRef failed: %s\n", file));
623+        SNMP_CFRelease(*prodName);
624+        return -1;
625+    }
626+    theResFile = FSOpenResFile(&theFSRef, fsRdPerm);
627+    if (ResError() != noErr) {
628+        DEBUGMSGTL(("swinst:arch:darwin", "FSOpenResFile failed: %s\n", file));
629+        SNMP_CFRelease(*prodName);
630+        return -1;
631+    }
632+    VersRecHndl versHandle = (VersRecHndl)Get1IndResource('vers', 1);
633+    if (versHandle != NULL) {
634+        *version = CFStringCreateWithPascalString(kCFAllocatorDefault,
635+                       (**versHandle).shortVersion, kCFStringEncodingMacRoman);
636+        if (*version == NULL) {
637+            StringPtr longVersionPtr = (**versHandle).shortVersion;
638+            longVersionPtr = (StringPtr)(((Ptr) longVersionPtr) +
639+                              1 + ((unsigned char) *longVersionPtr));
640+            *version = CFStringCreateWithPascalString(kCFAllocatorDefault,
641+                          longVersionPtr,  kCFStringEncodingMacRoman);
642+        }
643+        ReleaseResource((Handle)versHandle);
644+    }
645+    CloseResFile(theResFile);
646+    if(*version == NULL) {
647+        DEBUGMSGTL(("swinst:arch:darwin",
648+                    "\tmissing classic/file version: %s\n", file));
649+        SNMP_CFRelease(*prodName);
650+        return -1;
651+    }
652+
653+    return 0;
654+}
655diff -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
656--- SVN/agent/mibgroup/host/hrSWInstalledTable.c
657+++ APPLE/agent/mibgroup/host/hrSWInstalledTable.c
658@@ -0,0 +1,261 @@
659+/*
660+ * Note: this file originally auto-generated by mib2c using
661+ *  : mib2c.container.conf,v 1.8 2006/07/26 15:58:26 dts12 Exp $
662+ */
663+
664+#include <net-snmp/net-snmp-config.h>
665+#include <net-snmp/net-snmp-includes.h>
666+#include <net-snmp/agent/net-snmp-agent-includes.h>
667+#include <net-snmp/agent/table_container.h>
668+#include <net-snmp/data_access/swinst.h>
669+#include <net-snmp/agent/cache_handler.h>
670+#include "hrSWInstalledTable.h"
671+
672+#define MYTABLE "hrSWInstalledTable"
673+
674+static void _cache_free(netsnmp_cache * cache, void *magic);
675+static int _cache_load(netsnmp_cache * cache, void *magic);
676+
677+/** Initializes the hrSWInstalledTable module */
678+void
679+init_hrSWInstalledTable(void)
680+{
681+    /*
682+     * here we initialize all the tables we're planning on supporting 
683+     */
684+    initialize_table_hrSWInstalledTable();
685+}
686+
687+/** Initialize the hrSWInstalledTable table by defining its contents and how it's structured */
688+void
689+initialize_table_hrSWInstalledTable(void)
690+{
691+    static oid      hrSWInstalledTable_oid[] =
692+        { 1, 3, 6, 1, 2, 1, 25, 6, 3 };
693+    size_t          hrSWInstalledTable_oid_len =
694+        OID_LENGTH(hrSWInstalledTable_oid);
695+    netsnmp_handler_registration *reg;
696+    netsnmp_mib_handler *handler;
697+    netsnmp_container *container;
698+    netsnmp_cache *cache;
699+    netsnmp_table_registration_info *table_info;
700+
701+    DEBUGMSGTL(("hrSWInstalled", "initialize\n"));
702+
703+    reg =
704+        netsnmp_create_handler_registration("hrSWInstalledTable",
705+                                            hrSWInstalledTable_handler,
706+                                            hrSWInstalledTable_oid,
707+                                            hrSWInstalledTable_oid_len,
708+                                            HANDLER_CAN_RONLY);
709+    if (NULL == reg) {
710+        snmp_log(LOG_ERR,"error creating handler registration for "
711+                 MYTABLE "\n");
712+        goto bail;
713+    }
714+
715+    container = netsnmp_container_find("hrSWInstalledTable:table_container");
716+    if (NULL == container) {
717+        snmp_log(LOG_ERR,"error creating container for "
718+                 MYTABLE "\n");
719+        goto bail;
720+    }
721+
722+    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
723+    if (NULL == table_info) {
724+        snmp_log(LOG_ERR,"error allocating table registration for "
725+                 MYTABLE "\n");
726+        goto bail;
727+    }
728+
729+    netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER,   /* index: hrSWInstalledIndex */
730+                                     0);
731+    table_info->min_column = COLUMN_HRSWINSTALLEDINDEX;
732+    table_info->max_column = COLUMN_HRSWINSTALLEDDATE;
733+
734+    /*************************************************
735+     *
736+     * inject container_table helper
737+     */
738+    handler = netsnmp_container_table_handler_get(table_info, container,
739+                                                  TABLE_CONTAINER_KEY_NETSNMP_INDEX);
740+    if (NULL == handler) {
741+        snmp_log(LOG_ERR,"error allocating table registration for "
742+                 MYTABLE "\n");
743+        goto bail;
744+    }
745+    if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
746+        snmp_log(LOG_ERR,"error injecting container_table handler for "
747+                 MYTABLE "\n");
748+        goto bail;
749+    }
750+    handler = NULL; /* reg has it, will reuse below */
751+
752+    /*************************************************
753+     *
754+     * inject cache helper
755+     */
756+    cache = netsnmp_cache_create(30,    /* timeout in seconds */
757+                                 _cache_load, _cache_free,
758+                                 hrSWInstalledTable_oid,
759+                                 hrSWInstalledTable_oid_len);
760+
761+    if (NULL == cache) {
762+        snmp_log(LOG_ERR, "error creating cache for "
763+                 MYTABLE "\n");
764+        goto bail;
765+    }
766+    cache->magic = container;
767+
768+    handler = netsnmp_cache_handler_get(cache);
769+    if (NULL == handler) {
770+        snmp_log(LOG_ERR, "error creating cache handler for "
771+                 MYTABLE "\n");
772+        goto bail;
773+    }
774+    if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
775+        snmp_log(LOG_ERR,"error injecting cache handler for "
776+                 MYTABLE "\n");
777+        goto bail;
778+    }
779+    handler = NULL; /* reg has it*/
780+
781+    if (SNMPERR_SUCCESS != netsnmp_register_table(reg, table_info)) {
782+        snmp_log(LOG_ERR,"error registering table handler for "
783+                 MYTABLE "\n");
784+        goto bail;
785+    }
786+
787+    return; /* ok */
788+
789+
790+  bail: /* not ok */
791+    
792+    if (handler)
793+        netsnmp_handler_free(handler);
794+
795+    if (cache)
796+        netsnmp_cache_free(cache);
797+
798+    if (table_info)
799+        netsnmp_table_registration_info_free(table_info);
800+
801+    if (container)
802+        CONTAINER_FREE(container);
803+
804+    if (reg) 
805+        netsnmp_handler_registration_free(reg);
806+
807+}
808+
809+/** handles requests for the hrSWInstalledTable table */
810+int
811+hrSWInstalledTable_handler(netsnmp_mib_handler *handler,
812+                           netsnmp_handler_registration *reginfo,
813+                           netsnmp_agent_request_info *reqinfo,
814+                           netsnmp_request_info *requests)
815+{
816+
817+    netsnmp_request_info *request;
818+    netsnmp_table_request_info *table_info;
819+    netsnmp_swinst_entry *table_entry;
820+
821+    switch (reqinfo->mode) {
822+        /*
823+         * Read-support (also covers GetNext requests)
824+         */
825+    case MODE_GET:
826+        for (request = requests; request; request = request->next) {
827+            if (request->processed)
828+               continue;
829+            table_entry = (netsnmp_swinst_entry *)
830+                netsnmp_container_table_extract_context(request);
831+            table_info = netsnmp_extract_table_info(request);
832+            if ((NULL == table_entry) || (NULL == table_info)) {
833+                snmp_log(LOG_ERR, "could not extract table entry or info for "
834+                 MYTABLE "\n");
835+                snmp_set_var_typed_value(request->requestvb,
836+                                         SNMP_ERR_GENERR, NULL, 0);
837+                continue;
838+            }
839+
840+            switch (table_info->colnum) {
841+            case COLUMN_HRSWINSTALLEDINDEX:
842+                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
843+                                           table_entry->swIndex);
844+                break;
845+            case COLUMN_HRSWINSTALLEDNAME: {
846+                snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
847+                                         (u_char *) table_entry->swName,
848+                                         table_entry->swName_len);
849+                } break;
850+            case COLUMN_HRSWINSTALLEDID:
851+                snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
852+                                         (u_char *) &nullOid, nullOidLen);
853+                break;
854+            case COLUMN_HRSWINSTALLEDTYPE:
855+                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
856+                                           table_entry->swType);
857+                break;
858+            case COLUMN_HRSWINSTALLEDDATE:
859+                snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
860+                                         (u_char *) table_entry->swDate, 
861+                                         table_entry->swDate_len);
862+                break;
863+            default:
864+                /*
865+                 * An unsupported/unreadable column (if applicable) 
866+                 */
867+                snmp_set_var_typed_value(request->requestvb,
868+                                         SNMP_NOSUCHOBJECT, NULL, 0);
869+            }
870+        }
871+        break;
872+
873+    }
874+    return SNMP_ERR_NOERROR;
875+}
876+
877+/***********************************************************************
878+ *
879+ * DATA ACCESS
880+ *
881+ * The data access mechanism here is rather simple: let newsnmp_swinst_*
882+ * take care of it.
883+ ***********************************************************************/
884+/**
885+ * @internal
886+ */
887+static int
888+_cache_load(netsnmp_cache * cache, void *vmagic)
889+{
890+    DEBUGMSGTL(("hrSWInstalledTable:cache", "load\n"));
891+
892+    if ((NULL == cache) || (NULL == cache->magic)) {
893+        snmp_log(LOG_ERR, "invalid cache for hrSWInstalledTable_cache_load\n");
894+        return -1;
895+    }
896+
897+    /** should only be called for an invalid or expired cache */
898+    netsnmp_assert((0 == cache->valid) || (1 == cache->expired));
899+
900+    cache->magic =
901+        netsnmp_swinst_container_load((netsnmp_container *) cache->magic, 0);
902+
903+    return 0;
904+}                               /* _cache_load */
905+
906+/**
907+ * @internal
908+ */
909+static void
910+_cache_free(netsnmp_cache * cache, void *magic)
911+{
912+    if ((NULL == cache) || (NULL == cache->magic)) {
913+        snmp_log(LOG_ERR, "invalid cache in hrSWInstalledTable_cache_free\n");
914+        return;
915+    }
916+    DEBUGMSGTL(("hrSWInstalledTable:cache", "free\n"));
917+
918+    netsnmp_swinst_container_free_items((netsnmp_container *) cache->magic);
919+}                               /* _cache_free */
920diff -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
921--- SVN/agent/mibgroup/host/hrSWInstalledTable.h
922+++ APPLE/agent/mibgroup/host/hrSWInstalledTable.h
923@@ -0,0 +1,25 @@
924+/*
925+ * Note: this file originally auto-generated by mib2c using
926+ *  : mib2c.container.conf,v 1.8 2006/07/26 15:58:26 dts12 Exp $
927+ */
928+#ifndef HRSWINSTALLEDTABLE_H
929+#define HRSWINSTALLEDTABLE_H
930+
931+config_require(host/data_access/swinst)
932+
933+/*
934+ * function declarations 
935+ */
936+void            init_hrSWInstalledTable(void);
937+void            initialize_table_hrSWInstalledTable(void);
938+Netsnmp_Node_Handler hrSWInstalledTable_handler;
939+
940+/*
941+ * column number definitions for table hrSWInstalledTable 
942+ */
943+#define COLUMN_HRSWINSTALLEDINDEX		1
944+#define COLUMN_HRSWINSTALLEDNAME		2
945+#define COLUMN_HRSWINSTALLEDID		3
946+#define COLUMN_HRSWINSTALLEDTYPE		4
947+#define COLUMN_HRSWINSTALLEDDATE		5
948+#endif                          /* HRSWINSTALLEDTABLE_H */
949diff -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
950--- SVN/include/net-snmp/data_access/swinst.h
951+++ APPLE/include/net-snmp/data_access/swinst.h
952@@ -0,0 +1,67 @@
953+#ifndef NETSNMP_SWINST_H
954+#define NETSNMP_SWINST_H
955+
956+#ifdef  __cplusplus
957+extern "C" {
958+#endif
959+
960+    /*
961+     * Data structure for a swinst entry 
962+     */
963+    typedef struct hrSWInstalledTable_entry {
964+        netsnmp_index   oid_index;
965+        
966+        /*
967+         * Index values; MIB type is int32, but we use oid so this
968+         * structure can be used directly with a table_container.
969+         */
970+        oid             swIndex;
971+        
972+        /*
973+         * Column values 
974+         */
975+        char            swName[64];
976+        char            swDate[11];
977+#ifdef NETSNMP_HAVE_SWID
978+        oid            *swID;
979+        u_char          swID_len;
980+#endif
981+        u_char          swType;
982+        u_char          swName_len;
983+        u_char          swDate_len;
984+    } netsnmp_swinst_entry;
985+    
986+#define HRSWINSTALLEDTYPE_UNKNOWN  1
987+#define HRSWINSTALLEDTYPE_OPERATINGSYSTEM  2
988+#define HRSWINSTALLEDTYPE_DEVICEDRIVER  3
989+#define HRSWINSTALLEDTYPE_APPLICATION  4
990+
991+
992+#define NETSNMP_SWINST_NOFLAGS            0x00000000
993+
994+#define NETSNMP_SWINST_ALL_OR_NONE        0x00000001
995+#define NETSNMP_SWINST_DONT_FREE_ITEMS    0x00000002
996+
997+    netsnmp_container *
998+    netsnmp_swinst_container_load(netsnmp_container *container, int flags );
999+
1000+    void netsnmp_swinst_container_free(netsnmp_container *container,
1001+                                       u_int flags);
1002+    void netsnmp_swinst_container_free_items(netsnmp_container *container);
1003+
1004+    void netsnmp_swinst_entry_remove(netsnmp_container * container,
1005+                                     netsnmp_swinst_entry *entry);
1006+
1007+    netsnmp_swinst_entry * netsnmp_swinst_entry_create(int32_t index);
1008+    void netsnmp_swinst_entry_free(netsnmp_swinst_entry *entry);
1009+
1010+    int32_t netsnmp_swinst_add_name(const char *name);
1011+    int32_t netsnmp_swinst_get_id(const char *name);
1012+    const char * netsnmp_swinst_get_name(int32_t id);
1013+
1014+#ifdef  __cplusplus
1015+}
1016+#endif
1017+
1018+
1019+#endif /* NETSNMP_SWINST_H */
1020