#include <iostream>
#include <sstream>

#include <cassert>
#include <string>
#include <vector>

using namespace std;

string subdomain;		//the filename of the confined executable

/*
----- Debugging built structures -----
Name:           /usr/sbin/named
Subname:        NULL
Type:           Default Allow
Capabilities:   setgid setuid net_bind_service sys_chroot 
--- Entries ---
Mode:   r       Name:   (/ **)
Mode:   rw      Name:   (/dev/full)
*/

/*
r    - read
w    - write
ux   - unconstrained execute
Ux   - unconstrained execute -- scrub the environment
px   - discrete profile execute
Px   - discrete profile execute -- scrub the environment
ix   - inherit execute
m    - allow PROT_EXEC with mmap(2) calls
l    - link
*/

bool can_expand(vector<string> & names, int id)
{
	int left = -1;
	string part1, part2, part3;

//	cout << "debug expanding " << names[id] << endl;

	for (size_t i = 0; i < names[id].size(); ++i) {
		if (names[id][i] == '{')
			left = i;

		if (names[id][i] == '}') {
			assert(left != -1);
			part1 = names[id].substr(0, left);
			part2 = names[id].substr(left+1, i+1);
			part3 = names[id].substr(i+1);
			names[id] = "";

			string token="";
			for (size_t j = 0; j < part2.size(); ++j) {
				if (part2[j] == ',' || part2[j] == '}') {
					string new_name = part1 + token + part3;
					if (names[id] == "")
						names[id] = new_name;
					else
						names.push_back(new_name);
					token = "";
				} else
					token += part2[j];
			}

			return true;
		}
	}

	return false;
}

void expand_names(const string & filename, vector<string> & names)
{
	bool changed;

	names.clear();
	names.push_back(filename);

	do {
		changed = false;
		for (size_t i = 0; i < names.size(); ++i)
			if (can_expand(names, i))
				changed = true;
	} while (changed);
}

string wildcard_changed(string pattern)
{

	return pattern;
}

void process_mode(istream & str_in)
{
	int br = 0;
	int bw = 0;
	int bux = 0;
	int bpx = 0;
	int bix = 0;
	int bm = 0;
	int bl = 0;
	string modes;
	string keyword;
	string filename;
	vector<string> names;
	int mid;

	assert(str_in >> modes);
	assert(str_in >> keyword);
	assert(keyword == "Name:");

	assert(str_in >> filename);
	assert(filename.size() > 2);
	filename = filename.substr(1, filename.size()-2);

	if (modes.substr(0, 6) == "unsafe")
		modes = modes.substr(6);

	mid = modes.size() / 2;
	assert(modes[mid] == ':');
	assert(modes.substr(0, mid) == modes.substr(mid+1));
	modes = modes.substr(0, mid);

	for (size_t i = 0; i < modes.size(); ++i)
		switch (modes[i]) {
			case 'r': br = 1; break;
			case 'a':
			case 'w': bw = 1; break;
			case 'u': 
			case 'U': 
				if (modes[modes.size()-1] == 'x')
					bux = 1;
				else
					assert(modes[i] == 'U');
				break;
			case 'p':
			case 'P': bpx = 1; break;
			case 'i': bix = 1; break;
			case 'm': bm = 1; break;
			case 'l': bl = 1; break;
			case 'x': assert(i == modes.size()-1); break;
			case 'k': break;
			default :
				cerr << "error: unknown modes " << modes << endl;
				assert(0);
		}

//	cout << "debug1" << endl;

	expand_names(filename, names);

	for (size_t i = 0; i < names.size(); ++i)
		cout << "aa_access_mode('" << subdomain << "', '"
			<< names[i] << "', "
			<< "r(" << br << "), "
			<< "w(" << bw << "), "
			<< "ux(" << bux << "), "
			<< "px(" << bpx << "), "
			<< "ix(" << bix << "), "
			<< "m(" << bm << "), "
			<< "l(" << bl << "))."
			<< endl;
}

void process_line(string & line)
{
	istringstream str_in(line);
	string head, body;

	if (str_in >> head) {
		if (head == "-----")
			assert(line == "----- Debugging built structures -----");
		else
		if (head == "---")
			assert(line == "--- Entries ---");
		else
		if (head == "Name:") {
			if (subdomain == "")
				assert(str_in >> subdomain);
		} else
		if (head == "Subname:") {
			assert(str_in >> body);
			assert(body == "NULL");
		} else
		if (head == "Type:") {
			assert(str_in >> body);
			assert(body == "Default");
			assert(str_in >> body);
			assert(body == "Allow");
		} else
		if (head == "Capabilities:") {
			while (str_in >> body) {
				assert(subdomain != "");
				cout << "aa_capability('" << subdomain << "', '"
					<< body << "')." << endl;
			}
		} else
		if (head == "Mode:")
			process_mode(str_in);
		else
		if (head == "link:") {
		}
		else {
			cerr << "error: unknown head " << head << endl;
			assert(0);
		}
	}
}

int main()
{
	string line;

	subdomain = "";
	while ( getline(cin, line) )
		process_line(line);

	return 0;
}

