Merge branch 'upstream'

Conflicts:
	.gitignore
diff --git a/.gitignore b/.gitignore
index e4e5f6c..a7bd076 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
-*~
\ No newline at end of file
+checkmodule
+checkpolicy
+lex.yy.c
+y.tab.c
+y.tab.h
diff --git a/ChangeLog b/ChangeLog
index 688fcf5..96b1de8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2.1.8 2011-12-21
+	* add new helper to translate class sets into bitmaps
+
+2.1.7 2011-12-05
+	* dis* fixed signed vs unsigned errors
+	* dismod: fix unused parameter errors
+	* test: Makefile: include -W and -Werror
+	* allow ~ in filename transition rules
+
+2.1.6 2011-11-03
+	* Revert "checkpolicy: Redo filename/filesystem syntax to support filename trans rules"
+	* drop libsepol dynamic link in checkpolicy
+
+2.1.5 2011-09-15
+	* Separate tunable from boolean during compile.
+
+2.1.4 2011-08-26
+	* checkpolicy: fix spacing in output message
+
+2.1.3 2011-08-17
+	* add missing ; to attribute_role_def
+	*Redo filename/filesystem syntax to support filename trans
+
+2.1.2 2011-08-02
+	* .gitignore changes
+	* dispol output of role trans
+	* man page update: build a module with an older policy version
+
+2.1.1 2011-08-01
+	* Minor updates to filename trans rule output in dis{mod,pol}
+
 2.1.0 2011-07-27
 	* Release, minor version bump
 
diff --git a/VERSION b/VERSION
index 7ec1d6d..ebf14b4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.0
+2.1.8
diff --git a/checkmodule.8 b/checkmodule.8
index 54680e3..473f642 100644
--- a/checkmodule.8
+++ b/checkmodule.8
@@ -35,7 +35,7 @@
 Enable the MLS/MCS support when checking and compiling the policy module.
 .TP
 .B \-V,\-\-version
- Show policy versions created by this program
+ Show policy versions created by this program.  Note that you cannot currently build older versions.
 .TP
 .B \-o,\-\-output filename
 Write a binary policy module file to the specified filename.
diff --git a/module_compiler.c b/module_compiler.c
index 1c1d1d5..ffffaf1 100644
--- a/module_compiler.c
+++ b/module_compiler.c
@@ -1045,7 +1045,7 @@
 	}
 }
 
-int require_bool(int pass)
+static int require_bool_tunable(int pass, int is_tunable)
 {
 	char *id = queue_remove(id_queue);
 	cond_bool_datum_t *booldatum = NULL;
@@ -1063,6 +1063,8 @@
 		yyerror("Out of memory!");
 		return -1;
 	}
+	if (is_tunable)
+		booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
 	retval =
 	    require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
 			   &booldatum->s.value, &booldatum->s.value);
@@ -1094,6 +1096,16 @@
 	}
 }
 
+int require_bool(int pass)
+{
+	return require_bool_tunable(pass, 0);
+}
+
+int require_tunable(int pass)
+{
+	return require_bool_tunable(pass, 1);
+}
+
 int require_sens(int pass)
 {
 	char *id = queue_remove(id_queue);
@@ -1328,6 +1340,8 @@
 		     tmp = tmp->next) ;
 		tmp->next = cond->avfalse_list;
 	}
+
+	old_cond->flags |= cond->flags;
 }
 
 void append_avrule(avrule_t * avrule)
diff --git a/module_compiler.h b/module_compiler.h
index 45a21cd..72c2d9b 100644
--- a/module_compiler.h
+++ b/module_compiler.h
@@ -58,6 +58,7 @@
 int require_attribute_role(int pass);
 int require_user(int pass);
 int require_bool(int pass);
+int require_tunable(int pass);
 int require_sens(int pass);
 int require_cat(int pass);
 
diff --git a/policy_define.c b/policy_define.c
index 0bdfcd2..9f1e5d5 100644
--- a/policy_define.c
+++ b/policy_define.c
@@ -327,6 +327,30 @@
 	return -1;
 }
 
