--- gnome-menus-2.30.4/libmenu/Makefile.am-orig	2011-02-01 20:32:20.338888769 -0600
+++ gnome-menus-2.30.4/libmenu/Makefile.am	2011-02-01 20:32:53.397121492 -0600
@@ -19,7 +19,8 @@ libgnome_menu_sources =			\
 	gmenu-tree.c			\
 	menu-layout.c			\
 	menu-monitor.c			\
-	menu-util.c
+	menu-util.c			\
+	menu-solaris.c
 
 libgnome_menu_la_SOURCES =		\
 	$(libgnome_menu_sources)	\
@@ -29,7 +30,8 @@ libgnome_menu_la_SOURCES =		\
 	gmenu-tree.h			\
 	menu-layout.h			\
 	menu-monitor.h			\
-	menu-util.h
+	menu-util.h			\
+	menu-solaris.h
 
 libgnome_menu_la_LIBADD = 		\
 	$(GLIB_LIBS)
--- gnome-menus-2.30.4/libmenu/desktop-entries.c-orig	2011-01-31 14:33:59.083221487 -0600
+++ gnome-menus-2.30.4/libmenu/desktop-entries.c	2011-02-01 17:57:31.679887328 -0600
@@ -24,6 +24,7 @@
 #include <string.h>
 
 #include "menu-util.h"
+#include "menu-solaris.h"
 
 #define DESKTOP_ENTRY_GROUP     "Desktop Entry"
 #define KDE_DESKTOP_ENTRY_GROUP "KDE Desktop Entry"
