BUG #a2537: Support *BSD pkg-ng
diff --git a/agent/mibgroup/host/data_access/swinst_pkginfo.c b/agent/mibgroup/host/data_access/swinst_pkginfo.c
index 7301bfc..e7a4082 100644
--- a/agent/mibgroup/host/data_access/swinst_pkginfo.c
+++ b/agent/mibgroup/host/data_access/swinst_pkginfo.c
@@ -32,6 +32,11 @@
 #include <pkginfo.h>
 #endif
 
+#ifdef HAVE_PKG_H
+#define restrict
+#include <pkg.h>
+#endif
+
 #include <net-snmp/net-snmp-includes.h>
 #include <net-snmp/agent/net-snmp-agent-includes.h>
 #include <net-snmp/library/container.h>
@@ -97,53 +102,115 @@
     size_t                date_len;
     int                   i = 1;
     netsnmp_swinst_entry *entry;
+#ifdef HAVE_LIBPKG
+    struct pkgdb *db = NULL;
+    struct pkgdb_it *it = NULL;
+    struct pkg *pkg = NULL;
+    char pkgname[ SNMP_MAXPATH ];
+    char pkgdate[ BUFSIZ ];
+    int pkgng = 0;
 
-    if ( !pkg_directory[0] ) {
-        return 1;    /* Can't report installed packages
-                         if there isn't a list of them! */
+    if (pkg_init(NULL, NULL)) {
+        snmp_log( LOG_ERR, "SWInst: error initializing pkgng db\n" );
+        return 1;
     }
-    d = opendir( pkg_directory );
-    if (!d)
+
+    if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+	snmp_log( LOG_ERR, "SWInst: error opening pkgng db\n" );
 	return 1;
-    while ((dp = readdir(d)) != NULL) {
-        if ( '.' == dp->d_name[0] )
-            continue;
-        snprintf( buf, BUFSIZ, "%s/%s", pkg_directory, dp->d_name );
-        if (stat( buf, &stat_buf ) < 0)
-            continue;
-        entry = netsnmp_swinst_entry_create( i++ );
-        if (NULL == entry)
-            continue;   /* error already logged by function */
-        CONTAINER_INSERT(container, entry);
+    }
+
+    if (pkg_status(NULL) == PKG_STATUS_ACTIVE) {
+	pkgng = 1;
+    } else {
+	snmp_log( LOG_INFO, "SWInst: not a pkgng system\n" );
+    }
+
+    // if we are using FreeBSD's pkgng
+    if (pkgng) {
+        if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) {
+            snmp_log( LOG_ERR, "SWInst: error querying pkgng db\n" );
+            return 1;
+        }
+
+        while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
+            pkg_snprintf(pkgname, sizeof(pkgname), "%n-%v", pkg, pkg);
+            pkg_snprintf(pkgdate, sizeof(pkgdate), "%t", pkg);
+
+            entry = netsnmp_swinst_entry_create( i++ );
+
+            if (NULL == entry)
+                continue;   /* error already logged by function */
+
+            CONTAINER_INSERT(container, entry);
+
+            entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
+                                          "%s", pkgname );
+            if (entry->swName_len >= sizeof(entry->swName))
+                entry->swName_len = sizeof(entry->swName)-1;
+
+            install_time = atoi(pkgdate);
+            cp = date_n_time( &install_time, &date_len );
+            memcpy( entry->swDate, cp, date_len );
+            entry->swDate_len = date_len;
+        }
+
+        pkgdb_it_free(it);
+        pkgdb_close(db);
+        pkg_shutdown();
+    } else {
+#endif /* HAVE_LIBPKG */
+        if ( !pkg_directory[0] ) {
+            return 1;    /* Can't report installed packages
+                         if there isn't a list of them! */
+        }
+
+        d = opendir( pkg_directory );
+        if (!d)
+            return 1;
+
+        while ((dp = readdir(d)) != NULL) {
+            if ( '.' == dp->d_name[0] )
+                continue;
+            snprintf( buf, BUFSIZ, "%s/%s", pkg_directory, dp->d_name );
+            if (stat( buf, &stat_buf ) < 0)
+                continue;
+            entry = netsnmp_swinst_entry_create( i++ );
+            if (NULL == entry)
+                continue;   /* error already logged by function */
+            CONTAINER_INSERT(container, entry);
 
 #ifdef HAVE_PKGINFO
-        v = pkgparam( dp->d_name, "VERSION" );
-        c = pkgparam( dp->d_name, "CATEGORY" );
+	    v = pkgparam( dp->d_name, "VERSION" );
+	    c = pkgparam( dp->d_name, "CATEGORY" );
 
-        entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
-                                      "%s-%s", dp->d_name, v );
-	if (entry->swName_len >= sizeof(entry->swName))
-	    entry->swName_len = sizeof(entry->swName)-1;
-        entry->swType = (NULL != strstr( c, "system"))
-                        ? 2      /* operatingSystem */
-                        : 4;     /*  application    */
+	    entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
+					  "%s-%s", dp->d_name, v );
+	    if (entry->swName_len >= sizeof(entry->swName))
+		entry->swName_len = sizeof(entry->swName)-1;
+	    entry->swType = (NULL != strstr( c, "system"))
+			    ? 2      /* operatingSystem */
+			    : 4;     /*  application    */
 
