Blob Blame History Raw
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/audit2allow policycoreutils-2.0.74/audit2allow/audit2allow
--- nsapolicycoreutils/audit2allow/audit2allow	2009-01-13 08:45:35.000000000 -0500
+++ policycoreutils-2.0.74/audit2allow/audit2allow	2009-09-20 21:26:36.000000000 -0400
@@ -42,6 +42,8 @@
         from optparse import OptionParser
 
         parser = OptionParser(version=self.VERSION)
+        parser.add_option("-b", "--boot", action="store_true", dest="boot", default=False,
+                          help="audit messages since last boot conflicts with -i")
         parser.add_option("-a", "--all", action="store_true", dest="audit", default=False,
                           help="read input from audit log - conflicts with -i")
         parser.add_option("-d", "--dmesg", action="store_true", dest="dmesg", default=False,
@@ -80,11 +82,11 @@
         options, args = parser.parse_args()
 
         # Make -d, -a, and -i conflict
-        if options.audit is True:
+        if options.audit is True or options.boot:
             if options.input is not None:
-                sys.stderr.write("error: --all conflicts with --input\n")
+                sys.stderr.write("error: --all/--boot conflicts with --input\n")
             if options.dmesg is True:
-                sys.stderr.write("error: --all conflicts with --dmesg\n")
+                sys.stderr.write("error: --all/--boot conflicts with --dmesg\n")
         if options.input is not None and options.dmesg is True:
             sys.stderr.write("error: --input conflicts with --dmesg\n")
 
@@ -129,6 +131,12 @@
             except OSError, e:
                 sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
                 sys.exit(1)
+        elif self.__options.boot:
+            try:
+                messages = audit.get_audit_boot_msgs()
+            except OSError, e:
+                sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
+                sys.exit(1)
         else:
             # This is the default if no input is specified
             f = sys.stdin
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/load_policy/Makefile policycoreutils-2.0.74/load_policy/Makefile
--- nsapolicycoreutils/load_policy/Makefile	2008-08-28 09:34:24.000000000 -0400
+++ policycoreutils-2.0.74/load_policy/Makefile	2009-09-25 15:28:19.000000000 -0400
@@ -1,6 +1,7 @@
 # Installation directories.
 PREFIX ?= ${DESTDIR}/usr
-SBINDIR ?= $(PREFIX)/sbin
+SBINDIR ?= $(DESTDIR)/sbin
+USRSBINDIR ?= $(PREFIX)/sbin
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= /usr/share/locale
 
@@ -17,6 +18,8 @@
 	install -m 755 $(TARGETS) $(SBINDIR)
 	test -d $(MANDIR)/man8 || install -m 755 -d $(MANDIR)/man8
 	install -m 644 load_policy.8 $(MANDIR)/man8/
+	-mkdir -p $(USRSBINDIR)
+	ln -s /sbin/load_policy $(USRSBINDIR)/load_policy
 
 clean:
 	-rm -f $(TARGETS) *.o 
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/Makefile policycoreutils-2.0.74/Makefile
--- nsapolicycoreutils/Makefile	2008-08-28 09:34:24.000000000 -0400
+++ policycoreutils-2.0.74/Makefile	2009-09-20 21:26:36.000000000 -0400
@@ -1,4 +1,4 @@
-SUBDIRS = setfiles semanage load_policy newrole run_init secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps setsebool po
+SUBDIRS = setfiles semanage load_policy newrole run_init sandbox secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps setsebool po gui
 
 INOTIFYH = $(shell ls /usr/include/sys/inotify.h 2>/dev/null)
 
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/Makefile policycoreutils-2.0.74/restorecond/Makefile
--- nsapolicycoreutils/restorecond/Makefile	2009-08-20 15:49:21.000000000 -0400
+++ policycoreutils-2.0.74/restorecond/Makefile	2009-09-20 21:26:36.000000000 -0400
@@ -1,17 +1,28 @@
 # Installation directories.
 PREFIX ?= ${DESTDIR}/usr
 SBINDIR ?= $(PREFIX)/sbin
+LIBDIR ?= $(PREFIX)/lib
 MANDIR = $(PREFIX)/share/man
+AUTOSTARTDIR = $(DESTDIR)/etc/xdg/autostart
+DBUSSERVICEDIR = $(DESTDIR)/usr/share/dbus-1/services
+
+autostart_DATA = sealertauto.desktop
 INITDIR = $(DESTDIR)/etc/rc.d/init.d
 SELINUXDIR = $(DESTDIR)/etc/selinux
 
+DBUSFLAGS = -DHAVE_DBUS -I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/lib/dbus-1.0/include 
+DBUSLIB = -ldbus-glib-1 
+
 CFLAGS ?= -g -Werror -Wall -W
-override CFLAGS += -I$(PREFIX)/include -D_FILE_OFFSET_BITS=64
-LDLIBS += -lselinux -L$(PREFIX)/lib
+override CFLAGS += -I$(PREFIX)/include $(DBUSFLAGS) -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/lib/glib-2.0/include
+
+LDLIBS += -lselinux $(DBUSLIB) -lglib-2.0 -L$(LIBDIR)
 
 all: restorecond
 
-restorecond:  restorecond.o utmpwatcher.o stringslist.o
+restorecond.o utmpwatcher.o stringslist.o user.o watch.o: restorecond.h 
+
+restorecond:  ../setfiles/restore.o restorecond.o utmpwatcher.o stringslist.o user.o watch.o
 	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 
 install: all
@@ -22,7 +33,12 @@
 	-mkdir -p $(INITDIR)
 	install -m 755 restorecond.init $(INITDIR)/restorecond
 	-mkdir -p $(SELINUXDIR)
-	install -m 600 restorecond.conf $(SELINUXDIR)/restorecond.conf
+	install -m 644 restorecond.conf $(SELINUXDIR)/restorecond.conf
+	install -m 644 restorecond_user.conf $(SELINUXDIR)/restorecond_user.conf
+	-mkdir -p $(AUTOSTARTDIR)
+	install -m 644 restorecond.desktop $(AUTOSTARTDIR)/restorecond.desktop
+	-mkdir -p $(DBUSSERVICEDIR)
+	install -m 600 org.selinux.Restorecond.service  $(DBUSSERVICEDIR)/org.selinux.Restorecond.service
 
 relabel: install
 	/sbin/restorecon $(SBINDIR)/restorecond 
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/org.selinux.Restorecond.service policycoreutils-2.0.74/restorecond/org.selinux.Restorecond.service
--- nsapolicycoreutils/restorecond/org.selinux.Restorecond.service	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/restorecond/org.selinux.Restorecond.service	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.selinux.Restorecond
+Exec=/usr/sbin/restorecond -u
Binary files nsapolicycoreutils/restorecond/restorecond and policycoreutils-2.0.74/restorecond/restorecond differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.c policycoreutils-2.0.74/restorecond/restorecond.c
--- nsapolicycoreutils/restorecond/restorecond.c	2009-08-20 15:49:21.000000000 -0400
+++ policycoreutils-2.0.74/restorecond/restorecond.c	2009-09-24 22:59:01.000000000 -0400
@@ -48,294 +48,38 @@
 #include <signal.h>
 #include <string.h>
 #include <unistd.h>
-#include <ctype.h>
+#include "../setfiles/restore.h"
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <syslog.h>
 #include <limits.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
 #include <fcntl.h>
-
 #include "restorecond.h"
-#include "stringslist.h"
 #include "utmpwatcher.h"
 
-extern char *dirname(char *path);
+const char *homedir;
 static int master_fd = -1;
-static int master_wd = -1;
-static int terminate = 0;
-
-#include <selinux/selinux.h>
-#include <utmp.h>
-
-/* size of the event structure, not counting name */
-#define EVENT_SIZE  (sizeof (struct inotify_event))
-/* reasonable guess as to size of 1024 events */
-#define BUF_LEN        (1024 * (EVENT_SIZE + 16))
-
-static int debug_mode = 0;
-static int verbose_mode = 0;
-
-static void restore(const char *filename, int exact);
-
-struct watchList {
-	struct watchList *next;
-	int wd;
-	char *dir;
-	struct stringsList *files;
-};
-struct watchList *firstDir = NULL;
-
-/* Compare two contexts to see if their differences are "significant",
- * or whether the only difference is in the user. */
-static int only_changed_user(const char *a, const char *b)
-{
-	char *rest_a, *rest_b;	/* Rest of the context after the user */
-	if (!a || !b)
-		return 0;
-	rest_a = strchr(a, ':');
-	rest_b = strchr(b, ':');
-	if (!rest_a || !rest_b)
-		return 0;
-	return (strcmp(rest_a, rest_b) == 0);
-}
-
-/* 
-   A file was in a direcroty has been created. This function checks to 
-   see if it is one that we are watching.
-*/
-
-static int watch_list_find(int wd, const char *file)
-{
-	struct watchList *ptr = NULL;
-	ptr = firstDir;
-
-	if (debug_mode)
-		printf("%d: File=%s\n", wd, file);
-	while (ptr != NULL) {
-		if (ptr->wd == wd) {
-			int exact=0;
-			if (strings_list_find(ptr->files, file, &exact) == 0) {
-				char *path = NULL;
-				if (asprintf(&path, "%s/%s", ptr->dir, file) <
-				    0)
-					exitApp("Error allocating memory.");
-				restore(path, exact);
-				free(path);
-				return 0;
-			}
-			if (debug_mode)
-				strings_list_print(ptr->files);
-
-			/* Not found in this directory */
-			return -1;
-		}
-		ptr = ptr->next;
-	}
-	/* Did not find a directory */
-	return -1;
-}
-
-static void watch_list_free(int fd)
-{
-	struct watchList *ptr = NULL;
-	struct watchList *prev = NULL;
-	ptr = firstDir;
-
-	while (ptr != NULL) {
-		inotify_rm_watch(fd, ptr->wd);
-		strings_list_free(ptr->files);
-		free(ptr->dir);
-		prev = ptr;
-		ptr = ptr->next;
-		free(prev);
-	}
-	firstDir = NULL;
-}
-
-/* 
-   Set the file context to the default file context for this system.
-   Same as restorecon.
-*/
-static void restore(const char *filename, int exact)
-{
-	int retcontext = 0;
-	security_context_t scontext = NULL;
-	security_context_t prev_context = NULL;
-	struct stat st;
-	int fd = -1;
-	if (debug_mode)
-		printf("restore %s\n", filename);
-
-	fd = open(filename, O_NOFOLLOW | O_RDONLY);
-	if (fd < 0) {
-		if (verbose_mode)
-			syslog(LOG_ERR, "Unable to open file (%s) %s\n",
-			       filename, strerror(errno));
-		return;
-	}
-
-	if (fstat(fd, &st) != 0) {
-		syslog(LOG_ERR, "Unable to stat file (%s) %s\n", filename,
-		       strerror(errno));
-		close(fd);
-		return;
-	}
-
-	if (!(st.st_mode & S_IFDIR) && st.st_nlink > 1) {
-		if (exact) { 
-			syslog(LOG_ERR,
-			       "Will not restore a file with more than one hard link (%s) %s\n",
-			       filename, strerror(errno));
-		}
-		close(fd);
-		return;
-	}
-
-	if (matchpathcon(filename, st.st_mode, &scontext) < 0) {
-		if (errno == ENOENT)
-			return;
-		syslog(LOG_ERR, "matchpathcon(%s) failed %s\n", filename,
-		       strerror(errno));
-		return;
-	}
-	retcontext = fgetfilecon_raw(fd, &prev_context);
-
-	if (retcontext >= 0 || errno == ENODATA) {
-		if (retcontext < 0)
-			prev_context = NULL;
-		if (retcontext < 0 || (strcmp(prev_context, scontext) != 0)) {
-
-			if (only_changed_user(scontext, prev_context) != 0) {
-				free(scontext);
-				free(prev_context);
-				close(fd);
-				return;
-			}
-
-			if (fsetfilecon(fd, scontext) < 0) {
-				if (errno != EOPNOTSUPP) 
-					syslog(LOG_ERR,
-					       "set context %s->%s failed:'%s'\n",
-					       filename, scontext, strerror(errno));
-				if (retcontext >= 0)
-					free(prev_context);
-				free(scontext);
-				close(fd);
-				return;
-			}
-			syslog(LOG_WARNING, "Reset file context %s: %s->%s\n",
-			       filename, prev_context, scontext);
-		}
-		if (retcontext >= 0)
-			free(prev_context);
-	} else {
-		if (errno != EOPNOTSUPP) 
-			syslog(LOG_ERR, "get context on %s failed: '%s'\n",
-			       filename, strerror(errno));
-	}
-	free(scontext);
-	close(fd);
-}
-
-static void process_config(int fd, FILE * cfg)
-{
-	char *line_buf = NULL;
-	size_t len = 0;
-
-	while (getline(&line_buf, &len, cfg) > 0) {
-		char *buffer = line_buf;
-		while (isspace(*buffer))
-			buffer++;
-		if (buffer[0] == '#')
-			continue;
-		int l = strlen(buffer) - 1;
-		if (l <= 0)
-			continue;
-		buffer[l] = 0;
-		if (buffer[0] == '~')
-			utmpwatcher_add(fd, &buffer[1]);
-		else {
-			watch_list_add(fd, buffer);
-		}
-	}
-	free(line_buf);
-}
-
-/* 
-   Read config file ignoring Comment lines 
-   Files specified one per line.  Files with "~" will be expanded to the logged in users
-   homedirs.
-*/
 
-static void read_config(int fd)
-{
-	char *watch_file_path = "/etc/selinux/restorecond.conf";
+static char *server_watch_file  = "/etc/selinux/restorecond.conf";
+static char *user_watch_file  = "/etc/selinux/restorecond_user.conf";
+static char *watch_file;
+static struct restore_opts r_opts;
 
-	FILE *cfg = NULL;
-	if (debug_mode)
-		printf("Read Config\n");
-
-	watch_list_free(fd);
-
-	cfg = fopen(watch_file_path, "r");
-	if (!cfg)
-		exitApp("Error reading config file.");
-	process_config(fd, cfg);
-	fclose(cfg);
-
-	inotify_rm_watch(fd, master_wd);
-	master_wd =
-	    inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY);
-	if (master_wd == -1)
-		exitApp("Error watching config file.");
-}
+#include <selinux/selinux.h>
 