+static int read_classes(ebitmap_t *e_classes)
+{
+	char *id;
+	class_datum_t *cladatum;
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_CLASSES, id)) {
+			yyerror2("class %s is not within scope", id);
+			return -1;
+		}
+		cladatum = hashtab_search(policydbp->p_classes.table, id);
+		if (!cladatum) {
+			yyerror2("unknown class %s", id);
+			return -1;
+		}
+		if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) {
+			yyerror("Out of memory");
+			return -1;
+		}
+		free(id);
+	}
+	return 0;
+}
+
 int define_common_perms(void)
 {
 	char *id = 0, *perm = 0;
@@ -1360,7 +1384,6 @@
 {
 	char *id;
 	type_datum_t *datum;
-	class_datum_t *cladatum;
 	ebitmap_t tclasses;
 	ebitmap_node_t *node;
 	avrule_t *avrule;
@@ -1387,23 +1410,8 @@
 	}
 
 	ebitmap_init(&tclasses);
-	while ((id = queue_remove(id_queue))) {
-		if (!is_id_in_scope(SYM_CLASSES, id)) {
-			yyerror2("class %s is not within scope", id);
-			free(id);
-			goto bad;
-		}
-		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!cladatum) {
-			yyerror2("unknown class %s", id);
-			goto bad;
-		}
-		if (ebitmap_set_bit(&tclasses, cladatum->s.value - 1, TRUE)) {
-			yyerror("Out of memory");
-			goto bad;
-		}
-		free(id);
-	}
+	if (read_classes(&tclasses))
+		goto bad;
 
 	id = (char *)queue_remove(id_queue);
 	if (!id) {
@@ -1494,7 +1502,7 @@
 	return avrule;
 }
 
-int define_bool(void)
+int define_bool_tunable(int is_tunable)
 {
 	char *id, *bool_value;
 	cond_bool_datum_t *datum;
@@ -1524,6 +1532,8 @@
 		return -1;
 	}
 	memset(datum, 0, sizeof(cond_bool_datum_t));
+	if (is_tunable)
+		datum->flags |= COND_BOOL_FLAGS_TUNABLE;
 	ret = declare_symbol(SYM_BOOLS, id, datum, &value, &value);
 	switch (ret) {
 	case -3:{
@@ -1626,25 +1636,9 @@
 	}
 
 	ebitmap_init(&tclasses);
-	while ((id = queue_remove(id_queue))) {
-		if (!is_id_in_scope(SYM_CLASSES, id)) {
-			yyerror2("class %s is not within scope", id);
-			ret = -1;
-			goto out;
-		}
-		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!cladatum) {
-			yyerror2("unknown class %s used in rule", id);
-			ret = -1;
-			goto out;
-		}
-		if (ebitmap_set_bit(&tclasses, cladatum->s.value - 1, TRUE)) {
-			yyerror("Out of memory");
-			ret = -1;
-			goto out;
-		}
-		free(id);
-	}
+	ret = read_classes(&tclasses);
+	if (ret)
+		goto out;
 
 	perms = NULL;
 	ebitmap_for_each_bit(&tclasses, node, i) {
@@ -2240,22 +2234,8 @@
 	}
 
 	if (class_specified) {
-		while ((id = queue_remove(id_queue))) {
-			if (!is_id_in_scope(SYM_CLASSES, id)) {
-				yyerror2("class %s is not within scope", id);
-				free(id);
-				return -1;
-			}
-			cladatum = hashtab_search(policydbp->p_classes.table,
-						  id);
-			if (!cladatum) {
-				yyerror2("unknow class %s", id);
-				return -1;
-			}
-
-			ebitmap_set_bit(&e_classes, cladatum->s.value - 1, TRUE);
-			free(id);
-		}
+		if (read_classes(&e_classes))
+			return -1;
 	} else {
 		cladatum = hashtab_search(policydbp->p_classes.table,
 					  "process");
@@ -2408,7 +2388,6 @@
 	ebitmap_node_t *snode, *tnode, *cnode;
 	filename_trans_t *ft;
 	filename_trans_rule_t *ftr;
-	class_datum_t *cladatum;
 	type_datum_t *typdatum;
 	uint32_t otype;
 	unsigned int c, s, t;
@@ -2449,23 +2428,8 @@
 	}
 
 	ebitmap_init(&e_tclasses);