-        /* Do we need to free 'v' & 'c' ??? */
+	    /* Do we need to free 'v' & 'c' ??? */
 #else
-        entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
-                                      "%s", dp->d_name );
-	if (entry->swName_len >= sizeof(entry->swName))
-	    entry->swName_len = sizeof(entry->swName)-1;
+	    entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
+					  "%s", dp->d_name );
+	    if (entry->swName_len >= sizeof(entry->swName))
+		entry->swName_len = sizeof(entry->swName)-1;
 
-        /* no information about O/S vs application packages ??? */
+	    /* no information about O/S vs application packages ??? */
 #endif
 
-        install_time = stat_buf.st_mtime;
-        cp = date_n_time( &install_time, &date_len );
-        memcpy( entry->swDate, cp, date_len );
-        entry->swDate_len = date_len;
+	    install_time = stat_buf.st_mtime;
+	    cp = date_n_time( &install_time, &date_len );
+	    memcpy( entry->swDate, cp, date_len );
+	    entry->swDate_len = date_len;
+	}
+	closedir( d );
+#ifdef HAVE_LIBPKG
     }
-    closedir( d );
+#endif
 
     DEBUGMSGTL(("swinst:load:arch"," loaded %d entries\n",
                 (int)CONTAINER_SIZE(container)));
diff --git a/configure b/configure
index dab97ed..34eb25c 100755
--- a/configure
+++ b/configure
@@ -17031,6 +17031,197 @@
 done
 
 