-/* 
-   Inotify watch loop 
-*/
-static int watch(int fd)
-{
-	char buf[BUF_LEN];
-	int len, i = 0;
-	len = read(fd, buf, BUF_LEN);
-	if (len < 0) {
-		if (terminate == 0) {
-			syslog(LOG_ERR, "Read error (%s)", strerror(errno));
-			return 0;
-		}
-		syslog(LOG_ERR, "terminated");
-		return -1;
-	} else if (!len)
-		/* BUF_LEN too small? */
-		return -1;
-	while (i < len) {
-		struct inotify_event *event;
-		event = (struct inotify_event *)&buf[i];
-		if (debug_mode)
-			printf("wd=%d mask=%u cookie=%u len=%u\n",
-			       event->wd, event->mask,
-			       event->cookie, event->len);
-		if (event->wd == master_wd)
-			read_config(fd);
-		else {
-			switch (utmpwatcher_handle(fd, event->wd)) {
-			case -1:	/* Message was not for utmpwatcher */
-				if (event->len)
-					watch_list_find(event->wd, event->name);
-				break;
-
-			case 1:	/* utmp has changed need to reload */
-				read_config(fd);
-				break;
-
-			default:	/* No users logged in or out */
-				break;
-			}
-		}
+int debug_mode = 0;
+int terminate = 0;
+int master_wd = -1;
+int run_as_user = 0;
 
-		i += EVENT_SIZE + event->len;
-	}
-	return 0;
+static void done(void) {
+	watch_list_free(master_fd);
+	close(master_fd);
+	utmpwatcher_free();
+	matchpathcon_fini();
 }
 
 static const char *pidfile = "/var/run/restorecond.pid";
@@ -374,7 +118,7 @@
 
 static void usage(char *program)
 {
-	printf("%s [-d] [-v] \n", program);
+	printf("%s [-d] [-s] [-f restorecond_file ] [-v] \n", program);
 	exit(0);
 }
 
@@ -390,74 +134,33 @@
    to see if it is one that we are watching.
 */
 
-void watch_list_add(int fd, const char *path)
-{
-	struct watchList *ptr = NULL;
-	struct watchList *prev = NULL;
-	char *x = strdup(path);
-	if (!x)
-		exitApp("Out of Memory");
-	char *dir = dirname(x);
-	char *file = basename(path);
-	ptr = firstDir;
-
-	restore(path, 1);
-
-	while (ptr != NULL) {
-		if (strcmp(dir, ptr->dir) == 0) {
-			strings_list_add(&ptr->files, file);
-			free(x);
-			return;
-		}
-		prev = ptr;
-		ptr = ptr->next;
-	}
-	ptr = calloc(1, sizeof(struct watchList));
-
-	if (!ptr)
-		exitApp("Out of Memory");
-
-	ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
-	if (ptr->wd == -1) {
-		free(ptr);
-		syslog(LOG_ERR, "Unable to watch (%s) %s\n",
-		       path, strerror(errno));
-		return;
-	}
-
-	ptr->dir = strdup(dir);
-	if (!ptr->dir)
-		exitApp("Out of Memory");
-
-	strings_list_add(&ptr->files, file);
-	if (prev)
-		prev->next = ptr;
-	else
-		firstDir = ptr;
-
-	if (debug_mode)
-		printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file);
-
-	free(x);
-}
-
 int main(int argc, char **argv)
 {
 	int opt;
 	struct sigaction sa;
 
-#ifndef DEBUG
-	/* Make sure we are root */
-	if (getuid() != 0) {
-		fprintf(stderr, "You must be root to run this program.\n");
-		return 1;
-	}
-#endif
-	/* Make sure we are root */
-	if (is_selinux_enabled() != 1) {
-		fprintf(stderr, "Daemon requires SELinux be enabled to run.\n");
-		return 1;
-	}
+	memset(&r_opts, 0, sizeof(r_opts));
+
+	r_opts.progress = 0;
+	r_opts.count = 0;
+	r_opts.debug = 0;
+	r_opts.change = 1;
+	r_opts.verbose = 0;
+	r_opts.logging = 0;
+	r_opts.rootpath = NULL;
+	r_opts.rootpathlen = 0;
+	r_opts.outfile = NULL;
+	r_opts.force = 0;
+	r_opts.hard_links = 0;
+	r_opts.abort_on_error = 0;
+	r_opts.add_assoc = 0;
+	r_opts.fts_flags = FTS_PHYSICAL;
+	r_opts.selabel_opt_validate = NULL;
+	r_opts.selabel_opt_path = NULL;
+	
+	restore_init(&r_opts);
+	/* If we are not running SELinux then just exit */
+	if (is_selinux_enabled() != 1) return 0;
 
 	/* Register sighandlers */
 	sa.sa_flags = 0;
@@ -467,38 +170,59 @@
 
 	set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
 
-	master_fd = inotify_init();
-	if (master_fd < 0)
-		exitApp("inotify_init");
-
-	while ((opt = getopt(argc, argv, "dv")) > 0) {
+	atexit( done );
+	while ((opt = getopt(argc, argv, "uf:dv")) > 0) {
 		switch (opt) {
 		case 'd':
 			debug_mode = 1;
 			break;
+		case 'f':
+			watch_file = optarg;
+			break;
+		case 'u':
+			run_as_user = 1;
+			break;
 		case 'v':
-			verbose_mode = 1;
+			r_opts.verbose++;
 			break;
 		case '?':
 			usage(argv[0]);
 		}
 	}
-	read_config(master_fd);
+
+	master_fd = inotify_init();
+	if (master_fd < 0)
+		exitApp("inotify_init");
+
+	uid_t uid = getuid();
+	struct passwd *pwd = getpwuid(uid);
+	homedir = pwd->pw_dir;
+	if (uid != 0) {
+		if (run_as_user)
+			return server(master_fd, user_watch_file);
+		if (start() != 0) 
+			return server(master_fd, user_watch_file);
+		return 0;
+	}
+
+	watch_file = server_watch_file;
+	read_config(master_fd, watch_file);
 
 	if (!debug_mode)
 		daemon(0, 0);
 
 	write_pid_file();
 
-	while (watch(master_fd) == 0) {
+	while (watch(master_fd, watch_file) == 0) {
 	};
 
 	watch_list_free(master_fd);
 	close(master_fd);
 	matchpathcon_fini();
-	utmpwatcher_free();
 	if (pidfile)
 		unlink(pidfile);
 
 	return 0;
 }
+
+
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.conf policycoreutils-2.0.74/restorecond/restorecond.conf
--- nsapolicycoreutils/restorecond/restorecond.conf	2009-08-20 15:49:21.000000000 -0400
+++ policycoreutils-2.0.74/restorecond/restorecond.conf	2009-09-20 21:26:36.000000000 -0400
@@ -4,8 +4,5 @@
 /etc/mtab
 /var/run/utmp
 /var/log/wtmp
-~/*
-/root/.ssh
+/root/*
 /root/.ssh/*
-
-
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.desktop policycoreutils-2.0.74/restorecond/restorecond.desktop
--- nsapolicycoreutils/restorecond/restorecond.desktop	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/restorecond/restorecond.desktop	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=File Context maintainer
+Exec=/usr/sbin/restorecond -u
+Comment=Fix file context in owned by the user
+Encoding=UTF-8
+Type=Application
+StartupNotify=false
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.h policycoreutils-2.0.74/restorecond/restorecond.h
--- nsapolicycoreutils/restorecond/restorecond.h	2009-08-20 15:49:21.000000000 -0400
+++ policycoreutils-2.0.74/restorecond/restorecond.h	2009-09-20 21:26:36.000000000 -0400
@@ -24,7 +24,21 @@
 #ifndef RESTORED_CONFIG_H
 #define RESTORED_CONFIG_H
 
-void exitApp(const char *msg);
-void watch_list_add(int inotify_fd, const char *path);
+extern int debug_mode;
+extern const char *homedir;
+extern int terminate;
+extern int master_wd;
+extern int run_as_user;
+
+extern int start(void);
+extern int server(int, const char *watch_file);
+
+extern void exitApp(const char *msg);
+extern void read_config(int fd,	const char *watch_file);
+
+extern int watch(int fd, const char *watch_file);
+extern void watch_list_add(int inotify_fd, const char *path);
+extern int watch_list_find(int wd, const char *file);
+extern void watch_list_free(int fd);
 
 #endif
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.init policycoreutils-2.0.74/restorecond/restorecond.init
--- nsapolicycoreutils/restorecond/restorecond.init	2009-08-20 15:49:21.000000000 -0400
+++ policycoreutils-2.0.74/restorecond/restorecond.init	2009-09-20 21:26:36.000000000 -0400
@@ -75,16 +75,15 @@
 	status restorecond
 	RETVAL=$?
 	;;
-  restart|reload)
+  force-reload|restart|reload)
 	restart
 	;;
   condrestart)
 	[ -e /var/lock/subsys/restorecond ] && restart || :
 	;;
   *)
-        echo $"Usage: $0 {start|stop|restart|reload|condrestart}"
+        echo $"Usage: $0 {start|stop|restart|force-reload|status|condrestart}"
         RETVAL=3
 esac
 
 exit $RETVAL
-
Binary files nsapolicycoreutils/restorecond/restorecond.o and policycoreutils-2.0.74/restorecond/restorecond.o differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond_user.conf policycoreutils-2.0.74/restorecond/restorecond_user.conf
--- nsapolicycoreutils/restorecond/restorecond_user.conf	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/restorecond/restorecond_user.conf	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,2 @@
+~/*
+~/public_html/*
Binary files nsapolicycoreutils/restorecond/stringslist.o and policycoreutils-2.0.74/restorecond/stringslist.o differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/user.c policycoreutils-2.0.74/restorecond/user.c
--- nsapolicycoreutils/restorecond/user.c	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/restorecond/user.c	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,237 @@
+/*
+ * restorecond
+ *
+ * Copyright (C) 2006-2009 Red Hat 
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+.* 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     
+ * 02111-1307  USA
+ *
+ * Authors:  
+ *   Dan Walsh <dwalsh@redhat.com>
+ *
+*/
+
+#define _GNU_SOURCE
+#include <sys/inotify.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include "restorecond.h"
+#include "stringslist.h"
+#include <glib.h>
+#ifdef HAVE_DBUS
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
+
+static const char *PATH="/org/selinux/Restorecond";
+//static const char *BUSNAME="org.selinux.Restorecond";
+static const char *INTERFACE="org.selinux.RestorecondIface";
+static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
+
+
+static DBusHandlerResult
+signal_filter (DBusConnection *connection  __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
+{
+  /* User data is the event loop we are running in */
+  GMainLoop *loop = user_data;
+
+  /* A signal from the bus saying we are about to be disconnected */
+  if (dbus_message_is_signal 
+        (message, INTERFACE, "Stop")) {
+	  
+      /* Tell the main loop to quit */
+      g_main_loop_quit (loop);
+      /* We have handled this message, don't pass it on */
+      return DBUS_HANDLER_RESULT_HANDLED;
+  }
+  /* A Ping signal on the com.burtonini.dbus.Signal interface */
+  else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
+    DBusError error;
+    dbus_error_init (&error);
+    g_print("Start received\n");
+    return DBUS_HANDLER_RESULT_HANDLED;
+  }
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static int dbus_server(GMainLoop *loop) {
+    DBusConnection *bus;
+    DBusError error;
+    dbus_error_init (&error);
+    bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+    if (bus) {
+	dbus_connection_setup_with_g_main (bus, NULL);
+	
+	/* listening to messages from all objects as no path is specified */
+	dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
+	dbus_connection_add_filter (bus, signal_filter, loop, NULL);
+	return 0;
+    } 
+    return -1;
+}
+
+#endif
+#include <selinux/selinux.h>
+#include <sys/file.h>
+
+/* size of the event structure, not counting name */
+#define EVENT_SIZE  (sizeof (struct inotify_event))
+/* reasonable guess as to size of 1024 events */
+#define BUF_LEN        (1024 * (EVENT_SIZE + 16))
+
+static gboolean
+io_channel_callback
+ (GIOChannel *source,
+  GIOCondition condition,
+  gpointer data __attribute__((__unused__)))
+{
+
+  char buffer[BUF_LEN+1];
+  gsize bytes_read;
+  unsigned int i = 0;
+
+  if (condition & G_IO_IN) {
+    /* Data is available. */
+    g_io_channel_read
+      (source, buffer,
+       sizeof (buffer),
+       &bytes_read);
+
+    while (i < bytes_read) {
+	    struct inotify_event *event;
+	    event = (struct inotify_event *)&buffer[i];
+	    if (debug_mode)
+		    printf("wd=%d mask=%u cookie=%u len=%u\n",
+			   event->wd, event->mask,
+			   event->cookie, event->len);
+	    if (event->len)
+		    watch_list_find(event->wd, event->name);
+	    
+	    i += EVENT_SIZE + event->len;
+    }
+  }
+
+  /* An error happened while reading
+     the file. */
+
+  if (condition & G_IO_NVAL)
+    return FALSE;
+
+  /* We have reached the end of the
+     file. */
+
+  if (condition & G_IO_HUP) {
+    g_io_channel_close (source);
+    return FALSE;
+  }
+
+  /* Returning TRUE will make sure
+     the callback remains associated
+     to the channel. */
+
+  return TRUE;
+}
+
+int start() {
+#ifdef HAVE_DBUS
+	DBusConnection *bus;
+	DBusError error;
+	DBusMessage *message;
+	
+	/* Get a connection to the session bus */
+	dbus_error_init (&error);
+	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+	if (!bus) {
+		if (debug_mode)
+			g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
+		dbus_error_free (&error);
+		return 1;
+	}
+	
+
+	/* Create a new signal "Start" on the interface,
+	 * from the object  */
+	message = dbus_message_new_signal (PATH,
+					   INTERFACE, "Start");
+	/* Send the signal */
+	dbus_connection_send (bus, message, NULL);
+	/* Free the signal now we have finished with it */
+	dbus_message_unref (message);
+#endif /* HAVE_DBUS */
+	return 0;
+}
+
+static int local_server() {
+	// ! dbus, run as local service
+	char *ptr=NULL;
+	asprintf(&ptr, "%s/.restorecond", homedir);
+	int fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+	if (debug_mode)
+		g_warning ("Lock file: %s", ptr);
+	
+	free(ptr);
+	if (fd < 0) {
+		if (debug_mode)
+			perror("open");
+		return -1;
+	}
+	if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+		if (debug_mode)
+			perror("flock");
+		return -1;
+	}
+	return 0;
+}
+
+int server(int master_fd, const char *watch_file) {
+    GMainLoop *loop;
+
+    loop = g_main_loop_new (NULL, FALSE);
+    
+#ifdef HAVE_DBUS
+    if (dbus_server(loop) != 0) 
+#endif /* HAVE_DBUS */
+	    if (local_server(loop) != 0) 
+		    return 0;
+
+    read_config(master_fd, watch_file);
+    
+    set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
+    
+    GIOChannel *c = g_io_channel_unix_new(master_fd);
+    
+    g_io_add_watch_full( c,
+			 G_PRIORITY_HIGH,
+			 G_IO_IN|G_IO_ERR|G_IO_HUP,
+			 io_channel_callback, NULL, NULL);
+    
+    g_main_loop_run (loop);
+    return 0;
+}
+
Binary files nsapolicycoreutils/restorecond/user.o and policycoreutils-2.0.74/restorecond/user.o differ
Binary files nsapolicycoreutils/restorecond/utmpwatcher.o and policycoreutils-2.0.74/restorecond/utmpwatcher.o differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/watch.c policycoreutils-2.0.74/restorecond/watch.c
--- nsapolicycoreutils/restorecond/watch.c	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/restorecond/watch.c	2009-10-06 12:06:56.000000000 -0400
@@ -0,0 +1,253 @@
+#define _GNU_SOURCE
+#include <sys/inotify.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include "../setfiles/restore.h"
+#include <glob.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <selinux/selinux.h>
+#include "restorecond.h"
+#include "stringslist.h"
+#include "utmpwatcher.h"
+
+/* size of the event structure, not counting name */
+#define EVENT_SIZE  (sizeof (struct inotify_event))
+/* reasonable guess as to size of 1024 events */
+#define BUF_LEN        (1024 * (EVENT_SIZE + 16))
+
+
+struct watchList {
+	struct watchList *next;
+	int wd;
+	char *dir;
+	struct stringsList *files;
+};
+struct watchList *firstDir = NULL;
+
+
+void watch_list_add(int fd, const char *path)
+{
+	struct watchList *ptr = NULL;
+	size_t i = 0;
+	struct watchList *prev = NULL;
+	glob_t globbuf;
+	char *x = strdup(path);
+	if (!x) exitApp("Out of Memory");
+	char *file = basename(x);
+	char *dir = dirname(x);
+	ptr = firstDir;
+
+	globbuf.gl_offs = 1;
+	if (glob(path, 
+		 GLOB_TILDE | GLOB_PERIOD,
+		 NULL,
+		 &globbuf) >= 0) {
+		for (i=0; i < globbuf.gl_pathc; i++) {
+		  int len = strlen(globbuf.gl_pathv[i]) -2;
+		  if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) continue;
+		  if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) continue;
+		  if (process_one(globbuf.gl_pathv[i], 0) > 0)
+		    process_one(globbuf.gl_pathv[i], 1);
+		}
+		globfree(&globbuf);
+	}
+
+	while (ptr != NULL) {
+		if (strcmp(dir, ptr->dir) == 0) {
+			strings_list_add(&ptr->files, file);
+			free(x);
+			return;
+		}
+		prev = ptr;
+		ptr = ptr->next;
+	}
+	ptr = calloc(1, sizeof(struct watchList));
+
+	if (!ptr) exitApp("Out of Memory");
+
+	ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
+	if (ptr->wd == -1) {
+		free(ptr);
+		free(x);
+		syslog(LOG_ERR, "Unable to watch (%s) %s\n",
+		       path, strerror(errno));
+		return;
+	}
+
+	ptr->dir = strdup(dir);
+	if (!ptr->dir)
+		exitApp("Out of Memory");
+
+	strings_list_add(&ptr->files, file);
+	if (prev)
+		prev->next = ptr;
+	else
+		firstDir = ptr;
+
+	if (debug_mode)
+		printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file);
+
+	free(x);
+}
+
+/* 
+   A file was in a direcroty has been created. This function checks to 
+   see if it is one that we are watching.
+*/
+
+int watch_list_find(int wd, const char *file)
+{
+	struct watchList *ptr = NULL;
+	ptr = firstDir;
+	if (debug_mode)
+		printf("%d: File=%s\n", wd, file);
+	while (ptr != NULL) {
+		if (ptr->wd == wd) {
+			int exact=0;
+			if (strings_list_find(ptr->files, file, &exact) == 0) {
+				char *path = NULL;
+				if (asprintf(&path, "%s/%s", ptr->dir, file) <
+				    0)
+					exitApp("Error allocating memory.");
+				
+				process_one(path, 0);
+				free(path);
+				return 0;
+			}
+			if (debug_mode)
+				strings_list_print(ptr->files);
+
+			/* Not found in this directory */
+			return -1;
+		}
+		ptr = ptr->next;
+	}
+	/* Did not find a directory */
+	return -1;
+}
+
+void watch_list_free(int fd)
+{
+	struct watchList *ptr = NULL;
+	struct watchList *prev = NULL;
+	ptr = firstDir;
+
+	while (ptr != NULL) {
+		inotify_rm_watch(fd, ptr->wd);
+		strings_list_free(ptr->files);
+		free(ptr->dir);
+		prev = ptr;
+		ptr = ptr->next;
+		free(prev);
+	}
+	firstDir = NULL;
+}
+
+/* 
+   Inotify watch loop 
+*/
+int watch(int fd, const char *watch_file)
+{
+	char buf[BUF_LEN];
+	int len, i = 0;
+	len = read(fd, buf, BUF_LEN);
+	if (len < 0) {
+		if (terminate == 0) {
+			syslog(LOG_ERR, "Read error (%s)", strerror(errno));
+			return 0;
+		}
+		syslog(LOG_ERR, "terminated");
+		return -1;
+	} else if (!len)
+		/* BUF_LEN too small? */
+		return -1;
+	while (i < len) {
+		struct inotify_event *event;
+		event = (struct inotify_event *)&buf[i];
+		if (debug_mode)
+			printf("wd=%d mask=%u cookie=%u len=%u\n",
+			       event->wd, event->mask,
+			       event->cookie, event->len);
+		if (event->wd == master_wd)
+			read_config(fd, watch_file);
+		else {
+			if (event->len)
+				watch_list_find(event->wd, event->name);
+		}
+
+		i += EVENT_SIZE + event->len;
+	}
+	return 0;
+}
+
+static void process_config(int fd, FILE * cfg)
+{
+	char *line_buf = NULL;
+	size_t len = 0;
+
+	while (getline(&line_buf, &len, cfg) > 0) {
+		char *buffer = line_buf;
+		while (isspace(*buffer))
+			buffer++;
+		if (buffer[0] == '#')
+			continue;
+		int l = strlen(buffer) - 1;
+		if (l <= 0)
+			continue;
+		buffer[l] = 0;
+		if (buffer[0] == '~') {
+			if (run_as_user) {
+				char *ptr=NULL;
+				asprintf(&ptr, "%s%s", homedir, &buffer[1]);
+				watch_list_add(fd, ptr);
+				free(ptr);
+			} else {
+				utmpwatcher_add(fd, &buffer[1]);
+			}
+		} else {
+			watch_list_add(fd, buffer);
+		}
+	}
+	free(line_buf);
+}
+
+/* 
+   Read config file ignoring Comment lines 
+   Files specified one per line.  Files with "~" will be expanded to the logged in users
+   homedirs.
+*/
+
+void read_config(int fd, const char *watch_file_path)
+{
+
+	FILE *cfg = NULL;
+	if (debug_mode)
+		printf("Read Config\n");
+
+	watch_list_free(fd);
+
+	cfg = fopen(watch_file_path, "r");
+	if (!cfg){
+		perror(watch_file_path);
+		exitApp("Error reading config file");
+	}
+	process_config(fd, cfg);
+	fclose(cfg);
+
+	inotify_rm_watch(fd, master_wd);
+	master_wd =
+	    inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY);
+	if (master_wd == -1)
+		exitApp("Error watching config file.");
+}
+
Binary files nsapolicycoreutils/restorecond/watch.o and policycoreutils-2.0.74/restorecond/watch.o differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/basicwrapper policycoreutils-2.0.74/sandbox/deliverables/basicwrapper
--- nsapolicycoreutils/sandbox/deliverables/basicwrapper	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/deliverables/basicwrapper	2009-08-14 10:53:53.000000000 -0400
@@ -0,0 +1,4 @@
+import os, sys
+SANDBOX_ARGS = ['-f%s' % os.environ['_CONDOR_SCRATCH_DIR']]
+SANDBOX_ARGS.extend(sys.argv[1::])
+os.execv('/usr/bin/sandbox',SANDBOX_ARGS)
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/README policycoreutils-2.0.74/sandbox/deliverables/README
--- nsapolicycoreutils/sandbox/deliverables/README	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/deliverables/README	2009-08-14 10:56:22.000000000 -0400
@@ -0,0 +1,32 @@
+Files:
+run-in-sandbox.py:
+   adds the run in sandbox extension to nautilus
+   copy to .nautilus/python-extensions
+   yum install nautilus-python
+
+sandbox:
+   adds support for file checking, This was working I don't know why it didn't at that presentation
+   adds support for file relabeling, This is/was also working.
+
+basicwrapper:
+   This is pretty much the most basic condor wrapper you can create, it requires the -f option in sandbox. Also I can't make this work, maybe the grid team will have more luck.
+
+Other:
+Xguest Live cd:
+   There's a tutorial on live cds here: http://www.ibm.com/developerworks/library/l-fedora-livecd/index.html?ca=dgr-lnxw16FedoraLiveCD
+   It looks like David Zeuthen is head guy in the live cd department, he might be worth talking to.
+
+System-config-selinux:
+   wiki: fedorahosted.org/system-config-selinux
+   realeases: fedorahosted.org/releases/s/y/system-config-selinux/ includes a spec,srpm, and tarball of current version
+   The project is technically owned by Roman Rakus (rrakus@redhat.com) I've sent him an email asking him to make you a git contributor.
+   I'll continue making updates to this and make sure it gets into the repos.
+
+Assuming I don't get to keep my RedHat email you can contact me:
+email: chris.pardy@gmail.com
+phone: 1-207-838-7119
+
+I'll probably continue to be on the #fedora-selinux and #selinux irc channels
+
+Thanks for a great summer.
+Chris Pardy
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/run-in-sandbox.py policycoreutils-2.0.74/sandbox/deliverables/run-in-sandbox.py
--- nsapolicycoreutils/sandbox/deliverables/run-in-sandbox.py	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/deliverables/run-in-sandbox.py	2009-08-14 10:25:38.000000000 -0400
@@ -0,0 +1,49 @@
+import os
+import os.path
+import urllib
+
+import nautilus
+import gtk
+import gconf
+
+class RunInSandboxExtension(nautilus.MenuProvider):
+    def __init__(self):
+        self.client = gconf.client_get_default()
+
+    def sandbox_init(self,file,path):
+        if os.path.basename(path).endswith('.desktop'):
+            import re
+            f = open(path,'r')
+            for i in f.readlines():
+                m = re.match(r'Exec=(?P<name>\S+)',i)
+                if m:
+                    path = m.group('name')
+                    f.close()
+                    break
+        os.system('/usr/bin/sandbox -X %s &' % path)
+
+    def get_file_items(self, window, files):
+        if len(files) != 1:
+            return
+        
+        file = files[0]
+        
+        if file.is_directory():
+            return
+        
+        if file.get_uri_scheme() != 'file':
+            return
+
+        path = file.get_uri().replace('file://','',1)
+        if not os.access(path,os.X_OK):
+            return
+        
+        path = os.path.realpath(path)
+
+        item = nautilus.MenuItem('NautilusPython::openterminal_file_items','Run In Sandbox','Run %s in Sandbox' % file.get_name())
+        item.connect('activate',self.sandbox_init,path)
+        return item,
+
+    def get_background_items(self, window, file):
+        return
+
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/sandbox policycoreutils-2.0.74/sandbox/deliverables/sandbox
--- nsapolicycoreutils/sandbox/deliverables/sandbox	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/deliverables/sandbox	2009-08-14 10:22:47.000000000 -0400
@@ -0,0 +1,216 @@
+#!/usr/bin/python -E
+import os, sys, getopt, socket, random, fcntl, shutil
+import selinux
+
+PROGNAME = "policycoreutils"
+
+import gettext
+gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
+gettext.textdomain(PROGNAME)
+
+try:
+       gettext.install(PROGNAME,
+                       localedir = "/usr/share/locale",
+                       unicode=False,
+                       codeset = 'utf-8')
+except IOError:
+       import __builtin__
+       __builtin__.__dict__['_'] = unicode
+
+
+DEFAULT_TYPE = "sandbox_t"
+DEFAULT_X_TYPE = "sandbox_x_t"
+
+X_FILES = {}
+OLD_FCONTEXTS = {}
+
+random.seed(None)
+
+def error_exit(msg):
+    sys.stderr.write("%s: " % sys.argv[0])
+    sys.stderr.write("%s\n" % msg)
+    sys.stderr.flush()
+    sys.exit(1)
+
+def reserve(mcs):
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock.bind("\0%s" % mcs)
+    fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+
+def gen_context(setype):
+    while True:
+        i1 = random.randrange(0, 1024)
+        i2 = random.randrange(0, 1024)
+        if i1 == i2:
+            continue
+        if i1 > i2:
+            tmp = i1
+            i1 = i2
+            i2 = tmp
+        mcs = "s0:c%d,c%d" % (i1, i2)
+        reserve(mcs)
+        try:
+            reserve(mcs)
+        except:
+            continue
+        break
+    con = selinux.getcon()[1].split(":")
+
+    execcon = "%s:%s:%s:%s" % (con[0], con[1], setype, mcs)
+    
+    filecon = "%s:%s:%s:%s" % (con[0], 
+                               "object_r", 
+                               "%s_file_t" % setype[:-2], 
+                               mcs)
+    return execcon, filecon
+
+def copyfile(file, dir, dest):
+       import re
+       if file.startswith(dir):
+              dname = os.path.dirname(file)
+              bname = os.path.basename(file)
+              if dname == dir:
+                     dest = dest + "/" + bname
+              else:
+                     newdir = re.sub(dir, dest, dname)
+                     os.makedirs(newdir)
+                     dest = newdir + "/" + bname
+
+              if os.path.isdir(file):
+                     shutil.copytree(file, dest)
+              else:
+                     shutil.copy2(file, dest)
+              X_FILES[dest] = os.path.getmtime(dest)
+
+def copyfiles(newhomedir, newtmpdir, files):
+       import pwd
+       homedir=pwd.getpwuid(os.getuid()).pw_dir
+       
+       for f in files:
+              copyfile(f,homedir, newhomedir)
+              copyfile(f,"/tmp", newtmpdir)
+
+def uncopyfile(newhomedir,file):
+      import pwd
+      homedir=pwd.getpwuid(os.getuid()).pw_dir
+      copyfile(file,newhomedir,homedir)
+
+if __name__ == '__main__':
+    if selinux.is_selinux_enabled() != 1:
+        error_exit("Requires an SELinux enabled system")
+        
+    init_files = []
+
+    def usage(message = ""):
+        text = _("""
+sandbox [-h] [-I includefile ] [[-i file ] ...] [[-f file] ...][ -t type ] command
+""")
+        error_exit("%s\n%s" % (message, text))
+
+    setype = DEFAULT_TYPE
+    X_ind = False
+    try:
+           gopts, cmds = getopt.getopt(sys.argv[1:], "i:ht:XI:f:", 
+                                       ["help",
+                                        "include=", 
+                                        "includefile=", 
+                                        "type="
+					"file="
+                                        ])
+           for o, a in gopts:
+                  if o == "-t" or o == "--type":
+                         setype = a
+                         
+                  if o == "-i" or o == "--include":
+                         rp = os.path.realpath(a)
+                         if rp not in init_files:
+                                init_files.append(rp)
+
+                  if o == "-f" or o == "--file":
+                         rp = os.path.realpath(a)
+                         OLD_FCONTEXTS[a] = selinux.getfilecon(rp)[1]
+                         
+                  if o == "-I" or o == "--includefile":
+                         fd = open(a, "r")
+                         for i in fd.read().split("\n"):
+                                if os.path.exists(i):
+                                       rp = os.path.realpath(i)
+                                       if rp not in init_files:
+                                              init_files.append(rp)
+                                       
+                         fd.close
+                         
+                  if o == "-X":
+                         if DEFAULT_TYPE == setype:
+                                setype = DEFAULT_X_TYPE
+                         X_ind = True
+
+                  if o == "-h" or o == "--help":
+                         usage(_("Usage"));
+            
+           if len(cmds) == 0:
+                  usage(_("Command required"))
+
+           execcon, filecon = gen_context(setype)
+           rc = -1
+
+           if cmds[0][0] != "/" and cmds[0][:2] != "./" and cmds[0][:3] != "../":
+                  for i in  os.environ["PATH"].split(':'):
+                         f = "%s/%s" % (i, cmds[0])
+                         if os.access(f, os.X_OK):
+                                cmds[0] = f
+                                break
+
+           try:
+                  if X_ind:
+                         import warnings
+                         warnings.simplefilter("ignore")
+                         newhomedir = os.tempnam(".", ".sandbox%s")
+                         os.mkdir(newhomedir)
+                         selinux.setfilecon(newhomedir, filecon) 
+                         newtmpdir = os.tempnam("/tmp", ".sandbox")
+                         os.mkdir(newtmpdir)
+                         selinux.setfilecon(newtmpdir, filecon)
+                         warnings.resetwarnings()
+                         copyfiles(newhomedir, newtmpdir, init_files + cmds)
+                         execfile = newhomedir + "/.sandboxrc"
+                         fd = open(execfile, "w+")
+                         fd.write("""#! /bin/sh
+%s
+""" % " ".join(cmds))
+                         fd.close()
+                         os.chmod(execfile, 0700)
+                         
+                         cmds =  ("/usr/sbin/seunshare -t %s -h %s -- %s /usr/share/sandbox/sandboxX.sh" % (newtmpdir, newhomedir, execcon)).split()
+                         rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
+                         for i in X_FILES.keys():
+                             if os.path.getmtime(i) > X_FILES[i]:
+                                 yn = raw_input("do you want to save your changes to the file %s (Y/N): " % os.path.basename(i)).lower()
+                                 if yn.startswith('y'):
+                                      uncopyfile(newhomedir,i)
+                  else:
+                         for i in OLD_FCONTEXTS.keys():
+                            selinux.setfilecon(i,filecon)
+                         selinux.setexeccon(execcon)
+                         rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
+                         selinux.setexeccon(None)
+                         for i in OLD_FCONTEXTS.keys():
+                            selinux.setfilecon(i,OLD_FCONTEXTS[i])
+           finally:
+                  if X_ind:
+                         shutil.rmtree(newhomedir)
+                         shutil.rmtree(newtmpdir)
+                  
+    except getopt.GetoptError, error:
+           usage(_("Options Error %s ") % error.msg)
+    except OSError, error:
+           error_exit(error.args[1])
+    except ValueError, error:
+           error_exit(error.args[0])
+    except KeyError, error:
+           error_exit(_("Invalid value %s") % error.args[0])
+    except IOError, error:
+           error_exit(error.args[1])
+        
+    sys.exit(rc)
+
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/Makefile policycoreutils-2.0.74/sandbox/Makefile
--- nsapolicycoreutils/sandbox/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/Makefile	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,31 @@
+# Installation directories.
+PREFIX ?= ${DESTDIR}/usr
+BINDIR ?= $(PREFIX)/bin
+SBINDIR ?= $(PREFIX)/sbin
+MANDIR ?= $(PREFIX)/share/man
+LOCALEDIR ?= /usr/share/locale
+SHAREDIR ?= $(PREFIX)/share/sandbox
+override CFLAGS += $(LDFLAGS) -I$(PREFIX)/include -DPACKAGE="\"policycoreutils\""
+LDLIBS += -lselinux -lcap-ng 
+
+all: sandbox seunshare sandboxX.sh 
+
+seunshare: seunshare.o $(EXTRA_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+install: all
+	-mkdir -p $(BINDIR)
+	install -m 755 sandbox $(BINDIR)
+	-mkdir -p $(MANDIR)/man8
+	install -m 644 sandbox.8 $(MANDIR)/man8/
+	install -m 4755 seunshare $(SBINDIR)/
+	-mkdir -p $(SHAREDIR)
+	install -m 755 sandboxX.sh $(SHAREDIR)
+
+clean:
+	-rm -f seunshare *.o *~
+
+indent:
+	../../scripts/Lindent $(wildcard *.[ch])
+
+relabel:
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox policycoreutils-2.0.74/sandbox/sandbox
--- nsapolicycoreutils/sandbox/sandbox	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/sandbox	2009-10-06 11:48:36.000000000 -0400
@@ -0,0 +1,242 @@
+#!/usr/bin/python -E
+import os, sys, getopt, socket, random, fcntl, shutil
+import selinux
+import signal
+
+PROGNAME = "policycoreutils"
+
+import gettext
+gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
+gettext.textdomain(PROGNAME)
+
+try:
+       gettext.install(PROGNAME,
+                       localedir = "/usr/share/locale",
+                       unicode=False,
+                       codeset = 'utf-8')
+except IOError:
+       import __builtin__
+       __builtin__.__dict__['_'] = unicode
+
+
+DEFAULT_TYPE = "sandbox_t"
+DEFAULT_X_TYPE = "sandbox_x_t"
+X_FILES = {}
+
+random.seed(None)
+
+def sighandler(signum, frame):
+    signal.signal(signum,  signal.SIG_IGN)
+    os.kill(0, signum)
+    raise KeyboardInterrupt
+
+def setup_sighandlers():
+    signal.signal(signal.SIGHUP,  sighandler)
+    signal.signal(signal.SIGQUIT, sighandler)
+    signal.signal(signal.SIGTERM, sighandler)
+
+def error_exit(msg):
+    sys.stderr.write("%s: " % sys.argv[0])
+    sys.stderr.write("%s\n" % msg)
+    sys.stderr.flush()
+    sys.exit(1)
+
+def reserve(mcs):
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock.bind("\0%s" % mcs)
+    fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+
+def gen_context(setype):
+    while True:
+        i1 = random.randrange(0, 1024)
+        i2 = random.randrange(0, 1024)
+        if i1 == i2:
+            continue
+        if i1 > i2:
+            tmp = i1
+            i1 = i2
+            i2 = tmp
+        mcs = "s0:c%d,c%d" % (i1, i2)
+        reserve(mcs)
+        try:
+            reserve(mcs)
+        except:
+            continue
+        break
+    con = selinux.getcon()[1].split(":")
+
+    execcon = "%s:%s:%s:%s" % (con[0], con[1], setype, mcs)
+    
+    filecon = "%s:%s:%s:%s" % (con[0], 
+                               "object_r", 
+                               "%s_file_t" % setype[:-2], 
+                               mcs)
+    return execcon, filecon
+
+def copyfile(file, dir, dest):
+       import re
+       if file.startswith(dir):
+              dname = os.path.dirname(file)
+              bname = os.path.basename(file)
+              if dname == dir:
+                     dest = dest + "/" + bname
+              else:
+                     newdir = re.sub(dir, dest, dname)
+                     os.makedirs(newdir)
+                     dest = newdir + "/" + bname
+
+              if os.path.isdir(file):
+                     shutil.copytree(file, dest)
+              else:
+                     shutil.copy2(file, dest)
+              X_FILES[file] = (dest, os.path.getmtime(dest))
+
+def copyfiles(newhomedir, newtmpdir, files):
+       import pwd
+       homedir=pwd.getpwuid(os.getuid()).pw_dir
+       for f in files:
+              copyfile(f,homedir, newhomedir)
+              copyfile(f,"/tmp", newtmpdir)
+
+def savefile(new, orig):
+       import gtk
+       dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
+                               gtk.BUTTONS_YES_NO,
+                               _("Do you want to save changes to '%s' (Y/N): ") % orig)
+       dlg.set_title(_("Sandbox Message"))
+       dlg.set_position(gtk.WIN_POS_MOUSE)
+       dlg.show_all()
+       rc = dlg.run()
+       dlg.destroy()
+       if rc == gtk.RESPONSE_YES:
+              shutil.copy2(new,orig)
+
+if __name__ == '__main__':
+    setup_sighandlers()
+    if selinux.is_selinux_enabled() != 1:
+        error_exit("Requires an SELinux enabled system")
+        
+    init_files = []
+
+    def usage(message = ""):
+        text = _("""
+sandbox [-h] [-I includefile ] [[-i file ] ...] [ -t type ] command
+""")
+        error_exit("%s\n%s" % (message, text))
+
+    setype = DEFAULT_TYPE
+    X_ind = False
+    try:
+           gopts, cmds = getopt.getopt(sys.argv[1:], "i:ht:XI:", 
+                                       ["help",
+                                        "include=", 
+                                        "includefile=", 
+                                        "type="
+                                        ])
+           for o, a in gopts:
+                  if o == "-t" or o == "--type":
+                         setype = a
+                         
+                  if o == "-i" or o == "--include":
+                         rp = os.path.realpath(a)
+                         if rp not in init_files:
+                                init_files.append(rp)
+                         
+                  if o == "-I" or o == "--includefile":
+                         fd = open(a, "r")
+                         for i in fd.read().split("\n"):
+                                if os.path.exists(i):
+                                       rp = os.path.realpath(i)
+                                       if rp not in init_files:
+                                              init_files.append(rp)
+                                       
+                         fd.close
+                         
+                  if o == "-X":
+                         if DEFAULT_TYPE == setype:
+                                setype = DEFAULT_X_TYPE
+                         X_ind = True
+
+                  if o == "-h" or o == "--help":
+                         usage(_("Usage"));
+            
+           if len(cmds) == 0:
+                  usage(_("Command required"))
+
+           execcon, filecon = gen_context(setype)
+           rc = -1
+
+           if cmds[0][0] != "/" and cmds[0][:2] != "./" and cmds[0][:3] != "../":
+                  for i in  os.environ["PATH"].split(':'):
+                         f = "%s/%s" % (i, cmds[0])
+                         if os.access(f, os.X_OK):
+                                cmds[0] = f
+                                break
+
+           try:
+                  newhomedir = None
+                  newtmpdir = None
+                  if X_ind:
+                         if not os.path.exists("/usr/sbin/seunshare"):
+                                raise ValueError("""/usr/sbin/seunshare required for sandbox -X, to install you need to execute 
+#yum install /usr/sbin/seunshare""")
+                         import warnings
+                         warnings.simplefilter("ignore")
+                         newhomedir = os.tempnam(".", ".sandbox%s")
+                         os.mkdir(newhomedir)
+                         selinux.setfilecon(newhomedir, filecon) 
+                         newtmpdir = os.tempnam("/tmp", ".sandbox")
+                         os.mkdir(newtmpdir)
+                         selinux.setfilecon(newtmpdir, filecon)
+                         warnings.resetwarnings()
+                         paths = []
+                         for i in cmds:
+                                f = os.path.realpath(i)
+                                if os.path.exists(f):
+                                       paths.append(f)
+                                else:
+                                       paths.append(i)
+                                       
+                         copyfiles(newhomedir, newtmpdir, init_files + paths)
+                         execfile = newhomedir + "/.sandboxrc"
+                         fd = open(execfile, "w+")
+                         fd.write("""#! /bin/sh
+%s
+""" % " ".join(paths))
+                         fd.close()
+                         os.chmod(execfile, 0700)
+                         
+                         cmds =  ("/usr/sbin/seunshare -t %s -h %s -- %s /usr/share/sandbox/sandboxX.sh" % (newtmpdir, newhomedir, execcon)).split()
+                         rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
+                         for i in paths:
+                                if i not in X_FILES:
+                                       continue
+                                (dest, mtime) = X_FILES[i]
+                                if os.path.getmtime(dest) > mtime:
+                                       savefile(dest, i)
+                  else:
+                         selinux.setexeccon(execcon)
+                         rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
+                         selinux.setexeccon(None)
+           finally:
+                  if X_ind:
+                         if newhomedir:
+                                shutil.rmtree(newhomedir)
+                         if newtmpdir:
+                                shutil.rmtree(newtmpdir)
+                  
+    except getopt.GetoptError, error:
+           usage(_("Options Error %s ") % error.msg)
+    except OSError, error:
+           error_exit(error.args[1])
+    except ValueError, error:
+           error_exit(error.args[0])
+    except KeyError, error:
+           error_exit(_("Invalid value %s") % error.args[0])
+    except IOError, error:
+           error_exit(error.args[1])
+    except KeyboardInterrupt:
+           rc = 0
+           
+    sys.exit(rc)
+
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.8 policycoreutils-2.0.74/sandbox/sandbox.8
--- nsapolicycoreutils/sandbox/sandbox.8	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/sandbox.8	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,26 @@
+.TH SANDBOX "8" "May 2009" "chcat" "User Commands"
+.SH NAME
+sandbox \- Run cmd under an SELinux sandbox
+.SH SYNOPSIS
+.B sandbox
+[-X] [[-i file ]...] [ -t type ] cmd
+.br
+.SH DESCRIPTION
+.PP
+Run application within a tightly confined SELinux domain,   The default sandbox allows the application to only read and write stdin and stdout along with files handled to it by the shell.  
+Additionaly a -X qualifier allows you to run sandboxed X applications.  These apps will start up their own X Server and create a temporary homedir and /tmp.  The default policy does not allow any capabilities or network access.  Also prevents all access to the users other processes and files.  Any file specified on the command line will be copied into the sandbox.
+.PP
+.TP
+\fB\-t type\fR
+Use alternate sandbox type, defaults to sandbox_t or sandbox_x_t for -X.
+.TP
+\fB\-i file\fR
+Copy this file into the temporary sandbox homedir. Command can be repeated.
+.TP
+\fB\-X\fR
+Create an X based Sandbox for gui apps, temporary files for $HOME and /tmp, seconday Xserver, defaults to sandbox_x_t
+.TP
+.SH "SEE ALSO"
+.TP
+runcon(1)
+.PP
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandboxX.sh policycoreutils-2.0.74/sandbox/sandboxX.sh
--- nsapolicycoreutils/sandbox/sandboxX.sh	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/sandboxX.sh	2009-09-20 21:51:31.000000000 -0400
@@ -0,0 +1,16 @@
+#!/bin/bash 
+export TITLE="Sandbox: `/usr/bin/tail -1 ~/.sandboxrc | /usr/bin/cut -b1-70`"
+export SCREEN=`/usr/bin/xdpyinfo -display $DISPLAY | /bin/awk '/dimensions/ { print $2 }'`
+
+(/usr/bin/Xephyr -title "$TITLE" -terminate -screen 1000x700 -displayfd 5 5>&1 2>/dev/null) | while read D; do 
+export DISPLAY=:$D
+/usr/bin/matchbox-window-manager -use_titlebar no &
+WM_PID=$!
+~/.sandboxrc &
+CLIENT_PID=$!
+wait $CLIENT_PID
+export EXITCODE=$?
+kill -TERM $WM_PID
+kill -HUP 0
+break
+done
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/seunshare.c policycoreutils-2.0.74/sandbox/seunshare.c
--- nsapolicycoreutils/sandbox/seunshare.c	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/sandbox/seunshare.c	2009-09-20 21:48:31.000000000 -0400
@@ -0,0 +1,265 @@
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <syslog.h>
+#include <sys/mount.h>
+#include <pwd.h>
+#define _GNU_SOURCE
+#include <sched.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <cap-ng.h>
+#include <getopt.h>		/* for getopt_long() form of getopt() */
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <selinux/selinux.h>
+#include <selinux/context.h>	/* for context-mangling functions */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/**
+ * This function will drop all capabilities 
+ * Returns zero on success, non-zero otherwise
+ */
+static int drop_capabilities(uid_t uid)
+{
+	capng_clear(CAPNG_SELECT_BOTH);
+
+	if (capng_lock() < 0) 
+		return -1;
+	/* Change uid */
+	if (setresuid(uid, uid, uid)) {
+		fprintf(stderr, "Error changing uid, aborting.\n");
+		return -1;
+	}
+	return capng_apply(CAPNG_SELECT_BOTH);
+}
+
+#define DEFAULT_PATH "/usr/bin:/bin"
+#define TRUE 1
+#define FALSE 0
+
+/**
+ * Take care of any signal setup
+ */
+static int set_signal_handles(void)
+{
+	sigset_t empty;
+
+	/* Empty the signal mask in case someone is blocking a signal */
+	if (sigemptyset(&empty)) {
+		fprintf(stderr, "Unable to obtain empty signal set\n");
+		return -1;
+	}
+
+	(void)sigprocmask(SIG_SETMASK, &empty, NULL);
+
+	/* Terminate on SIGHUP. */
+	if (signal(SIGHUP, SIG_DFL) == SIG_ERR) {
+		perror("Unable to set SIGHUP handler");
+		return -1;
+	}
+
+	return 0;
+}
+#define USAGE_STRING "USAGE: seunshare [ -t tmpdir ] [ -h homedir ] -- CONTEXT executable [args] "
+
+
+
+static int verify_mount(const char *mntdir, struct passwd *pwd) {
+	struct stat sb;
+	if (stat(mntdir, &sb) == -1) {
+		perror("Invalid mount point");
+		return -1;
+	}
+	if (sb.st_uid != pwd->pw_uid) {
+		errno = EPERM;
+		syslog(LOG_AUTHPRIV | LOG_ALERT, "%s attempted to mount an invalid directory, %s", pwd->pw_name, mntdir);
+		perror("Invalid mount point, reporting to administrator");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * This function checks to see if the shell is known in /etc/shells.
+ * If so, it returns 1. On error or illegal shell, it returns 0.
+ */
+static int verify_shell(const char *shell_name)
+{
+	int found = 0;
+	const char *buf;
+
+	if (!(shell_name && shell_name[0]))
+		return found;
+
+	while ((buf = getusershell()) != NULL) {
+		/* ignore comments */
+		if (*buf == '#')
+			continue;
+
+		/* check the shell skipping newline char */
+		if (!strcmp(shell_name, buf)) {
+			found = 1;
+			break;
+		}
+	}
+	endusershell();
+	return found;
+}
+
+int main(int argc, char **argv) {
+	int rc;
+	int status = -1;
+
+	security_context_t scontext;
+
+	int flag_index;		/* flag index in argv[] */
+	int clflag;		/* holds codes for command line flags */
+	char *tmpdir_s = NULL;	/* tmpdir spec'd by user in argv[] */
+	char *homedir_s = NULL;	/* homedir spec'd by user in argv[] */
+
+	const struct option long_options[] = {
+		{"homedir", 1, 0, 'h'},
+		{"tmpdir", 1, 0, 't'},
+		{NULL, 0, 0, 0}
+	};
+
+	uid_t uid = getuid();
+
+	if (!uid) {
+		fprintf(stderr, "Must not be root");
+		return -1;
+	}
+
+	struct passwd *pwd=getpwuid(uid);
+	if (!pwd) {
+		perror("getpwduid failed");
+		return -1;
+	}
+
+	if (verify_shell(pwd->pw_shell) == 0) {
+		fprintf(stderr, "Error!  Shell is not valid.\n");
+		return -1;
+	}
+
+	while (1) {
+		clflag = getopt_long(argc, argv, "h:t:", long_options,
+				     &flag_index);
+		if (clflag == -1)
+			break;
+
+		switch (clflag) {
+		case 't':
+			tmpdir_s = optarg;
+			if (verify_mount(tmpdir_s, pwd) < 0) return -1;
+			break;
+		case 'h':
+			homedir_s = optarg;
+			if (verify_mount(homedir_s, pwd) < 0) return -1;
+			if (verify_mount(pwd->pw_dir, pwd) < 0) return -1;
+			break;
+		default:
+			fprintf(stderr, "%s\n", USAGE_STRING);
+			return -1;
+		}
+	}
+
+	if (! homedir_s && ! tmpdir_s) {
+		fprintf(stderr, "Error: tmpdir and/or homedir required \n"
+			"%s\n", USAGE_STRING);
+		return -1;
+	}
+
+	if (argc - optind < 2) {
+		fprintf(stderr, "Error: executable required \n"
+			"%s\n", USAGE_STRING);
+		return -1;
+	}
+
+	scontext = argv[optind++];
+	
+	if (set_signal_handles())
+		return -1;
+
+        if (unshare(CLONE_NEWNS) < 0) {
+		perror("Failed to unshare");
+		return -1;
+	}
+
+	if (homedir_s && mount(homedir_s, pwd->pw_dir, NULL, MS_BIND, NULL) < 0) {
+		perror("Failed to mount HOMEDIR");
+		return -1;
+	}
+
+	if (homedir_s && verify_mount(pwd->pw_dir, pwd) < 0) 
+		return -1;
+
+	if (tmpdir_s && mount(tmpdir_s, "/tmp", NULL, MS_BIND, NULL) < 0) {
+		perror("Failed to mount /tmp");
+		return -1;
+	}
+
+	if (tmpdir_s && verify_mount("/tmp", pwd) < 0) 
+		return -1;
+
+	if (drop_capabilities(uid)) {
+		perror("Failed to drop all capabilities");
+		return -1;
+	}
+
+	int child = fork();
+	if (!child) {
+		char *display=NULL;
+		/* Construct a new environment */
+		char *d = getenv("DISPLAY");
+		if (d) {
+			display =  strdup(d);
+			if (!display) {
+				perror("Out of memory");
+				exit(-1);
+			}
+		}
+
+		if ((rc = clearenv())) {
+			perror("Unable to clear environment");
+			free(display);
+			exit(-1);
+		}
+		
+		if (setexeccon(scontext)) {
+			fprintf(stderr, "Could not set exec context to %s.\n",
+				scontext);
+			free(display);
+			exit(-1);
+		}
+
+		if (display) 
+			rc |= setenv("DISPLAY", display, 1);
+		rc |= setenv("HOME", pwd->pw_dir, 1);
+		rc |= setenv("SHELL", pwd->pw_shell, 1);
+		rc |= setenv("USER", pwd->pw_name, 1);
+		rc |= setenv("LOGNAME", pwd->pw_name, 1);
+		rc |= setenv("PATH", DEFAULT_PATH, 1);
+		
+		if (chdir(pwd->pw_dir)) {
+			perror("Failed to change dir to homedir");
+			exit(-1);
+		}
+		
+		execv(argv[optind], argv + optind);
+		free(display);
+		perror("execv");
+		exit(-1);
+	} else {
+		waitpid(child, &status, 0);
+	}
+
+	return status;
+}
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/chcat policycoreutils-2.0.74/scripts/chcat
--- nsapolicycoreutils/scripts/chcat	2009-06-23 15:36:07.000000000 -0400
+++ policycoreutils-2.0.74/scripts/chcat	2009-09-20 21:26:36.000000000 -0400
@@ -435,6 +435,8 @@
                     continue
     except ValueError, e:
         error(e)
+    except OSError, e:
+        error(e)
     
     sys.exit(errors)
     
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/fixfiles policycoreutils-2.0.74/scripts/fixfiles
--- nsapolicycoreutils/scripts/fixfiles	2009-08-05 15:10:56.000000000 -0400
+++ policycoreutils-2.0.74/scripts/fixfiles	2009-10-14 08:51:36.000000000 -0400
@@ -136,6 +136,7 @@
     fi
     return
 fi
+[ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon
 LogReadOnly
 ${SETFILES} -q ${OUTFILES} ${SYSLOGFLAG} ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW} 2>&1 >> $LOGFILE
 rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-*
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/Makefile policycoreutils-2.0.74/scripts/Makefile
--- nsapolicycoreutils/scripts/Makefile	2008-08-28 09:34:24.000000000 -0400
+++ policycoreutils-2.0.74/scripts/Makefile	2009-09-20 21:26:36.000000000 -0400
@@ -5,7 +5,7 @@
 MANDIR ?= $(PREFIX)/share/man
 LOCALEDIR ?= /usr/share/locale
 
-all: fixfiles genhomedircon
+all: fixfiles genhomedircon chcat
 
 install: all
 	-mkdir -p $(BINDIR)
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/semanage policycoreutils-2.0.74/semanage/semanage
--- nsapolicycoreutils/semanage/semanage	2009-09-08 09:03:10.000000000 -0400
+++ policycoreutils-2.0.74/semanage/semanage	2009-10-01 11:43:48.000000000 -0400
@@ -39,19 +39,26 @@
        __builtin__.__dict__['_'] = unicode
 
 if __name__ == '__main__':
+        action  = False
 
+        def set_action(option):
+               global action
+               if action:
+                      raise ValueError(_("%s bad option") % option)
+               action = True
+                      
 	def usage(message = ""):
                text = _("""
 semanage [ -S store ] -i [ input_file | - ]
 
-semanage {boolean|login|user|port|interface|node|fcontext|translation} -{l|D} [-n]
+semanage {boolean|login|user|port|interface|module|node|fcontext} -{l|D} [-n]
 semanage login -{a|d|m} [-sr] login_name | %groupname
 semanage user -{a|d|m} [-LrRP] selinux_name
 semanage port -{a|d|m} [-tr] [ -p proto ] port | port_range
 semanage interface -{a|d|m} [-tr] interface_spec
+semanage module -{a|d|m} [--enable|--disable] module
 semanage node -{a|d|m} [-tr] [ -p protocol ] [-M netmask] addr
 semanage fcontext -{a|d|m} [-frst] file_spec
-semanage translation -{a|d|m} [-T] level
 semanage boolean -{d|m} [--on|--off|-1|-0] -F boolean | boolean_file
 semanage permissive -{d|a} type
 semanage dontaudit [ on | off ]
@@ -85,14 +92,15 @@
         -F, --file       Treat target as an input file for command, change multiple settings
 	-p, --proto      Port protocol (tcp or udp) or internet protocol version of node (ipv4 or ipv6)
 	-M, --mask       Netmask
+        -e, --equal      Make target equal to this paths labeling
 	-P, --prefix     Prefix for home directory labeling
 	-L, --level      Default SELinux Level (MLS/MCS Systems only)
 	-R, --roles      SELinux Roles (ex: "sysadm_r staff_r")
-	-T, --trans      SELinux Level Translation (MLS/MCS Systems only)
-
 	-s, --seuser     SELinux User Name
 	-t, --type       SELinux Type for the object
 	-r, --range      MLS/MCS Security Range (MLS/MCS Systems only)
+        --enable         Enable a module
+        --disable        Disable a module
 """)
                raise ValueError("%s\n%s" % (text, message))
 		
@@ -115,11 +123,11 @@
 		valid_option["interface"] += valid_everyone + [ '-t', '--type', '-r', '--range']
 		valid_option["node"] = []
 		valid_option["node"] += valid_everyone + [ '-M', '--mask', '-t', '--type', '-r', '--range', '-p', '--protocol']
+		valid_option["module"] = []
+		valid_option["module"] += valid_everyone + [ '--enable', '--disable']
 		valid_option["fcontext"] = []
-		valid_option["fcontext"] += valid_everyone + [ '-f', '--ftype', '-s', '--seuser',  '-t', '--type', '-r', '--range'] 
+		valid_option["fcontext"] += valid_everyone + [ '-e', '--equal', '-f', '--ftype', '-s', '--seuser',  '-t', '--type', '-r', '--range'] 
 		valid_option["dontaudit"] = [ '-S', '--store' ]
-		valid_option["translation"] = []
-		valid_option["translation"] += valid_everyone + [ '-T', '--trans' ] 
 		valid_option["boolean"] = []
 		valid_option["boolean"] += valid_everyone + [ '--on', "--off", "-1", "-0", "-F", "--file"] 
 		valid_option["permissive"] = []
@@ -180,7 +188,6 @@
 		selevel = ""
 		setype = ""
 		ftype = ""
-		setrans = ""
 		roles = ""
 		seuser = ""
 		prefix = "user"
@@ -190,10 +197,13 @@
 		modify = False
 		delete = False
 		deleteall = False
+		enable = False
+		disable = False
 		list = False
 		locallist = False
 		use_file = False
                 store = ""
+                equal=""
 			
 		object = argv[0]
 		option_dict=get_options()
@@ -203,10 +213,13 @@
 		args = argv[1:]
 
 		gopts, cmds = getopt.getopt(args,
-					    '01adf:i:lhmnp:s:FCDR:L:r:t:T:P:S:M:',
+					    '01ade:f:i:lhmnp:s:FCDR:L:r:t:P:S:M:',
 					    ['add',
 					     'delete',
 					     'deleteall',
+					     'equal=',
+					     'enable',
+					     'disable',
 					     'ftype=',
 					     'file',
 					     'help',
@@ -225,7 +238,6 @@
 					     'level=',
 					     'roles=',
 					     'type=',
-					     'trans=',
 					     'prefix=',
                                              'mask='
 					     ])
@@ -235,26 +247,39 @@
 				
 		for o,a in gopts:
 			if o == "-a" or o == "--add":
-				if modify or delete:
-                                       raise ValueError(_("%s bad option") % o)
+                                set_action(o)
 				add = True
 				
 			if o == "-d"  or o == "--delete":
-				if modify or add:
-                                       raise ValueError(_("%s bad option") % o)
+                                set_action(o)
 				delete = True
+
 			if o == "-D"  or o == "--deleteall":
-				if modify:
-                                       raise ValueError(_("%s bad option") % o)
+                                set_action(o)
 				deleteall = True
+
 			if o == "-f"  or o == "--ftype":
 				ftype=a
 
+			if o == "-e"  or o == "--equal":
+				equal = a
+
+			if o == "--enable":
+                                if disable:
+                                       raise ValueError(_("You can't disable and enable at the same time"))
+
+				enable = True
+
+			if o == "--disable":
+                                if enable:
+                                       raise ValueError(_("You can't disable and enable at the same time"))
+				disable = True
+
 			if o == "-F"  or o == "--file":
 				use_file = True
 
 			if o == "-h" or o == "--help":
-                               raise ValueError(_("%s bad option") % o)
+                               raise usage()
 
 			if o == "-n" or o == "--noheading":
 				heading = False
@@ -263,8 +288,7 @@
 				locallist = True
 
 			if o == "-m"or o == "--modify":
-				if delete or add:
-                                       raise ValueError(_("%s bad option") % o)
+                                set_action(o)
 				modify = True
 				
 			if o == "-S" or o == '--store':
@@ -297,9 +321,6 @@
 			if o == "-t" or o == "--type":
 				setype = a
 
-			if o == "-T" or o == "--trans":
-				setrans = a
-
                         if o == "--on" or o == "-1":
                                value = "on"
                         if o == "--off" or o == "-0":
@@ -325,9 +346,10 @@
 		
 		if object == "boolean":
 			OBJECT = seobject.booleanRecords(store)
+                        modify = True
 		
-		if object == "translation":
-			OBJECT = seobject.setransRecords()
+		if object == "module":
+			OBJECT = seobject.moduleRecords(store)
 		
 		if object == "permissive":
 			OBJECT = seobject.permissiveRecords(store)
@@ -358,9 +380,6 @@
 			if object == "login":
 				OBJECT.add(target, seuser, serange)
 
-			if object == "translation":
-				OBJECT.add(target, setrans)
-
 			if object == "user":
 				OBJECT.add(target, roles.split(), selevel, serange, prefix)
 
@@ -370,11 +389,17 @@
 			if object == "interface":
 				OBJECT.add(target, serange, setype)
 
+			if object == "module":
+				OBJECT.add(target)
+
 			if object == "node":
 				OBJECT.add(target, mask, proto, serange, setype)
 
 			if object == "fcontext":
-				OBJECT.add(target, setype, ftype, serange, seuser)
+                                if equal == "":
+                                       OBJECT.add(target, setype, ftype, serange, seuser)
+                                else:
+                                       OBJECT.add_equal(target, equal)
 			if object == "permissive":
 				OBJECT.add(target)
 
@@ -387,13 +412,18 @@
 			if object == "login":
 				OBJECT.modify(target, seuser, serange)
 
-			if object == "translation":
-				OBJECT.modify(target, setrans)
-
 			if object == "user":
 				rlist = roles.split()
 				OBJECT.modify(target, rlist, selevel, serange, prefix)
 
+			if object == "module":
+                                if enable:
+                                       OBJECT.enable(target)
+                                elif disable:
+                                       OBJECT.disable(target)
+                                else:
+                                       OBJECT.modify(target)
+
 			if object == "port":
 				OBJECT.modify(target, proto, serange, setype)
 
@@ -404,7 +434,10 @@
 				OBJECT.modify(target, mask, proto, serange, setype)
 
 			if object == "fcontext":
-				OBJECT.modify(target, setype, ftype, serange, seuser)
+                                if equal == "":
+                                       OBJECT.modify(target, setype, ftype, serange, seuser)
+                                else:
+                                       OBJECT.modify_equal(target, equal)
 
                         return
 
@@ -423,7 +456,7 @@
 
                         return
 
-                raise ValueError(_("Invalid command") % " ".join(argv))
+                raise ValueError(_("Invalid command: semanage %s") % " ".join(argv))
 
 	#
 	# 
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/seobject.py policycoreutils-2.0.74/semanage/seobject.py
--- nsapolicycoreutils/semanage/seobject.py	2009-09-08 09:03:10.000000000 -0400
+++ policycoreutils-2.0.74/semanage/seobject.py	2009-10-01 11:34:19.000000000 -0400
@@ -195,88 +195,6 @@
 	else:
 		return raw
 	
-class setransRecords:
-	def __init__(self):
-		self.filename = selinux.selinux_translations_path()
-		try:
-			fd = open(self.filename, "r")
-			translations = fd.readlines()
-			fd.close()
-		except IOError, e:
-			raise ValueError(_("Unable to open %s: translations not supported on non-MLS machines: %s") % (self.filename, e) )
-			
-		self.ddict = {}
-		self.comments = []
-		for r in translations:
-			if len(r) == 0:
-				continue
-			i = r.strip()
-			if i == "" or i[0] == "#":
-				self.comments.append(r)
-				continue
-			i = i.split("=")
-			if len(i) != 2:
-				self.comments.append(r)
-				continue
-                        if self.ddict.has_key(i[0]) == 0:
-                               self.ddict[i[0]] = i[1]
-
-	def get_all(self):
-		return self.ddict
-
-	def out(self):
-		rec = ""
-		for c in self.comments:
-			rec += c
-		keys = self.ddict.keys()
-		keys.sort()
-		for k in keys:
-			rec += "%s=%s\n" %  (k, self.ddict[k])
-		return rec
-	
-	def list(self, heading = 1, locallist = 0):
-		if heading:
-			print "\n%-25s %s\n" % (_("Level"), _("Translation"))
-		keys = self.ddict.keys()
-		keys.sort()
-		for k in keys:
-			print "%-25s %s" % (k, self.ddict[k])
-		
-	def add(self, raw, trans):
-		if trans.find(" ") >= 0:
-			raise ValueError(_("Translations can not contain spaces '%s' ") % trans)
-
-		if validate_level(raw) == None:
-			raise ValueError(_("Invalid Level '%s' ") % raw)
-		
-		if self.ddict.has_key(raw):
-			raise ValueError(_("%s already defined in translations") % raw)
-		else:
-			self.ddict[raw] = trans
-		self.save()
-	
-	def modify(self, raw, trans):
-		if trans.find(" ") >= 0:
-
-			raise ValueError(_("Translations can not contain spaces '%s' ") % trans)
-		if self.ddict.has_key(raw):
-			self.ddict[raw] = trans
-		else:
-			raise ValueError(_("%s not defined in translations") % raw)
-		self.save()
-		
-	def delete(self, raw):
-		self.ddict.pop(raw)
-		self.save()
-
-	def save(self):
-		(fd, newfilename) = tempfile.mkstemp('', self.filename)
-		os.write(fd, self.out())
-		os.close(fd)
-		os.chmod(newfilename, os.stat(self.filename)[stat.ST_MODE])
-		os.rename(newfilename, self.filename)
-                os.system("/sbin/service mcstrans reload > /dev/null")
-
 class semanageRecords:
 	def __init__(self, store):
                global handle
@@ -315,6 +233,77 @@
                self.transaction = False
                self.commit()
 
+class moduleRecords(semanageRecords):
+	def __init__(self, store):
+               semanageRecords.__init__(self, store)
+
+	def get_all(self):
+               l = []
+               (rc, mlist, number) = semanage_module_list(self.sh)
+               if rc < 0:
+                      raise ValueError(_("Could not list SELinux modules"))
+
+               for i in range(number):
+                      mod = semanage_module_list_nth(mlist, i)
+                      l.append((semanage_module_get_name(mod), semanage_module_get_version(mod), semanage_module_get_enabled(mod)))
+               return l
+
+	def list(self, heading = 1, locallist = 0):
+		if heading:
+			print "\n%-25s%-10s\n" % (_("Modules Name"), _("Version"))
+                for t in self.get_all():
+                       if t[2] == 0:
+                              disabled = _("Disabled")
+                       else:
+                              disabled = ""
+                       print "%-25s%-10s%s" % (t[0], t[1], disabled)
+
+	def add(self, file):
+               rc = semanage_module_install_file(self.sh, file);
+               if rc >= 0:
+                      self.commit()
+
+	def disable(self, module):
+               need_commit = False                      
+               for m in module.split():
+                      rc = semanage_module_disable(self.sh, m)
+                      if rc < 0 and rc != -3:
+                             raise ValueError(_("Could not disable module %s (remove failed)") % m)
+                      if rc != -3:
+                             need_commit = True 
+               if need_commit:
+                      self.commit()
+			
+	def enable(self, module):
+               need_commit = False                      
+               for m in module.split():
+                      rc = semanage_module_enable(self.sh, m)
+                      if rc < 0 and rc != -3:
+                             raise ValueError(_("Could not enable module %s (remove failed)") % m)
+                      if rc != -3:
+                             need_commit = True 
+               if need_commit:
+                      self.commit()
+
+	def modify(self, file):
+               rc = semanage_module_update_file(self.sh, file);
+               if rc >= 0:
+                      self.commit()
+
+	def delete(self, module):
+               for m in module.split():
+                      rc = semanage_module_remove(self.sh, m)
+                      if rc < 0 and rc != -2:
+                             raise ValueError(_("Could not remove module %s (remove failed)") % m)
+                      
+               self.commit()
+			
+	def deleteall(self):
+               l = self.get_all()
+               if len(l) > 0:
+                      all = " ".join(l[0])
+                      self.delete(all)
+
 class dontauditClass(semanageRecords):
 	def __init__(self, store):
                semanageRecords.__init__(self, store)
@@ -341,6 +330,7 @@
                       name = semanage_module_get_name(mod)
                       if name and name.startswith("permissive_"):
                              l.append(name.split("permissive_")[1])
+
                return l
 
 	def list(self, heading = 1, locallist = 0):
@@ -1120,7 +1110,7 @@
 
        def add(self, addr, mask, proto, serange, ctype):
                 self.begin()
-                self.__add(self, addr, mask, proto, serange, ctype)
+                self.__add(addr, mask, proto, serange, ctype)
                 self.commit()
 
        def __modify(self, addr, mask, proto, serange, setype):
@@ -1420,6 +1410,48 @@
 class fcontextRecords(semanageRecords):
 	def __init__(self, store = ""):
 		semanageRecords.__init__(self, store)
+                self.equiv = {}
+                self.equal_ind = False
+                try:
+                       fd = open(selinux.selinux_file_context_subs_path(), "r")
+                       for i in fd.readlines():
+                              src, dst = i.split()
+                              self.equiv[src] = dst
+                       fd.close()
+                except IOError:
+                       pass
+
+        def commit(self):
+                if self.equal_ind:
+                       subs_file = selinux.selinux_file_context_subs_path()
+                       tmpfile = "%s.tmp" % subs_file
+                       fd = open(tmpfile, "w")
+                       for src in self.equiv.keys():
+                              fd.write("%s %s\n" % (src, self.equiv[src]))
+                       fd.close()
+                       try:
+                              os.chmod(tmpfile, os.stat(subs_file)[stat.ST_MODE])
+                       except:
+                              pass
+                       os.rename(tmpfile,subs_file)
+                       self.equal_ind = False
+		semanageRecords.commit(self)
+
+        def add_equal(self, src, dst):
+                self.begin()
+                if src in self.equiv.keys():
+                       raise ValueError(_("Equivalence class for %s already exists") % src)
+                self.equiv[src] = dst
+                self.equal_ind = True
+                self.commit()
+
+        def modify_equal(self, src, dst):
+                self.begin()
+                if src not in self.equiv.keys():
+                       raise ValueError(_("Equivalence class for %s does not exists") % src)
+                self.equiv[src] = dst
+                self.equal_ind = True
+                self.commit()
 
         def createcon(self, target, seuser = "system_u"):
                 (rc, con) = semanage_context_create(self.sh)
@@ -1586,9 +1618,16 @@
                               raise ValueError(_("Could not delete the file context %s") % target)
                        semanage_fcontext_key_free(k)
 	
+                self.equiv = {}
+                self.equal_ind = True
                 self.commit()
 
 	def __delete(self, target, ftype):
+                if target in self.equiv.keys():
+                       self.equiv.pop(target)
+                       self.equal_ind = True
+                       return
+
 		(rc,k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
 		if rc < 0:
 			raise ValueError(_("Could not create a key for %s") % target)
@@ -1644,11 +1683,11 @@
 		return ddict
 			
 	def list(self, heading = 1, locallist = 0 ):
-		if heading:
-			print "%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context"))
 		fcon_dict = self.get_all(locallist)
                 keys = fcon_dict.keys()
                 keys.sort()
+                if len(keys) > 0 and heading:
+			print "%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context"))
 		for k in keys:
 			if fcon_dict[k]:
 				if is_mls_enabled:
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semodule/semodule.8 policycoreutils-2.0.74/semodule/semodule.8
--- nsapolicycoreutils/semodule/semodule.8	2009-09-17 08:59:43.000000000 -0400
+++ policycoreutils-2.0.74/semodule/semodule.8	2009-09-25 15:21:16.000000000 -0400
@@ -35,6 +35,12 @@
 .B  \-b,\-\-base=MODULE_PKG   
 install/replace base module package
 .TP
