| /* | 
 |  * Copyright (C) Tildeslash Ltd. All rights reserved. | 
 |  * | 
 |  * This program is free software: you can redistribute it and/or modify | 
 |  * it under the terms of the GNU Affero General Public License version 3. | 
 |  * | 
 |  * 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 Affero General Public License | 
 |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
 |  * | 
 |  * In addition, as a special exception, the copyright holders give | 
 |  * permission to link the code of portions of this program with the | 
 |  * OpenSSL library under certain conditions as described in each | 
 |  * individual source file, and distribute linked combinations | 
 |  * including the two. | 
 |  * | 
 |  * You must obey the GNU Affero General Public License in all respects | 
 |  * for all of the code used other than OpenSSL.   | 
 |  */ | 
 |  | 
 |  | 
 | %option noyywrap | 
 |  | 
 |  | 
 | %{ | 
 |    | 
 | /* | 
 |  * DESCRIPTION | 
 |  * | 
 |  *   Lexical grammar for tokenizing the control file.  | 
 |  * | 
 |  */ | 
 |  | 
 | #include "config.h" | 
 |    | 
 | #ifdef HAVE_STRING_H | 
 | #include <string.h> | 
 | #endif | 
 |  | 
 | #ifdef HAVE_GLOB_H | 
 | #include <glob.h> | 
 | #endif | 
 |  | 
 | #ifdef HAVE_STRINGS_H | 
 | #include <strings.h> | 
 | #endif | 
 |  | 
 | #include "monit.h" | 
 | #include "tokens.h" | 
 |          | 
 | // libmonit | 
 | #include "util/Str.h" | 
 |  | 
 |  | 
 | #define MAX_STACK_DEPTH 512 | 
 |  | 
 |   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*,...); | 
 |   extern void yywarning(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})?["] | 
 | restartarg  restart{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 EVERY_COND INCLUDE | 
 |  | 
 | %% | 
 |  | 
 | {wws}             { /* Wide white space */ } | 
 | (#.*)?\\?\n       { lineno++; }  | 
 |  | 
 | is                {/* EMPTY */} | 
 | as                {/* EMPTY */} | 
 | are               {/* EMPTY */} | 
 | for               {/* EMPTY */} | 
 | on(ly)?           {/* EMPTY */} | 
 | with(in|out)?     {/* 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 */} | 
 | does              {/* EMPTY */} | 
 |  | 
 | {startarg}        { BEGIN(ARGUMENT_COND); return START; } | 
 | {stoparg}         { BEGIN(ARGUMENT_COND); return STOP; } | 
 | {restartarg}      { BEGIN(ARGUMENT_COND); return RESTART; } | 
 | {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; } | 
 | delay             { return DELAY; } | 
 | 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; } | 
 | idfile            { return IDFILE; } | 
 | 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; } | 
 | retry             { return RETRY; } | 
 | checksum          { return CHECKSUM; } | 
 | mailserver        { return MAILSERVER; } | 
 | host              { return HOST; } | 
 | hostheader        { return HOSTHEADER; } | 
 | status            { return STATUS; } | 
 | 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; } | 
 | lmtp              { return LMTP; } | 
 | rsync             { return RSYNC; } | 
 | tns               { return TNS; } | 
 | pgsql             { return PGSQL; } | 
 | sip               { return SIP; }  | 
 | gps               { return GPS; }  | 
 | radius            { return RADIUS; } | 
 | memcache          { return MEMCACHE; } | 
 | target            { return TARGET; } | 
 | maxforward        { return MAXFORWARD; } | 
 | mode              { return MODE; } | 
 | active            { return ACTIVE; } | 
 | passive           { return PASSIVE; } | 
 | manual            { return MANUAL; } | 
 | uid               { return UID; } | 
 | gid               { return GID; } | 
 | request           { return REQUEST; } | 
 | secret            { return SECRET; } | 
 | 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; } | 
 | swap              { return SWAP; } | 
 | totalmem(ory)?    { return TOTALMEMORY; } | 
 | cpu               { return CPU; } | 
 | totalcpu          { return TOTALCPU; } | 
 | 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; } | 
 | uptime            { return UPTIME; } | 
 | basedir           { return BASEDIR; } | 
 | slot(s)?          { return SLOT; } | 
 | eventqueue        { return EVENTQUEUE; } | 
 | match(ing)?       { return MATCH; } | 
 | not               { return NOT; } | 
 | ignore            { return IGNORE; } | 
 | connection        { return CONNECTION; } | 
 | unmonitor         { return UNMONITOR; } | 
 | action            { return ACTION; } | 
 | icmp              { return ICMP; } | 
 | echo              { return ICMPECHO; } | 
 | send              { return SEND; } | 
 | expect            { return EXPECT; } | 
 | expectbuffer      { return EXPECTBUFFER; } | 
 | cleartext         { return CLEARTEXT; } | 
 | md5               { return MD5HASH; } | 
 | sha1              { return SHA1HASH; } | 
 | crypt             { return CRYPT; } | 
 | signature         { return SIGNATURE; } | 
 | nonexist          { return NONEXIST; } | 
 | exist             { return EXIST; } | 
 | invalid           { return INVALID; } | 
 | data              { return DATA; } | 
 | recovered         { return RECOVERED; } | 
 | passed            { return PASSED; } | 
 | succeeded         { return SUCCEEDED; } | 
 | else              { return ELSE; } | 
 | mmonit            { return MMONIT; } | 
 | url               { return URL; } | 
 | content           { return CONTENT; } | 
 | pid               { return PID; } | 
 | ppid              { return PPID; } | 
 | count             { return COUNT; } | 
 | reminder          { return REMINDER; } | 
 | instance          { return INSTANCE; } | 
 | hostname          { return HOSTNAME; } | 
 | username          { return USERNAME; } | 
 | password          { return PASSWORD; } | 
 | credentials       { return CREDENTIALS; } | 
 | register          { return REGISTER; } | 
 | fsflag(s)?        { return FSFLAG; } | 
 | fips              { return FIPS; } | 
 | {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); } | 
 |  | 
 | not[ ]+every      {  | 
 |                     BEGIN(EVERY_COND); | 
 |                     return NOTEVERY; | 
 |                   } | 
 |  | 
 | every             {  | 
 |                     BEGIN(EVERY_COND); | 
 |                     return EVERY; | 
 |                   } | 
 |  | 
 | depend(s)?[ \t]+(on[ \t]*)? { | 
 |                     BEGIN(DEPEND_COND); | 
 |                     return DEPENDS; | 
 |                   }  | 
 |  | 
 | check[ \t]+(process[ \t])? { | 
 |                     BEGIN(SERVICE_COND); | 
 |                     return CHECKPROC; | 
 |                   } | 
 |  | 
 | check[ \t]+(program[ \t])? { | 
 |                     BEGIN(SERVICE_COND); | 
 |                     return CHECKPROGRAM; | 
 |                   } | 
 |  | 
 | check[ \t]+device { /* Filesystem alias for backward compatibility  */ | 
 |                     BEGIN(SERVICE_COND); | 
 |                     return CHECKFILESYS; | 
 |                   } | 
 |  | 
 | check[ \t]+filesystem { | 
 |                     BEGIN(SERVICE_COND); | 
 |                     return CHECKFILESYS; | 
 |                   } | 
 |  | 
 | 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; | 
 |                   } | 
 |  | 
 | check[ \t]+program   { | 
 |                     BEGIN(SERVICE_COND); | 
 |                         return CHECKPROGRAM; | 
 |                   } | 
 |  | 
 | group[ \t]+       { | 
 |                     BEGIN(STRING_COND); | 
 |                     return GROUP; | 
 |                   } | 
 |  | 
 | [a-zA-Z0-9]+"://" { | 
 | 		    yylval.url=  | 
 | 		      create_URL(Str_ndup(yytext, strlen(yytext)-3)); | 
 |                     BEGIN(URL_COND); | 
 |                   } | 
 | [0-9]{2}":"[0-9]{2}":"[0-9]{2} { | 
 |                     yylval.string= Str_dup(yytext); | 
 |                     save_arg(); return TIMESPEC; | 
 |                   } | 
 |  | 
 | {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= Str_dup(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= Str_dup(yytext); | 
 |                     save_arg(); return MAILADDR; | 
 |                   } | 
 |  | 
 | [/]{str}          { | 
 |                      yylval.string= Str_dup(yytext); | 
 |                      save_arg(); return PATH; | 
 |                   } | 
 |  | 
 | "/"               { | 
 |                      yylval.string= Str_dup(yytext); | 
 |                      save_arg(); return PATH; | 
 |                   } | 
 |  | 
 | "from:"[ \t]*{str}[@]{str} { | 
 |                       char *p= yytext+strlen("from:"); | 
 |                       yylval.string = Str_trim(Str_dup(p)); | 
 |                       save_arg(); return MAILFROM; | 
 |                   } | 
 |  | 
 | "reply-to:"[ \t]*{str}[@]{str} { | 
 |                       char *p= yytext+strlen("reply-to:"); | 
 |                       yylval.string = Str_trim(Str_dup(p)); | 
 |                       save_arg(); return MAILREPLYTO; | 
 |                   } | 
 |  | 
 | "subject:"[^}\n]* { | 
 |                       char *p= yytext+strlen("subject:"); | 
 |                       yylval.string = Str_trim(Str_dup(p)); | 
 |                       save_arg(); return MAILSUBJECT; | 
 |                   } | 
 |  | 
 | "message:"[^}]*   { | 
 |                       char *p= yytext+strlen("message:"); | 
 |                       steplinenobycr(yytext); | 
 |                       yylval.string = Str_trim(Str_dup(p)); | 
 |                       save_arg(); return MAILBODY; | 
 |                   } | 
 |  | 
 | {hostname}        { | 
 |                       yylval.string = Str_dup(yytext); | 
 |                       save_arg(); return STRING; | 
 |                   } | 
 |  | 
 | [\"\']            { | 
 |                       yyerror("unbalanced quotes"); | 
 |                   } | 
 |  | 
 | <SERVICE_COND>{ | 
 |  | 
 |   {ws}            ; | 
 |  | 
 |   [\n]            { | 
 |                     lineno++; | 
 |                   } | 
 |  | 
 |   {str}           { | 
 |                     yylval.string= Str_dup(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"); | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 | <DEPEND_COND>{ | 
 |  | 
 |   {wws}           ; | 
 |  | 
 |   {wws}?[\n]{wws}? { | 
 |                     lineno++; | 
 |                   } | 
 |  | 
 |   {str}           { | 
 |                     yylval.string= Str_dup(yytext); | 
 |                     save_arg(); return SERVICENAME; | 
 |                   } | 
 |  | 
 |   [ \r\n\t]+[^,]  { | 
 |                     steplinenobycr(yytext); | 
 |                     unput(yytext[strlen(yytext)-1]); | 
 |                     BEGIN(INITIAL); | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 | <ARGUMENT_COND>{ | 
 |  | 
 |   {ws}            ; | 
 |  | 
 |   [\n]            { | 
 |                     lineno++; | 
 |                   } | 
 |  | 
 |   \"              { | 
 |                       BEGIN(INITIAL); | 
 |                   } | 
 |  | 
 |   \'[^\']*\'      { | 
 |                       steplinenobycr(yytext); | 
 |                       yylval.string= handle_quoted_string(yytext); | 
 |                       save_arg(); return STRING; | 
 |                   } | 
 |  | 
 |   \'              { | 
 |                       yyerror("unbalanced quotes"); | 
 |                   } | 
 |  | 
 |   [^ \t\n\"]+     { | 
 |                       yylval.string= Str_dup(yytext); | 
 |                       save_arg(); return STRING; | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 | <URL_COND>{ | 
 |  | 
 |   {ws}|[\n]       { | 
 |                       BEGIN(INITIAL); | 
 | 		      if(!yylval.url->hostname) | 
 | 			yyerror("missing hostname in URL"); | 
 | 		      if(!yylval.url->path) | 
 | 			yylval.url->path= Str_dup("/"); | 
 |                       yylval.url->url= Str_cat("%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= Str_dup(yytext); | 
 |                   } | 
 |  | 
 |   [:][^@ ]+[@]    { | 
 | 	              yytext++; | 
 | 	              yylval.url->password= Str_ndup(yytext, strlen(yytext)-1); | 
 |                   } | 
 |  | 
 |   [^/?:#\r\n ]+   { | 
 | 	              yylval.url->hostname= Str_dup(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 */  | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 | <STRING_COND>{ | 
 |  | 
 |   {str}           { | 
 |                     yylval.string= Str_dup(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"); | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 | <EVERY_COND>{ | 
 |          | 
 |   {ws}            ; | 
 |  | 
 |   {number}        { | 
 |                     yylval.number= atoi(yytext); | 
 |                     BEGIN(INITIAL); | 
 |                     save_arg(); return NUMBER; | 
 |                   } | 
 |          | 
 |   ['"]{ws}?[0-9,*-]+{ws}[0-9,*-]+{ws}[0-9,*-]+{ws}[0-9,*-]+{ws}[0-9,*-]+{ws}?['"] { // A minimal syntax check of the cron format string; 5 fields separated with white-space | 
 |                     yylval.string= Str_dup(Str_unquote(yytext)); | 
 |                     BEGIN(INITIAL); | 
 |                     save_arg(); return TIMESPEC; | 
 |                   } | 
 |  | 
 |   .               { | 
 |                       BEGIN(INITIAL); | 
 |                       yyerror("invalid every format"); | 
 |                   } | 
 |  | 
 | } | 
 |  | 
 |  | 
 | <INITIAL,ARGUMENT_COND,SERVICE_COND,DEPEND_COND,URL_COND,STRING_COND,EVERY_COND>. { | 
 |                       return yytext[0]; | 
 |                   }   | 
 |  | 
 |  | 
 | <INCLUDE>[ \t]*      /* eat the whitespace */ | 
 |  | 
 | <INCLUDE>\"[^\"\r\n]+\" { /* got the include file name with double quotes */ | 
 |                      char *temp=Str_dup(yytext); | 
 |                      Str_unquote(temp);     | 
 |                      include_file(temp); | 
 |                      FREE(temp); | 
 |                      BEGIN(INITIAL); | 
 |                    } | 
 |  | 
 | <INCLUDE>\'[^\'\r\n]+\' { /* got the include file name with single quotes*/ | 
 |                      char *temp=Str_dup(yytext); | 
 |                      Str_unquote(temp);     | 
 |                      include_file(temp); | 
 |                      FREE(temp); | 
 |                      BEGIN(INITIAL); | 
 |                    } | 
 |  | 
 | <INCLUDE>[^ \t\r\n]+ { /* got the include file name without quotes*/ | 
 |                      char *temp=Str_dup(yytext); | 
 |                      include_file(temp); | 
 |                      FREE(temp); | 
 |                      BEGIN(INITIAL); | 
 |                    } | 
 |  | 
 |  | 
 | <<EOF>>           { | 
 |                         | 
 |                        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= Str_dup(string); | 
 |   Str_unquote(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) | 
 |     return; // no include files found | 
 |  | 
 |   for (i = 0; i < globbuf.gl_pathc; i++) { | 
 |     FILE *yyin; | 
 |     size_t filename_length = strlen(globbuf.gl_pathv[i]); | 
 |  | 
 |     /* check whenever we have caught a directory or file backup copy */ | 
 |     if ((filename_length == 0) || (globbuf.gl_pathv[i][filename_length-1] == '~' ) || (globbuf.gl_pathv[i][filename_length-1] == '/' )) | 
 |       continue; | 
 |  | 
 |     yyin = fopen( globbuf.gl_pathv[i], "r" ); | 
 |      | 
 |     if (! yyin) | 
 |       yyerror( "failed to include file" ); | 
 |     else | 
 |       push_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ), globbuf.gl_pathv[i]); | 
 |   } | 
 |   globfree(&globbuf); | 
 | } | 
 |  | 
 |  | 
 | static void push_buffer_state(YY_BUFFER_STATE buffer, char *filename) { | 
 |  | 
 |   if ( buffer_stack_ptr >= 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 = Str_dup(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=Str_dup(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; | 
 | } |