+for ac_header in pkg.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pkg.h" "ac_cv_header_pkg_h" "$ac_includes_default"
+if test "x$ac_cv_header_pkg_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PKG_H 1
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pkg_init" >&5
+$as_echo_n "checking for library containing pkg_init... " >&6; }
+if ${netsnmp_cv_func_pkg_init_LIBS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  netsnmp_func_search_save_LIBS="$LIBS"
+     netsnmp_target_val="$LIBS"
+          netsnmp_temp_LIBS=" ${LIBS}"
+     netsnmp_result=no
+     LIBS="${netsnmp_temp_LIBS}"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pkg_init ();
+int
+main ()
+{
+return pkg_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result="none required"
+else
+  for netsnmp_cur_lib in pkg ; do
+              LIBS="-l${netsnmp_cur_lib} ${netsnmp_temp_LIBS}"
+              cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pkg_init ();
+int
+main ()
+{
+return pkg_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result=-l${netsnmp_cur_lib}
+                   break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+          done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     LIBS="${netsnmp_func_search_save_LIBS}"
+     netsnmp_cv_func_pkg_init_LIBS="${netsnmp_result}"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netsnmp_cv_func_pkg_init_LIBS" >&5
+$as_echo "$netsnmp_cv_func_pkg_init_LIBS" >&6; }
+ if test "${netsnmp_cv_func_pkg_init_LIBS}" != "no" ; then
+    if test "${netsnmp_cv_func_pkg_init_LIBS}" != "none required" ; then
+       LIBS="${netsnmp_result} ${netsnmp_target_val}"
+    fi
+
+$as_echo "#define HAVE_LIBPKG 1" >>confdefs.h
+
+
+ fi
+
+fi
+
+done
+
+
+if test $ac_cv_header_pkg_h = no
+then
+    unset ac_cv_header_pkg_h
+    netsnmp_save_CPPFLAGS="$CPPFLAGS"
+    netsnmp_save_LD_FLAGS="$LDFLAGS"
+    CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+    LDFLAGS="$LDFLAGS -L/usr/local/lib"
+    for ac_header in pkg.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pkg.h" "ac_cv_header_pkg_h" "$ac_includes_default"
+if test "x$ac_cv_header_pkg_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PKG_H 1
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pkg_init" >&5
+$as_echo_n "checking for library containing pkg_init... " >&6; }
+if ${netsnmp_cv_func_pkg_init_LIBS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  netsnmp_func_search_save_LIBS="$LIBS"
+     netsnmp_target_val="$LIBS"
+          netsnmp_temp_LIBS=" ${LIBS}"
+     netsnmp_result=no
+     LIBS="${netsnmp_temp_LIBS}"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pkg_init ();
+int
+main ()
+{
+return pkg_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result="none required"
+else
+  for netsnmp_cur_lib in pkg ; do
+              LIBS="-l${netsnmp_cur_lib} ${netsnmp_temp_LIBS}"
+              cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pkg_init ();
+int
+main ()
+{
+return pkg_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result=-l${netsnmp_cur_lib}
+                   break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+          done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     LIBS="${netsnmp_func_search_save_LIBS}"
+     netsnmp_cv_func_pkg_init_LIBS="${netsnmp_result}"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netsnmp_cv_func_pkg_init_LIBS" >&5
+$as_echo "$netsnmp_cv_func_pkg_init_LIBS" >&6; }
+ if test "${netsnmp_cv_func_pkg_init_LIBS}" != "no" ; then
+    if test "${netsnmp_cv_func_pkg_init_LIBS}" != "none required" ; then
+       LIBS="${netsnmp_result} ${netsnmp_target_val}"
+    fi
+
+$as_echo "#define HAVE_LIBPKG 1" >>confdefs.h
+
+
+ fi
+
+fi
+
+done
+
+    if test $ac_cv_header_pkg_h = no
+    then
+        CPPFLAGS="$netsnmp_save_CPPFLAGS"
+        LDFLAGS="$netsnmp_save_LDFLAGS"
+    fi
+fi
+
 case $target_os in
     aix*)
         #       for CPU/memory statistics               (AIX)
diff --git a/configure.d/config_os_headers b/configure.d/config_os_headers
index d8127ca..def3bce 100644
--- a/configure.d/config_os_headers
+++ b/configure.d/config_os_headers
@@ -473,6 +473,27 @@
     NETSNMP_SEARCH_LIBS(pkginfo, adm,
         AC_DEFINE(HAVE_PKGINFO, 1, [define if you have pkginfo]),,,LMIBLIBS))
 
+AC_CHECK_HEADERS(pkg.h,
+    NETSNMP_SEARCH_LIBS(pkg_init, pkg,
+        AC_DEFINE(HAVE_LIBPKG, 1, [define if you have BSD pkg-ng])))
+
+if test $ac_cv_header_pkg_h = no
+then
+    unset ac_cv_header_pkg_h
+    netsnmp_save_CPPFLAGS="$CPPFLAGS"
+    netsnmp_save_LD_FLAGS="$LDFLAGS"
+    CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+    LDFLAGS="$LDFLAGS -L/usr/local/lib"
+    AC_CHECK_HEADERS(pkg.h,
+        NETSNMP_SEARCH_LIBS(pkg_init, pkg,
+	    AC_DEFINE(HAVE_LIBPKG, 1, [define if you have BSD pkg-ng])))
+    if test $ac_cv_header_pkg_h = no
+    then
+        CPPFLAGS="$netsnmp_save_CPPFLAGS"
+        LDFLAGS="$netsnmp_save_LDFLAGS"
+    fi
+fi
+
 case $target_os in
     aix*)
         #       for CPU/memory statistics               (AIX)
diff --git a/include/net-snmp/net-snmp-config.h.in b/include/net-snmp/net-snmp-config.h.in
index 84af89a..1db0237 100644
--- a/include/net-snmp/net-snmp-config.h.in
+++ b/include/net-snmp/net-snmp-config.h.in
@@ -362,6 +362,9 @@
 /* Define to 1 if you have the `pkcs11' library (-lpkcs11). */
 #undef HAVE_LIBPKCS11
 
+/* define if you have BSD pkg-ng */
+#undef HAVE_LIBPKG
+
 /* Define to 1 if you have the `pthread' library (-lpthread). */
 #undef HAVE_LIBPTHREAD
 
@@ -629,6 +632,9 @@
 /* Define to 1 if you have the <pkglocs.h> header file. */
 #undef HAVE_PKGLOCS_H
 
+/* Define to 1 if you have the <pkg.h> header file. */
+#undef HAVE_PKG_H
+
 /* Define to 1 if you have the `poll' function. */
 #undef HAVE_POLL