+.B  \-d,\-\-disable=MODULE_NAME
+disable existing module
+.TP
+.B  \-e,\-\-enable=MODULE_NAME
+enable existing module
+.TP
 .B  \-r,\-\-remove=MODULE_NAME
 remove existing module
 .TP
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semodule/semodule.c policycoreutils-2.0.74/semodule/semodule.c
--- nsapolicycoreutils/semodule/semodule.c	2009-09-17 08:59:43.000000000 -0400
+++ policycoreutils-2.0.74/semodule/semodule.c	2009-09-20 21:26:36.000000000 -0400
@@ -22,12 +22,12 @@
 
 #include <semanage/modules.h>
 
-enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, REMOVE_M,
+enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, ENABLE_M, DISABLE_M, REMOVE_M,
 	LIST_M, RELOAD
 };
 /* list of modes in which one ought to commit afterwards */
 static const int do_commit[] = {
-	0, 1, 1, 1, 1,
+	0, 1, 1, 1, 1, 1, 1,
 	0, 0
 };
 
@@ -104,9 +104,11 @@
 	printf("  -R, --reload		    reload policy\n");
 	printf("  -B, --build		    build and reload policy\n");
 	printf("  -i,--install=MODULE_PKG   install a new module\n");
-	printf("  -u,--upgrade=MODULE_PKG   upgrades or install module to a newer version\n");
+	printf("  -u,--upgrade=MODULE_PKG   upgrade existing module\n");
 	printf("  -b,--base=MODULE_PKG      install new base module\n");
