--- l.l 6 Feb 2004 20:02:20 -0000 1.71 +++ l.l 13 Feb 2004 14:02:04 -0000 @@ -51,21 +51,32 @@ #include "monitor.h" #include "y.tab.h" -#define COMPAT_YY_MAX_DEPTH 10 +#define MAX_STACK_DEPTH 10 - int compat_yy_stack_ptr=0; - YY_BUFFER_STATE compat_yy_stack[COMPAT_YY_MAX_DEPTH]; - void compat_yypush_buffer_state(YY_BUFFER_STATE); - void compat_yypop_buffer_state(void); + 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; + char *argcurrentfile; + char *argyytext=NULL; /* Prototypes */ - void yyerror(const char*); - static char *handle_quoted_string(char *); - void steplinenobycr(char *); + 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 void pop_buffer_state(void); %} @@ -261,92 +272,91 @@ } {number} { - yylval.number= atoi(yytext); return NUMBER; + yylval.number= atoi(yytext); + save_arg(); return NUMBER; } {real} { - yylval.real= atof(yytext); return REAL; + yylval.real= atof(yytext); + save_arg(); return REAL; } {real}{percent} { if(sscanf(yytext, "%f%*s", &yylval.real) != 1) { - log("%s: Internal lexer error, parsing '%s'\n", - prog, yytext); + yyerror("internal lexer error, parsing '%s'"); exit(1); } - return PERCENT; + save_arg(); return PERCENT; } [a-zA-Z0-9]{str} { yylval.string= xstrdup(yytext); - return STRING; + save_arg(); return STRING; } \"[/][^\"\n]*\" { yylval.string= handle_quoted_string(yytext); - return PATH; + save_arg(); return PATH; } \'[/][^\'\n]*\' { yylval.string= handle_quoted_string(yytext); - return PATH; + save_arg(); return PATH; } \"[^\"]*\" { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); - return STRING; + save_arg(); return STRING; } \'[^\']*\' { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); - return STRING; + save_arg(); return STRING; } address@hidden { yylval.string= xstrdup(yytext); - return MAILADDR; + save_arg(); return MAILADDR; } [/]{str} { yylval.string= xstrdup(yytext); - return PATH; + save_arg(); return PATH; } "/" { yylval.string= xstrdup(yytext); - return PATH; + save_arg(); return PATH; } "from:"[ address@hidden { char *p= yytext+strlen("from:"); yylval.string = trim(xstrdup(p)); - return MAILFROM; + save_arg(); return MAILFROM; } "subject:"[^}\n]* { char *p= yytext+strlen("subject:"); yylval.string = trim(xstrdup(p)); - return MAILSUBJECT; + save_arg(); return MAILSUBJECT; } "message:"[^}]* { char *p= yytext+strlen("message:"); steplinenobycr(yytext); yylval.string = trim(xstrdup(p)); - return MAILBODY; + save_arg(); return MAILBODY; } {hostname} { yylval.string = xstrdup(yytext); - return STRING; + save_arg(); return STRING; } [\"\'] { - - yyerror("Unbalanced quotes"); - + yyerror("unbalanced quotes"); } { @@ -360,23 +370,23 @@ {str} { yylval.string= xstrdup(yytext); BEGIN(INITIAL); - return SERVICENAME; + save_arg(); return SERVICENAME; } \"{str}\" { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); - return SERVICENAME; + save_arg(); return SERVICENAME; } \'{str}\' { yylval.string= handle_quoted_string(yytext); BEGIN(INITIAL); - return SERVICENAME; + save_arg(); return SERVICENAME; } [\"\'] { - yyerror("Unbalanced quotes"); + yyerror("unbalanced quotes"); } } @@ -391,7 +401,7 @@ {str} { yylval.string= xstrdup(yytext); - return SERVICENAME; + save_arg(); return SERVICENAME; } [ \n\t]+[^,] { @@ -417,16 +427,16 @@ \'[^\']*\' { steplinenobycr(yytext); yylval.string= handle_quoted_string(yytext); - return STRING; + save_arg(); return STRING; } \' { - yyerror("Unbalanced quotes"); + yyerror("unbalanced quotes"); } [^ \t\n\"]+ { yylval.string= xstrdup(yytext); - return STRING; + save_arg(); return STRING; } } @@ -463,7 +473,7 @@ <> { - compat_yypop_buffer_state(); + pop_buffer_state(); if ( !YY_CURRENT_BUFFER ) { @@ -478,7 +488,7 @@ * necessary whenever a yytext has an unknown number of CRs. */ -void steplinenobycr(char *string) { +static void steplinenobycr(char *string) { char *pos= string; @@ -531,44 +541,67 @@ yyin=fopen( globbuf.gl_pathv[i], "r" ); - if ( ! yyin ) - yyerror( "error including file" ); + if ( ! yyin ) { + + yyerror( "failed to include file" ); + + } else { - compat_yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); - + push_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ), + globbuf.gl_pathv[i]); + + } } globfree(&globbuf); } -void compat_yypush_buffer_state(YY_BUFFER_STATE buffer) { +static void push_buffer_state(YY_BUFFER_STATE buffer, char *filename) { - if ( compat_yy_stack_ptr >= COMPAT_YY_MAX_DEPTH ) + if ( buffer_stack_ptr >= MAX_STACK_DEPTH ) { - yyerror( "Includes nested too deeply" ); + yyerror( "include files are nested too deeply" ); exit( 1 ); } - compat_yy_stack[compat_yy_stack_ptr++] = - YY_CURRENT_BUFFER; - + 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); } -void compat_yypop_buffer_state(void) { +static void pop_buffer_state(void) { - if ( --compat_yy_stack_ptr < 0 ) { + if ( --buffer_stack_ptr < 0 ) { yy_delete_buffer( YY_CURRENT_BUFFER ); } else { + 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( compat_yy_stack[compat_yy_stack_ptr] ); + yy_switch_to_buffer( buffer_stack[buffer_stack_ptr].buffer ); } +} + +static void save_arg(void) { + arglineno=lineno; + argcurrentfile=currentfile; + FREE(argyytext); + argyytext=xstrdup(yytext); } --- p.y 11 Feb 2004 21:43:31 -0000 1.160 +++ p.y 13 Feb 2004 14:04:20 -0000 @@ -194,13 +194,20 @@ }; /* yacc interface */ - void yyerror(const char *); + void yyerror(const char *,...); + void yyerror2(const char *,...); + void yywarning(const char *,...); + void yywarning2(const char *,...); /* lexer interface */ int yylex(void); extern FILE *yyin; extern int lineno; + extern int arglineno; extern char *yytext; + extern char *argyytext; + extern char *currentfile; + extern char *argcurrentfile; /* Local variables */ @@ -256,8 +263,6 @@ static void addgid(struct GidSet *); static void addeuid(uid_t); static void addegid(gid_t); - static uid_t get_uid(char *, uid_t); - static gid_t get_gid(char *, gid_t); static void setlogfile(char *); static void setpidfile(char *); static void reset_mailset(); @@ -347,7 +352,6 @@ | checkhost opthostlist ; - optproclist : /* EMPTY */ | optproclist optproc ; @@ -625,9 +629,7 @@ allowuserlist { FREE(htpasswd_file);} | ALLOW STRING { if(!add_host_allow($2)) { - log("%s: error: Hostname '%s' did not resolve" - " at line %d\n", prog, $2, lineno-1); - cfg_errflag++; + yyerror2("hostname did not resolve",$2); } FREE($2); } @@ -806,10 +808,10 @@ ; timeout : TIMEOUT NUMBER NUMBER { - log("%s: The timeout statement at line %d is deprecated." - "\n\tPlease use the new version:\n" - "\tif x restarts within y cycles then timeout\n", - prog, lineno); + yywarning("The TIMEOUT statement is deprecated." + "\n\tPlease use the new version:" + "\n\tIF x RESTARTS WITHIN y CYCLES THEN TIMEOUT" + "\n\t"); check_timeout($2, $3); current->def_timeout= TRUE; current->to_start= $2; @@ -902,16 +904,16 @@ resource : /* Old syntax */ CPUUSAGE operator value { - YERROR("parse error: 'CPUUSAGE' is obsolete -" - " use the 'CPU' statement instead"); + yyerror("CPUUSAGE is obsolete -" + " use the CPU statement instead"); } | MEMUSAGE operator value { - YERROR("parse error: 'MEMUSAGE' is obsolete -" - " use the 'MEMORY' statement instead"); + yyerror("MEMUSAGE is obsolete -" + " use the MEMORY statement instead"); } | MEMKBYTE operator value { - YERROR("parse error: 'MEMKBYTE' is obsolete -" - " use the 'MEMORY' statement instead"); + yyerror("MEMKBYTE is obsolete -" + " use the MEMORY statement instead"); } /* New syntax */ | MEMORY operator value unit { @@ -931,9 +933,9 @@ resourceset.limit= (int) ($3 * ($4 / 1024.0)); #ifdef LINUX - log("%s: Warning: The TOTALMEMORY statement used at line %d" - " does not work properly on Linux.\n", - prog, lineno); + yywarning("TOTALMEMORY statement " + "does not work properly on Linux\n", + prog, lineno); #endif } | TOTALMEMORY operator PERCENT { @@ -941,9 +943,9 @@ resourceset.operator= $2; resourceset.limit= (int) ($3 * 10); #ifdef LINUX - log("%s: Warning: The TOTALMEMORY statement used at line %d" - " does not work properly on Linux.\n", - prog, lineno); + yywarning("TOTALMEMORY statement" + "does not work properly on Linux.\n", + prog, lineno); #endif } | CPU operator PERCENT { @@ -1043,9 +1045,8 @@ space : IF SPACE operator value unit THEN action { if(!DeviceInfo_Usage(current->devinfo, current->path)) { - log("%s: Cannot read usage of device %s at line %d\n", - prog, current->path, lineno); - cfg_errflag++; + yyerror2("cannot read usage of device %s", + current->path); } deviceset.resource= RESOURCE_ID_SPACE; deviceset.operator= $3; @@ -1096,6 +1097,7 @@ uidset.uid= get_uid($4, 0); uidset.action= $6; adduid(&uidset); + FREE($4); } | IF FAILED UID NUMBER THEN action { uidset.uid= get_uid(NULL, $4); @@ -1108,6 +1110,7 @@ gidset.gid= get_gid($4, 0); gidset.action= $6; addgid(&gidset); + FREE($4); } | IF FAILED GID NUMBER THEN action { gidset.gid= get_gid(NULL, $4); @@ -1128,13 +1131,78 @@ /** * Syntactic error routine */ -void yyerror(const char *msg) { +void yyerror(const char *s, ...) { + + long len; + va_list ap; + char *msg= NULL; + + ASSERT(s); + + va_start(ap,s); + msg= format(s, ap, &len); + va_end(ap); + + log("%s:%i: Error: %s '%s'\n", currentfile, lineno, msg, yytext); + cfg_errflag++; + + FREE(msg); + +} + +void yywarning(const char *s, ...) { + + long len; + va_list ap; + char *msg= NULL; + + ASSERT(s); + + va_start(ap,s); + msg= format(s, ap, &len); + va_end(ap); + + log("%s:%i: Warning: %s '%s'\n", currentfile, lineno, msg, yytext); + + FREE(msg); + +} - ASSERT(msg); +void yyerror2(const char *s, ...) { + + long len; + va_list ap; + char *msg= NULL; - log("%s: %s '%s' at line %d\n", prog, msg, yytext, lineno); + ASSERT(s); + + va_start(ap,s); + msg= format(s, ap, &len); + va_end(ap); + + log("%s:%i: Error: %s '%s'\n", argcurrentfile, arglineno, msg, argyytext); cfg_errflag++; + + FREE(msg); + +} + +void yywarning2(const char *s, ...) { + + long len; + va_list ap; + char *msg= NULL; + ASSERT(s); + + va_start(ap,s); + msg= format(s, ap, &len); + va_end(ap); + + log("%s:%i: Warning: %s '%s'\n", argcurrentfile, arglineno, msg, argyytext); + + FREE(msg); + } @@ -1156,12 +1224,14 @@ if ((yyin = fopen(controlfile,"r")) == (FILE *)NULL) { - log("%s: error opening the control file '%s' -- %s\n", + log("%s: Error: cannot open the control file '%s' -- %s\n", prog, controlfile, STRERROR); return(FALSE); } + currentfile=xstrdup(controlfile); + /* Creation of the global service list is synchronized */ LOCK(Run.mutex) @@ -1175,6 +1245,11 @@ END_LOCK; + FREE(currentfile); + + if (argyytext!=NULL) + FREE(argyytext); + postparse(); return(cfg_errflag == 0); @@ -1236,7 +1311,7 @@ /* Check that we do not start monit in daemon mode without having a * poll time */ if(!Run.polltime && (Run.isdaemon || Run.init)) { - log("%s: configure error, poll time not defined. Please define poll time" + log("%s: Error: Poll time not defined. Please define poll time" " in the\n control file or use the -d option when starting monit\n", prog); cfg_errflag++; @@ -1247,8 +1322,8 @@ if(s->type != TYPE_REMOTE) continue; if(!s->portlist && !s->icmplist) { - log("%s: 'check host' statement error; Please specify a port number" - " to test\n or an icmp test at the remote host: '%s'\n", + log("%s: Error: 'check host' statement is incomplete; Please specify a" + " port number to test\n or an icmp test at the remote host: '%s'\n", prog, s->name); cfg_errflag++; } @@ -1410,10 +1485,7 @@ if(pp->ssl == TRUE) { if(!have_ssl()) { - log("%s: error: The ssl check cannot be activated at line %d, " - "SSL is not support.\n", - prog,lineno); - cfg_errflag++; + yyerror("ssl check cannot be activated. SSL is not supported"); } else { if (pp->certmd5 != NULL) { p->SSL.certmd5= pp->certmd5; @@ -1449,11 +1521,10 @@ NEW(r); if(! Run.doprocess) { - log("%s: error: Cannot activate service check at line %d\n" - "\t(The process status engine was disabled. On certain" - " systems you must\n\trun monit as root to utilize this" - " feature)\n", prog, lineno); - cfg_errflag++; + yyerror("cannot activate service check.\n" + "\t(The process status engine was disabled. On certain" + " systems you must\n\trun monit as root to utilize this" + " feature)\n\t"); } @@ -1467,9 +1538,7 @@ if(r->max_cycle < 1) { - log("%s: error: The number of cycles must be greater then 0 in line %d\n", - prog, lineno); - cfg_errflag++; + yyerror2("the number of cycles must be greater then 0"); } @@ -1501,13 +1570,10 @@ if(t->test_changes) { if(!exist_file(current->path)) { - log("%s: error: The path '%s' used in the TIMESTAMP statement at line %d " - "does not exist\n", prog, current->path, lineno); - cfg_errflag++; + yyerror2("the path '%s' used in the TIMESTAMP statement" + " does not exist", current->path); } else if(!(t->timestamp= get_timestamp(current->path, S_IFDIR|S_IFREG))) { - log("%s: error: Cannot get the timestamp for '%s' at line %d -- %s\n", - prog, current->path, lineno, STRERROR); - cfg_errflag++; + yyerror2("cannot get the timestamp for '%s'", current->path); } } @@ -1535,9 +1601,9 @@ ASSERT(ss); if(ss->test_changes && stat(current->path, &buf) != 0) { - log("%s: error: Cannot get size for '%s' at line %d -- %s\n", - prog, current->path, lineno, STRERROR); - cfg_errflag++; + yyerror2("cannot get size for '%s'", current->path); + reset_sizeset(); + return; } NEW(s); @@ -1571,9 +1637,8 @@ if(!cs->md5) { if( !(cs->md5= get_md5sum(current->path)) ) { - log("%s: error: Cannot compute a checksum for a file %s at line %d\n", - prog, current->path, lineno); - cfg_errflag++; + yyerror2("cannot compute a checksum for a file %s", current->path); + reset_checksumset(); return; } } @@ -1726,9 +1791,7 @@ } else { - log("%s: error: icmp statement at line %d, you must run as root.\n", - prog, lineno); - cfg_errflag++; + yyerror("icmp statements must be run as root\n"); } @@ -1831,9 +1894,7 @@ char errbuf[STRLEN]; regerror(reg_return, g->expect, errbuf, STRLEN); - log("%s: regex error: %s '%s' at line %d\n", - prog, errbuf, expect, lineno); - cfg_errflag++; + yyerror2("regex parsing error:%s", errbuf); } @@ -1885,9 +1946,7 @@ if(command->length >= ARGMAX) { - log("%s: error: Exceeded maximum number of program arguments at line %d\n", - prog, lineno); - cfg_errflag++; + yyerror("exceeded maximum number of program arguments"); } @@ -1930,16 +1989,20 @@ if(user) { pwd= getpwnam(user); - FREE(user); - if(pwd == NULL) - yyerror("Requested user not found on the system."); + if(pwd == NULL) { + yyerror2("requested user not found on the system"); + + return(0); + } } else { - if( (pwd= getpwuid(uid)) == NULL ) - yyerror("Requested uid not found on the system."); + if( (pwd= getpwuid(uid)) == NULL ) { + yyerror2("requested uid not found on the system"); + return(0); + } } return(pwd->pw_uid); @@ -1959,15 +2022,20 @@ if(group) { grd= getgrnam(group); - FREE(group); - if(grd == NULL) - yyerror("Requested group not found on the system."); + if(grd == NULL) { + yyerror2("requested group not found on the system"); + + return(0); + } } else { - if( (grd= getgrgid(gid)) == NULL ) - yyerror("Requested gid not found on the system."); + if( (grd= getgrgid(gid)) == NULL ) { + yyerror2("requested gid not found on the system"); + + return(0); + } } @@ -1988,9 +2056,7 @@ } else { - log("%s: error: uid statement at line %d, you must run as root.\n", - prog, lineno); - cfg_errflag++; + yyerror("uid statement requires root privileges"); } @@ -2009,9 +2075,7 @@ } else { - log("%s: error: gid statement at line %d, you must run as root.\n", - prog, lineno); - cfg_errflag++; + yyerror("gid statement requires root privileges"); } @@ -2083,8 +2147,12 @@ if ( handle==NULL ) { - log("%s: error: Cannot read htpasswd %s at line %d -- %s\n", - prog, filename, lineno, STRERROR); + if (username!=NULL) { + yyerror2("cannot read htpasswd (%s)", filename); + } else { + yyerror2("cannot read htpasswd", filename); + } + return; } @@ -2158,15 +2226,13 @@ if ( username == NULL ) { - log("%s: warning: htpasswd file %s in line %i has no usable" - " credentials.\n", - prog, filename, lineno); + yywarning2("htpasswd file (%s) has no usable credentials", + filename); } else { - log("%s: warning htpasswd file %s in line %i has no usable" - " credentials for user %s.\n", - prog, filename, lineno, username); + yywarning2("htpasswd file (%s) has no usable credentials " + "for user %s", filename, username); } @@ -2197,8 +2263,8 @@ if (get_user_credentials(uname) != NULL) { - log("%s: warning: credentials for user %s was already added," - "entry at line %i ignored.\n", prog, uname, lineno); + yywarning2("credentials for user %s were already added, entry ignored", + uname); FREE(uname); FREE(passwd); return FALSE; @@ -2224,7 +2290,7 @@ c->digesttype=dtype; c->is_readonly= readonly; - DEBUG("%s: Adding credenitials for user '%s'.\n", prog, uname); + DEBUG("%s: Debug: Adding credenitials for user '%s'.\n", prog, uname); return TRUE; @@ -2265,9 +2331,7 @@ } else if(IS(facility, "log_daemon")) { Run.facility = LOG_DAEMON; } else { - log("%s: error: Invalid syslog facility '%s' used at line %d\n", - prog, facility, lineno); - cfg_errflag++; + yyerror2("invalid syslog facility"); } } else { Run.facility= LOG_USER; @@ -2447,9 +2511,7 @@ if(exist_service(name) || (current && IS(name, current->name))) { - log("%s: error: Name conflict at line %d - check name '%s'" - " already defined\n", prog, lineno, name); - cfg_errflag++; + yyerror2("service name conflict, %s already defined", name); } @@ -2471,9 +2533,9 @@ if( *status != '\0' || result < 0 || result > 07777 ) { - yyerror("An permission statement must have an octal value between 0 " - "and 07777."); - + yyerror2("permission statements must have an octal value " + "between 0 and 07777"); + } return result; @@ -2488,13 +2550,13 @@ if(s > c) { - yyerror("The number of restarts must be less than poll cycles"); + yyerror2("the number of restarts must be less than poll cycles"); } if(s <= 0 || c <= 0) { - yyerror("Zero or negative values not allowed in a timeout statement"); + yyerror2("zero or negative values not allowed in a timeout statement"); } @@ -2508,7 +2570,7 @@ if(every <= 1) { - yyerror("An every statement must have a value greater than 1."); + yyerror2("an EVERY statement must have a value greater than 1"); } @@ -2524,8 +2586,8 @@ if(!check_host(hostname)) { - yyerror("Hostname did not resolve"); - + yyerror2("hostname did not resolve"); + } } @@ -2576,9 +2638,7 @@ static void check_exec(char *exec) { if(! exist_file(exec)) { - log("%s: error: The executable '%s' at line %d does not exist\n", - prog, exec, lineno); - cfg_errflag++; + yyerror2("the executable does not exist"); } } @@ -2635,13 +2695,13 @@ Service_T dp= get_service(d->dependant); if(!dp) { - log("%s: parse error, depend service '%s' is not defined in the " + log("%s: Error: Depend service '%s' is not defined in the " "control file\n", prog, d->dependant); exit(1); } if(dp->depend_visited) { - log("%s: parse error, found a depend loop in the control file " + log("%s: Error: Found a depend loop in the control file " "involving the service '%s'\n", prog, s->name); exit(1); }