@@ -80,6 +81,7 @@ get_flags_from_key_file (DesktopEntry *e
   char      *tryexec;
   guint      flags;
   int        i;
+  gboolean   use_global = FALSE;
 
   error = NULL;
   no_display = g_key_file_get_boolean (key_file,
@@ -142,21 +144,41 @@ get_flags_from_key_file (DesktopEntry *e
     }
   g_strfreev (strv);
 
+  if (strncmp (entry->path,
+               "/usr/share/gnome/trusted/applications",
+               strlen ("/usr/share/gnome/trusted/applications")) == 0)
+    {
+      use_global = TRUE;
+    }
+
   tryexec_failed = FALSE;
   tryexec = g_key_file_get_string (key_file,
                                    desktop_entry_group,
                                    "TryExec",
                                    NULL);
+
+  /*
+   * Call filter_with_rbac to check TryExec and also see if the
+   * menu item should be filtered out for RBAC purposes.
+   */
   if (tryexec)
     {
-      char *path;
-
-      path = g_find_program_in_path (g_strstrip (tryexec));
+      tryexec_failed = filter_with_rbac (tryexec, use_global);
+      g_free (tryexec);
+    }
 
-      tryexec_failed = (path == NULL);
+  if (tryexec_failed == FALSE)
+    {
+      tryexec = g_key_file_get_string (key_file,
+                                       desktop_entry_group,
+                                       "Exec",
+                                       NULL);
 
-      g_free (path);
-      g_free (tryexec);
+      if (tryexec)
+        {
+          tryexec_failed = filter_with_rbac (tryexec, use_global);
+          g_free (tryexec);
+        }
     }
 
   flags = 0;
--- gnome-menus-2.30.4/libmenu/entry-directories.c-orig	2011-01-31 21:26:01.492500629 -0600
+++ gnome-menus-2.30.4/libmenu/entry-directories.c	2011-01-31 21:55:41.687967111 -0600
@@ -292,6 +292,9 @@ cached_dir_remove_entry (CachedDir  *dir
 {
   GSList *tmp;
 
+  if (dir_cache == NULL)
+    return;
+
   tmp = dir->entries;
   while (tmp != NULL)
     {
@@ -345,6 +348,9 @@ cached_dir_remove_subdir (CachedDir  *di
 {
   CachedDir *subdir;
 
+  if (dir_cache == NULL)
+    return;
+
   subdir = find_subdir (dir, basename);
 
   if (subdir != NULL)
@@ -585,6 +591,9 @@ cached_dir_remove_monitor (CachedDir    
 {
   GSList *tmp;
 
+  if (dir_cache == NULL)
+    return;
+
   tmp = dir->monitors;
   while (tmp != NULL)
     {
@@ -619,6 +628,9 @@ cached_dir_remove_reference (CachedDir *
 {
   CachedDir *parent;
 
+  if (dir_cache == NULL)
+    return;
+
   parent = dir->parent;
 
   if (--dir->references == 0 && dir->deleted)
@@ -1221,3 +1233,14 @@ entry_directory_list_remove_monitors (En
       tmp = tmp->next;
     }
 }
+
+void
+_reset_dir_cache (void)
+{
+  if (dir_cache != NULL)
+    {
+      cached_dir_free (dir_cache);
+      dir_cache = NULL;
+    }
+}
+
--- gnome-menus-2.30.4/libmenu/gmenu-tree.c-orig	2011-01-31 15:51:01.017894153 -0600
+++ gnome-menus-2.30.4/libmenu/gmenu-tree.c	2011-02-01 18:20:16.637612233 -0600
@@ -19,6 +19,12 @@
 
 #include <config.h>
 
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
 #include "gmenu-tree.h"
 
 #include <string.h>
@@ -29,6 +35,8 @@
 #include "menu-util.h"
 #include "canonicalize.h"
 
+#include "menu-solaris.h"
+
 /*
  * FIXME: it might be useful to be able to construct a menu
  * tree from a traditional directory based menu hierarchy
@@ -63,6 +71,18 @@ struct GMenuTree
   gpointer       user_data;
   GDestroyNotify dnotify;
 
+  gpointer wnckscreen;
+  guint workspace_handler;
+  guint roles_handler;
+  guint labels_handler;
+
+  GFileMonitor *rbac_monitor1;
+  GFileMonitor *rbac_monitor2;
+  GFileMonitor *rbac_monitor3;
+  guint rbac_handler1;
+  guint rbac_handler2;
+  guint rbac_handler3;
+
   guint canonical : 1;
 };
 
@@ -229,6 +249,11 @@ gmenu_tree_remove_from_cache (GMenuTree 
 
   menu_verbose ("Removing menu tree from cache: %s\n", cache_key);
 
+  if (gmenu_tree_cache == NULL)
+    {
+      g_free (cache_key);
+      return;
+    }
   g_hash_table_remove (gmenu_tree_cache, cache_key);
 
   g_free (cache_key);
@@ -630,6 +655,74 @@ gmenu_tree_lookup (const char     *menu_
   return retval;
 }
 
+/*
+ * This function completely clears the cache which forces the panel to reload
+ * via the monitors it invokes.  We want to reload the entire menu when RBAC
+ * configuration files change or when the users RBAC profile changes (e.g.
+ * on workspace switch in Trusted mode).
+ */
+static void
+rebuild_menu (GMenuTree *tree)
+{
+  if (tree != NULL)
+    {
+      if (gmenu_tree_cache != NULL) 
+        {
+          g_hash_table_destroy (gmenu_tree_cache);
+          gmenu_tree_cache = NULL;
+        }
+
+      _entry_directory_list_empty_desktop_cache ();
+      gmenu_tree_force_reload (tree);
+      _reset_dir_cache ();
+      gmenu_tree_invoke_monitors (tree);
+    }
+}
+
+/*
+ * On workspace switch, reload the entire menu when in Trusted mode.
+ */
+static void
+workspace_changed_callback (gpointer screen, gpointer prev_workspace, gpointer data)
+{
+  GMenuTree *tree;
+
+  tree = (GMenuTree *)data;
+  if (tree != NULL)
+    {
+      rebuild_menu (tree);
+    }
+}
+
+static void
+role_or_label_changed_callback (gpointer workspace, gpointer data)
+{
+  GMenuTree *tree;
+
+  tree = (GMenuTree *)data;
+  if (tree != NULL)
+    {
+      rebuild_menu (tree);
+    }
+}
+
+static gboolean
+rbac_callback (GFileMonitor      *monitor,
+               GFile             *child,
+               GFile             *other_file,
+               GFileMonitorEvent eflags,
+               gpointer          data)
+{
+  GMenuTree *tree;
+
+  tree = (GMenuTree *)data;
+  if (tree != NULL) 
+    {
+      rebuild_menu (tree);
+    }
+}
+
+
 static GMenuTree *
 gmenu_tree_new (GMenuTreeType   type,
 		const char     *menu_file,
@@ -637,12 +730,25 @@ gmenu_tree_new (GMenuTreeType   type,
 		GMenuTreeFlags  flags)
 {
   GMenuTree *tree;
+  GFile *rbac_file;
+  gboolean trusted;
 
   tree = g_new0 (GMenuTree, 1);
 
   tree->type     = type;
   tree->flags    = flags;
   tree->refcount = 1;
+  tree->root              = NULL;
+  tree->wnckscreen        = NULL;
+  tree->workspace_handler = 0;
+  tree->roles_handler     = 0;
+  tree->labels_handler    = 0;
+  tree->rbac_monitor1     = NULL;
+  tree->rbac_monitor2     = NULL;
+  tree->rbac_monitor3     = NULL;
+  tree->rbac_handler1     = 0;
+  tree->rbac_handler2     = 0;
+  tree->rbac_handler3     = 0;
 
   tree->sort_key = GMENU_TREE_SORT_NAME;
 
@@ -671,6 +777,70 @@ gmenu_tree_new (GMenuTreeType   type,
 	}
     }
 
+  /*
+   * Gince the panel is already monitoring all desktop files, add
+   * monitors for RBAC configuration files.  If these change, we want
+   * to reload the panel.  We check for these files and clear the
+   * cache in handle_entries_changed ().
+   */
+  rbac_file = g_file_new_for_path ("/etc/user_attr");
+  if (rbac_file != NULL) 
+    {
+      tree->rbac_monitor1 = g_file_monitor_file (rbac_file,
+                            G_FILE_MONITOR_NONE, NULL, NULL);
+      if (tree->rbac_monitor1)
+        {
+          tree->rbac_handler1 = g_signal_connect (tree->rbac_monitor1,
+                                "changed",
+                                G_CALLBACK (rbac_callback), tree);
+        }
+      g_object_unref (G_OBJECT (rbac_file));
+    }
+  rbac_file = g_file_new_for_path ("/etc/security/exec_attr");
+  if (rbac_file != NULL) 
+    {
+      tree->rbac_monitor2 = g_file_monitor_file (rbac_file,
+                            G_FILE_MONITOR_NONE, NULL, NULL);
+      if (tree->rbac_monitor2)
+        {
+          tree->rbac_handler2 = g_signal_connect (tree->rbac_monitor2,
+                                "changed",
+                                G_CALLBACK (rbac_callback), tree);
+        }
+      g_object_unref (G_OBJECT (rbac_file));
+    }
+  rbac_file = g_file_new_for_path ("/etc/security/prof_attr");
+  if (rbac_file != NULL) 
+    {
+      tree->rbac_monitor3 = g_file_monitor_file (rbac_file,
+                            G_FILE_MONITOR_NONE, NULL, NULL);
+      if (tree->rbac_monitor3)
+        {
+          tree->rbac_handler3 = g_signal_connect (tree->rbac_monitor3,
+                                "changed",
+                                G_CALLBACK (rbac_callback), tree);
+        }
+      g_object_unref (G_OBJECT (rbac_file));
+    }
+
+  /*
+   * Set up a signal handler to cause the menu to reload on workspace
+   * switch or when the label or role changes, but only do this in Trusted mode.
+   * In Trusted, workspaces are associated with RBAC roles, so a workspace
+   * switch should trigger a menu reload in this situation.
+   */
+  trusted = use_trusted_extensions ();
+  if (trusted == TRUE)
+    {
+      tree->wnckscreen = libmenu_wnck_screen_get_default ();
+      if (tree->wnckscreen)
+        {
+          tree->workspace_handler = g_signal_connect (tree->wnckscreen, "active-workspace-changed", G_CALLBACK(workspace_changed_callback), tree);
+          tree->labels_handler = g_signal_connect (tree->wnckscreen, "labels_changed", G_CALLBACK(role_or_label_changed_callback), tree);
+          tree->roles_handler = g_signal_connect (tree->wnckscreen, "roles_changed", G_CALLBACK(role_or_label_changed_callback), tree);
+        }
+    }
+
   gmenu_tree_add_to_cache (tree, tree->flags);
 
   return tree;
@@ -696,6 +866,46 @@ gmenu_tree_unref (GMenuTree *tree)
   if (--tree->refcount > 0)
     return;
 
+  if (tree->wnckscreen != NULL)
+    {
+      if (tree->workspace_handler != 0)
+        g_signal_handler_disconnect (tree->wnckscreen, tree->workspace_handler);
+      if (tree->roles_handler != 0)
+        g_signal_handler_disconnect (tree->wnckscreen, tree->roles_handler);
+      if (tree->labels_handler != 0)
+        g_signal_handler_disconnect (tree->wnckscreen, tree->labels_handler);
+    }
+
+  if (tree->rbac_monitor1 != NULL)
+    {
+      if (tree->rbac_handler1 != 0)
+        g_signal_handler_disconnect (tree->rbac_monitor1, tree->rbac_handler1);
+      g_object_unref (tree->rbac_monitor1);
+    }
+  if (tree->rbac_monitor2 != NULL)
+    {
+      if (tree->rbac_handler2 != 0)
+        g_signal_handler_disconnect (tree->rbac_monitor2, tree->rbac_handler2);
+      g_object_unref (tree->rbac_monitor2);
+    }
+  if (tree->rbac_monitor3 != NULL)
+    {
+      if (tree->rbac_handler3 != 0)
+        g_signal_handler_disconnect (tree->rbac_monitor3, tree->rbac_handler3);
+      g_object_unref (tree->rbac_monitor3);
+    }
+
+  tree->wnckscreen        = NULL;
+  tree->workspace_handler = 0;
+  tree->roles_handler     = 0;
+  tree->labels_handler    = 0;
+  tree->rbac_monitor1     = NULL;
+  tree->rbac_monitor2     = NULL;
+  tree->rbac_monitor3     = NULL;
+  tree->rbac_handler1     = 0;
+  tree->rbac_handler2     = 0;
+  tree->rbac_handler3     = 0;
+
   if (tree->dnotify)
     tree->dnotify (tree->user_data);
   tree->user_data = NULL;
@@ -850,6 +1060,7 @@ gmenu_tree_get_directory_from_path (GMen
 {
   GMenuTreeDirectory *root;
   GMenuTreeDirectory *directory;
+  gboolean trusted;
 
   g_return_val_if_fail (tree != NULL, NULL);
   g_return_val_if_fail (path != NULL, NULL);
@@ -857,6 +1068,40 @@ gmenu_tree_get_directory_from_path (GMen
   if (path[0] != G_DIR_SEPARATOR)
     return NULL;
 
+  trusted = use_trusted_extensions ();
+
+  /*
+   * If the zone /usr/share/application directory is not available, just return
+   * NULL.  This will show an empty menu, but the menu will populate when the
+   * directory becomes available since this function is called each time the
+   * panel menu is opened.
+   */
+  if (trusted == TRUE)
+    {
+      char *trusted_system_data_dir = NULL;
+      char *zoneroot = NULL;
+      struct stat statbuf;
+      int r;
+
+      zoneroot = get_zoneroot ();
+      if (zoneroot != NULL)
+        {
+          trusted_system_data_dir = g_strdup_printf ("%s/usr/share",
+                                                   zoneroot);
+          r = g_stat (trusted_system_data_dir, &statbuf);
+          g_free (trusted_system_data_dir);
+
+          if (r < 0 || ! S_ISDIR (statbuf.st_mode))
+            {
+              return NULL;
+            }
+        }
+      else
+        {
+          return NULL;
+        }
+    }
+
   if (!(root = gmenu_tree_get_root_directory (tree)))
     return NULL;
 
@@ -2081,7 +2326,48 @@ resolve_default_app_dirs (GMenuTree     
   MenuLayoutNode     *before;
   const char * const *system_data_dirs;
   int                 i;
+  gboolean trusted;
+  gboolean using_trusted = FALSE;
+
+  trusted = use_trusted_extensions ();
 
+  /*
+   * Load the applications from the zone specific /usr/share/applications
+   * directory.  The zone is determined from the label associated with the
+   * workspace.
+   */ 
+  if (trusted == TRUE)
+    {
+      char *trusted_system_data_dir = NULL;
+      char *zoneroot = NULL;
+
+      zoneroot = get_zoneroot ();
+
+      if (zoneroot != NULL)
+        {
+          using_trusted = TRUE;
+          trusted_system_data_dir = g_strdup_printf ("%s/usr/share",
+                                                  zoneroot);
+
+          before = add_app_dir (tree,
+			        menu_layout_node_ref (layout),
+			        trusted_system_data_dir);
+
+          g_free (trusted_system_data_dir);
+
+          /*
+           * Add /usr/share/gnome/trusted/applications since desktop files
+           * associated with /usr/share/gnome/TrustedPathExecutables need to
+           * be loaded.
+           */
+          before = add_app_dir (tree,
+			        menu_layout_node_ref (layout),
+			        "/usr/share/gnome/trusted");
+        }
+    }
+
+  if (using_trusted == FALSE)
+    {
   system_data_dirs = g_get_system_data_dirs ();
 
   before = add_app_dir (tree,
@@ -2095,6 +2381,7 @@ resolve_default_app_dirs (GMenuTree     
 
       ++i;
     }
+    }
 
   menu_layout_node_unref (before);
 
@@ -4492,7 +4779,16 @@ static void
 handle_entries_changed (MenuLayoutNode *layout,
                         GMenuTree       *tree)
 {
-  if (tree->layout == layout)
+  /* If an RBAC configuration file changes, then reload the whole menu */
+  if (tree->basename != NULL &&
+     (strcmp (tree->basename, "user_attr") == 0 ||
+      strcmp (tree->basename, "exec_attr") == 0 ||
+      strcmp (tree->basename, "prof_attr") == 0 ||
+      strcmp (tree->basename, "auth_attr") == 0))
+    {
+      rebuild_menu (tree);
+    }   
+  else if (tree->layout == layout)
     {
       gmenu_tree_force_rebuild (tree);
       gmenu_tree_invoke_monitors (tree);
--- /dev/null	2011-02-17 17:51:25.000000000 -0600
+++ gnome-menus-2.30.4/libmenu/menu-solaris.h	2011-02-17 17:50:08.763540499 -0600
@@ -0,0 +1,90 @@
+
+#ifndef __MENU_SOLARIS_H__
+#define __MENU_SOLARIS_H__
+
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xtsol.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+gboolean use_trusted_extensions (void);
+gboolean filter_with_rbac (gchar *, gboolean);
+char * get_zoneroot (void);
+
+/* Libtsol functions */
+
+typedef int     (*tsol_blequal) (const m_label_t *label1, const m_label_t *label2);
+typedef int     (*tsol_label_to_str) (const m_label_t *label, char **string,
+                 const m_label_str_t conversion_type,
+                 uint_t flags);
+typedef int            (*tsol_str_to_label) (const char *string, m_label_t **label,
+                 const m_label_type_t label_type, uint_t flags,
+                 int *error);
+typedef void (*tsol_m_label_dup) (m_label_t **dst, const m_label_t *src);
+typedef void   (*tsol_m_label_free) (m_label_t *label);
+
+/* Other misc. libtsol functions that seem to be stable */
+typedef blrange_t*             (*tsol_getuserrange) (const char *username);
+typedef int                            (*tsol_blinrange) (const m_label_t *label,
+                         const blrange_t *range);
+typedef void                   (*tsol_blminimum) (m_label_t *minimum_label,
+                         const m_label_t *bounding_label);
+typedef void                   (*tsol_blmaximum) (m_label_t *maximum_label,
+                         const m_label_t *bounding_label);
+typedef m_label_t*             (*tsol_blabel_alloc) (void);
+typedef void                   (*tsol_blabel_free)  (m_label_t *label_p);
+typedef void                   (*tsol_bsllow)  (m_label_t *label);
+typedef void                   (*tsol_bslhigh) (m_label_t *label);
+
+/* libXtsol functions */
+typedef Status (*xtsol_XTSOLgetClientLabel) (Display *dpy, XID xid,
+                 bslabel_t *sl);
+typedef Bool   (*xtsol_XTSOLIsWindowTrusted) (Display *dpy, Window win);
+
+/* libgnometsol functions */
+typedef gpointer       (*gnometsol_gnome_label_builder_new) (char *msg,
+                        blevel_t *upper, blevel_t *lower, int mode);
+typedef GType          (*gnometsol_gnome_label_builder_get_type) (void);
+
+/* libwnck functions */
+typedef gpointer        (*menu_wnck_screen_get_default) (void);
+typedef gpointer        (*menu_wnck_screen_get_active_workspace) (gpointer);
+typedef const char*     (*menu_wnck_workspace_get_role) (gpointer);
+typedef const char*     (*menu_wnck_workspace_get_label) (gpointer);
+
+/* libtsol functions */
+tsol_blequal           libtsol_blequal;
+tsol_label_to_str      libtsol_label_to_str;
+tsol_str_to_label      libtsol_str_to_label;
+tsol_m_label_dup libtsol_m_label_dup;
+tsol_m_label_free      libtsol_m_label_free;
+/* Other misc. libtsol functions */
+tsol_blminimum         libtsol_blminimum;
+tsol_blmaximum         libtsol_blmaximum;
+tsol_blinrange      libtsol_blinrange;
+tsol_getuserrange      libtsol_getuserrange;
+tsol_blabel_alloc      libtsol_blabel_alloc;
+tsol_blabel_free       libtsol_blabel_free;
+tsol_bsllow                    libtsol_bsllow;
+tsol_bslhigh           libtsol_bslhigh;
+
+xtsol_XTSOLgetClientLabel      libxtsol_XTSOLgetClientLabel;
+xtsol_XTSOLIsWindowTrusted     libxtsol_XTSOLIsWindowTrusted;
+
+gnometsol_gnome_label_builder_new libgnometsol_gnome_label_builder_new;
+gnometsol_gnome_label_builder_get_type libgnometsol_gnome_label_builder_get_type;
+
+/* libwnck functions */
+menu_wnck_screen_get_default          libmenu_wnck_screen_get_default;
+menu_wnck_screen_get_active_workspace libmenu_wnck_screen_get_active_workspace;
+menu_wnck_workspace_get_role          libmenu_wnck_workspace_get_role;
+menu_wnck_workspace_get_label         libmenu_wnck_workspace_get_label;
+
+G_END_DECLS
+
+#endif /* __MENU_SOLARIS_H__ */
--- /dev/null	2011-02-01 18:21:34.000000000 -0600
+++ gnome-menus-2.30.4/libmenu/menu-solaris.c	2011-02-01 18:28:12.721308906 -0600
@@ -0,0 +1,432 @@
+/*
+ * Note that the following code is in three patches:
+ * - gnome-panel-XX-rbac.diff (filter_with_rbac)
+ * - gnome-menus-XX-rbac.diff (filter_with_rbac)
+ * - glib-XX-gio-rbac.diff    (get_gksu_role)
+ * - gnome-session-XX-rbac.diff (get_gksu_role)
+ *
+ * So if there is a need to fix this code, it is probably necessary to fix the
+ * code in these other two places as well.  Though the functions are a bit
+ * different.
+ */
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <user_attr.h>
+#include <exec_attr.h>
+#include <secdb.h>
+
+#include "menu-solaris.h"
+
+static
+void * dlopen_tsol (void)
+{
+   void  *handle = NULL;
+
+   /*
+    * No 64-bit version of libwnck so we can get away with hardcoding
+    * to a single path on this occasion
+    */
+   if ((handle = dlopen ("/usr/lib/libtsol.so.2", RTLD_LAZY)) != NULL)
+       return handle;
+
+   return handle;
+}
+
+static
+void * dlopen_xtsol (void)
+{
+   void  *handle = NULL;
+
+   if ((handle = dlopen ("/usr/lib/libXtsol.so.1", RTLD_LAZY)) != NULL)
+       return handle;
+   if ((handle = dlopen ("/usr/openwin/lib/libXtsol.so.1", RTLD_LAZY)) != NULL)
+       return handle;
+
+   return handle;
+}
+
+static
+void * dlopen_gnometsol (void)
+{
+   void  *handle = NULL;
+
+   if ((handle = dlopen ("/usr/lib/libgnometsol.so", RTLD_LAZY)) != NULL)
+       return handle;
+
+   return handle;
+}
+
+static
+void * dlopen_libwnck (void)
+{
+   void  *handle = NULL;
+
+   if ((handle = dlopen ("/usr/lib/libwnck-1.so", RTLD_LAZY)) != NULL)
+       return handle;
+
+   return handle;
+}
+
+gboolean
+use_trusted_extensions (void)
+{
+    static int trusted = -1;
+
+    /*
+     * Sun Trusted Extensions (tm) for Solaris (tm) support. (Damn I should be a lawyer).
+     *
+     * It is necessary to use dlopen because the label aware extensions to libwnck work
+     * only on systems with the trusted extensions installed and with the SUN_TSOL
+     * xserver extension present
+     */
+
+    if (trusted < 0) {
+        static gpointer tsol_handle = NULL;
+        static gpointer xtsol_handle = NULL;
+        static gpointer gnometsol_handle = NULL;
+        static gpointer libwnck_handle = NULL;
+
+        if (getenv ("TRUSTED_SESSION") == NULL) {
+            trusted = 0;
+            return 0;
+        }
+
+	libwnck_handle = dlopen_libwnck ();
+        if (libwnck_handle != NULL)
+            tsol_handle = dlopen_tsol ();
+        if (tsol_handle != NULL)
+            xtsol_handle = dlopen_xtsol ();
+        if (libwnck_handle && tsol_handle && xtsol_handle) {
+
+           libmenu_wnck_screen_get_default = (menu_wnck_screen_get_default) dlsym (libwnck_handle, "wnck_screen_get_default");
+           libmenu_wnck_screen_get_active_workspace = (menu_wnck_screen_get_active_workspace) dlsym (libwnck_handle, "wnck_screen_get_active_workspace");
+           libmenu_wnck_workspace_get_role = (menu_wnck_workspace_get_role) dlsym (libwnck_handle, "wnck_workspace_get_role");
+           libmenu_wnck_workspace_get_label = (menu_wnck_workspace_get_label) dlsym (libwnck_handle, "wnck_workspace_get_label");
+
+           /* libtsol functions */
+           libtsol_blequal = (tsol_blequal) dlsym (tsol_handle, "blequal");
+           libtsol_label_to_str = (tsol_label_to_str) dlsym (tsol_handle, "label_to_str");
+           libtsol_str_to_label = (tsol_str_to_label) dlsym (tsol_handle, "str_to_label");
+           libtsol_m_label_dup = (tsol_m_label_dup) dlsym (tsol_handle, "m_label_dup");
+           libtsol_m_label_free = (tsol_m_label_free) dlsym (tsol_handle, "m_label_free");
+
+           /* Other misc. libtsol functions */
+           libtsol_blminimum = (tsol_blminimum) dlsym (tsol_handle, "blminimum");
+           libtsol_blmaximum = (tsol_blmaximum) dlsym (tsol_handle, "blmaximum");
+           libtsol_blinrange = (tsol_blinrange) dlsym (tsol_handle, "blinrange");
+           libtsol_getuserrange = (tsol_getuserrange) dlsym (tsol_handle, "getuserrange");
+           libtsol_blabel_alloc = (tsol_blabel_alloc) dlsym (tsol_handle, "blabel_alloc");
+           libtsol_blabel_free  = (tsol_blabel_free)  dlsym (tsol_handle, "blabel_free");
+           libtsol_bsllow  = (tsol_bsllow)  dlsym (tsol_handle, "bsllow");
+           libtsol_bslhigh = (tsol_bslhigh) dlsym (tsol_handle, "bslhigh");
+
+           /* libXtsol functions */
+           libxtsol_XTSOLgetClientLabel = (xtsol_XTSOLgetClientLabel) dlsym (xtsol_handle,
+                                     "XTSOLgetClientLabel");
+           libxtsol_XTSOLIsWindowTrusted = (xtsol_XTSOLIsWindowTrusted) dlsym (xtsol_handle,
+                                      "XTSOLIsWindowTrusted");
+
+           if (libtsol_label_to_str == NULL ||
+               libtsol_str_to_label == NULL ||
+               libtsol_m_label_dup == NULL ||
+               libtsol_m_label_free == NULL ||
+               libtsol_blminimum == NULL ||
+               libtsol_blmaximum == NULL ||
+               libtsol_blinrange == NULL ||
+               libtsol_getuserrange == NULL ||
+               libtsol_blabel_alloc == NULL ||
+               libtsol_blabel_free  == NULL ||
+               libtsol_bsllow  == NULL ||
+               libtsol_bslhigh == NULL ||
+               libxtsol_XTSOLgetClientLabel == NULL ||
+               libxtsol_XTSOLIsWindowTrusted == NULL ||
+               libmenu_wnck_screen_get_default == NULL ||
+               libmenu_wnck_screen_get_active_workspace == NULL ||
+               libmenu_wnck_workspace_get_role == NULL ||
+               libmenu_wnck_workspace_get_label == NULL) {
+               dlclose (tsol_handle);
+               dlclose (xtsol_handle);
+               dlclose (libwnck_handle);
+               tsol_handle = NULL;
+               xtsol_handle = NULL;
+               libwnck_handle = NULL;
+            }
+        }
+
+        gnometsol_handle = dlopen_gnometsol ();
+        if (gnometsol_handle != NULL)
+            {
+               libgnometsol_gnome_label_builder_new =
+                               (gnometsol_gnome_label_builder_new) dlsym (gnometsol_handle,
+                               "gnome_label_builder_new");
+              libgnometsol_gnome_label_builder_get_type =
+                               (gnometsol_gnome_label_builder_get_type) dlsym (gnometsol_handle,
+                               "gnome_label_builder_get_type");
+              if (libgnometsol_gnome_label_builder_new == NULL ||
+                  libgnometsol_gnome_label_builder_get_type == NULL)
+                  gnometsol_handle = NULL;
+            }
+        trusted = ((tsol_handle != NULL) && (xtsol_handle != NULL) && (gnometsol_handle != NULL) && (libwnck_handle != NULL)) ? 1 : 0;
+    }
+    return trusted ? TRUE : FALSE;
+}
+
+static gchar *
+get_stripped_exec (const gchar *full_exec, gboolean use_global)
+{
+	gchar *str1, *str2, *retval, *p;
+	char *zoneroot = NULL;
+	gboolean trusted;
+
+	str1 = g_strdup (full_exec);
+	p = strtok (str1, " ");
+
+	if (p != NULL)
+		str2 = g_strdup (p);
+	else
+		str2 = g_strdup (full_exec);
+
+	g_free (str1);
+
+	trusted = use_trusted_extensions ();
+	if (trusted && use_global == FALSE) {
+		zoneroot = get_zoneroot ();
+	}
+
+	if (g_path_is_absolute (str2)) {
+		if (zoneroot != NULL) {
+			retval = g_strdup_printf ("%s/%s", zoneroot, str2);
+		} else {
+			retval = g_strdup (str2);
+		}
+	} else {
+		if (zoneroot != NULL) {
+			/*
+			 * If the desktop file doesn't specify the full path
+			 * and in Trusted mode, then check the zone's /usr/bin
+			 * directory.
+			 */
+			retval = g_strdup_printf ("%s/usr/bin/%s", zoneroot, str2);
+		} else {
+			retval = g_strdup (g_find_program_in_path ((const gchar *)str2));
+
+			/*
+			 * If a program is not installed in the global zone,
+			 * then assume it is installed in /usr/bin.
+			 */
+			if (use_global == TRUE && retval == NULL) {
+				retval = g_strdup_printf ("/usr/bin/%s", str2);
+			}
+		}
+	}
+	g_free (str2);
+
+	return retval;
+}
+
+/*
+ * Checks RBAC to see if the user can run the command.
+ */
+gboolean
+filter_with_rbac (gchar *command, gboolean use_global)
+{
+	execattr_t *exec;
+	gchar *stripped_cmd;
+	gchar *real_cmd;
+	char *path;
+	const char *username = NULL;
+	userattr_t *user;
+	int        i;
+	gboolean   program_has_profile;
+	gboolean   rc;
+	gboolean   trusted;
+
+	rc = TRUE;
+
+	stripped_cmd = get_stripped_exec (command, TRUE);
+	real_cmd     = get_stripped_exec (command, use_global);
+
+	trusted = use_trusted_extensions ();
+	if (trusted) {
+		/*
+		 * In trusted mode, use the single role associated with
+		 * the workspace.
+		 */
+		gpointer wnckscreen = NULL;
+		gpointer wnckworkspace = NULL;
+
+		wnckscreen = libmenu_wnck_screen_get_default ();
+		if (wnckscreen != NULL)
+			wnckworkspace = libmenu_wnck_screen_get_active_workspace (wnckscreen);
+
+		if (wnckworkspace != NULL)
+			username = libmenu_wnck_workspace_get_role (wnckworkspace);
+	}
+
+	if (username == NULL) {
+		username = g_get_user_name ();
+	}
+
+	/* If the command does not exist, do not show it. */
+	if (real_cmd == NULL || stripped_cmd == NULL) {
+		goto out;
+	}
+
+	path = g_find_program_in_path (g_strstrip (real_cmd));
+	if (path == NULL)
+		goto out;
+
+	/*
+	 * All programs should be available to root.  This check is done after
+	 * verifying the binary is in path.
+	 */
+	if (strcmp (username, "root") == 0) {
+		rc = FALSE;
+		goto out;
+	}
+
+	/* Check if the program is in any profile. */
+	program_has_profile = FALSE;
+	exec = getexecprof (NULL, KV_COMMAND, stripped_cmd, GET_ONE);
+	if (exec == NULL) {
+		goto out;
+	}
+
+	while (exec != NULL) {
+		if (exec->attr != NULL) {
+			program_has_profile = TRUE;
+			break;
+		}
+		exec = exec->next;
+	}
+
+	free_execattr (exec);
+
+	/* Check if the user can run the command.  If not filter it. */
+	exec = getexecuser (username, KV_COMMAND, stripped_cmd, GET_ONE);
+
+	/*
+	 * If the program is not associated with any profile, then do not
+	 * show it.
+	 */
+	if (exec == NULL)
+		goto out;
+
+	/*
+	 * If getexecuser does not return NULL and the program is not
+	 * associated with any profile, then show it.  Otherwise, more
+	 * tests are needed.
+	 */
+	if (use_global == TRUE || program_has_profile == FALSE) {
+		rc = FALSE;
+		free_execattr (exec);
+		goto out;
+	}
+
+	/*
+	 * If the user has a profile that can run the command, then it can
+	 * be shown.
+	 */
+	while (exec != NULL) {
+		if (exec->attr != NULL) {
+			rc = FALSE;
+			break;
+		}
+		exec = exec->next;
+	}
+
+	free_execattr (exec);
+
+	if (rc == FALSE)
+		goto out;
+
+	if (!trusted) {
+		/* If no gksu is available, then do not try to use it */
+	        path = g_find_program_in_path ("/usr/bin/gksu");
+		if (path == NULL)
+			goto out;
+	}
+
+	/* Check if the user is in a role that can run the command. */
+	/* If so, use gksu with that role */
+	if ((user = getusernam (username)) != NULL) {
+		const char *rolelist = NULL;
+		char **v = NULL;
+		char *role = NULL;
+
+		if (trusted && username != NULL) {
+			/* In trusted mode, use role associated with workspace */
+			rolelist = username;
+		} else {
+			/* Otherwise use roles associated with the user. */
+			rolelist = kva_match (user->attr, USERATTR_ROLES_KW);
+		}
+
+		if (rolelist != NULL)
+			v = g_strsplit (rolelist, ",", -1);
+
+		for (i=0; v != NULL && v[i] != NULL; i++) {
+			role = g_strdup (v[i]);
+			g_strstrip (role);
+
+			exec = getexecuser (role, KV_COMMAND, stripped_cmd, GET_ONE);
+			while (exec != NULL) {
+				if ((strcmp (role, "root") == 0) ||
+				    (exec->attr != NULL)) {
+					rc = FALSE;
+					break;
+				}
+				exec = exec->next;
+			}
+
+			g_free (role);
+			free_execattr (exec);
+
+			if (rc == FALSE) {
+				break;
+			}
+		}
+		if (v != NULL)
+			g_strfreev (v);
+	}
+
+out:
+	if (stripped_cmd)
+		g_free (stripped_cmd);
+	if (real_cmd)
+		g_free (real_cmd);
+
+	return (rc);
+}
+
+/* Function to return the zone root directory for the current workspace. */
+char *
+get_zoneroot (void)
+{
+  gpointer    wnckscreen    = NULL;
+  gpointer    wnckworkspace = NULL;
+  const char *zonelabelstr  = NULL;
+  m_label_t  *zonelabel     = NULL;
+  char       *zoneroot      = NULL;
+  int         err;
+
+  wnckscreen = libmenu_wnck_screen_get_default ();
+  if (wnckscreen != NULL)
+    wnckworkspace = libmenu_wnck_screen_get_active_workspace (wnckscreen);
+
+  if (wnckworkspace != NULL)
+    zonelabelstr = libmenu_wnck_workspace_get_label (wnckworkspace);
+
+  if (zonelabelstr != NULL)
+    str_to_label (zonelabelstr, &zonelabel, MAC_LABEL, L_NO_CORRECTION, &err);
+
+  if (zonelabel != NULL)
+    zoneroot = getzonerootbylabel (zonelabel);
+
+  return zoneroot;
+}
+