-	printf("  -r,--remove=MODULE_NAME   remove existing module\n");
+	printf("  -e,--enable=MODULE_PKG    enable existing module\n");
+	printf("  -d,--disable=MODULE_PKG   disable existing module\n");
+ 	printf("  -r,--remove=MODULE_NAME   remove existing module\n");
 	printf
 	    ("  -l,--list-modules         display list of installed modules\n");
 	printf("Other options:\n");
@@ -152,6 +154,8 @@
 		{"install", required_argument, NULL, 'i'},
 		{"list-modules", 0, NULL, 'l'},
 		{"verbose", 0, NULL, 'v'},
+		{"enable", required_argument, NULL, 'e'},
+		{"disable", required_argument, NULL, 'd'},
 		{"remove", required_argument, NULL, 'r'},
 		{"upgrade", required_argument, NULL, 'u'},
 		{"reload", 0, NULL, 'R'},
@@ -166,7 +170,7 @@
 	no_reload = 0;
 	create_store = 0;
 	while ((i =
-		getopt_long(argc, argv, "s:b:hi:lvqr:u:RnBD", opts,
+		getopt_long(argc, argv, "s:b:hi:lvqe:d:r:u:RnBD", opts,
 			    NULL)) != -1) {
 		switch (i) {
 		case 'b':
@@ -185,6 +189,12 @@
 		case 'v':
 			verbose = 1;
 			break;
+		case 'e':
+			set_mode(ENABLE_M, optarg);
+			break;
+		case 'd':
+			set_mode(DISABLE_M, optarg);
+			break;
 		case 'r':
 			set_mode(REMOVE_M, optarg);
 			break;
@@ -238,6 +248,10 @@
 			mode = UPGRADE_M;
 		} else if (commands && commands[num_commands - 1].mode == REMOVE_M) {
 			mode = REMOVE_M;
+		} else if (commands && commands[num_commands - 1].mode == ENABLE_M) {
+			mode = ENABLE_M;
+		} else if (commands && commands[num_commands - 1].mode == DISABLE_M) {
+			mode = DISABLE_M;
 		} else {
 			fprintf(stderr, "unknown additional arguments:\n");
 			while (optind < argc)
@@ -352,6 +366,30 @@
 				    semanage_module_install_base_file(sh, mode_arg);
 				break;
 			}
+		case ENABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to enable module '%s':\n",
+					     mode_arg);
+				}
+				result = semanage_module_enable(sh, mode_arg);
+				if ( result == -2 ) { 
+					continue;
+				}
+				break;
+			}
+		case DISABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to disable module '%s':\n",
+					     mode_arg);
+				}
+				result = semanage_module_disable(sh, mode_arg);
+				if ( result == -2 ) { 
+					continue;
+				}
+				break;
+			}
 		case REMOVE_M:{
 				if (verbose) {
 					printf
@@ -382,11 +420,12 @@
 						semanage_module_info_t *m =
 						    semanage_module_list_nth
 						    (modinfo, j);
-						printf("%s\t%s\n",
+						printf("%s\t%s\t%s\n",
 						       semanage_module_get_name
 						       (m),
 						       semanage_module_get_version
-						       (m));
+						       (m), 
+						       (semanage_module_get_enabled(m) ? "" : "Disabled"));
 						semanage_module_info_datum_destroy
 						    (m);
 					}
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/Makefile policycoreutils-2.0.74/setfiles/Makefile
--- nsapolicycoreutils/setfiles/Makefile	2009-07-07 15:32:32.000000000 -0400
+++ policycoreutils-2.0.74/setfiles/Makefile	2009-09-25 15:21:58.000000000 -0400
@@ -16,7 +16,7 @@
 
 all: setfiles restorecon
 
-setfiles:  setfiles.o 
+setfiles:  setfiles.o restore.o
 
 restorecon: setfiles
 	ln -sf setfiles restorecon
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/restore.c policycoreutils-2.0.74/setfiles/restore.c
--- nsapolicycoreutils/setfiles/restore.c	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/setfiles/restore.c	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,519 @@
+#include "restore.h"
+
+#define SKIP -2
+#define ERR -1
+#define MAX_EXCLUDES 1000
+
+/*
+ * The hash table of associations, hashed by inode number.
+ * Chaining is used for collisions, with elements ordered
+ * by inode number in each bucket.  Each hash bucket has a dummy 
+ * header.
+ */
+#define HASH_BITS 16
+#define HASH_BUCKETS (1 << HASH_BITS)
+#define HASH_MASK (HASH_BUCKETS-1)
+
+/*
+ * An association between an inode and a context.
+ */
+typedef struct file_spec {
+	ino_t ino;		/* inode number */
+	char *con;		/* matched context */
+	char *file;		/* full pathname */
+	struct file_spec *next;	/* next association in hash bucket chain */
+} file_spec_t;
+
+struct edir {
+	char *directory;
+	size_t size;
+};
+
+
+static file_spec_t *fl_head;
+static int exclude(const char *file);
+static int filespec_add(ino_t ino, const security_context_t con, const char *file);
+static int only_changed_user(const char *a, const char *b);
+struct restore_opts *r_opts = NULL;
+static void filespec_destroy(void);
+static void filespec_eval(void);
+static int excludeCtr = 0;
+static struct edir excludeArray[MAX_EXCLUDES];
+
+void remove_exclude(const char *directory)
+{
+	int i = 0;
+	for (i = 0; i < excludeCtr; i++) {
+		if (strcmp(directory, excludeArray[i].directory) == 0) {
+			if (i != excludeCtr-1)
+				excludeArray[i] = excludeArray[excludeCtr-1];
+			excludeCtr--;
+			return;
+		}
+	}
+	return;
+
+}
+
+void restore_init(struct restore_opts *opts)
+{	
+	r_opts = opts;
+	struct selinux_opt selinux_opts[] = {
+		{ SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
+		{ SELABEL_OPT_PATH, r_opts->selabel_opt_path }
+	};
+	r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 2);
+	if (!r_opts->hnd) {
+		perror(r_opts->selabel_opt_path);
+		exit(1);
+	}	
+}
+
+void restore_finish()
+{
+	int i;
+	for (i = 0; i < excludeCtr; i++) {
+		free(excludeArray[i].directory);
+	}
+}
+
+static int match(const char *name, struct stat *sb, char **con)
+{
+	if (!(r_opts->hard_links) && !S_ISDIR(sb->st_mode) && (sb->st_nlink > 1)) {
+		fprintf(stderr, "Warning! %s refers to a hard link, not fixing hard links.\n",
+					name);
+		return -1;
+	}
+	
+	if (NULL != r_opts->rootpath) {
+		if (0 != strncmp(r_opts->rootpath, name, r_opts->rootpathlen)) {
+			fprintf(stderr, "%s:  %s is not located in %s\n",
+				r_opts->progname, name, r_opts->rootpath);
+			return -1;
+		}
+		name += r_opts->rootpathlen;
+	}
+
+	if (r_opts->rootpath != NULL && name[0] == '\0')
+		/* this is actually the root dir of the alt root */
+		return selabel_lookup_raw(r_opts->hnd, con, "/", sb->st_mode);
+	else
+		return selabel_lookup_raw(r_opts->hnd, con, name, sb->st_mode);
+}
+static int restore(FTSENT *ftsent)
+{
+	char *my_file = strdupa(ftsent->fts_path);
+	int ret;
+	char *context, *newcon;
+	int user_only_changed = 0;
+	if (match(my_file, ftsent->fts_statp, &newcon) < 0)
+		/* Check for no matching specification. */
+		return (errno == ENOENT) ? 0 : -1;
+
+	if (r_opts->progress) {
+		r_opts->count++;
+		if (r_opts->count % (80 * STAR_COUNT) == 0) {
+			fprintf(stdout, "\n");
+			fflush(stdout);
+		}
+		if (r_opts->count % STAR_COUNT == 0) {
+			fprintf(stdout, "*");
+			fflush(stdout);
+		}
+	}
+
+	/*
+	 * Try to add an association between this inode and
+	 * this specification.  If there is already an association
+	 * for this inode and it conflicts with this specification,
+	 * then use the last matching specification.
+	 */
+	if (r_opts->add_assoc) {
+		ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file);
+		if (ret < 0)
+			goto err;
+
+		if (ret > 0)
+			/* There was already an association and it took precedence. */
+			goto out;
+	}
+
+	if (r_opts->debug) {
+		printf("%s:  %s matched by %s\n", r_opts->progname, my_file, newcon);
+	}
+
+	/* Get the current context of the file. */
+	ret = lgetfilecon_raw(ftsent->fts_accpath, &context);
+	if (ret < 0) {
+		if (errno == ENODATA) {
+			context = NULL;
+		} else {
+			fprintf(stderr, "%s get context on %s failed: '%s'\n",
+				r_opts->progname, my_file, strerror(errno));
+			goto err;
+		}
+		user_only_changed = 0;
+	} else
+		user_only_changed = only_changed_user(context, newcon);
+	/* lgetfilecon returns number of characters and ret needs to be reset
+	 * to 0.
+	 */
+	ret = 0;
+
+	/*
+	 * Do not relabel the file if the matching specification is 
+	 * <<none>> or the file is already labeled according to the 
+	 * specification.
+	 */
+	if ((strcmp(newcon, "<<none>>") == 0) ||
+	    (context && (strcmp(context, newcon) == 0))) {
+		freecon(context);
+		goto out;
+	}
+
+	if (!r_opts->force && context && (is_context_customizable(context) > 0)) {
+		if (r_opts->verbose > 1) {
+			fprintf(stderr,
+				"%s: %s not reset customized by admin to %s\n",
+				r_opts->progname, my_file, context);
+		}
+		freecon(context);
+		goto out;
+	}
+
+	if (r_opts->verbose) {
+		/* If we're just doing "-v", trim out any relabels where
+		 * the user has r_opts->changed but the role and type are the
+		 * same.  For "-vv", emit everything. */
+		if (r_opts->verbose > 1 || !user_only_changed) {
+			printf("%s reset %s context %s->%s\n",
+			       r_opts->progname, my_file, context ?: "", newcon);
+		}
+	}
+
+	if (r_opts->logging && !user_only_changed) {
+		if (context)
+			syslog(LOG_INFO, "relabeling %s from %s to %s\n",
+			       my_file, context, newcon);
+		else
+			syslog(LOG_INFO, "labeling %s to %s\n",
+			       my_file, newcon);
+	}
+
+	if (r_opts->outfile && !user_only_changed)
+		fprintf(r_opts->outfile, "%s\n", my_file);
+
+	if (context)
+		freecon(context);
+
+	/*
+	 * Do not relabel the file if -n was used.
+	 */
+	if (!r_opts->change || user_only_changed)
+		goto out;
+
+	/*
+	 * Relabel the file to the specified context.
+	 */
+	ret = lsetfilecon(ftsent->fts_accpath, newcon);
+	if (ret) {
+		fprintf(stderr, "%s set context %s->%s failed:'%s'\n",
+			r_opts->progname, my_file, newcon, strerror(errno));
+		goto skip;
+	}
+	ret = 1;
+out:
+	freecon(newcon);
+	return ret;
+skip:
+	freecon(newcon);
+	return SKIP;
+err:
+	freecon(newcon);
+	return ERR;
+}
+/*
+ * Apply the last matching specification to a file.
+ * This function is called by fts on each file during
+ * the directory traversal.
+ */
+static int apply_spec(FTSENT *ftsent)
+{
+	if (ftsent->fts_info == FTS_DNR) {
+		fprintf(stderr, "%s:  unable to read directory %s\n",
+			r_opts->progname, ftsent->fts_path);
+		return SKIP;
+	}
+	
+	int rc = restore(ftsent);
+	if (rc == ERR) {
+		if (!r_opts->abort_on_error)
+			return SKIP;
+	}
+	return rc;
+}
+
+int process_one(char *name, int recurse_this_path)
+{
+	int rc = 0;
+	const char *namelist[2] = {name, NULL};
+	dev_t dev_num = 0;
+	FTS *fts_handle;
+	FTSENT *ftsent;
+
+	if (r_opts == NULL){
+		fprintf(stderr,
+			"Must call initialize first!");
+		goto err;
+	}
+
+	fts_handle = fts_open((char **)namelist, r_opts->fts_flags, NULL);
+	if (fts_handle  == NULL) {
+		fprintf(stderr,
+			"%s: error while labeling %s:  %s\n",
+			r_opts->progname, namelist[0], strerror(errno));
+		goto err;
+	}
+
+
+	ftsent = fts_read(fts_handle);
+	if (ftsent != NULL) {
+		/* Keep the inode of the first one. */
+		dev_num = ftsent->fts_statp->st_dev;
+	}
+
+	do {
+		rc = 0;
+		/* Skip the post order nodes. */
+		if (ftsent->fts_info == FTS_DP)
+			continue;
+		/* If the XDEV flag is set and the device is different */
+		if (ftsent->fts_statp->st_dev != dev_num &&
+		    FTS_XDEV == (r_opts->fts_flags & FTS_XDEV))
+			continue;
+		if (excludeCtr > 0) {
+			if (exclude(ftsent->fts_path)) {
+				fts_set(fts_handle, ftsent, FTS_SKIP);
+				continue;
+			}
+		}
+		rc = apply_spec(ftsent);
+		if (rc == SKIP)
+			fts_set(fts_handle, ftsent, FTS_SKIP);
+		if (rc == ERR)
+			goto err;
+		if (!recurse_this_path)
+			break;
+	} while ((ftsent = fts_read(fts_handle)) != NULL);
+
+
+out:
+	if (r_opts->add_assoc) {
+		if (!r_opts->quiet)
+			filespec_eval();
+		filespec_destroy();
+	}
+	if (fts_handle)
+		fts_close(fts_handle);
+	return rc;
+
+err:
+	rc = -1;
+	goto out;
+}
+
+static int exclude(const char *file)
+{
+	int i = 0;
+	for (i = 0; i < excludeCtr; i++) {
+		if (strncmp
+		    (file, excludeArray[i].directory,
+		     excludeArray[i].size) == 0) {
+			if (file[excludeArray[i].size] == 0
+			    || file[excludeArray[i].size] == '/') {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+int add_exclude(const char *directory)
+{
+	size_t len = 0;
+
+	if (directory == NULL || directory[0] != '/') {
+		fprintf(stderr, "Full path required for exclude: %s.\n",
+			directory);
+		return 1;
+	}
+	if (excludeCtr == MAX_EXCLUDES) {
+		fprintf(stderr, "Maximum excludes %d exceeded.\n",
+			MAX_EXCLUDES);
+		return 1;
+	}
+
+	len = strlen(directory);
+	while (len > 1 && directory[len - 1] == '/') {
+		len--;
+	}
+	excludeArray[excludeCtr].directory = strndup(directory, len);
+
+	if (excludeArray[excludeCtr].directory == NULL) {
+		fprintf(stderr, "Out of memory.\n");
+		return 1;
+	}
+	excludeArray[excludeCtr++].size = len;
+
+	return 0;
+}
+
+/* Compare two contexts to see if their differences are "significant",
+ * or whether the only difference is in the user. */
+static int only_changed_user(const char *a, const char *b)
+{
+	char *rest_a, *rest_b;	/* Rest of the context after the user */
+	if (r_opts->force)
+		return 0;
+	if (!a || !b)
+		return 0;
+	rest_a = strchr(a, ':');
+	rest_b = strchr(b, ':');
+	if (!rest_a || !rest_b)
+		return 0;
+	return (strcmp(rest_a, rest_b) == 0);
+}
+
+/*
+ * Evaluate the association hash table distribution.
+ */
+static void filespec_eval(void)
+{
+	file_spec_t *fl;
+	int h, used, nel, len, longest;
+
+	if (!fl_head)
+		return;
+
+	used = 0;
+	longest = 0;
+	nel = 0;
+	for (h = 0; h < HASH_BUCKETS; h++) {
+		len = 0;
+		for (fl = fl_head[h].next; fl; fl = fl->next) {
+			len++;
+		}
+		if (len)
+			used++;
+		if (len > longest)
+			longest = len;
+		nel += len;
+	}
+
+	if (r_opts->verbose > 1)
+		printf
+		    ("%s:  hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n",
+		     __FUNCTION__, nel, used, HASH_BUCKETS, longest);
+}
+
+/*
+ * Destroy the association hash table.
+ */
+static void filespec_destroy(void)
+{
+	file_spec_t *fl, *tmp;
+	int h;
+
+	if (!fl_head)
+		return;
+
+	for (h = 0; h < HASH_BUCKETS; h++) {
+		fl = fl_head[h].next;
+		while (fl) {
+			tmp = fl;
+			fl = fl->next;
+			freecon(tmp->con);
+			free(tmp->file);
+			free(tmp);
+		}
+		fl_head[h].next = NULL;
+	}
+	free(fl_head);
+	fl_head = NULL;
+}
+/*
+ * Try to add an association between an inode and a context.
+ * If there is a different context that matched the inode,
+ * then use the first context that matched.
+ */
+static int filespec_add(ino_t ino, const security_context_t con, const char *file)
+{
+	file_spec_t *prevfl, *fl;
+	int h, ret;
+	struct stat sb;
+
+	if (!fl_head) {
+		fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
+		if (!fl_head)
+			goto oom;
+		memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
+	}
+
+	h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
+	for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
+	     prevfl = fl, fl = fl->next) {
+		if (ino == fl->ino) {
+			ret = lstat(fl->file, &sb);
+			if (ret < 0 || sb.st_ino != ino) {
+				freecon(fl->con);
+				free(fl->file);
+				fl->file = strdup(file);
+				if (!fl->file)
+					goto oom;
+				fl->con = strdup(con);
+				if (!fl->con)
+					goto oom;
+				return 1;
+			}
+
+			if (strcmp(fl->con, con) == 0)
+				return 1;
+
+			fprintf(stderr,
+				"%s:  conflicting specifications for %s and %s, using %s.\n",
+				__FUNCTION__, file, fl->file, fl->con);
+			free(fl->file);
+			fl->file = strdup(file);
+			if (!fl->file)
+				goto oom;
+			return 1;
+		}
+
+		if (ino > fl->ino)
+			break;
+	}
+
+	fl = malloc(sizeof(file_spec_t));
+	if (!fl)
+		goto oom;
+	fl->ino = ino;
+	fl->con = strdup(con);
+	if (!fl->con)
+		goto oom_freefl;
+	fl->file = strdup(file);
+	if (!fl->file)
+		goto oom_freefl;
+	fl->next = prevfl->next;
+	prevfl->next = fl;
+	return 0;
+      oom_freefl:
+	free(fl);
+      oom:
+	fprintf(stderr,
+		"%s:  insufficient memory for file label entry for %s\n",
+		__FUNCTION__, file);
+	return -1;
+}
+
+
+
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/restore.h policycoreutils-2.0.74/setfiles/restore.h
--- nsapolicycoreutils/setfiles/restore.h	1969-12-31 19:00:00.000000000 -0500
+++ policycoreutils-2.0.74/setfiles/restore.h	2009-09-20 21:26:36.000000000 -0400
@@ -0,0 +1,49 @@
+#ifndef RESTORE_H
+#define RESTORE_H
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <fts.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sepol/sepol.h>
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#define STAR_COUNT 1000
+
+/* Things that need to be init'd */
+struct restore_opts {
+	int add_assoc; /* Track inode associations for conflict detection. */
+	int progress;
+	unsigned long long count;
+	int debug;
+	int change;
+	int hard_links;
+	int verbose;
+	int logging;
+	char *rootpath;
+	int rootpathlen;
+	char *progname;
+	FILE *outfile;
+	int force;
+	struct selabel_handle *hnd;
+	int abort_on_error; /* Abort the file tree walk upon an error. */
+	int quiet;
+	int fts_flags; /* Flags to fts, e.g. follow links, follow mounts */
+	const char *selabel_opt_validate;
+	const char *selabel_opt_path;
+};
+
+void restore_init(struct restore_opts *opts);
+void restore_finish();
+int add_exclude(const char *directory);
+void remove_exclude(const char *directory);
+int process_one(char *name, int recurse);
+
+#endif
Binary files nsapolicycoreutils/setfiles/restore.o and policycoreutils-2.0.74/setfiles/restore.o differ
diff --exclude-from=exclude --exclude=sepolgen-1.0.17 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/setfiles.c policycoreutils-2.0.74/setfiles/setfiles.c
--- nsapolicycoreutils/setfiles/setfiles.c	2009-09-17 08:59:43.000000000 -0400
+++ policycoreutils-2.0.74/setfiles/setfiles.c	2009-09-20 21:26:36.000000000 -0400
@@ -1,26 +1,12 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
+#include "restore.h"
 #include <unistd.h>
-#include <stdlib.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <stdio_ext.h>
-#include <string.h>
-#include <errno.h>
 #include <ctype.h>
 #include <regex.h>
 #include <sys/vfs.h>
 #include <sys/utsname.h>
 #define __USE_XOPEN_EXTENDED 1	/* nftw */
-#define SKIP -2
-#define ERR -1
-#include <fts.h>
-#include <limits.h>
-#include <sepol/sepol.h>
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-#include <syslog.h>
 #include <libgen.h>
 #ifdef USE_AUDIT
 #include <libaudit.h>
@@ -32,40 +18,22 @@
 static int mass_relabel;
 static int mass_relabel_errs;
 
-#define STAR_COUNT 1000
-
-static FILE *outfile = NULL;
-static int force = 0;
-#define STAT_BLOCK_SIZE 1
-static int progress = 0;
-static unsigned long long count = 0;
-
-#define MAX_EXCLUDES 1000
-static int excludeCtr = 0;
-struct edir {
-	char *directory;
-	size_t size;
-};
-static struct edir excludeArray[MAX_EXCLUDES];
 
 /*
  * Command-line options.
  */
+
 static char *policyfile = NULL;
-static int debug = 0;
-static int change = 1;
-static int quiet = 0;
-static int ignore_enoent;
-static int verbose = 0;
-static int logging = 0;
 static int warn_no_match = 0;
 static int null_terminated = 0;
-static char *rootpath = NULL;
-static int rootpathlen = 0;
 static int recurse; /* Recursive descent. */
 static int errors;
+static int ignore_enoent;
+static struct restore_opts r_opts;
+
+#define STAT_BLOCK_SIZE 1
+
 
-static char *progname;
 
 #define SETFILES "setfiles"
 #define RESTORECON "restorecon"
@@ -73,246 +41,9 @@
 
 /* Behavior flags determined based on setfiles vs. restorecon */
 static int expand_realpath;  /* Expand paths via realpath. */
-static int abort_on_error; /* Abort the file tree walk upon an error. */
-static int add_assoc; /* Track inode associations for conflict detection. */
-static int fts_flags; /* Flags to fts, e.g. follow links, follow mounts */
 static int ctx_validate; /* Validate contexts */
 static const char *altpath; /* Alternate path to file_contexts */
 
-/* Label interface handle */
-static struct selabel_handle *hnd;
-
-/*
- * An association between an inode and a context.
- */
-typedef struct file_spec {
-	ino_t ino;		/* inode number */
-	char *con;		/* matched context */
-	char *file;		/* full pathname */
-	struct file_spec *next;	/* next association in hash bucket chain */
-} file_spec_t;
-
-/*
- * The hash table of associations, hashed by inode number.
- * Chaining is used for collisions, with elements ordered
- * by inode number in each bucket.  Each hash bucket has a dummy 
- * header.
- */
-#define HASH_BITS 16
-#define HASH_BUCKETS (1 << HASH_BITS)
-#define HASH_MASK (HASH_BUCKETS-1)
-static file_spec_t *fl_head;
-
-/*
- * Try to add an association between an inode and a context.
- * If there is a different context that matched the inode,
- * then use the first context that matched.
- */
-int filespec_add(ino_t ino, const security_context_t con, const char *file)
-{
-	file_spec_t *prevfl, *fl;
-	int h, ret;
-	struct stat sb;
-
-	if (!fl_head) {
-		fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
-		if (!fl_head)
-			goto oom;
-		memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
-	}
-
-	h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
-	for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
-	     prevfl = fl, fl = fl->next) {
-		if (ino == fl->ino) {
-			ret = lstat(fl->file, &sb);
-			if (ret < 0 || sb.st_ino != ino) {
-				freecon(fl->con);
-				free(fl->file);
-				fl->file = strdup(file);
-				if (!fl->file)
-					goto oom;
-				fl->con = strdup(con);
-				if (!fl->con)
-					goto oom;
-				return 1;
-			}
-
-			if (strcmp(fl->con, con) == 0)
-				return 1;
-
-			fprintf(stderr,
-				"%s:  conflicting specifications for %s and %s, using %s.\n",
-				__FUNCTION__, file, fl->file, fl->con);
-			free(fl->file);
-			fl->file = strdup(file);
-			if (!fl->file)
-				goto oom;
-			return 1;
-		}
-
-		if (ino > fl->ino)
-			break;
-	}
-
-	fl = malloc(sizeof(file_spec_t));
-	if (!fl)
-		goto oom;
-	fl->ino = ino;
-	fl->con = strdup(con);
-	if (!fl->con)
-		goto oom_freefl;
-	fl->file = strdup(file);
-	if (!fl->file)
-		goto oom_freefl;
-	fl->next = prevfl->next;
-	prevfl->next = fl;
-	return 0;
-      oom_freefl:
-	free(fl);
-      oom:
-	fprintf(stderr,
-		"%s:  insufficient memory for file label entry for %s\n",
-		__FUNCTION__, file);
-	return -1;
-}
-
-/*
- * Evaluate the association hash table distribution.
- */
-void filespec_eval(void)
-{
-	file_spec_t *fl;
-	int h, used, nel, len, longest;
-
-	if (!fl_head)
-		return;
-
-	used = 0;
-	longest = 0;
-	nel = 0;
-	for (h = 0; h < HASH_BUCKETS; h++) {
-		len = 0;
-		for (fl = fl_head[h].next; fl; fl = fl->next) {
-			len++;
-		}
-		if (len)
-			used++;
-		if (len > longest)
-			longest = len;
-		nel += len;
-	}
-
-	printf
-	    ("%s:  hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n",
-	     __FUNCTION__, nel, used, HASH_BUCKETS, longest);
-}
-
-/*
- * Destroy the association hash table.
- */
-void filespec_destroy(void)
-{
-	file_spec_t *fl, *tmp;
-	int h;
-
-	if (!fl_head)
-		return;
-
-	for (h = 0; h < HASH_BUCKETS; h++) {
-		fl = fl_head[h].next;
-		while (fl) {
-			tmp = fl;
-			fl = fl->next;
-			freecon(tmp->con);
-			free(tmp->file);
-			free(tmp);
-		}
-		fl_head[h].next = NULL;
-	}
-	free(fl_head);
-	fl_head = NULL;
-}
-
-static int add_exclude(const char *directory)
-{
-	size_t len = 0;
-
-	if (directory == NULL || directory[0] != '/') {
-		fprintf(stderr, "Full path required for exclude: %s.\n",
-			directory);
-		return 1;
-	}
-	if (excludeCtr == MAX_EXCLUDES) {
-		fprintf(stderr, "Maximum excludes %d exceeded.\n",
-			MAX_EXCLUDES);
-		return 1;
-	}
-
-	len = strlen(directory);
-	while (len > 1 && directory[len - 1] == '/') {
-		len--;
-	}
-	excludeArray[excludeCtr].directory = strndup(directory, len);
-
-	if (excludeArray[excludeCtr].directory == NULL) {
-		fprintf(stderr, "Out of memory.\n");
-		return 1;
-	}
-	excludeArray[excludeCtr++].size = len;
-
-	return 0;
-}
-
-static void remove_exclude(const char *directory)
-{
-	int i = 0;
-	for (i = 0; i < excludeCtr; i++) {
-		if (strcmp(directory, excludeArray[i].directory) == 0) {
-			free(excludeArray[i].directory);
-			if (i != excludeCtr-1)
-				excludeArray[i] = excludeArray[excludeCtr-1];
-			excludeCtr--;
-			return;
-		}
-	}
-	return;
-}
-
-static int exclude(const char *file)
-{
-	int i = 0;
-	for (i = 0; i < excludeCtr; i++) {
-		if (strncmp
-		    (file, excludeArray[i].directory,
-		     excludeArray[i].size) == 0) {
-			if (file[excludeArray[i].size] == 0
-			    || file[excludeArray[i].size] == '/') {
-				return 1;
-			}
-		}
-	}
-	return 0;
-}
-
-int match(const char *name, struct stat *sb, char **con)
-{
-	if (NULL != rootpath) {
-		if (0 != strncmp(rootpath, name, rootpathlen)) {
-			fprintf(stderr, "%s:  %s is not located in %s\n",
-				progname, name, rootpath);
-			return -1;
-		}
-		name += rootpathlen;
-	}
-
-	if (rootpath != NULL && name[0] == '\0')
-		/* this is actually the root dir of the alt root */
-		return selabel_lookup_raw(hnd, con, "/", sb->st_mode);
-	else
-		return selabel_lookup_raw(hnd, con, name, sb->st_mode);
-}
-
 void usage(const char *const name)
 {
 	if (iamrestorecon) {
@@ -334,194 +65,30 @@
 void inc_err()
 {
 	nerr++;
-	if (nerr > 9 && !debug) {
+	if (nerr > 9 && !r_opts.debug) {
 		fprintf(stderr, "Exiting after 10 errors.\n");
 		exit(1);
 	}
 }
 
-/* Compare two contexts to see if their differences are "significant",
- * or whether the only difference is in the user. */
-static int only_changed_user(const char *a, const char *b)
-{
-	char *rest_a, *rest_b;	/* Rest of the context after the user */
-	if (force)
-		return 0;
-	if (!a || !b)
-		return 0;
-	rest_a = strchr(a, ':');
-	rest_b = strchr(b, ':');
-	if (!rest_a || !rest_b)
-		return 0;
-	return (strcmp(rest_a, rest_b) == 0);
-}
-
-static int restore(FTSENT *ftsent)
-{
-	char *my_file = strdupa(ftsent->fts_path);
-	int ret;
-	char *context, *newcon;
-	int user_only_changed = 0;
-
-	if (match(my_file, ftsent->fts_statp, &newcon) < 0)
-		/* Check for no matching specification. */
-		return (errno == ENOENT) ? 0 : -1;
-
-	if (progress) {
-		count++;
-		if (count % (80 * STAR_COUNT) == 0) {
-			fprintf(stdout, "\n");
-			fflush(stdout);
-		}
-		if (count % STAR_COUNT == 0) {
-			fprintf(stdout, "*");
-			fflush(stdout);
-		}
-	}
-
-	/*
-	 * Try to add an association between this inode and
-	 * this specification.  If there is already an association
-	 * for this inode and it conflicts with this specification,
-	 * then use the last matching specification.
-	 */
-	if (add_assoc) {
-		ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file);
-		if (ret < 0)
-			goto err;
-
-		if (ret > 0)
-			/* There was already an association and it took precedence. */
-			goto out;
-	}
-
-	if (debug) {
-		printf("%s:  %s matched by %s\n", progname, my_file, newcon);
-	}
-
-	/* Get the current context of the file. */
-	ret = lgetfilecon_raw(ftsent->fts_accpath, &context);
-	if (ret < 0) {
-		if (errno == ENODATA) {
-			context = NULL;
-		} else {
-			fprintf(stderr, "%s get context on %s failed: '%s'\n",
-				progname, my_file, strerror(errno));
-			goto err;
-		}
-		user_only_changed = 0;
-	} else
-		user_only_changed = only_changed_user(context, newcon);
-
-	/*
-	 * Do not relabel the file if the matching specification is 
-	 * <<none>> or the file is already labeled according to the 
-	 * specification.
-	 */
-	if ((strcmp(newcon, "<<none>>") == 0) ||
-	    (context && (strcmp(context, newcon) == 0))) {
-		freecon(context);
-		goto out;
-	}
-
-	if (!force && context && (is_context_customizable(context) > 0)) {
-		if (verbose > 1) {
-			fprintf(stderr,
-				"%s: %s not reset customized by admin to %s\n",
-				progname, my_file, context);
-		}
-		freecon(context);
-		goto out;
-	}
-
-	if (verbose) {
-		/* If we're just doing "-v", trim out any relabels where
-		 * the user has changed but the role and type are the
-		 * same.  For "-vv", emit everything. */
-		if (verbose > 1 || !user_only_changed) {
-			printf("%s reset %s context %s->%s\n",
-			       progname, my_file, context ?: "", newcon);
-		}
-	}
-
-	if (logging && !user_only_changed) {
-		if (context)
-			syslog(LOG_INFO, "relabeling %s from %s to %s\n",
-			       my_file, context, newcon);
-		else
-			syslog(LOG_INFO, "labeling %s to %s\n",
-			       my_file, newcon);
-	}
-
-	if (outfile && !user_only_changed)
-		fprintf(outfile, "%s\n", my_file);
-
-	if (context)
-		freecon(context);
 
-	/*
-	 * Do not relabel the file if -n was used.
-	 */
-	if (!change || user_only_changed)
-		goto out;
-
-	/*
-	 * Relabel the file to the specified context.
-	 */
-	ret = lsetfilecon(ftsent->fts_accpath, newcon);
-	if (ret) {
-		fprintf(stderr, "%s set context %s->%s failed:'%s'\n",
-			progname, my_file, newcon, strerror(errno));
-		goto skip;
-	}
-out:
-	freecon(newcon);
-	return 0;
-skip:
-	freecon(newcon);
-	return SKIP;
-err:
-	freecon(newcon);
-	return ERR;
-}
-
-/*
- * Apply the last matching specification to a file.
- * This function is called by fts on each file during
- * the directory traversal.
- */
-static int apply_spec(FTSENT *ftsent)
-{
-	if (ftsent->fts_info == FTS_DNR) {
-		fprintf(stderr, "%s:  unable to read directory %s\n",
-			progname, ftsent->fts_path);
-		return SKIP;
-	}
-
-	int rc = restore(ftsent);
-	if (rc == ERR) {
-		if (!abort_on_error)
-			return SKIP;
-	}
-	return rc;
-}
 
 void set_rootpath(const char *arg)
 {
 	int len;
 
-	rootpath = strdup(arg);
-	if (NULL == rootpath) {
-		fprintf(stderr, "%s:  insufficient memory for rootpath\n",
-			progname);
+	r_opts.rootpath = strdup(arg);
+	if (NULL == r_opts.rootpath) {
+		fprintf(stderr, "%s:  insufficient memory for r_opts.rootpath\n",
+			r_opts.progname);
 		exit(1);
 	}
 
 	/* trim trailing /, if present */
-	len = strlen(rootpath);
-	while (len && ('/' == rootpath[len - 1]))
-		rootpath[--len] = 0;
-	rootpathlen = len;
+	len = strlen(r_opts.rootpath);
+	while (len && ('/' == r_opts.rootpath[len - 1]))
+		r_opts.rootpath[--len] = 0;
+	r_opts.rootpathlen = len;
 }
 
 int canoncon(char **contextp)
@@ -585,77 +152,6 @@
 	return 0;
 }
 
-static int process_one(char *name, int recurse_this_path)
-{
-	int rc = 0;
-	const char *namelist[2];
-	dev_t dev_num = 0;
-	FTS *fts_handle;
-	FTSENT *ftsent;
-
-	if (!strcmp(name, "/"))
-		mass_relabel = 1;
-
-	namelist[0] = name;
-	namelist[1] = NULL;
-	fts_handle = fts_open((char **)namelist, fts_flags, NULL);
-	if (fts_handle  == NULL) {
-		fprintf(stderr,
-			"%s: error while labeling %s:  %s\n",
-			progname, namelist[0], strerror(errno));
-		goto err;
-	}
-
-
-	ftsent = fts_read(fts_handle);
-	if (ftsent != NULL) {
-		/* Keep the inode of the first one. */
-		dev_num = ftsent->fts_statp->st_dev;
-	}
-
-	do {
-		/* Skip the post order nodes. */
-		if (ftsent->fts_info == FTS_DP)
-			continue;
-		/* If the XDEV flag is set and the device is different */
-		if (ftsent->fts_statp->st_dev != dev_num &&
-		    FTS_XDEV == (fts_flags & FTS_XDEV))
-			continue;
-		if (excludeCtr > 0) {
-			if (exclude(ftsent->fts_path)) {
-				fts_set(fts_handle, ftsent, FTS_SKIP);
-				continue;
-			}
-		}
-		int rc = apply_spec(ftsent);
-		if (rc == SKIP)
-			fts_set(fts_handle, ftsent, FTS_SKIP);
-		if (rc == ERR)
-			goto err;
-		if (!recurse_this_path)
-			break;
-	} while ((ftsent = fts_read(fts_handle)) != NULL);
-
-	if (!strcmp(name, "/"))
-		mass_relabel_errs = 0;
-
-out:
-	if (add_assoc) {
-		if (!quiet)
-			filespec_eval();
-		filespec_destroy();
-	}
-	if (fts_handle)
-		fts_close(fts_handle);
-	return rc;
-
-err:
-	if (!strcmp(name, "/"))
-		mass_relabel_errs = 1;
-	rc = -1;
-	goto out;
-}
-
 static int process_one_realpath(char *name)
 {
 	int rc = 0;
@@ -668,7 +164,7 @@
 		rc = lstat(name, &sb);
 		if (rc < 0) {
 			fprintf(stderr, "%s:  lstat(%s) failed:  %s\n",
-				progname, name,	strerror(errno));
+				r_opts.progname, name,	strerror(errno));
 			return -1;
 		}
 
@@ -804,20 +300,30 @@
 	char *buf = NULL;
 	size_t buf_len;
 	char *base;
-	struct selinux_opt opts[] = {
-		{ SELABEL_OPT_VALIDATE, NULL },
-		{ SELABEL_OPT_PATH, NULL }
-	};
+	
+	memset(&r_opts, 0, sizeof(r_opts));
+
+	/* Initialize variables */
+	r_opts.progress = 0;
+	r_opts.count = 0;
+	r_opts.debug = 0;
+	r_opts.change = 1;
+	r_opts.verbose = 0;
+	r_opts.logging = 0;
+	r_opts.rootpath = NULL;
+	r_opts.rootpathlen = 0;
+	r_opts.outfile = NULL;
+	r_opts.force = 0;
+	r_opts.hard_links = 1;
 
-	memset(excludeArray, 0, sizeof(excludeArray));
 	altpath = NULL;
 
-	progname = strdup(argv[0]);
-	if (!progname) {
+	r_opts.progname = strdup(argv[0]);
+	if (!r_opts.progname) {
 		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
 		exit(1);
 	}
-	base = basename(progname);
+	base = basename(r_opts.progname);
 	
 	if (!strcmp(base, SETFILES)) {
 		/* 
@@ -832,28 +338,28 @@
 		iamrestorecon = 0;
 		recurse = 1;
 		expand_realpath = 0;
-		abort_on_error = 1;
-		add_assoc = 1;
-		fts_flags = FTS_PHYSICAL | FTS_XDEV;
+		r_opts.abort_on_error = 1;
+		r_opts.add_assoc = 1;
+		r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV;
 		ctx_validate = 1;
 	} else {
 		/*
 		 * restorecon:  
 		 * No recursive descent unless -r/-R,
-		 * Expands paths via realpath, 
 		 * Do not abort on errors during the file tree walk,
+		 * Expands paths via realpath, 
 		 * Do not try to track inode associations for conflict detection,
 		 * Follows mounts,
 		 * Does lazy validation of contexts upon use. 
 		 */
-		if (strcmp(base, RESTORECON) && !quiet) 
+		if (strcmp(base, RESTORECON) && !r_opts.quiet) 
 			printf("Executed with an unrecognized name (%s), defaulting to %s behavior.\n", base, RESTORECON);
 		iamrestorecon = 1;
 		recurse = 0;
 		expand_realpath = 1;
-		abort_on_error = 0;
-		add_assoc = 0;
-		fts_flags = FTS_PHYSICAL;
+		r_opts.abort_on_error = 0;
+		r_opts.add_assoc = 0;
+		r_opts.fts_flags = FTS_PHYSICAL;
 		ctx_validate = 0;
 
 		/* restorecon only:  silent exit if no SELinux.
@@ -915,37 +421,37 @@
 			input_filename = optarg;
 			break;			
 		case 'd':
-			debug = 1;
+			r_opts.debug = 1;
 			break;
 		case 'i':
 			ignore_enoent = 1;
 			break;
 		case 'l':
-			logging = 1;
+			r_opts.logging = 1;
 			break;
 		case 'F':
-			force = 1;
+			r_opts.force = 1;
 			break;
 		case 'n':
-			change = 0;
+			r_opts.change = 0;
 			break;
 		case 'o':
 			if (strcmp(optarg, "-") == 0) {
-				outfile = stdout;
+				r_opts.outfile = stdout;
 				break;
 			}
 
-			outfile = fopen(optarg, "w");
-			if (!outfile) {
+			r_opts.outfile = fopen(optarg, "w");
+			if (!r_opts.outfile) {
 				fprintf(stderr, "Error opening %s: %s\n",
 					optarg, strerror(errno));
 
 				usage(argv[0]);
 			}
-			__fsetlocking(outfile, FSETLOCKING_BYCALLER);
+			__fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER);
 			break;
 		case 'q':
-			quiet = 1;
+			r_opts.quiet = 1;
 			break;
 		case 'R':
 		case 'r':
@@ -958,7 +464,7 @@
 					argv[0]);
 				exit(1);
 			}
-			if (NULL != rootpath) {
+			if (NULL != r_opts.rootpath) {
 				fprintf(stderr,
 					"%s: only one -r can be specified\n",
 					argv[0]);
@@ -969,23 +475,23 @@
 		case 's':
 			use_input_file = 1;
 			input_filename = "-";
-			add_assoc = 0;
+			r_opts.add_assoc = 0;
 			break;
 		case 'v':
-			if (progress) {
+			if (r_opts.progress) {
 				fprintf(stderr,
 					"Progress and Verbose mutually exclusive\n");
 				exit(1);
 			}
-			verbose++;
+			r_opts.verbose++;
 			break;
 		case 'p':
-			if (verbose) {
+			if (r_opts.verbose) {
 				fprintf(stderr,
 					"Progress and Verbose mutually exclusive\n");
 				usage(argv[0]);
 			}
-			progress = 1;
+			r_opts.progress = 1;
 			break;
 		case 'W':
 			warn_no_match = 1;
@@ -1033,18 +539,13 @@
 	}
 
 	/* Load the file contexts configuration and check it. */
-	opts[0].value = (ctx_validate ? (char*)1 : NULL);
-	opts[1].value = altpath;
-
-	hnd = selabel_open(SELABEL_CTX_FILE, opts, 2);
-	if (!hnd) {
-		perror(altpath);
-		exit(1);
-	}
+	r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL);
+	r_opts.selabel_opt_path = altpath;
 
 	if (nerr)
 		exit(1);
 
+	restore_init(&r_opts);
 	if (use_input_file) {
 		FILE *f = stdin;
 		ssize_t len;
@@ -1061,6 +562,9 @@
 		delim = (null_terminated != 0) ? '\0' : '\n';
 		while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) {
 			buf[len - 1] = 0;
+			if (!strcmp(buf, "/"))
+				mass_relabel = 1;
+	
 			errors |= process_one_realpath(buf);
 		}
 		if (strcmp(input_filename, "-") != 0)
@@ -1070,22 +574,21 @@
 			errors |= process_one_realpath(argv[i]);
 		}
 	}
-
+	
+	if (mass_relabel)
+		mass_relabel_errs = errors;
 	maybe_audit_mass_relabel();
 
 	if (warn_no_match)
-		selabel_stats(hnd);
+		selabel_stats(r_opts.hnd);
 
-	selabel_close(hnd);
+	selabel_close(r_opts.hnd);
+	restore_finish();
 
-	if (outfile)
-		fclose(outfile);
-
-	for (i = 0; i < excludeCtr; i++) {
-		free(excludeArray[i].directory);
-	}
+	if (r_opts.outfile)
+		fclose(r_opts.outfile);
 
-       if (progress && count >= STAR_COUNT)
+       if (r_opts.progress && r_opts.count >= STAR_COUNT)
                printf("\n");
 	exit(errors);
 }