-	while ((id = queue_remove(id_queue))) {
-		if (!is_id_in_scope(SYM_CLASSES, id)) {
-			yyerror2("class %s is not within scope", id);
-			free(id);
-			goto bad;
-		}
-		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!cladatum) {
-			yyerror2("unknown class %s", id);
-			goto bad;
-		}
-		if (ebitmap_set_bit(&e_tclasses, cladatum->s.value - 1, TRUE)) {
-			yyerror("Out of memory");
-			goto bad;
-		}
-		free(id);
-	}
+	if (read_classes(&e_tclasses))
+		goto bad;
 
 	id = (char *)queue_remove(id_queue);
 	if (!id) {
@@ -4553,23 +4517,8 @@
 	}
 
 	if (class_specified) {
-		while ((id = queue_remove(id_queue))) {
-			if (!is_id_in_scope(SYM_CLASSES, id)) {
-				yyerror2("class %s is not within scope", id);
-				free(id);
-				goto out;
-			}
-			cladatum = hashtab_search(policydbp->p_classes.table,
-			                          id);
-			if (!cladatum) {
-				yyerror2("unknown class %s", id);
-				goto out;
-			}
-
-			ebitmap_set_bit(&rule->tclasses, cladatum->s.value - 1,
-			                TRUE);
-			free(id);
-		}
+		if (read_classes(&rule->tclasses))
+			goto out;
 	} else {
 		cladatum = hashtab_search(policydbp->p_classes.table,
 		                          "process");
diff --git a/policy_define.h b/policy_define.h
index fc8cd4d..92a9be7 100644
--- a/policy_define.h
+++ b/policy_define.h
@@ -21,7 +21,7 @@
 int define_attrib(void);
 int define_attrib_role(void);
 int define_av_perms(int inherits);
-int define_bool(void);
+int define_bool_tunable(int is_tunable);
 int define_category(void);
 int define_class(void);
 int define_common_perms(void);
diff --git a/policy_parse.y b/policy_parse.y
index 6567369..d808111 100644
--- a/policy_parse.y
+++ b/policy_parse.y
@@ -101,6 +101,7 @@
 %token ALIAS
 %token ATTRIBUTE
 %token BOOL
+%token TUNABLE
 %token IF
 %token ELSE
 %token TYPE_TRANSITION
@@ -269,6 +270,7 @@
                         | typeattribute_def
                         | typebounds_def
                         | bool_def
+			| tunable_def
                         | transition_def
                         | range_trans_def
                         | te_avtab_def
@@ -295,8 +297,11 @@
 			| 
 			;
 bool_def                : BOOL identifier bool_val ';'
-                        {if (define_bool()) return -1;}
+                        { if (define_bool_tunable(0)) return -1; }
                         ;
+tunable_def		: TUNABLE identifier bool_val ';'
+			{ if (define_bool_tunable(1)) return -1; }
+			;
 bool_val                : CTRUE
  			{ if (insert_id("T",0)) return -1; }
                         | CFALSE
@@ -424,6 +429,7 @@
 		        ;
 attribute_role_def	: ATTRIBUTE_ROLE identifier ';'
 			{if (define_attrib_role()) return -1; }
+		        ;
 role_type_def		: ROLE identifier TYPES names ';'
 			{if (define_role_types()) return -1;}
 			;
@@ -817,6 +823,7 @@
                         | ATTRIBUTE_ROLE   { $$ = require_attribute_role; }
                         | USER        { $$ = require_user; }
                         | BOOL        { $$ = require_bool; }
+			| TUNABLE     { $$ = require_tunable; }
                         | SENSITIVITY { $$ = require_sens; }
                         | CATEGORY    { $$ = require_cat; }
                         ;
diff --git a/policy_scan.l b/policy_scan.l
index 3e6c940..22b91a3 100644
--- a/policy_scan.l
+++ b/policy_scan.l
@@ -96,6 +96,8 @@
 type				{ return(TYPE); }
 BOOL |
 bool                            { return(BOOL); }
+TUNABLE |
+tunable				{ return(TUNABLE); }
 IF |
 if				{ return(IF); }
 ELSE |
@@ -224,7 +226,7 @@
 permissive |
 PERMISSIVE			{ return(PERMISSIVE); }
 "/"({alnum}|[_\.\-/])*	        { return(PATH); }
-\"({alnum}|[_\.\-])+\"			{ return(FILENAME); }
+\"({alnum}|[_\.\-\~])+\"	{ return(FILENAME); }
 {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))*	{ return(IDENTIFIER); }
 {alnum}*{letter}{alnum}*        { return(FILESYSTEM); }
 {digit}+|0x{hexval}+            { return(NUMBER); }
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..dbb03b9
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,2 @@
+dismod
+dispol
diff --git a/test/Makefile b/test/Makefile
index fe1bf5d..0731e89 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -6,10 +6,10 @@
 LIBDIR=$(PREFIX)/lib
 INCLUDEDIR ?= $(PREFIX)/include
 
