/* * Copyright (C), 2000-2007 by the monit project group. * All Rights Reserved. * * 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 3 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, see . */ %option noyywrap %{ /* * DESCRIPTION * Lexical grammar for tokenizing the control file. * * AUTHOR * Jan-Henrik Haukeland, * Olivier Beyssac, * Christian Hopp, * Martin Pala, * * CVS INFO * $Id: l.l,v 1.119 2007/08/31 02:12:25 hauk Exp $ */ #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_GLOB_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include "monitor.h" #include "tokens.h" #define MAX_STACK_DEPTH 128 int buffer_stack_ptr=0; struct buffer_stack_s { int lineno; char *currentfile; YY_BUFFER_STATE buffer; } buffer_stack[MAX_STACK_DEPTH]; int lineno= 1; int arglineno= 1; char *currentfile=NULL; char *argcurrentfile=NULL; char *argyytext=NULL; /* Prototypes */ extern void yyerror(const char*,...); static void steplinenobycr(char *); static void save_arg(void); static void include_file(char *); static char *handle_quoted_string(char *); static void push_buffer_state(YY_BUFFER_STATE, char*); static int pop_buffer_state(void); static URL_T create_URL(char *proto); %} ws [ \r\t]+ wws [ \r\t;,()]+ number [0-9]+ real [0-9]+([.][0-9]+)? str [^\000-\041@:{}"';(),%]+ hostname {str}(\.{str})* greater ("greater"|"gt"|">") less ("less"|"lt"|"<") equal ("equal"|"eq"|"=="|"=") notequal ("notequal"|"ne"|"!=") loadavg1 load(avg)[ ]*(\([ ]*1[ ]*(m|min)?[ ]*\))? loadavg5 load(avg)[ ]*\([ ]*5[ ]*(m|min)?[ ]*\) loadavg15 load(avg)[ ]*\([ ]*15[ ]*(m|min)?[ ]*\) cpuuser cpu[ ]*(usage)*[ ]*\([ ]*(us|usr|user)?[ ]*\) cpusyst cpu[ ]*(usage)*[ ]*\([ ]*(sy|sys|system)?[ ]*\) cpuwait cpu[ ]*(usage)*[ ]*\([ ]*(wa|wait)?[ ]*\) startarg start{ws}?(program)?{ws}?([=]{ws})?["] stoparg stop{ws}?(program)?{ws}?([=]{ws})?["] execarg exec(ute)?{ws}?["] percent ("percent"|"%") byte ("byte"|"b") kilobyte ("kilobyte"|"kb") megabyte ("megabyte"|"mb") gigabyte ("gigabyte"|"gb") %x ARGUMENT_COND DEPEND_COND SERVICE_COND URL_COND STRING_COND INCLUDE %% {wws} { /* Wide white space */ } (#.*)?\\?\n { lineno++; } is {/* EMPTY */} as {/* EMPTY */} are {/* EMPTY */} for {/* EMPTY */} on(ly)? {/* EMPTY */} with(in)? {/* EMPTY */} program(s)? {/* EMPTY */} and {/* EMPTY */} has {/* EMPTY */} using {/* EMPTY */} use {/* EMPTY */} the {/* EMPTY */} sum {/* EMPTY */} than {/* EMPTY */} usage {/* EMPTY */} was {/* EMPTY */} times {/* EMPTY */} but {/* EMPTY */} of {/* EMPTY */} {startarg} { BEGIN(ARGUMENT_COND); return START; } {stoparg} { BEGIN(ARGUMENT_COND); return STOP; } {execarg} { BEGIN(ARGUMENT_COND); return EXEC; } if { return IF; } or { return OR; } then { return THEN; } failed { return FAILED; } ssl { return HTTPDSSL; } enable { return ENABLE; } disable { return DISABLE; } set { return SET; } daemon { return DAEMON; } logfile { return LOGFILE; } syslog { return SYSLOG; } facility { return FACILITY; } httpd { return HTTPD; } address { return ADDRESS; } clientpemfile { return CLIENTPEMFILE; } allowselfcertification { return ALLOWSELFCERTIFICATION; } certmd5 { return CERTMD5; } pemfile { return PEMFILE; } init { return INIT; } allow { return ALLOW; } read[-]?only { return READONLY; } pidfile { return PIDFILE; } statefile { return STATEFILE; } path { return PATHTOK; } start { return START; } stop { return STOP; } port(number)? { return PORT; } unix(socket)? { return UNIXSOCKET; } type { return TYPE; } proto(col)? { return PROTOCOL; } tcp { return TCP; } tcpssl { return TCPSSL; } udp { return UDP; } alert { return ALERT; } noalert { return NOALERT; } mail-format { return MAILFORMAT; } resource { return RESOURCE; } restart(s)? { return RESTART; } cycle(s)? { return CYCLE;} timeout { return TIMEOUT; } checksum { return CHECKSUM; } mailserver { return MAILSERVER; } every { return EVERY; } host { return HOST; } system { return SYSTEM; } default { return DEFAULT; } http { return HTTP; } apache-status { return APACHESTATUS; } ftp { return FTP; } smtp { return SMTP; } postfix-policy { return POSTFIXPOLICY; } pop { return POP; } imap { return IMAP; } clamav { return CLAMAV; } dns { return DNS; } mysql { return MYSQL; } nntp { return NNTP; } ntp3 { return NTP3; } ssh { return SSH; } dwp { return DWP; } ldap2 { return LDAP2; } ldap3 { return LDAP3; } rdate { return RDATE; } rsync { return RSYNC; } tns { return TNS; } pgsql { return PGSQL; } mode { return MODE; } active { return ACTIVE; } passive { return PASSIVE; } manual { return MANUAL; } uid { return UID; } gid { return GID; } request { return REQUEST; } loglimit { return LOGLIMIT; } closelimit { return CLOSELIMIT; } dnslimit { return DNSLIMIT; } keepalivelimit { return KEEPALIVELIMIT; } replylimit { return REPLYLIMIT; } requestlimit { return REQUESTLIMIT; } startlimit { return STARTLIMIT; } waitlimit { return WAITLIMIT; } gracefullimit { return GRACEFULLIMIT; } cleanuplimit { return CLEANUPLIMIT; } mem(ory)? { return MEMORY; } totalmem(ory)? { return TOTALMEMORY; } cpu { return CPU; } child(ren) { return CHILDREN; } timestamp { return TIMESTAMP; } changed { return CHANGED; } second(s)? { return SECOND; } minute(s)? { return MINUTE; } hour(s)? { return HOUR; } day(s)? { return DAY; } sslv2 { return SSLV2; } sslv3 { return SSLV3; } tlsv1 { return TLSV1; } sslauto { return SSLAUTO; } inode(s)? { return INODE; } space { return SPACE; } perm(ission)? { return PERMISSION; } exec(ute)? { return EXEC; } size { return SIZE; } basedir { return BASEDIR; } slot(s)? { return SLOT; } eventqueue { return EVENTQUEUE; } match { return MATCH; } not { return NOT; } ignore { return IGNORE; } connection { return CONNECTION; } unmonitor { return UNMONITOR; } icmp { return ICMP; } echo { return ICMPECHO; } send { return SEND; } expect { return EXPECT; } cleartext { return CLEARTEXT; } md5 { return MD5HASH; } sha1 { return SHA1HASH; } crypt { return CRYPT; } signature { return SIGNATURE; } nonexist { return NONEXIST; } invalid { return INVALID; } data { return DATA; } recovered { return RECOVERED; } passed { return PASSED; } else { return ELSE; } collector { return COLLECTOR; } url { return URL; } content { return CONTENT; } pid { return PID; } ppid { return PPID; } count { return COUNT; } reminder { return REMINDER; } instance { return INSTANCE; } username { return USERNAME; } password { return PASSWORD; } fsflag(s)? { return FSFLAG; } {byte} { return BYTE; } {kilobyte} { return KILOBYTE; } {megabyte} { return MEGABYTE; } {gigabyte} { return GIGABYTE; } {loadavg1} { return LOADAVG1; } {loadavg5} { return LOADAVG5; } {loadavg15} { return LOADAVG15; } {cpuuser} { return CPUUSER; } {cpusyst} { return CPUSYSTEM; } {cpuwait} { return CPUWAIT; } {greater} { return GREATER; } {less} { return LESS; } {equal} { return EQUAL; } {notequal} { return NOTEQUAL; } include { BEGIN(INCLUDE); } depend(s)?[ \t]+(on[ \t]*)? { BEGIN(DEPEND_COND); return DEPENDS; } check[ \t]+(process[ \t])? { BEGIN(SERVICE_COND); return CHECKPROC; } check[ \t]+device { BEGIN(SERVICE_COND); return CHECKDEV; } check[ \t]+file { BEGIN(SERVICE_COND); return CHECKFILE; } check[ \t]+directory { BEGIN(SERVICE_COND); return CHECKDIR; } check[ \t]+host { BEGIN(SERVICE_COND); return CHECKHOST; } check[ \t]+system { BEGIN(SERVICE_COND); return CHECKSYSTEM; } check[ \t]+fifo { BEGIN(SERVICE_COND); return CHECKFIFO; } group[ \t]+ { BEGIN(STRING_COND); return GROUP; } [a-zA-Z0-9]+"://" { yylval.url= create_URL(xstrndup(yytext, strlen(yytext)-3)); BEGIN(URL_COND); } {number} { yylval.number= atoi(yytext); save_arg(); return NUMBER; } {real} { yylval.real= atof(yytext); save_arg(); return REAL; } {percent} { return PERCENT; } [a-zA-Z0-9]{str} { yylval.string= xstrdup(yytext); save_arg(); return STRING; } \"[/][^\"\n]*\" { yylval.string= handle_quoted_string(yytext); save_arg(); return PATH; } \'[/][^\'\n]*\' { yylval.string= handle_quoted_string(yytext); save_arg(); return PATH; } \"[^\"]*\" { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); save_arg(); return STRING; } \'[^\']*\' { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); save_arg(); return STRING; } {str}[@]{str} { yylval.string= xstrdup(yytext); save_arg(); return MAILADDR; } [/]{str} { yylval.string= xstrdup(yytext); save_arg(); return PATH; } "/" { yylval.string= xstrdup(yytext); save_arg(); return PATH; } "from:"[ \t]*{str}[@]{str} { char *p= yytext+strlen("from:"); yylval.string = Util_trim(xstrdup(p)); save_arg(); return MAILFROM; } "subject:"[^}\n]* { char *p= yytext+strlen("subject:"); yylval.string = Util_trim(xstrdup(p)); save_arg(); return MAILSUBJECT; } "message:"[^}]* { char *p= yytext+strlen("message:"); steplinenobycr(yytext); yylval.string = Util_trim(xstrdup(p)); save_arg(); return MAILBODY; } {hostname} { yylval.string = xstrdup(yytext); save_arg(); return STRING; } [\"\'] { yyerror("unbalanced quotes"); } { {ws} ; [\n] { lineno++; } {str} { yylval.string= xstrdup(yytext); BEGIN(INITIAL); save_arg(); return SERVICENAME; } \"{str}\" { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); save_arg(); return SERVICENAME; } \'{str}\' { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); save_arg(); return SERVICENAME; } [\"\'] { yyerror("unbalanced quotes"); } } { {wws} ; {wws}?[\n]{wws}? { lineno++; } {str} { yylval.string= xstrdup(yytext); save_arg(); return SERVICENAME; } [ \r\n\t]+[^,] { steplinenobycr(yytext); unput(yytext[strlen(yytext)-1]); BEGIN(INITIAL); } } { {ws} ; [\n] { lineno++; } \" { BEGIN(INITIAL); } \'[^\']*\' { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); save_arg(); return STRING; } \' { yyerror("unbalanced quotes"); } [^ \t\n\"]+ { yylval.string= xstrdup(yytext); save_arg(); return STRING; } } { {ws}|[\n] { BEGIN(INITIAL); if(!yylval.url->hostname) yyerror("missing hostname in URL"); if(!yylval.url->path) yylval.url->path= xstrdup("/"); yylval.url->url= Util_getString("%s://%s:%d%s%s%s", yylval.url->protocol, /* possible credentials are hidden */ yylval.url->hostname, yylval.url->port, yylval.url->path, yylval.url->query?"?":"", yylval.url->query?yylval.url->query:""); save_arg(); return URLOBJECT; } [^:@ ]+/[:][^@: ]+[@] { yylval.url->user= xstrdup(yytext); } [:][^@ ]+[@] { yytext++; yylval.url->password= xstrndup(yytext, strlen(yytext)-1); } [^/?:#\r\n ]+ { yylval.url->hostname= xstrdup(yytext); } [:]{number} { yylval.url->port= atoi(++yytext); } [/][^?#\r\n ]* { yylval.url->path= Util_urlEncode(yytext); } [?][^#\r\n ]* { yylval.url->query= Util_urlEncode(++yytext); } [#][^\r\n ]* { /* EMPTY - reference is ignored */ } } { {str} { yylval.string= xstrdup(yytext); BEGIN(INITIAL); save_arg(); return STRINGNAME; } \"{str}\" { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); save_arg(); return STRINGNAME; } \'{str}\' { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); save_arg(); return STRINGNAME; } [\"\'] { yyerror("unbalanced quotes"); } } . { return yytext[0]; } [ \t]* /* eat the whitespace */ \"[^\"\r\n]+\" { /* got the include file name with double quotes */ char *temp=xstrdup(yytext); Util_trimQuotes(temp); include_file(temp); FREE(temp); BEGIN(INITIAL); } \'[^\'\r\n]+\' { /* got the include file name with single quotes*/ char *temp=xstrdup(yytext); Util_trimQuotes(temp); include_file(temp); FREE(temp); BEGIN(INITIAL); } [^ \t\r\n]+ { /* got the include file name without quotes*/ char *temp=xstrdup(yytext); include_file(temp); FREE(temp); BEGIN(INITIAL); } <> { if ( !pop_buffer_state() ) { yyterminate(); } else { BEGIN(INITIAL); } } %% /* * Do lineno++ for every occurrence of '\n' in a string. This is * necessary whenever a yytext has an unknown number of CRs. */ static void steplinenobycr(char *string) { char *pos= string; while(*pos) if('\n'==*pos++) { lineno++; } } static char *handle_quoted_string(char *string) { char *buf= xstrdup(string); Util_trimQuotes(buf); Util_handleEscapes(buf); return buf; } static void include_file(char *pattern) { glob_t globbuf; int i; if ( glob(pattern, GLOB_MARK, NULL, &globbuf) != 0 ) { yyerror("include files not found"); return; } for(i=0; i= MAX_STACK_DEPTH ) { yyerror("include files are nested too deeply" ); exit( 1 ); } buffer_stack[buffer_stack_ptr].lineno=lineno; buffer_stack[buffer_stack_ptr].currentfile=currentfile; buffer_stack[buffer_stack_ptr].buffer=YY_CURRENT_BUFFER; buffer_stack_ptr++; lineno=1; currentfile=xstrdup(filename); yy_switch_to_buffer(buffer); BEGIN(INITIAL); } static int pop_buffer_state(void) { if ( --buffer_stack_ptr < 0 ) { return 0; } else { fclose(yyin); lineno=buffer_stack[buffer_stack_ptr].lineno; FREE(currentfile); currentfile=buffer_stack[buffer_stack_ptr].currentfile; yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( buffer_stack[buffer_stack_ptr].buffer ); } return 1; } static void save_arg(void) { arglineno=lineno; argcurrentfile=currentfile; FREE(argyytext); argyytext=xstrdup(yytext); } static URL_T create_URL(char *proto) { URL_T url; ASSERT(proto); NEW(url); url->protocol= proto; if(IS(url->protocol, "https")) { url->port= 443; if(!have_ssl()) yyerror("HTTPS protocol not supported -- SSL support disabled" ); } else if(IS(url->protocol, "http")) { url->port= 80; } else { yyerror("URL protocol not supported -- "); } return url; }