int main(int argc, char **argv)
{
	char *file = txtfile, *outfile = NULL;
	unsigned int binary = 0;
	int ch;
	int show_version = 0;
	policydb_t modpolicydb;
	struct option long_options[] = {
		{"help", no_argument, NULL, 'h'},
		{"output", required_argument, NULL, 'o'},
		{"binary", no_argument, NULL, 'b'},
		{"version", no_argument, NULL, 'V'},
		{"handle-unknown", optional_argument, NULL, 'U'},
		{"mls", no_argument, NULL, 'M'},
		{NULL, 0, NULL, 0}
	};

	while ((ch = getopt_long(argc, argv, "ho:bVU:mM", long_options, NULL)) != -1) {
		switch (ch) {
		case 'h':
			usage(argv[0]);
			break;
		case 'o':
			outfile = optarg;
			break;
		case 'b':
			binary = 1;
			file = binfile;
			break;
		case 'V':
			show_version = 1;
			break;
		case 'U':
			if (!strcasecmp(optarg, "deny")) {
				handle_unknown = DENY_UNKNOWN;
				break;
			}
			if (!strcasecmp(optarg, "reject")) {
				handle_unknown = REJECT_UNKNOWN;
				break;
			}
			if (!strcasecmp(optarg, "allow")) {
				handle_unknown = ALLOW_UNKNOWN;
				break;
			}
			usage(argv[0]);
		case 'm':
			policy_type = POLICY_MOD;
			policyvers = MOD_POLICYDB_VERSION_MAX;
			break;
		case 'M':
			mlspol = 1;
			break;
		default:
			usage(argv[0]);
		}
	}

	if (show_version) {
		printf("Module versions %d-%d\n",
		       MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX);
		exit(0);
	}

	if (handle_unknown && (policy_type != POLICY_BASE)) {
		printf("Handling of unknown classes and permissions is only ");
		printf("valid in the base module\n");
		exit(1);
	}

	if (optind != argc) {
		file = argv[optind++];
		if (optind != argc)
			usage(argv[0]);
	}
	printf("%s:  loading policy configuration from %s\n", argv[0], file);

	/* Set policydb and sidtab used by libsepol service functions
	   to my structures, so that I can directly populate and
	   manipulate them. */
	sepol_set_policydb(&modpolicydb);
	sepol_set_sidtab(&sidtab);

	if (binary) {
		if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) {
			exit(1);
		}
	} else {
		if (policydb_init(&modpolicydb)) {
			fprintf(stderr, "%s: out of memory!\n", argv[0]);
			return -1;
		}

		modpolicydb.policy_type = policy_type;
		modpolicydb.mls = mlspol;
		modpolicydb.handle_unknown = handle_unknown;

		if (read_source_policy(&modpolicydb, file, argv[0]) == -1) {
			exit(1);
		}

		if (hierarchy_check_constraints(NULL, &modpolicydb)) {
			return -1;
		}
	}

	if (modpolicydb.policy_type == POLICY_BASE) {
		/* Verify that we can successfully expand the base module. */
		policydb_t kernpolicydb;

		if (policydb_init(&kernpolicydb)) {
			fprintf(stderr, "%s:  policydb_init failed\n", argv[0]);
			exit(1);
		}
		if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) {
			fprintf(stderr, "%s:  link modules failed\n", argv[0]);
			exit(1);
		}
		if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) {
			fprintf(stderr, "%s:  expand module failed\n", argv[0]);
			exit(1);
		}
		policydb_destroy(&kernpolicydb);
	}

	if (policydb_load_isids(&modpolicydb, &sidtab))
		exit(1);

	sepol_sidtab_destroy(&sidtab);

	printf("%s:  policy configuration loaded\n", argv[0]);

	if (outfile &&
	    write_binary_policy(&modpolicydb, outfile, argv[0]) == -1) {
		exit(1);
	}
	policydb_destroy(&modpolicydb);

	return 0;
}
int main_seinject(int argc, char **argv) {
	char *policy = NULL, *source = NULL, *target = NULL, *clazz = NULL, *perm = NULL, *perm_token = NULL, *perm_saveptr = NULL, *outfile = NULL, *permissive = NULL;
	policydb_t policydb;
	struct policy_file pf, outpf;
	sidtab_t sidtab;
	int ret_add_rule;
	int load = 0;
	int quiet = 0;
	FILE *fp;
	int i;

	for (i=1; i<argc; i++) {
		if (argv[i][0] == '-') {
			if (argv[i][1] == 's') {
				i++;
				source = argv[i];
				continue;
			}
			if (argv[i][1] == 't') {
				i++;
				target = argv[i];
				continue;
			}
			if (argv[i][1] == 'c') {
				i++;
				clazz = argv[i];
				continue;
			}
			if (argv[i][1] == 'p') {
				i++;
				perm = argv[i];
				continue;
			}
			if (argv[i][1] == 'P') {
				i++;
				policy = argv[i];
				continue;
			}
			if (argv[i][1] == 'o') {
				i++;
				outfile = argv[i];
				continue;
			}
			if (argv[i][1] == 'Z') {
				i++;
				permissive = argv[i];
				continue;
			}
			if (argv[i][1] == 'l') {
				load = 1;
				continue;
			}
			if (argv[i][1] == 'q') {
				quiet = 1;
				continue;
			}
			break;
		}
	}

	if (i < argc || argc == 1 || ((!source || !target || !clazz || !perm) && !permissive)) {
		fprintf(stderr, "%s -s <source type> -t <target type> -c <class> -p <perm>[,<perm2>,<perm3>,...] [-P <policy file>] [-o <output file>] [-l|--load]\n", argv[0]);
		fprintf(stderr, "%s -Z permissive_type [-P <policy file>] [-o <output file>] [-l|--load]\n", argv[0]);
		exit(1);
	}

	if (!policy)
		policy = "/sys/fs/selinux/policy";

	sepol_set_policydb(&policydb);
	sepol_set_sidtab(&sidtab);

	if (load_policy(policy, &policydb, &pf)) {
		fprintf(stderr, "Could not load policy\n");
		return 1;
	}

	if (policydb_load_isids(&policydb, &sidtab))
		return 1;

	if (permissive) {
		type_datum_t *type;
		type = hashtab_search(policydb.p_types.table, permissive);
		if (type == NULL) {
			fprintf(stderr, "type %s does not exist\n", permissive);
			return 2;
		}
		if (ebitmap_set_bit(&policydb.permissive_map, type->s.value, 1)) {
			fprintf(stderr, "Could not set bit in permissive map\n");
			return 1;
		}
	} else {
		perm_token = strtok_r(perm, ",", &perm_saveptr);
		while (perm_token) {
			ret_add_rule = add_rule(source, target, clazz, perm_token, &policydb);
			if (ret_add_rule) {
				fprintf(stderr, "Could not add rule for perm: %s\n", perm_token);
				return ret_add_rule;
			}
			perm_token = strtok_r(NULL, ",", &perm_saveptr);
		}
	}

	if (outfile) {
		fp = fopen(outfile, "wb");
		if (!fp) {
			fprintf(stderr, "Could not open outfile\n");
			return 1;
		}

		policy_file_init(&outpf);
		outpf.type = PF_USE_STDIO;
		outpf.fp = fp;

		if (policydb_write(&policydb, &outpf)) {
			fprintf(stderr, "Could not write policy\n");
			return 1;
		}

		fclose(fp);
	}

	if (load) {
		if (load_policy_into_kernel(&policydb)) {
			fprintf(stderr, "Could not load new policy into kernel\n");
			return 1;
		}
	}

	policydb_destroy(&policydb);

	if (quiet == 0)
		fprintf(stdout, "Success\n");
	return 0;
}