-CFLAGS ?= -g -Wall -O2 -pipe
+CFLAGS ?= -g -Wall -W -Werror -O2 -pipe
 override CFLAGS += -I$(INCLUDEDIR)
 
-LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
+LDLIBS=-lfl -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
 
 all: dispol dismod
 
diff --git a/test/dismod.c b/test/dismod.c
index 66f976f..6a951f6 100644
--- a/test/dismod.c
+++ b/test/dismod.c
@@ -115,7 +115,7 @@
 int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
 		     FILE * fp)
 {
-	int i, num_types;
+	unsigned int i, num_types;
 
 	if (set->flags & TYPE_STAR) {
 		fprintf(fp, " * ");
@@ -178,7 +178,7 @@
 
 int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
 {
-	int i, num = 0;
+	unsigned int i, num = 0;
 
 	if (roles->flags & ROLE_STAR) {
 		fprintf(fp, " * ");
@@ -211,13 +211,7 @@
 
 }
 
-/* 'what' values for this function */
-#define	RENDER_UNCONDITIONAL	0x0001	/* render all regardless of enabled state */
-#define RENDER_ENABLED		0x0002
-#define RENDER_DISABLED		0x0004
-#define RENDER_CONDITIONAL	(RENDER_ENABLED|RENDER_DISABLED)
-
-int display_avrule(avrule_t * avrule, uint32_t what, policydb_t * policy,
+int display_avrule(avrule_t * avrule, policydb_t * policy,
 		   FILE * fp)
 {
 	class_perm_node_t *cur;
@@ -299,7 +293,7 @@
 {
 	type_datum_t *type;
 	FILE *fp;
-	int i, first_attrib = 1;
+	unsigned int i, first_attrib = 1;
 
 	type = (type_datum_t *) datum;
 	fp = (FILE *) data;
@@ -346,7 +340,7 @@
 
 int display_users(policydb_t * p, FILE * fp)
 {
-	int i, j;
+	unsigned int i, j;
 	ebitmap_t *bitmap;
 	for (i = 0; i < p->p_users.nprim; i++) {
 		display_id(p, fp, SYM_USERS, i, "");
@@ -365,7 +359,7 @@
 
 int display_bools(policydb_t * p, FILE * fp)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < p->p_bools.nprim; i++) {
 		display_id(p, fp, SYM_BOOLS, i, "");
@@ -409,30 +403,11 @@
 	}
 }
 
-void display_policycon(policydb_t * p, FILE * fp)
+void display_policycon(FILE * fp)
 {
-#if 0
-	int i;
-	ocontext_t *cur;
-	char *name;
-
-	for (i = 0; i < POLICYCON_NUM; i++) {
-		fprintf(fp, "%s:", symbol_labels[i]);
-		for (cur = p->policycon[i].head; cur != NULL; cur = cur->next) {
-			if (*(cur->u.name) == '\0') {
-				name = "{default}";
-			} else {
-				name = cur->u.name;
-			}
-			fprintf(fp, "\n%16s - %s:%s:%s", name,
-				p->p_user_val_to_name[cur->context[0].user - 1],
-				p->p_role_val_to_name[cur->context[0].role - 1],
-				p->p_type_val_to_name[cur->context[0].type -
-						      1]);
-		}
-		fprintf(fp, "\n");
-	}
-#endif
+	/* There was an attempt to implement this at one time.  Look through
+	 * git history to find it. */
+	fprintf(fp, "Sorry, not implemented\n");
 }
 
 void display_initial_sids(policydb_t * p, FILE * fp)
@@ -462,7 +437,7 @@
 
 void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
 {
-	int i, num = 0;
+	unsigned int i, num = 0;
 
 	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
 		if (!ebitmap_get_bit(classes, i))
@@ -506,19 +481,20 @@
 	}
 }
 
-void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
+static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
 {
+	fprintf(fp, "filename transition");
 	for (; tr; tr = tr->next) {
-		fprintf(fp, "filename transition %s", tr->name);
 		display_type_set(&tr->stypes, 0, p, fp);
 		display_type_set(&tr->ttypes, 0, p, fp);
 		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
 		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
-		fprintf(fp, "\n");
+		fprintf(fp, " %s\n", tr->name);
 	}
 }
 
-int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
+int role_display_callback(hashtab_key_t key __attribute__((unused)),
+			  hashtab_datum_t datum, void *data)
 {
 	role_datum_t *role;
 	FILE *fp;
@@ -538,9 +514,9 @@
 static int display_scope_index(scope_index_t * indices, policydb_t * p,
 			       FILE * out_fp)
 {
-	int i;
+	unsigned int i;
 	for (i = 0; i < SYM_NUM; i++) {
-		int any_found = 0, j;
+		unsigned int any_found = 0, j;
 		fprintf(out_fp, "%s:", symbol_labels[i]);
 		for (j = ebitmap_startbit(&indices->scope[i]);
 		     j < ebitmap_length(&indices->scope[i]); j++) {
@@ -611,7 +587,7 @@
 }
 #endif
 
-int display_avdecl(avrule_decl_t * decl, int field, uint32_t what,
+int display_avdecl(avrule_decl_t * decl, int field,
 		   policydb_t * policy, FILE * out_fp)
 {
 	fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
@@ -629,7 +605,6 @@
 				avrule = cond->avtrue_list;
 				while (avrule) {
 					display_avrule(avrule,
-						       RENDER_UNCONDITIONAL,
 						       &policydb, out_fp);
 					avrule = avrule->next;
 				}
@@ -637,7 +612,6 @@
 				avrule = cond->avfalse_list;
 				while (avrule) {
 					display_avrule(avrule,
-						       RENDER_UNCONDITIONAL,
 						       &policydb, out_fp);
 					avrule = avrule->next;
 				}
@@ -651,10 +625,8 @@
 				fprintf(out_fp, "  <empty>\n");
 			}
 			while (avrule != NULL) {
-				if (display_avrule
-				    (avrule, what, policy, out_fp)) {
+				if (display_avrule(avrule, policy, out_fp))
 					return -1;
-				}
 				avrule = avrule->next;
 			}
 			break;
@@ -688,7 +660,6 @@
 	case DISPLAY_AVBLOCK_FILENAME_TRANS:
 		display_filename_trans(decl->filename_trans_rules, policy,
 				       out_fp);
-			return -1;
 		break;
 	default:{
 			assert(0);
@@ -697,7 +668,7 @@
 	return 0;		/* should never get here */
 }
 
-int display_avblock(int field, uint32_t what, policydb_t * policy,
+int display_avblock(int field, policydb_t * policy,
 		    FILE * out_fp)
 {
 	avrule_block_t *block = policydb.global;
@@ -705,7 +676,7 @@
 		fprintf(out_fp, "--- begin avrule block ---\n");
 		avrule_decl_t *decl = block->branch_list;
 		while (decl != NULL) {
-			if (display_avdecl(decl, field, what, policy, out_fp)) {
+			if (display_avdecl(decl, field, policy, out_fp)) {
 				return -1;
 			}
 			decl = decl->next;
@@ -821,7 +792,7 @@
 	ebitmap_node_t *node;
 	const char *capname;
 	char buf[64];
-	int i;
+	unsigned int i;
 
 	fprintf(fp, "policy capabilities:\n");
 	ebitmap_for_each_bit(&p->policycaps, node, i) {
@@ -916,14 +887,12 @@
 		case '1':
 			fprintf(out_fp, "unconditional avtab:\n");
 			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
-					RENDER_UNCONDITIONAL, &policydb,
-					out_fp);
+					&policydb, out_fp);
 			break;
 		case '2':
 			fprintf(out_fp, "conditional avtab:\n");
 			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
-					RENDER_UNCONDITIONAL, &policydb,
-					out_fp);
+					&policydb, out_fp);
 			break;
 		case '3':
 			display_users(&policydb, out_fp);
@@ -945,28 +914,28 @@
 			break;
 		case '7':
 			fprintf(out_fp, "role transitions:\n");
-			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, 0,
+			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
 					&policydb, out_fp);
 			break;
 		case '8':
 			fprintf(out_fp, "role allows:\n");
-			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, 0,
+			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
 					&policydb, out_fp);
 			break;
 		case '9':
-			display_policycon(&policydb, out_fp);
+			display_policycon(out_fp);
 			break;
 		case '0':
 			display_initial_sids(&policydb, out_fp);
 			break;
 		case 'a':
 			fprintf(out_fp, "avrule block requirements:\n");
-			display_avblock(DISPLAY_AVBLOCK_REQUIRES, 0,
+			display_avblock(DISPLAY_AVBLOCK_REQUIRES,
 					&policydb, out_fp);
 			break;
 		case 'b':
 			fprintf(out_fp, "avrule block declarations:\n");
-			display_avblock(DISPLAY_AVBLOCK_DECLARES, 0,
+			display_avblock(DISPLAY_AVBLOCK_DECLARES,
 					&policydb, out_fp);
 			break;
 		case 'c':
@@ -994,7 +963,7 @@
 		case 'F':
 			fprintf(out_fp, "filename_trans rules:\n");
 			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
-					0, &policydb, out_fp);
+					&policydb, out_fp);
 			break;
 		case 'l':
 			link_module(&policydb, out_fp);
diff --git a/test/dispol.c b/test/dispol.c
index ee2cf02..f41acdc 100644
--- a/test/dispol.c
+++ b/test/dispol.c
@@ -157,7 +157,7 @@
 
 int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
 {
-	int i;
+	unsigned int i;
 	avtab_ptr_t cur;
 	avtab_t expa;
 
@@ -184,7 +184,7 @@
 
 int display_bools(policydb_t * p, FILE * fp)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < p->p_bools.nprim; i++) {
 		fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i],
@@ -304,7 +304,7 @@
 	ebitmap_node_t *node;
 	const char *capname;
 	char buf[64];
-	int i;
+	unsigned int i;
 
 	fprintf(fp, "policy capabilities:\n");
 	ebitmap_for_each_bit(&p->policycaps, node, i) {
@@ -329,7 +329,7 @@
 static void display_permissive(policydb_t *p, FILE *fp)
 {
 	ebitmap_node_t *node;
-	int i;
+	unsigned int i;
 
 	fprintf(fp, "permissive sids:\n");
 	ebitmap_for_each_bit(&p->permissive_map, node, i) {
@@ -341,18 +341,31 @@
 	}
 }
 
+static void display_role_trans(policydb_t *p, FILE *fp)
+{
+	role_trans_t *rt;
+
+	fprintf(fp, "role_trans rules:\n");
+	for (rt = p->role_tr; rt; rt = rt->next) {
+		display_id(p, fp, SYM_ROLES, rt->role - 1, "");
+		display_id(p, fp, SYM_TYPES, rt->type - 1, "");
+		display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
+		display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
+		fprintf(fp, "\n");
+	}
+}
+
 static void display_filename_trans(policydb_t *p, FILE *fp)
 {
 	filename_trans_t *ft;
 
 	fprintf(fp, "filename_trans rules:\n");
 	for (ft = p->filename_trans; ft; ft = ft->next) {
-		fprintf(fp, "%s\n", ft->name);
 		display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
 		display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
 		display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
 		display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
-		fprintf(fp, "\n");
+		fprintf(fp, " %s\n", ft->name);
 	}
 }
 
@@ -366,6 +379,7 @@
 	printf("5)  display conditional bools\n");
 	printf("6)  display conditional expressions\n");
 	printf("7)  change a boolean value\n");
+	printf("8)  display role transitions\n");
 	printf("\n");
 	printf("c)  display policy capabilities\n");
 	printf("p)  display the list of permissive types\n");
@@ -484,6 +498,9 @@
 			change_bool(name, state, &policydb, out_fp);
 			free(name);
 			break;
+		case '8':
+			display_role_trans(&policydb, out_fp);
+			break;
 		case 'c':
 			display_policycaps(&policydb, out_fp);
 			break;