%{
#include "gradm.h"
#include "gradm.tab.h"

extern unsigned long lineno;
char * gr_line;

void gradmerror(const char *s);
int gradmwrap(void);

int res_modes = 0;

unsigned char old_state = 0;
%}

IP [0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}
IPWITHMASK [0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}"/"[0-9]{1,2}

%option nounput

%x COMMENT
%x CONNECTBIND
%s RES_MOD
%%

<*>"#"		{
			if (YYSTATE != COMMENT)
				old_state = YYSTATE;
			BEGIN COMMENT;
		}
<COMMENT>[.]*	;
<COMMENT>"\n"	{
			lineno++;
			BEGIN(old_state);
		}
<*>"\n"		{
			lineno++;
		}
<*>[ \t]+		;
"include"		return INCLUDE;

<RES_MOD>[0-9]+[smhdKMG]?	{
			res_modes++;

			if(res_modes == 2)			
				BEGIN INITIAL;
			gradmlval.gr_tmpbuf = strdup(yytext);
			return RES_ACL_MOD;
			}
<RES_MOD>"unlimited"	{
			res_modes++;

			if(res_modes == 2)			
				BEGIN INITIAL;
			gradmlval.gr_tmpbuf = strdup(yytext);
			return RES_ACL_MOD;
			}

"+CAP_"[_A-Z]+	{
			gradmlval.gr_tmpbuf = strdup(yytext);
			return CAP_RAISE;
		}
"-CAP_"[_A-Z]+	{ 
			gradmlval.gr_tmpbuf = strdup(yytext);
			return CAP_DROP;
		}
"RES_"[A-Z]+	{
			gradmlval.gr_tmpbuf = strdup(yytext);
			res_modes = 0;
			BEGIN RES_MOD;
			return RES_ACL;
		}
[rwxaotdsbFWIAOPXSRMGKChlivpk]+	{ 
			gradmlval.gr_tmpbuf = strdup(yytext);
			return ACL_MODE;
		}
[/][^ \t\n]*	{ 
			gradmlval.gr_tmpbuf = strdup(yytext);
			return ACL_SUBJECT;
		}
["][/].*["]	{
			gr_line = yytext;
			gr_line++;
			*(gr_line + strlen(gr_line) - 1) = '\0';
			gradmlval.gr_tmpbuf = strdup(gr_line);
			return ACL_SUBJECT;
		}
[<].+[>]	{
			gr_line = yytext;
			gr_line++;
			*(gr_line + strlen(gr_line) - 1) = '\0';
			gradmlval.gr_tmpbuf = strdup(gr_line);
			return INCLUDE_FNAME;
		}

connect		{
			BEGIN CONNECTBIND;
			return CONNECT;
		}
bind		{
			BEGIN CONNECTBIND;
			return	BIND;
		}
<CONNECTBIND>disabled		return DISABLED;
<CONNECTBIND>{IP}	{
				gradmlval.gr_tmpbuf = strdup(yytext);
				return IP;
			}	
<CONNECTBIND>{IPWITHMASK}	{
				gradmlval.gr_tmpbuf = strdup(yytext);
				return IPWITHMASK;
			}	
<CONNECTBIND>[a-z_]+	{	gradmlval.gr_tmpbuf = strdup(yytext);
				return TYPE;
			}
<CONNECTBIND>[0-9]{1,5}	{
				gradmlval.gr_tmpbuf = strdup(yytext);
				return MASKPORT;
			}
<CONNECTBIND>[\-:]		return *yytext;
<CONNECTBIND>[{}]	{
				if(*yytext == '}') BEGIN INITIAL;
				return *yytext;
			}
[{}]			return *yytext;
.			gradmerror("invalid character");

%%

int gradmwrap(void)
{
	return 1;
}

void gradmerror(const char *s) 
{
        fflush(stderr);
        fprintf(stderr, "\"%s\" caused a %s on line %lu of %s\n", yytext, s, 
		lineno, current_acl_file);
	exit(EXIT_FAILURE);
}

void no_coredump(void)
{
	struct rlimit rlim;

	rlim.rlim_cur = 0;
	rlim.rlim_max = 0;

	setrlimit(RLIMIT_CORE, &rlim);

	return;
}


int main(int argc, char *argv[])
{
#ifdef GRADM_DEBUG
	struct file_acl *filp;
	struct proc_acl *proc;
	extern struct rlimconv rlim_table[];
	int i;
#endif
	no_coredump();

	init_variables();

	parse_args(argc, argv);

#ifdef GRADM_DEBUG
	for(proc = def_acl_tmp->proc;proc;proc=proc->prev) {
		printf("SUBJECT: %s dev:%d inode:%lu mode:%d c_raise:%x c_drop:%x\n", 
			proc->filename, proc->dev, proc->inode, proc->mode, proc->cap_raise, 
			proc->cap_drop);
		if (!proc->ip_object)
			printf("\tNo socket restrictions\n");
		for(filp = proc->proc_object;filp;filp=filp->prev)
			printf("\tOBJECT: %s dev:%d inode:%lu mode:%d\n", filp->filename, filp->dev, filp->inode, filp->mode);	
		for(i=0;i<GR_NLIMITS;i++)
			if(proc->resmask & (1 << i))
				printf("\t%s: soft: %lu hard: %lu\n", rlim_table[i].name, proc->res[i].rlim_cur, proc->res[i].rlim_max);
	}
#endif
	return 0;
}
