"Fossies" - the Fresh Open Source Software Archive

Member "monit-5.28.0/src/p.y" (28 Mar 2021, 195380 Bytes) of package /linux/privat/monit-5.28.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bison source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "p.y": 5.27.2_vs_5.28.0.

    1 /*
    2  * Copyright (C) Tildeslash Ltd. All rights reserved.
    3  *
    4  * This program is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU Affero General Public License version 3.
    6  *
    7  * This program is distributed in the hope that it will be useful,
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10  * GNU General Public License for more details.
   11  *
   12  * You should have received a copy of the GNU Affero General Public License
   13  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   14  *
   15  * In addition, as a special exception, the copyright holders give
   16  * permission to link the code of portions of this program with the
   17  * OpenSSL library under certain conditions as described in each
   18  * individual source file, and distribute linked combinations
   19  * including the two.
   20  *
   21  * You must obey the GNU Affero General Public License in all respects
   22  * for all of the code used other than OpenSSL.
   23  */
   24 
   25 
   26 %{
   27 
   28 /*
   29  * DESCRIPTION
   30  *   Simple context-free grammar for parsing the control file.
   31  *
   32  */
   33 
   34 #include "config.h"
   35 
   36 #ifdef HAVE_STDIO_H
   37 #include <stdio.h>
   38 #endif
   39 
   40 #ifdef HAVE_STDLIB_H
   41 #include <stdlib.h>
   42 #endif
   43 
   44 #ifdef HAVE_ERRNO_H
   45 #include <errno.h>
   46 #endif
   47 
   48 #ifdef HAVE_CTYPE_H
   49 #include <ctype.h>
   50 #endif
   51 
   52 #ifdef HAVE_PWD_H
   53 #include <pwd.h>
   54 #endif
   55 
   56 #ifdef HAVE_GRP_H
   57 #include <grp.h>
   58 #endif
   59 
   60 #ifdef HAVE_SYS_TYPES_H
   61 #include <sys/types.h>
   62 #endif
   63 
   64 #ifdef HAVE_SYS_TIME_H
   65 #include <sys/time.h>
   66 #endif
   67 
   68 #ifdef HAVE_TIME_H
   69 #include <time.h>
   70 #endif
   71 
   72 #ifdef HAVE_SYS_SOCKET_H
   73 #include <sys/socket.h>
   74 #endif
   75 
   76 #ifdef HAVE_ASM_PARAM_H
   77 #include <asm/param.h>
   78 #endif
   79 
   80 #ifdef HAVE_STRING_H
   81 #include <string.h>
   82 #endif
   83 
   84 #ifdef HAVE_STRINGS_H
   85 #include <strings.h>
   86 #endif
   87 
   88 #ifdef HAVE_NETDB_H
   89 #include <netdb.h>
   90 #endif
   91 
   92 #ifdef HAVE_SYSLOG_H
   93 #include <syslog.h>
   94 #endif
   95 
   96 #ifdef HAVE_NETINET_IN_SYSTM_H
   97 #include <netinet/in_systm.h>
   98 #endif
   99 
  100 #ifdef HAVE_NETINET_IN_H
  101 #include <netinet/in.h>
  102 #endif
  103 
  104 #ifdef HAVE_NETINET_IP_H
  105 #include <netinet/ip.h>
  106 #endif
  107 
  108 #ifdef HAVE_NETINET_IP_ICMP_H
  109 #include <netinet/ip_icmp.h>
  110 #endif
  111 
  112 #ifdef HAVE_REGEX_H
  113 #include <regex.h>
  114 #endif
  115 
  116 #ifdef HAVE_UNISTD_H
  117 #include <unistd.h>
  118 #endif
  119 
  120 #ifdef HAVE_OPENSSL
  121 #include <openssl/ssl.h>
  122 #endif
  123 
  124 #include "monit.h"
  125 #include "protocol.h"
  126 #include "engine.h"
  127 #include "alert.h"
  128 #include "ProcessTree.h"
  129 #include "device.h"
  130 #include "processor.h"
  131 #include "md5.h"
  132 #include "sha1.h"
  133 #include "checksum.h"
  134 #include "process_sysdep.h"
  135 
  136 // libmonit
  137 #include "io/File.h"
  138 #include "util/Str.h"
  139 #include "thread/Thread.h"
  140 
  141 
  142 /* ------------------------------------------------------------- Definitions */
  143 
  144 
  145 struct precedence_t {
  146         bool daemon;
  147         bool logfile;
  148         bool pidfile;
  149 };
  150 
  151 struct rate_t {
  152         unsigned int count;
  153         unsigned int cycles;
  154 };
  155 
  156 /* yacc interface */
  157 void  yyerror(const char *,...) __attribute__((format (printf, 1, 2)));
  158 void  yyerror2(const char *,...) __attribute__((format (printf, 1, 2)));
  159 void  yywarning(const char *,...) __attribute__((format (printf, 1, 2)));
  160 void  yywarning2(const char *,...) __attribute__((format (printf, 1, 2)));
  161 
  162 /* lexer interface */
  163 int yylex(void);
  164 extern FILE *yyin;
  165 extern int lineno;
  166 extern int arglineno;
  167 extern char *yytext;
  168 extern char *argyytext;
  169 extern char *currentfile;
  170 extern char *argcurrentfile;
  171 extern int buffer_stack_ptr;
  172 
  173 /* Local variables */
  174 static int cfg_errflag = 0;
  175 static Service_T tail = NULL;
  176 static Service_T current = NULL;
  177 static Request_T urlrequest = NULL;
  178 static command_t command = NULL;
  179 static command_t command1 = NULL;
  180 static command_t command2 = NULL;
  181 static Service_T depend_list = NULL;
  182 static struct Uid_T uidset = {};
  183 static struct Gid_T gidset = {};
  184 static struct Pid_T pidset = {};
  185 static struct Pid_T ppidset = {};
  186 static struct FsFlag_T fsflagset = {};
  187 static struct NonExist_T nonexistset = {};
  188 static struct Exist_T existset = {};
  189 static struct Status_T statusset = {};
  190 static struct Perm_T permset = {};
  191 static struct Size_T sizeset = {};
  192 static struct Uptime_T uptimeset = {};
  193 static struct ResponseTime_T responsetimeset = {};
  194 static struct LinkStatus_T linkstatusset = {};
  195 static struct LinkSpeed_T linkspeedset = {};
  196 static struct LinkSaturation_T linksaturationset = {};
  197 static struct Bandwidth_T bandwidthset = {};
  198 static struct Match_T matchset = {};
  199 static struct Icmp_T icmpset = {};
  200 static struct Mail_T mailset = {};
  201 static struct SslOptions_T sslset = {};
  202 static struct Port_T portset = {};
  203 static struct MailServer_T mailserverset = {};
  204 static struct Mmonit_T mmonitset = {};
  205 static struct FileSystem_T filesystemset = {};
  206 static struct Resource_T resourceset = {};
  207 static struct Checksum_T checksumset = {};
  208 static struct Timestamp_T timestampset = {};
  209 static struct ActionRate_T actionrateset = {};
  210 static struct precedence_t ihp = {false, false, false};
  211 static struct rate_t rate = {1, 1};
  212 static struct rate_t rate1 = {1, 1};
  213 static struct rate_t rate2 = {1, 1};
  214 static char * htpasswd_file = NULL;
  215 static unsigned int repeat = 0;
  216 static unsigned int repeat1 = 0;
  217 static unsigned int repeat2 = 0;
  218 static Digest_Type digesttype = Digest_Cleartext;
  219 
  220 #define BITMAP_MAX (sizeof(long long) * 8)
  221 
  222 
  223 /* -------------------------------------------------------------- Prototypes */
  224 
  225 static void  preparse(void);
  226 static void  postparse(void);
  227 static bool _parseOutgoingAddress(const char *ip, Outgoing_T *outgoing);
  228 static void  addmail(char *, Mail_T, Mail_T *);
  229 static Service_T createservice(Service_Type, char *, char *, State_Type (*)(Service_T));
  230 static void  addservice(Service_T);
  231 static void  adddependant(char *);
  232 static void  addservicegroup(char *);
  233 static void  addport(Port_T *, Port_T);
  234 static void  addhttpheader(Port_T, const char *);
  235 static void  addresource(Resource_T);
  236 static void  addtimestamp(Timestamp_T);
  237 static void  addactionrate(ActionRate_T);
  238 static void  addsize(Size_T);
  239 static void  adduptime(Uptime_T);
  240 static void  addpid(Pid_T);
  241 static void  addppid(Pid_T);
  242 static void  addfsflag(FsFlag_T);
  243 static void  addnonexist(NonExist_T);
  244 static void  addexist(Exist_T);
  245 static void  addlinkstatus(Service_T, LinkStatus_T);
  246 static void  addlinkspeed(Service_T, LinkSpeed_T);
  247 static void  addlinksaturation(Service_T, LinkSaturation_T);
  248 static void  addbandwidth(Bandwidth_T *, Bandwidth_T);
  249 static void  addfilesystem(FileSystem_T);
  250 static void  addicmp(Icmp_T);
  251 static void  addgeneric(Port_T, char*, char*);
  252 static void  addcommand(int, unsigned);
  253 static void  addargument(char *);
  254 static void  addmmonit(Mmonit_T);
  255 static void  addmailserver(MailServer_T);
  256 static bool addcredentials(char *, char *, Digest_Type, bool);
  257 #ifdef HAVE_LIBPAM
  258 static void  addpamauth(char *, int);
  259 #endif
  260 static void  addhtpasswdentry(char *, char *, Digest_Type);
  261 static uid_t get_uid(char *, uid_t);
  262 static gid_t get_gid(char *, gid_t);
  263 static void  addchecksum(Checksum_T);
  264 static void  addperm(Perm_T);
  265 static void  addmatch(Match_T, int, int);
  266 static void  addmatchpath(Match_T, Action_Type);
  267 static void  addstatus(Status_T);
  268 static Uid_T adduid(Uid_T);
  269 static Gid_T addgid(Gid_T);
  270 static void  addeuid(uid_t);
  271 static void  addegid(gid_t);
  272 static void  addeventaction(EventAction_T *, Action_Type, Action_Type);
  273 static void  prepare_urlrequest(URL_T U);
  274 static void  seturlrequest(int, char *);
  275 static void  setlogfile(char *);
  276 static void  setpidfile(char *);
  277 static void  reset_sslset(void);
  278 static void  reset_mailset(void);
  279 static void  reset_mailserverset(void);
  280 static void  reset_mmonitset(void);
  281 static void  reset_portset(void);
  282 static void  reset_resourceset(void);
  283 static void  reset_timestampset(void);
  284 static void  reset_actionrateset(void);
  285 static void  reset_sizeset(void);
  286 static void  reset_uptimeset(void);
  287 static void  reset_responsetimeset(void);
  288 static void  reset_pidset(void);
  289 static void  reset_ppidset(void);
  290 static void  reset_fsflagset(void);
  291 static void  reset_nonexistset(void);
  292 static void  reset_existset(void);
  293 static void  reset_linkstatusset(void);
  294 static void  reset_linkspeedset(void);
  295 static void  reset_linksaturationset(void);
  296 static void  reset_bandwidthset(void);
  297 static void  reset_checksumset(void);
  298 static void  reset_permset(void);
  299 static void  reset_uidset(void);
  300 static void  reset_gidset(void);
  301 static void  reset_statusset(void);
  302 static void  reset_filesystemset(void);
  303 static void  reset_icmpset(void);
  304 static void  reset_rateset(struct rate_t *);
  305 static void  check_name(char *);
  306 static int   check_perm(int);
  307 static void  check_exec(char *);
  308 static int   cleanup_hash_string(char *);
  309 static void  check_depend(void);
  310 static void  setsyslog(char *);
  311 static command_t copycommand(command_t);
  312 static int verifyMaxForward(int);
  313 static void _setPEM(char **store, char *path, const char *description, bool isFile);
  314 static void _setSSLOptions(SslOptions_T options);
  315 #ifdef HAVE_OPENSSL
  316 static void _setSSLVersion(short version);
  317 #endif
  318 static void _unsetSSLVersion(short version);
  319 static void addsecurityattribute(char *, Action_Type, Action_Type);
  320 static void addfiledescriptors(Operator_Type, bool, long long, float, Action_Type, Action_Type);
  321 
  322 %}
  323 
  324 %union {
  325         URL_T url;
  326         Address_T address;
  327         float real;
  328         int   number;
  329         char *string;
  330 }
  331 
  332 %token IF ELSE THEN FAILED
  333 %token SET LOGFILE FACILITY DAEMON SYSLOG MAILSERVER HTTPD ALLOW REJECTOPT ADDRESS INIT TERMINAL BATCH
  334 %token READONLY CLEARTEXT MD5HASH SHA1HASH CRYPT DELAY
  335 %token PEMFILE PEMKEY PEMCHAIN ENABLE DISABLE SSLTOKEN CIPHER CLIENTPEMFILE ALLOWSELFCERTIFICATION SELFSIGNED VERIFY CERTIFICATE CACERTIFICATEFILE CACERTIFICATEPATH VALID
  336 %token INTERFACE LINK PACKET BYTEIN BYTEOUT PACKETIN PACKETOUT SPEED SATURATION UPLOAD DOWNLOAD TOTAL UP DOWN
  337 %token IDFILE STATEFILE SEND EXPECT CYCLE COUNT REMINDER REPEAT
  338 %token LIMITS SENDEXPECTBUFFER EXPECTBUFFER FILECONTENTBUFFER HTTPCONTENTBUFFER PROGRAMOUTPUT NETWORKTIMEOUT PROGRAMTIMEOUT STARTTIMEOUT STOPTIMEOUT RESTARTTIMEOUT
  339 %token PIDFILE START STOP PATHTOK RSAKEY
  340 %token HOST HOSTNAME PORT IPV4 IPV6 TYPE UDP TCP TCPSSL PROTOCOL CONNECTION
  341 %token ALERT NOALERT MAILFORMAT UNIXSOCKET SIGNATURE
  342 %token TIMEOUT RETRY RESTART CHECKSUM EVERY NOTEVERY
  343 %token DEFAULT HTTP HTTPS APACHESTATUS FTP SMTP SMTPS POP POPS IMAP IMAPS CLAMAV NNTP NTP3 MYSQL MYSQLS DNS WEBSOCKET MQTT
  344 %token SSH DWP LDAP2 LDAP3 RDATE RSYNC TNS PGSQL POSTFIXPOLICY SIP LMTP GPS RADIUS MEMCACHE REDIS MONGODB SIEVE SPAMASSASSIN FAIL2BAN
  345 %token <string> STRING PATH MAILADDR MAILFROM MAILREPLYTO MAILSUBJECT
  346 %token <string> MAILBODY SERVICENAME STRINGNAME
  347 %token <number> NUMBER PERCENT LOGLIMIT CLOSELIMIT DNSLIMIT KEEPALIVELIMIT
  348 %token <number> REPLYLIMIT REQUESTLIMIT STARTLIMIT WAITLIMIT GRACEFULLIMIT
  349 %token <number> CLEANUPLIMIT
  350 %token <real> REAL
  351 %token CHECKPROC CHECKFILESYS CHECKFILE CHECKDIR CHECKHOST CHECKSYSTEM CHECKFIFO CHECKPROGRAM CHECKNET
  352 %token THREADS CHILDREN METHOD GET HEAD STATUS ORIGIN VERSIONOPT READ WRITE OPERATION SERVICETIME DISK
  353 %token RESOURCE MEMORY TOTALMEMORY LOADAVG1 LOADAVG5 LOADAVG15 SWAP
  354 %token MODE ACTIVE PASSIVE MANUAL ONREBOOT NOSTART LASTSTATE
  355 %token CORE CPU TOTALCPU CPUUSER CPUSYSTEM CPUWAIT CPUNICE CPUHARDIRQ CPUSOFTIRQ CPUSTEAL CPUGUEST CPUGUESTNICE
  356 %token GROUP REQUEST DEPENDS BASEDIR SLOT EVENTQUEUE SECRET HOSTHEADER
  357 %token UID EUID GID MMONIT INSTANCE USERNAME PASSWORD
  358 %token TIME ATIME CTIME MTIME CHANGED MILLISECOND SECOND MINUTE HOUR DAY MONTH 
  359 %token SSLV2 SSLV3 TLSV1 TLSV11 TLSV12 TLSV13 CERTMD5 AUTO
  360 %token NOSSLV2 NOSSLV3 NOTLSV1 NOTLSV11 NOTLSV12 NOTLSV13
  361 %token BYTE KILOBYTE MEGABYTE GIGABYTE
  362 %token INODE SPACE TFREE PERMISSION SIZE MATCH NOT IGNORE ACTION UPTIME RESPONSETIME
  363 %token EXEC UNMONITOR PING PING4 PING6 ICMP ICMPECHO NONEXIST EXIST INVALID DATA RECOVERED PASSED SUCCEEDED
  364 %token URL CONTENT PID PPID FSFLAG
  365 %token REGISTER CREDENTIALS
  366 %token <url> URLOBJECT
  367 %token <address> ADDRESSOBJECT
  368 %token <string> TARGET TIMESPEC HTTPHEADER
  369 %token <number> MAXFORWARD
  370 %token FIPS
  371 %token SECURITY ATTRIBUTE
  372 %token FILEDESCRIPTORS
  373 
  374 %left GREATER GREATEROREQUAL LESS LESSOREQUAL EQUAL NOTEQUAL
  375 
  376 
  377 %%
  378 cfgfile         : /* EMPTY */
  379                 | statement_list
  380                 ;
  381 
  382 statement_list  : statement
  383                 | statement_list statement
  384                 ;
  385 
  386 statement       : setalert
  387                 | setssl
  388                 | setdaemon
  389                 | setterminal
  390                 | setlog
  391                 | seteventqueue
  392                 | setmmonits
  393                 | setmailservers
  394                 | setmailformat
  395                 | sethttpd
  396                 | setpid
  397                 | setidfile
  398                 | setstatefile
  399                 | setexpectbuffer
  400                 | setinit
  401                 | setlimits
  402                 | setonreboot
  403                 | setfips
  404                 | checkproc optproclist
  405                 | checkfile optfilelist
  406                 | checkfilesys optfilesyslist
  407                 | checkdir optdirlist
  408                 | checkhost opthostlist
  409                 | checksystem optsystemlist
  410                 | checkfifo optfifolist
  411                 | checkprogram optprogramlist
  412                 | checknet optnetlist
  413                 ;
  414 
  415 optproclist     : /* EMPTY */
  416                 | optproclist optproc
  417                 ;
  418 
  419 optproc         : start
  420                 | stop
  421                 | restart
  422                 | exist
  423                 | pid
  424                 | ppid
  425                 | uid
  426                 | euid
  427                 | secattr
  428                 | filedescriptorsprocess
  429                 | filedescriptorsprocesstotal
  430                 | gid
  431                 | uptime
  432                 | connection
  433                 | connectionurl
  434                 | connectionunix
  435                 | actionrate
  436                 | alert
  437                 | every
  438                 | mode
  439                 | onreboot
  440                 | group
  441                 | depend
  442                 | resourceprocess
  443                 ;
  444 
  445 optfilelist      : /* EMPTY */
  446                 | optfilelist optfile
  447                 ;
  448 
  449 optfile         : start
  450                 | stop
  451                 | restart
  452                 | exist
  453                 | timestamp
  454                 | actionrate
  455                 | every
  456                 | alert
  457                 | permission
  458                 | uid
  459                 | gid
  460                 | checksum
  461                 | size
  462                 | match
  463                 | mode
  464                 | onreboot
  465                 | group
  466                 | depend
  467                 ;
  468 
  469 optfilesyslist  : /* EMPTY */
  470                 | optfilesyslist optfilesys
  471                 ;
  472 
  473 optfilesys      : start
  474                 | stop
  475                 | restart
  476                 | exist
  477                 | actionrate
  478                 | every
  479                 | alert
  480                 | permission
  481                 | uid
  482                 | gid
  483                 | mode
  484                 | onreboot
  485                 | group
  486                 | depend
  487                 | inode
  488                 | space
  489                 | read
  490                 | write
  491                 | servicetime
  492                 | fsflag
  493                 ;
  494 
  495 optdirlist      : /* EMPTY */
  496                 | optdirlist optdir
  497                 ;
  498 
  499 optdir          : start
  500                 | stop
  501                 | restart
  502                 | exist
  503                 | timestamp
  504                 | actionrate
  505                 | every
  506                 | alert
  507                 | permission
  508                 | uid
  509                 | gid
  510                 | mode
  511                 | onreboot
  512                 | group
  513                 | depend
  514                 ;
  515 
  516 opthostlist     : /* EMPTY */
  517                 | opthostlist opthost
  518                 ;
  519 
  520 opthost         : start
  521                 | stop
  522                 | restart
  523                 | connection
  524                 | connectionurl
  525                 | icmp
  526                 | actionrate
  527                 | alert
  528                 | every
  529                 | mode
  530                 | onreboot
  531                 | group
  532                 | depend
  533                 ;
  534 
  535 optnetlist      : /* EMPTY */
  536                 | optnetlist optnet
  537                 ;
  538 
  539 optnet          : start
  540                 | stop
  541                 | restart
  542                 | linkstatus
  543                 | linkspeed
  544                 | linksaturation
  545                 | upload
  546                 | download
  547                 | actionrate
  548                 | every
  549                 | mode
  550                 | onreboot
  551                 | alert
  552                 | group
  553                 | depend
  554                 ;
  555 
  556 optsystemlist   : /* EMPTY */
  557                 | optsystemlist optsystem
  558                 ;
  559 
  560 optsystem       : start
  561                 | stop
  562                 | restart
  563                 | actionrate
  564                 | alert
  565                 | every
  566                 | mode
  567                 | onreboot
  568                 | group
  569                 | depend
  570                 | resourcesystem
  571                 | uptime
  572                 | filedescriptorssystem
  573                 ;
  574 
  575 optfifolist     : /* EMPTY */
  576                 | optfifolist optfifo
  577                 ;
  578 
  579 optfifo         : start
  580                 | stop
  581                 | restart
  582                 | exist
  583                 | timestamp
  584                 | actionrate
  585                 | every
  586                 | alert
  587                 | permission
  588                 | uid
  589                 | gid
  590                 | mode
  591                 | onreboot
  592                 | group
  593                 | depend
  594                 ;
  595 
  596 optprogramlist  : /* EMPTY */
  597                 | optprogramlist optprogram
  598                 ;
  599 
  600 optprogram      : start
  601                 | stop
  602                 | restart
  603                 | actionrate
  604                 | alert
  605                 | every
  606                 | mode
  607                 | onreboot
  608                 | group
  609                 | depend
  610                 | statusvalue
  611                 ;
  612 
  613 setalert        : SET alertmail formatlist reminder {
  614                         mailset.events = Event_All;
  615                         addmail($<string>2, &mailset, &Run.maillist);
  616                   }
  617                 | SET alertmail '{' eventoptionlist '}' formatlist reminder {
  618                         addmail($<string>2, &mailset, &Run.maillist);
  619                   }
  620                 | SET alertmail NOT '{' eventoptionlist '}' formatlist reminder {
  621                         mailset.events = ~mailset.events;
  622                         addmail($<string>2, &mailset, &Run.maillist);
  623                   }
  624                 ;
  625 
  626 setdaemon       : SET DAEMON NUMBER startdelay {
  627                         if (! (Run.flags & Run_Daemon) || ihp.daemon) {
  628                                 ihp.daemon     = true;
  629                                 Run.flags      |= Run_Daemon;
  630                                 Run.polltime   = $3;
  631                                 Run.startdelay = $<number>4;
  632                         }
  633                   }
  634                 ;
  635 
  636 setterminal     : SET TERMINAL BATCH {
  637                         Run.flags |= Run_Batch;
  638                   }
  639                 ;
  640 
  641 startdelay      : /* EMPTY */ {
  642                         $<number>$ = 0;
  643                   }
  644                 | START DELAY NUMBER {
  645                         $<number>$ = $3;
  646                   }
  647                 ;
  648 
  649 setinit         : SET INIT {
  650                         Run.flags |= Run_Foreground;
  651                   }
  652                 ;
  653 
  654 setonreboot     : SET ONREBOOT START {
  655                         Run.onreboot = Onreboot_Start;
  656                   }
  657                 | SET ONREBOOT NOSTART {
  658                         Run.onreboot = Onreboot_Nostart;
  659                   }
  660                 | SET ONREBOOT LASTSTATE {
  661                         Run.onreboot = Onreboot_Laststate;
  662                   }
  663                 ;
  664 
  665 setexpectbuffer : SET EXPECTBUFFER NUMBER unit {
  666                         // Note: deprecated (replaced by "set limits" statement's "sendExpectBuffer" option)
  667                         Run.limits.sendExpectBuffer = $3 * $<number>4;
  668                   }
  669                 ;
  670 
  671 setlimits       : SET LIMITS '{' limitlist '}'
  672                 ;
  673 
  674 limitlist       : /* EMPTY */
  675                 | limitlist limit
  676                 ;
  677 
  678 limit           : SENDEXPECTBUFFER ':' NUMBER unit {
  679                         Run.limits.sendExpectBuffer = $3 * $<number>4;
  680                   }
  681                 | FILECONTENTBUFFER ':' NUMBER unit {
  682                         Run.limits.fileContentBuffer = $3 * $<number>4;
  683                   }
  684                 | HTTPCONTENTBUFFER ':' NUMBER unit {
  685                         Run.limits.httpContentBuffer = $3 * $<number>4;
  686                   }
  687                 | PROGRAMOUTPUT ':' NUMBER unit {
  688                         Run.limits.programOutput = $3 * $<number>4;
  689                   }
  690                 | NETWORKTIMEOUT ':' NUMBER MILLISECOND {
  691                         Run.limits.networkTimeout = $3;
  692                   }
  693                 | NETWORKTIMEOUT ':' NUMBER SECOND {
  694                         Run.limits.networkTimeout = $3 * 1000;
  695                   }
  696                 | PROGRAMTIMEOUT ':' NUMBER MILLISECOND {
  697                         Run.limits.programTimeout = $3;
  698                   }
  699                 | PROGRAMTIMEOUT ':' NUMBER SECOND {
  700                         Run.limits.programTimeout = $3 * 1000;
  701                   }
  702                 | STOPTIMEOUT ':' NUMBER MILLISECOND {
  703                         Run.limits.stopTimeout = $3;
  704                   }
  705                 | STOPTIMEOUT ':' NUMBER SECOND {
  706                         Run.limits.stopTimeout = $3 * 1000;
  707                   }
  708                 | STARTTIMEOUT ':' NUMBER MILLISECOND {
  709                         Run.limits.startTimeout = $3;
  710                   }
  711                 | STARTTIMEOUT ':' NUMBER SECOND {
  712                         Run.limits.startTimeout = $3 * 1000;
  713                   }
  714                 | RESTARTTIMEOUT ':' NUMBER MILLISECOND {
  715                         Run.limits.restartTimeout = $3;
  716                   }
  717                 | RESTARTTIMEOUT ':' NUMBER SECOND {
  718                         Run.limits.restartTimeout = $3 * 1000;
  719                   }
  720                 ;
  721 
  722 setfips         : SET FIPS {
  723                         Run.flags |= Run_FipsEnabled;
  724                   }
  725                 ;
  726 
  727 setlog          : SET LOGFILE PATH   {
  728                         if (! Run.files.log || ihp.logfile) {
  729                                 ihp.logfile = true;
  730                                 setlogfile($3);
  731                                 Run.flags &= ~Run_UseSyslog;
  732                                 Run.flags |= Run_Log;
  733                         }
  734                   }
  735                 | SET LOGFILE SYSLOG {
  736                         setsyslog(NULL);
  737                   }
  738                 | SET LOGFILE SYSLOG FACILITY STRING {
  739                         setsyslog($5); FREE($5);
  740                   }
  741                 ;
  742 
  743 seteventqueue   : SET EVENTQUEUE BASEDIR PATH {
  744                         Run.eventlist_dir = $4;
  745                   }
  746                 | SET EVENTQUEUE BASEDIR PATH SLOT NUMBER {
  747                         Run.eventlist_dir = $4;
  748                         Run.eventlist_slots = $6;
  749                   }
  750                 | SET EVENTQUEUE SLOT NUMBER {
  751                         Run.eventlist_dir = Str_dup(MYEVENTLISTBASE);
  752                         Run.eventlist_slots = $4;
  753                   }
  754                 ;
  755 
  756 setidfile       : SET IDFILE PATH {
  757                         Run.files.id = $3;
  758                   }
  759                 ;
  760 
  761 setstatefile    : SET STATEFILE PATH {
  762                         Run.files.state = $3;
  763                   }
  764                 ;
  765 
  766 setpid          : SET PIDFILE PATH {
  767                         if (! Run.files.pid || ihp.pidfile) {
  768                                 ihp.pidfile = true;
  769                                 setpidfile($3);
  770                         }
  771                   }
  772                 ;
  773 
  774 setmmonits      : SET MMONIT mmonitlist
  775                 ;
  776 
  777 mmonitlist      : mmonit credentials
  778                 | mmonitlist mmonit credentials
  779                 ;
  780 
  781 mmonit          : URLOBJECT mmonitoptlist {
  782                         mmonitset.url = $<url>1;
  783                         addmmonit(&mmonitset);
  784                   }
  785                 ;
  786 
  787 mmonitoptlist : /* EMPTY */
  788                 | mmonitoptlist mmonitopt
  789                 ;
  790 
  791 mmonitopt       : TIMEOUT NUMBER SECOND {
  792                         mmonitset.timeout = $<number>2 * 1000; // net timeout is in milliseconds internally
  793                   }
  794                 | ssl
  795                 | sslchecksum
  796                 | sslversion
  797                 | certmd5
  798                 ;
  799 
  800 credentials     : /* EMPTY */
  801                 | REGISTER CREDENTIALS {
  802                         Run.flags &= ~Run_MmonitCredentials;
  803                   }
  804                 ;
  805 
  806 setssl          : SET SSLTOKEN '{' ssloptionlist '}' {
  807                         _setSSLOptions(&(Run.ssl));
  808                   }
  809                 ;
  810 
  811 ssl             : SSLTOKEN {
  812                         sslset.flags = SSL_Enabled;
  813                   }
  814                 | SSLTOKEN '{' ssloptionlist '}'
  815                 ;
  816 
  817 ssloptionlist   : /* EMPTY */
  818                 | ssloptionlist ssloption
  819                 ;
  820 
  821 ssloption       : VERIFY ':' ENABLE {
  822                         sslset.flags = SSL_Enabled;
  823                         sslset.verify = true;
  824                   }
  825                 | VERIFY ':' DISABLE {
  826                         sslset.flags = SSL_Enabled;
  827                         sslset.verify = false;
  828                   }
  829                 | SELFSIGNED ':' ALLOW {
  830                         sslset.flags = SSL_Enabled;
  831                         sslset.allowSelfSigned = true;
  832                   }
  833                 | SELFSIGNED ':' REJECTOPT {
  834                         sslset.flags = SSL_Enabled;
  835                         sslset.allowSelfSigned = false;
  836                   }
  837                 | VERSIONOPT ':' sslversionlist {
  838                         sslset.flags = SSL_Enabled;
  839                   }
  840                 | CIPHER ':' STRING {
  841                         FREE(sslset.ciphers);
  842                         sslset.ciphers = $<string>3;
  843                   }
  844                 | PEMFILE ':' PATH {
  845                         _setPEM(&(sslset.pemfile), $3, "SSL server PEM file", true);
  846                   }
  847                 | PEMCHAIN ':' PATH {
  848                         _setPEM(&(sslset.pemchain), $3, "SSL certificate chain PEM file", true);
  849                   }
  850                 | PEMKEY ':' PATH {
  851                         _setPEM(&(sslset.pemkey), $3, "SSL server private key PEM file", true);
  852                   }
  853                 | CLIENTPEMFILE ':' PATH {
  854                         _setPEM(&(sslset.clientpemfile), $3, "SSL client PEM file", true);
  855                   }
  856                 | CACERTIFICATEFILE ':' PATH {
  857                         _setPEM(&(sslset.CACertificateFile), $3, "SSL CA certificates file", true);
  858                   }
  859                 | CACERTIFICATEPATH ':' PATH {
  860                         _setPEM(&(sslset.CACertificatePath), $3, "SSL CA certificates directory", false);
  861                   }
  862                 ;
  863 
  864 sslexpire       : CERTIFICATE VALID expireoperator NUMBER DAY {
  865                         sslset.flags = SSL_Enabled;
  866                         portset.target.net.ssl.certificate.minimumDays = $<number>4;
  867                   }
  868                 ;
  869 
  870 expireoperator  : /* EMPTY */
  871                 | GREATER
  872                 ;
  873 
  874 sslchecksum     : CERTIFICATE CHECKSUM checksumoperator STRING {
  875                         sslset.flags = SSL_Enabled;
  876                         sslset.checksum = $<string>4;
  877                         switch (cleanup_hash_string(sslset.checksum)) {
  878                                 case 32:
  879                                         sslset.checksumType = Hash_Md5;
  880                                         break;
  881                                 case 40:
  882                                         sslset.checksumType = Hash_Sha1;
  883                                         break;
  884                                 default:
  885                                         yyerror2("Unknown checksum type: [%s] is not MD5 nor SHA1", sslset.checksum);
  886                         }
  887                   }
  888                 | CERTIFICATE CHECKSUM MD5HASH checksumoperator STRING {
  889                         sslset.flags = SSL_Enabled;
  890                         sslset.checksum = $<string>5;
  891                         if (cleanup_hash_string(sslset.checksum) != 32)
  892                                 yyerror2("Unknown checksum type: [%s] is not MD5", sslset.checksum);
  893                         sslset.checksumType = Hash_Md5;
  894                   }
  895                 | CERTIFICATE CHECKSUM SHA1HASH checksumoperator STRING {
  896                         sslset.flags = SSL_Enabled;
  897                         sslset.checksum = $<string>5;
  898                         if (cleanup_hash_string(sslset.checksum) != 40)
  899                                 yyerror2("Unknown checksum type: [%s] is not SHA1", sslset.checksum);
  900                         sslset.checksumType = Hash_Sha1;
  901                   }
  902                 ;
  903 
  904 checksumoperator : /* EMPTY */
  905                  | EQUAL
  906                  ;
  907 
  908 sslversionlist  : /* EMPTY */
  909                 | sslversionlist sslversion
  910                 ;
  911 
  912 sslversion      : SSLV2 {
  913 #if defined OPENSSL_NO_SSL2 || ! defined HAVE_SSLV2 || ! defined HAVE_OPENSSL
  914                         yyerror("Your SSL Library does not support SSL version 2");
  915 #else
  916                         _setSSLVersion(SSL_V2);
  917 #endif
  918                   }
  919                 | NOSSLV2 {
  920                         _unsetSSLVersion(SSL_V2);
  921                   }
  922                 | SSLV3 {
  923 #if defined OPENSSL_NO_SSL3 || ! defined HAVE_OPENSSL
  924                         yyerror("Your SSL Library does not support SSL version 3");
  925 #else
  926                         _setSSLVersion(SSL_V3);
  927 #endif
  928                   }
  929                 | NOSSLV3 {
  930                         _unsetSSLVersion(SSL_V3);
  931                   }
  932                 | TLSV1 {
  933 #if defined OPENSSL_NO_TLS1_METHOD || ! defined HAVE_OPENSSL
  934                         yyerror("Your SSL Library does not support TLS version 1.0");
  935 #else
  936                         _setSSLVersion(SSL_TLSV1);
  937 #endif
  938                   }
  939                 | NOTLSV1 {
  940                         _unsetSSLVersion(SSL_TLSV1);
  941                   }
  942                 | TLSV11 {
  943 #if defined OPENSSL_NO_TLS1_1_METHOD || ! defined HAVE_TLSV1_1 || ! defined HAVE_OPENSSL
  944                         yyerror("Your SSL Library does not support TLS version 1.1");
  945 #else
  946                         _setSSLVersion(SSL_TLSV11);
  947 #endif
  948                 }
  949                 | NOTLSV11 {
  950                         _unsetSSLVersion(SSL_TLSV11);
  951                   }
  952                 | TLSV12 {
  953 #if defined OPENSSL_NO_TLS1_2_METHOD || ! defined HAVE_TLSV1_2 || ! defined HAVE_OPENSSL
  954                         yyerror("Your SSL Library does not support TLS version 1.2");
  955 #else
  956                         _setSSLVersion(SSL_TLSV12);
  957 #endif
  958                 }
  959                 | NOTLSV12 {
  960                         _unsetSSLVersion(SSL_TLSV12);
  961                   }
  962                 | TLSV13 {
  963 #if defined OPENSSL_NO_TLS1_3_METHOD || ! defined HAVE_TLSV1_3 || ! defined HAVE_OPENSSL
  964                         yyerror("Your SSL Library does not support TLS version 1.3");
  965 #else
  966                         _setSSLVersion(SSL_TLSV13);
  967 #endif
  968                 }
  969                 | NOTLSV13 {
  970                         _unsetSSLVersion(SSL_TLSV13);
  971                   }
  972                 | AUTO {
  973                         // Enable just TLS 1.2 and 1.3 by default
  974 #if ! defined OPENSSL_NO_TLS1_2_METHOD && defined HAVE_TLSV1_2 && defined HAVE_OPENSSL
  975                         _setSSLVersion(SSL_TLSV12);
  976 #endif
  977 #if ! defined OPENSSL_NO_TLS1_3_METHOD && defined HAVE_TLSV1_3 && defined HAVE_OPENSSL
  978                         _setSSLVersion(SSL_TLSV13);
  979 #endif
  980                   }
  981                 ;
  982 
  983 certmd5         : CERTMD5 STRING { // Backward compatibility
  984                         sslset.flags = SSL_Enabled;
  985                         sslset.checksum = $<string>2;
  986                         if (cleanup_hash_string(sslset.checksum) != 32)
  987                                 yyerror2("Unknown checksum type: [%s] is not MD5", sslset.checksum);
  988                         sslset.checksumType = Hash_Md5;
  989                   }
  990                 ;
  991 
  992 setmailservers  : SET MAILSERVER mailserverlist nettimeout hostname {
  993                         if (($<number>4) > SMTP_TIMEOUT)
  994                                 Run.mailserver_timeout = $<number>4;
  995                         Run.mail_hostname = $<string>5;
  996                   }
  997                 ;
  998 
  999 setmailformat   : SET MAILFORMAT '{' formatoptionlist '}' {
 1000                         if (mailset.from) {
 1001                                 Run.MailFormat.from = mailset.from;
 1002                         } else {
 1003                                 Run.MailFormat.from = Address_new();
 1004                                 Run.MailFormat.from->address = Str_dup(ALERT_FROM);
 1005                         }
 1006                         if (mailset.replyto)
 1007                                 Run.MailFormat.replyto = mailset.replyto;
 1008                         Run.MailFormat.subject = mailset.subject ?  mailset.subject : Str_dup(ALERT_SUBJECT);
 1009                         Run.MailFormat.message = mailset.message ?  mailset.message : Str_dup(ALERT_MESSAGE);
 1010                         reset_mailset();
 1011                   }
 1012                 ;
 1013 
 1014 mailserverlist  : mailserver
 1015                 | mailserverlist mailserver
 1016                 ;
 1017 
 1018 mailserver      : STRING mailserveroptlist {
 1019                         /* Restore the current text overridden by lookahead */
 1020                         FREE(argyytext);
 1021                         argyytext = Str_dup($1);
 1022 
 1023                         mailserverset.host = $1;
 1024                         mailserverset.port = PORT_SMTP;
 1025                         addmailserver(&mailserverset);
 1026                   }
 1027                 | STRING PORT NUMBER mailserveroptlist {
 1028                         /* Restore the current text overridden by lookahead */
 1029                         FREE(argyytext);
 1030                         argyytext = Str_dup($1);
 1031 
 1032                         mailserverset.host = $1;
 1033                         mailserverset.port = $<number>3;
 1034                         addmailserver(&mailserverset);
 1035                   }
 1036                 ;
 1037 
 1038 mailserveroptlist : /* EMPTY */
 1039                   | mailserveroptlist mailserveropt
 1040                   ;
 1041 
 1042 mailserveropt   : username {
 1043                         mailserverset.username = $<string>1;
 1044                   }
 1045                 | password {
 1046                         mailserverset.password = $<string>1;
 1047                   }
 1048                 | ssl
 1049                 | sslchecksum
 1050                 | sslversion
 1051                 | certmd5
 1052                 ;
 1053 
 1054 sethttpd        : SET HTTPD httpdlist {
 1055                         if (sslset.flags & SSL_Enabled) {
 1056 #ifdef HAVE_OPENSSL
 1057                                 if (sslset.pemfile) {
 1058                                         if (sslset.pemchain || sslset.pemkey) {
 1059                                                 yyerror("SSL server option pemfile and pemchain|pemkey are mutually exclusive");
 1060                                         } else if (! file_checkStat(sslset.pemfile, "SSL server PEM file", S_IRWXU)) {
 1061                                                 yyerror("SSL server PEM file permissions check failed");
 1062                                         } else {
 1063                                                 _setSSLOptions(&(Run.httpd.socket.net.ssl));
 1064                                         }
 1065                                 } else if (sslset.pemchain && sslset.pemkey) {
 1066                                         if (! file_checkStat(sslset.pemkey, "SSL server private key PEM file", S_IRWXU)) {
 1067                                                 yyerror("SSL server private key PEM file permissions check failed");
 1068                                         } else {
 1069                                                 _setSSLOptions(&(Run.httpd.socket.net.ssl));
 1070                                         }
 1071                                 } else {
 1072                                         yyerror("SSL server PEM file is required (please use ssl pemfile option)");
 1073                                 }
 1074 #else
 1075                                 yyerror("SSL is not supported");
 1076 #endif
 1077                         }
 1078                   }
 1079                 ;
 1080 
 1081 httpdlist       : /* EMPTY */
 1082                 | httpdlist httpdoption
 1083                 ;
 1084 
 1085 httpdoption     : ssl
 1086                 | pemfile
 1087                 | clientpemfile
 1088                 | allowselfcert
 1089                 | signature
 1090                 | bindaddress
 1091                 | allow
 1092                 | httpdport
 1093                 | httpdsocket
 1094                 ;
 1095 
 1096 /* deprecated by "ssl" options since monit 5.21 (kept for backward compatibility) */
 1097 pemfile         : PEMFILE PATH {
 1098                         _setPEM(&(sslset.pemfile), $2, "SSL server PEM file", true);
 1099                   }
 1100                 ;
 1101 
 1102 /* deprecated by "ssl" options since monit 5.21 (kept for backward compatibility) */
 1103 clientpemfile   : CLIENTPEMFILE PATH {
 1104                         _setPEM(&(sslset.clientpemfile), $2, "SSL client PEM file", true);
 1105                   }
 1106                 ;
 1107 
 1108 /* deprecated by "ssl" options since monit 5.21 (kept for backward compatibility) */
 1109 allowselfcert   : ALLOWSELFCERTIFICATION {
 1110                         sslset.flags = SSL_Enabled;
 1111                         sslset.allowSelfSigned = true;
 1112                   }
 1113                 ;
 1114 
 1115 httpdport       : PORT NUMBER {
 1116                         Run.httpd.flags |= Httpd_Net;
 1117                         Run.httpd.socket.net.port = $2;
 1118                   }
 1119                 ;
 1120 
 1121 httpdsocket     : UNIXSOCKET PATH httpdsocketoptionlist {
 1122                         Run.httpd.flags |= Httpd_Unix;
 1123                         Run.httpd.socket.unix.path = $2;
 1124                   }
 1125                 ;
 1126 
 1127 httpdsocketoptionlist : /* EMPTY */
 1128                       | httpdsocketoptionlist httpdsocketoption
 1129                       ;
 1130 
 1131 httpdsocketoption : UID STRING {
 1132                         Run.httpd.flags |= Httpd_UnixUid;
 1133                         Run.httpd.socket.unix.uid = get_uid($2, 0);
 1134                         FREE($2);
 1135                     }
 1136                   | GID STRING {
 1137                         Run.httpd.flags |= Httpd_UnixGid;
 1138                         Run.httpd.socket.unix.gid = get_gid($2, 0);
 1139                         FREE($2);
 1140                     }
 1141                   | UID NUMBER {
 1142                         Run.httpd.flags |= Httpd_UnixUid;
 1143                         Run.httpd.socket.unix.uid = get_uid(NULL, $2);
 1144                     }
 1145                   | GID NUMBER {
 1146                         Run.httpd.flags |= Httpd_UnixGid;
 1147                         Run.httpd.socket.unix.gid = get_gid(NULL, $2);
 1148                     }
 1149                   | PERMISSION NUMBER {
 1150                         Run.httpd.flags |= Httpd_UnixPermission;
 1151                         Run.httpd.socket.unix.permission = check_perm($2);
 1152                     }
 1153                   ;
 1154 
 1155 sigenable       : SIGNATURE ENABLE
 1156                 | ENABLE SIGNATURE
 1157                 ;
 1158 
 1159 sigdisable      : SIGNATURE DISABLE
 1160                 | DISABLE SIGNATURE
 1161                 ;
 1162 
 1163 signature       : sigenable  {
 1164                         Run.httpd.flags |= Httpd_Signature;
 1165                   }
 1166                 | sigdisable {
 1167                         Run.httpd.flags &= ~Httpd_Signature;
 1168                   }
 1169                 ;
 1170 
 1171 bindaddress     : ADDRESS STRING {
 1172                         Run.httpd.socket.net.address = $2;
 1173                   }
 1174                 ;
 1175 
 1176 allow           : ALLOW STRING':'STRING readonly {
 1177                         addcredentials($2, $4, Digest_Cleartext, $<number>5);
 1178                   }
 1179                 | ALLOW '@'STRING readonly {
 1180 #ifdef HAVE_LIBPAM
 1181                         addpamauth($3, $<number>4);
 1182 #else
 1183                         yyerror("PAM is not supported");
 1184                         FREE($3);
 1185 #endif
 1186                   }
 1187                 | ALLOW PATH {
 1188                         addhtpasswdentry($2, NULL, Digest_Cleartext);
 1189                         FREE($2);
 1190                   }
 1191                 | ALLOW CLEARTEXT PATH {
 1192                         addhtpasswdentry($3, NULL, Digest_Cleartext);
 1193                         FREE($3);
 1194                   }
 1195                 | ALLOW MD5HASH PATH {
 1196                         addhtpasswdentry($3, NULL, Digest_Md5);
 1197                         FREE($3);
 1198                   }
 1199                 | ALLOW CRYPT PATH {
 1200                         addhtpasswdentry($3, NULL, Digest_Crypt);
 1201                         FREE($3);
 1202                   }
 1203                 | ALLOW PATH {
 1204                         htpasswd_file = $2;
 1205                         digesttype = Digest_Cleartext;
 1206                   }
 1207                   allowuserlist {
 1208                         FREE(htpasswd_file);
 1209                   }
 1210                 | ALLOW CLEARTEXT PATH {
 1211                         htpasswd_file = $3;
 1212                         digesttype = Digest_Cleartext;
 1213                   }
 1214                   allowuserlist {
 1215                         FREE(htpasswd_file);
 1216                   }
 1217                 | ALLOW MD5HASH PATH {
 1218                         htpasswd_file = $3;
 1219                         digesttype = Digest_Md5;
 1220                   }
 1221                   allowuserlist {
 1222                         FREE(htpasswd_file);
 1223                   }
 1224                 | ALLOW CRYPT PATH {
 1225                         htpasswd_file = $3;
 1226                         digesttype = Digest_Crypt;
 1227                   }
 1228                   allowuserlist {
 1229                         FREE(htpasswd_file);
 1230                   }
 1231                 | ALLOW STRING {
 1232                         if (! Engine_addAllow($2))
 1233                                 yywarning2("invalid allow option: %s", $2);
 1234                         FREE($2);
 1235                   }
 1236                 ;
 1237 
 1238 allowuserlist   : allowuser
 1239                 | allowuserlist allowuser
 1240                 ;
 1241 
 1242 allowuser       : STRING {
 1243                         addhtpasswdentry(htpasswd_file, $1, digesttype);
 1244                         FREE($1);
 1245                   }
 1246                 ;
 1247 
 1248 readonly        : /* EMPTY */ {
 1249                         $<number>$ = false;
 1250                   }
 1251                 | READONLY {
 1252                         $<number>$ = true;
 1253                   }
 1254                 ;
 1255 
 1256 checkproc       : CHECKPROC SERVICENAME PIDFILE PATH {
 1257                         createservice(Service_Process, $<string>2, $4, check_process);
 1258                   }
 1259                 | CHECKPROC SERVICENAME PATHTOK PATH {
 1260                         createservice(Service_Process, $<string>2, $4, check_process);
 1261                   }
 1262                 | CHECKPROC SERVICENAME MATCH STRING {
 1263                         createservice(Service_Process, $<string>2, $4, check_process);
 1264                         matchset.ignore = false;
 1265                         matchset.match_path = NULL;
 1266                         matchset.match_string = Str_dup($4);
 1267                         addmatch(&matchset, Action_Ignored, 0);
 1268                   }
 1269                 | CHECKPROC SERVICENAME MATCH PATH {
 1270                         createservice(Service_Process, $<string>2, $4, check_process);
 1271                         matchset.ignore = false;
 1272                         matchset.match_path = NULL;
 1273                         matchset.match_string = Str_dup($4);
 1274                         addmatch(&matchset, Action_Ignored, 0);
 1275                   }
 1276                 ;
 1277 
 1278 checkfile       : CHECKFILE SERVICENAME PATHTOK PATH {
 1279                         createservice(Service_File, $<string>2, $4, check_file);
 1280                   }
 1281                 ;
 1282 
 1283 checkfilesys    : CHECKFILESYS SERVICENAME PATHTOK PATH {
 1284                         createservice(Service_Filesystem, $<string>2, $4, check_filesystem);
 1285                   }
 1286                 | CHECKFILESYS SERVICENAME PATHTOK STRING {
 1287                         createservice(Service_Filesystem, $<string>2, $4, check_filesystem);
 1288                   }
 1289                 ;
 1290 
 1291 checkdir        : CHECKDIR SERVICENAME PATHTOK PATH {
 1292                         createservice(Service_Directory, $<string>2, $4, check_directory);
 1293                   }
 1294                 ;
 1295 
 1296 checkhost       : CHECKHOST SERVICENAME ADDRESS STRING {
 1297                         createservice(Service_Host, $<string>2, $4, check_remote_host);
 1298                   }
 1299                 ;
 1300 
 1301 checknet        : CHECKNET SERVICENAME ADDRESS STRING {
 1302                         if (Link_isGetByAddressSupported()) {
 1303                                 createservice(Service_Net, $<string>2, $4, check_net);
 1304                                 current->inf.net->stats = Link_createForAddress($4);
 1305                         } else {
 1306                                 yyerror("Network monitoring by IP address is not supported on this platform, please use 'check network <foo> with interface <bar>' instead");
 1307                         }
 1308                   }
 1309                 | CHECKNET SERVICENAME INTERFACE STRING {
 1310                         createservice(Service_Net, $<string>2, $4, check_net);
 1311                         current->inf.net->stats = Link_createForInterface($4);
 1312                   }
 1313                 ;
 1314 
 1315 checksystem     : CHECKSYSTEM SERVICENAME {
 1316                         char *servicename = $<string>2;
 1317                         if (Str_sub(servicename, "$HOST")) {
 1318                                 char hostname[STRLEN];
 1319                                 if (gethostname(hostname, sizeof(hostname))) {
 1320                                         Log_error("System hostname error -- %s\n", STRERROR);
 1321                                         cfg_errflag++;
 1322                                 } else {
 1323                                         Util_replaceString(&servicename, "$HOST", hostname);
 1324                                 }
 1325                         }
 1326                         Run.system = createservice(Service_System, servicename, NULL, check_system); // The name given in the 'check system' statement overrides system hostname
 1327                   }
 1328                 ;
 1329 
 1330 checkfifo       : CHECKFIFO SERVICENAME PATHTOK PATH {
 1331                         createservice(Service_Fifo, $<string>2, $4, check_fifo);
 1332                   }
 1333                 ;
 1334 
 1335 checkprogram    : CHECKPROGRAM SERVICENAME PATHTOK argumentlist programtimeout {
 1336                         createservice(Service_Program, $<string>2, NULL, check_program);
 1337                         current->program->timeout = $<number>5;
 1338                         current->program->lastOutput = StringBuffer_create(64);
 1339                         current->program->inprogressOutput = StringBuffer_create(64);
 1340                  }
 1341                 | CHECKPROGRAM SERVICENAME PATHTOK argumentlist useroptionlist programtimeout {
 1342                         createservice(Service_Program, $<string>2, NULL, check_program);
 1343                         current->program->timeout = $<number>6;
 1344                         current->program->lastOutput = StringBuffer_create(64);
 1345                         current->program->inprogressOutput = StringBuffer_create(64);
 1346                  }
 1347                 ;
 1348 
 1349 start           : START argumentlist starttimeout {
 1350                         addcommand(START, $<number>3);
 1351                   }
 1352                 | START argumentlist useroptionlist starttimeout {
 1353                         addcommand(START, $<number>4);
 1354                   }
 1355                 ;
 1356 
 1357 stop            : STOP argumentlist stoptimeout {
 1358                         addcommand(STOP, $<number>3);
 1359                   }
 1360                 | STOP argumentlist useroptionlist stoptimeout {
 1361                         addcommand(STOP, $<number>4);
 1362                   }
 1363                 ;
 1364 
 1365 
 1366 restart         : RESTART argumentlist restarttimeout {
 1367                         addcommand(RESTART, $<number>3);
 1368                   }
 1369                 | RESTART argumentlist useroptionlist restarttimeout {
 1370                         addcommand(RESTART, $<number>4);
 1371                   }
 1372                 ;
 1373 
 1374 argumentlist    : argument
 1375                 | argumentlist argument
 1376                 ;
 1377 
 1378 useroptionlist  : useroption
 1379                 | useroptionlist useroption
 1380                 ;
 1381 
 1382 argument        : STRING {
 1383                         addargument($1);
 1384                   }
 1385                 | PATH {
 1386                         addargument($1);
 1387                   }
 1388                 ;
 1389 
 1390 useroption      : UID STRING {
 1391                         addeuid(get_uid($2, 0));
 1392                         FREE($2);
 1393                   }
 1394                 | GID STRING {
 1395                         addegid(get_gid($2, 0));
 1396                         FREE($2);
 1397                   }
 1398                 | UID NUMBER {
 1399                         addeuid(get_uid(NULL, $2));
 1400                   }
 1401                 | GID NUMBER {
 1402                         addegid(get_gid(NULL, $2));
 1403                   }
 1404                 ;
 1405 
 1406 username        : USERNAME MAILADDR {
 1407                         $<string>$ = $2;
 1408                   }
 1409                 | USERNAME STRING {
 1410                         $<string>$ = $2;
 1411                   }
 1412                 ;
 1413 
 1414 password        : PASSWORD STRING {
 1415                         $<string>$ = $2;
 1416                   }
 1417                 ;
 1418 
 1419 hostname        : /* EMPTY */     {
 1420                         $<string>$ = NULL;
 1421                   }
 1422                 | HOSTNAME STRING {
 1423                         $<string>$ = $2;
 1424                   }
 1425                 ;
 1426 
 1427 connection      : IF FAILED host port connectionoptlist rate1 THEN action1 recovery_success {
 1428                         /* This is a workaround to support content match without having to create an URL object. 'urloption' creates the Request_T object we need minus the URL object, but with enough information to perform content test.
 1429                            TODO: Parser is in need of refactoring */
 1430                         portset.url_request = urlrequest;
 1431                         portset.check_invers = false;
 1432                         portset.responsetime.operator = responsetimeset.operator;
 1433                         portset.responsetime.limit = responsetimeset.limit;
 1434                         addeventaction(&(portset).action, $<number>8, $<number>9);
 1435                         addport(&(current->portlist), &portset);
 1436                   }
 1437                 | IF SUCCEEDED host port connectionoptlist rate1 THEN action1 recovery_failure {
 1438                         portset.url_request = urlrequest;
 1439                         portset.check_invers = true;
 1440                         portset.responsetime.operator = responsetimeset.operator;
 1441                         portset.responsetime.limit = responsetimeset.limit;
 1442                         addeventaction(&(portset).action, $<number>8, $<number>9);
 1443                         addport(&(current->portlist), &portset);
 1444                   }
 1445                 ;
 1446 
 1447 connectionoptlist : /* EMPTY */
 1448                 | connectionoptlist connectionopt
 1449                 ;
 1450 
 1451 connectionopt   : ip
 1452                 | type
 1453                 | protocol
 1454                 | sendexpect
 1455                 | urloption
 1456                 | connectiontimeout
 1457                 | responsetime
 1458                 | outgoing
 1459                 | retry
 1460                 | ssl
 1461                 | sslchecksum
 1462                 | sslexpire
 1463                 ;
 1464 
 1465 connectionurl   : IF FAILED URL URLOBJECT connectionurloptlist rate1 THEN action1 recovery_success {
 1466                         portset.check_invers = false;
 1467                         portset.responsetime.operator = responsetimeset.operator;
 1468                         portset.responsetime.limit = responsetimeset.limit;
 1469                         prepare_urlrequest($<url>4);
 1470                         addeventaction(&(portset).action, $<number>8, $<number>9);
 1471                         addport(&(current->portlist), &portset);
 1472                   }
 1473                 | IF SUCCEEDED URL URLOBJECT connectionurloptlist rate1 THEN action1 recovery_failure {
 1474                         portset.check_invers = true;
 1475                         portset.responsetime.operator = responsetimeset.operator;
 1476                         portset.responsetime.limit = responsetimeset.limit;
 1477                         prepare_urlrequest($<url>4);
 1478                         addeventaction(&(portset).action, $<number>8, $<number>9);
 1479                         addport(&(current->portlist), &portset);
 1480                   }
 1481                 ;
 1482 
 1483 connectionurloptlist : /* EMPTY */
 1484                 | connectionurloptlist connectionurlopt
 1485                 ;
 1486 
 1487 connectionurlopt : urloption
 1488                  | connectiontimeout
 1489                  | retry
 1490                  | ssl
 1491                  | sslchecksum
 1492                  | sslexpire
 1493                  ;
 1494 
 1495 connectionunix  : IF FAILED unixsocket connectionuxoptlist rate1 THEN action1 recovery_success {
 1496                         portset.check_invers = false;
 1497                         portset.responsetime.operator = responsetimeset.operator;
 1498                         portset.responsetime.limit = responsetimeset.limit;
 1499                         addeventaction(&(portset).action, $<number>7, $<number>8);
 1500                         addport(&(current->socketlist), &portset);
 1501                   }
 1502                 | IF SUCCEEDED unixsocket connectionuxoptlist rate1 THEN action1 recovery_failure {
 1503                         portset.check_invers = true;
 1504                         portset.responsetime.operator = responsetimeset.operator;
 1505                         portset.responsetime.limit = responsetimeset.limit;
 1506                         addeventaction(&(portset).action, $<number>7, $<number>8);
 1507                         addport(&(current->socketlist), &portset);
 1508                   }
 1509                 ;
 1510 
 1511 connectionuxoptlist : /* EMPTY */
 1512                 | connectionuxoptlist connectionuxopt
 1513                 ;
 1514 
 1515 connectionuxopt : type
 1516                 | protocol
 1517                 | sendexpect
 1518                 | connectiontimeout
 1519                 | responsetime
 1520                 | retry
 1521                 ;
 1522 
 1523 icmp            : IF FAILED ICMP icmptype icmpoptlist rate1 THEN action1 recovery_success {
 1524                         icmpset.family = Socket_Ip;
 1525                         icmpset.check_invers = false;
 1526                         icmpset.type = $<number>4;
 1527                         icmpset.responsetime.operator = responsetimeset.operator;
 1528                         icmpset.responsetime.limit = responsetimeset.limit;
 1529                         addeventaction(&(icmpset).action, $<number>8, $<number>9);
 1530                         addicmp(&icmpset);
 1531                   }
 1532                 | IF FAILED PING icmpoptlist rate1 THEN action1 recovery_success {
 1533                         icmpset.family = Socket_Ip;
 1534                         icmpset.check_invers = false;
 1535                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1536                         addicmp(&icmpset);
 1537                  }
 1538                 | IF FAILED PING4 icmpoptlist rate1 THEN action1 recovery_success {
 1539                         icmpset.family = Socket_Ip4;
 1540                         icmpset.check_invers = false;
 1541                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1542                         addicmp(&icmpset);
 1543                  }
 1544                 | IF FAILED PING6 icmpoptlist rate1 THEN action1 recovery_success {
 1545                         icmpset.family = Socket_Ip6;
 1546                         icmpset.check_invers = false;
 1547                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1548                         addicmp(&icmpset);
 1549                  }
 1550                 | IF SUCCEEDED ICMP icmptype icmpoptlist rate1 THEN action1 recovery_failure {
 1551                         icmpset.family = Socket_Ip;
 1552                         icmpset.check_invers = true;
 1553                         icmpset.type = $<number>4;
 1554                         icmpset.responsetime.operator = responsetimeset.operator;
 1555                         icmpset.responsetime.limit = responsetimeset.limit;
 1556                         addeventaction(&(icmpset).action, $<number>8, $<number>9);
 1557                         addicmp(&icmpset);
 1558                   }
 1559                 | IF SUCCEEDED PING icmpoptlist rate1 THEN action1 recovery_failure {
 1560                         icmpset.family = Socket_Ip;
 1561                         icmpset.check_invers = true;
 1562                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1563                         addicmp(&icmpset);
 1564                  }
 1565                 | IF SUCCEEDED PING4 icmpoptlist rate1 THEN action1 recovery_failure {
 1566                         icmpset.family = Socket_Ip4;
 1567                         icmpset.check_invers = true;
 1568                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1569                         addicmp(&icmpset);
 1570                  }
 1571                 | IF SUCCEEDED PING6 icmpoptlist rate1 THEN action1 recovery_failure {
 1572                         icmpset.family = Socket_Ip6;
 1573                         icmpset.check_invers = true;
 1574                         addeventaction(&(icmpset).action, $<number>7, $<number>8);
 1575                         addicmp(&icmpset);
 1576                  }
 1577                 ;
 1578 
 1579 icmpoptlist     : /* EMPTY */
 1580                 | icmpoptlist icmpopt
 1581                 ;
 1582 
 1583 icmpopt         : icmpcount
 1584                 | icmpsize
 1585                 | icmptimeout
 1586                 | icmpoutgoing
 1587                 ;
 1588 
 1589 host            : /* EMPTY */ {
 1590                         portset.hostname = Str_dup(current->type == Service_Host ? current->path : LOCALHOST);
 1591                   }
 1592                 | HOST STRING {
 1593                         portset.hostname = $2;
 1594                   }
 1595                 ;
 1596 
 1597 port            : PORT NUMBER {
 1598                         portset.target.net.port = $2;
 1599                   }
 1600                 ;
 1601 
 1602 unixsocket      : UNIXSOCKET PATH {
 1603                         portset.family = Socket_Unix;
 1604                         portset.target.unix.pathname = $2;
 1605                   }
 1606                 ;
 1607 
 1608 ip              : IPV4 {
 1609                         portset.family = Socket_Ip4;
 1610                   }
 1611                 | IPV6 {
 1612                         portset.family = Socket_Ip6;
 1613                   }
 1614                 ;
 1615 
 1616 type            : TYPE TCP {
 1617                         portset.type = Socket_Tcp;
 1618                   }
 1619                 | TYPE TCPSSL typeoptlist { // The typelist is kept for backward compatibility (replaced by ssloptionlist)
 1620                         portset.type = Socket_Tcp;
 1621                         sslset.flags = SSL_Enabled;
 1622                   }
 1623                 | TYPE UDP {
 1624                         portset.type = Socket_Udp;
 1625                   }
 1626                 ;
 1627 
 1628 typeoptlist     : /* EMPTY */
 1629                 | typeoptlist typeopt
 1630                 ;
 1631 
 1632 typeopt         : sslversion
 1633                 | certmd5
 1634                 ;
 1635 
 1636 outgoing        : ADDRESS STRING {
 1637                         _parseOutgoingAddress($<string>2, &(portset.outgoing));
 1638                   }
 1639                 ;
 1640 
 1641 protocol        : PROTOCOL APACHESTATUS apache_stat_list {
 1642                         portset.protocol = Protocol_get(Protocol_APACHESTATUS);
 1643                   }
 1644                 | PROTOCOL DEFAULT {
 1645                         portset.protocol = Protocol_get(Protocol_DEFAULT);
 1646                   }
 1647                 | PROTOCOL DNS {
 1648                         portset.protocol = Protocol_get(Protocol_DNS);
 1649                   }
 1650                 | PROTOCOL DWP  {
 1651                         portset.protocol = Protocol_get(Protocol_DWP);
 1652                   }
 1653                 | PROTOCOL FAIL2BAN {
 1654                         portset.protocol = Protocol_get(Protocol_FAIL2BAN);
 1655                 }
 1656                 | PROTOCOL FTP {
 1657                         portset.protocol = Protocol_get(Protocol_FTP);
 1658                   }
 1659                 | PROTOCOL HTTP httplist {
 1660                         portset.protocol = Protocol_get(Protocol_HTTP);
 1661                   }
 1662                 | PROTOCOL HTTPS httplist {
 1663                         sslset.flags = SSL_Enabled;
 1664                         portset.type = Socket_Tcp;
 1665                         portset.protocol = Protocol_get(Protocol_HTTP);
 1666                  }
 1667                 | PROTOCOL IMAP {
 1668                         portset.protocol = Protocol_get(Protocol_IMAP);
 1669                   }
 1670                 | PROTOCOL IMAPS {
 1671                         sslset.flags = SSL_Enabled;
 1672                         portset.type = Socket_Tcp;
 1673                         portset.protocol = Protocol_get(Protocol_IMAP);
 1674                   }
 1675                 | PROTOCOL CLAMAV {
 1676                         portset.protocol = Protocol_get(Protocol_CLAMAV);
 1677                   }
 1678                 | PROTOCOL LDAP2 {
 1679                         portset.protocol = Protocol_get(Protocol_LDAP2);
 1680                   }
 1681                 | PROTOCOL LDAP3 {
 1682                         portset.protocol = Protocol_get(Protocol_LDAP3);
 1683                   }
 1684                 | PROTOCOL MONGODB  {
 1685                         portset.protocol = Protocol_get(Protocol_MONGODB);
 1686                   }
 1687                 | PROTOCOL MQTT mqttlist {
 1688                         portset.protocol = Protocol_get(Protocol_MQTT);
 1689                   }
 1690                 | PROTOCOL MYSQL mysqllist {
 1691                         portset.protocol = Protocol_get(Protocol_MYSQL);
 1692                   }
 1693                 | PROTOCOL MYSQLS mysqllist {
 1694                         sslset.flags = SSL_StartTLS;
 1695                         portset.protocol = Protocol_get(Protocol_MYSQL);
 1696                   }
 1697                 | PROTOCOL SIP siplist {
 1698                         portset.protocol = Protocol_get(Protocol_SIP);
 1699                   }
 1700                 | PROTOCOL NNTP {
 1701                         portset.protocol = Protocol_get(Protocol_NNTP);
 1702                   }
 1703                 | PROTOCOL NTP3  {
 1704                         portset.protocol = Protocol_get(Protocol_NTP3);
 1705                         portset.type = Socket_Udp;
 1706                   }
 1707                 | PROTOCOL POSTFIXPOLICY {
 1708                         portset.protocol = Protocol_get(Protocol_POSTFIXPOLICY);
 1709                   }
 1710                 | PROTOCOL POP {
 1711                         portset.protocol = Protocol_get(Protocol_POP);
 1712                   }
 1713                 | PROTOCOL POPS {
 1714                         sslset.flags = SSL_Enabled;
 1715                         portset.type = Socket_Tcp;
 1716                         portset.protocol = Protocol_get(Protocol_POP);
 1717                   }
 1718                 | PROTOCOL SIEVE {
 1719                         portset.protocol = Protocol_get(Protocol_SIEVE);
 1720                   }
 1721                 | PROTOCOL SMTP smtplist {
 1722                         portset.protocol = Protocol_get(Protocol_SMTP);
 1723                   }
 1724                 | PROTOCOL SMTPS smtplist {
 1725                         sslset.flags = SSL_Enabled;
 1726                         portset.type = Socket_Tcp;
 1727                         portset.protocol = Protocol_get(Protocol_SMTP);
 1728                  }
 1729                 | PROTOCOL SPAMASSASSIN {
 1730                         portset.protocol = Protocol_get(Protocol_SPAMASSASSIN);
 1731                   }
 1732                 | PROTOCOL SSH  {
 1733                         portset.protocol = Protocol_get(Protocol_SSH);
 1734                   }
 1735                 | PROTOCOL RDATE {
 1736                         portset.protocol = Protocol_get(Protocol_RDATE);
 1737                   }
 1738                 | PROTOCOL REDIS  {
 1739                         portset.protocol = Protocol_get(Protocol_REDIS);
 1740                   }
 1741                 | PROTOCOL RSYNC {
 1742                         portset.protocol = Protocol_get(Protocol_RSYNC);
 1743                   }
 1744                 | PROTOCOL TNS {
 1745                         portset.protocol = Protocol_get(Protocol_TNS);
 1746                   }
 1747                 | PROTOCOL PGSQL {
 1748                         portset.protocol = Protocol_get(Protocol_PGSQL);
 1749                   }
 1750                 | PROTOCOL LMTP {
 1751                         portset.protocol = Protocol_get(Protocol_LMTP);
 1752                   }
 1753                 | PROTOCOL GPS {
 1754                         portset.protocol = Protocol_get(Protocol_GPS);
 1755                   }
 1756                 | PROTOCOL RADIUS radiuslist {
 1757                         portset.protocol = Protocol_get(Protocol_RADIUS);
 1758                   }
 1759                 | PROTOCOL MEMCACHE {
 1760                         portset.protocol = Protocol_get(Protocol_MEMCACHE);
 1761                   }
 1762                 | PROTOCOL WEBSOCKET websocketlist {
 1763                         portset.protocol = Protocol_get(Protocol_WEBSOCKET);
 1764                   }
 1765                 ;
 1766 
 1767 sendexpect      : SEND STRING {
 1768                         if (portset.protocol->check == check_default || portset.protocol->check == check_generic) {
 1769                                 portset.protocol = Protocol_get(Protocol_GENERIC);
 1770                                 addgeneric(&portset, $2, NULL);
 1771                         } else {
 1772                                 yyerror("The SEND statement is not allowed in the %s protocol context", portset.protocol->name);
 1773                         }
 1774                   }
 1775                 | EXPECT STRING {
 1776                         if (portset.protocol->check == check_default || portset.protocol->check == check_generic) {
 1777                                 portset.protocol = Protocol_get(Protocol_GENERIC);
 1778                                 addgeneric(&portset, NULL, $2);
 1779                         } else {
 1780                                 yyerror("The EXPECT statement is not allowed in the %s protocol context", portset.protocol->name);
 1781                         }
 1782                   }
 1783                 ;
 1784 
 1785 websocketlist   : websocket
 1786                 | websocketlist websocket
 1787                 ;
 1788 
 1789 websocket       : ORIGIN STRING {
 1790                         portset.parameters.websocket.origin = $<string>2;
 1791                   }
 1792                 | REQUEST PATH {
 1793                         portset.parameters.websocket.request = $<string>2;
 1794                   }
 1795                 | HOST STRING {
 1796                         portset.parameters.websocket.host = $<string>2;
 1797                   }
 1798                 | VERSIONOPT NUMBER {
 1799                         portset.parameters.websocket.version = $<number>2;
 1800                   }
 1801                 ;
 1802 
 1803 smtplist        : /* EMPTY */
 1804                 | smtplist smtp
 1805                 ;
 1806 
 1807 smtp            : username {
 1808                         portset.parameters.smtp.username = $<string>1;
 1809                   }
 1810                 | password {
 1811                         portset.parameters.smtp.password = $<string>1;
 1812                   }
 1813                 ;
 1814 
 1815 mqttlist        : /* EMPTY */
 1816                 | mqttlist mqtt
 1817                 ;
 1818 
 1819 mqtt            : username {
 1820                         portset.parameters.mqtt.username = $<string>1;
 1821                   }
 1822                 | password {
 1823                         portset.parameters.mqtt.password = $<string>1;
 1824                   }
 1825                 ;
 1826 
 1827 mysqllist       : /* EMPTY */
 1828                 | mysqllist mysql
 1829                 ;
 1830 
 1831 mysql           : username {
 1832                         portset.parameters.mysql.username = $<string>1;
 1833                   }
 1834                 | password {
 1835                         portset.parameters.mysql.password = $<string>1;
 1836                   }
 1837                 | RSAKEY CHECKSUM checksumoperator STRING {
 1838                         portset.parameters.mysql.rsaChecksum = $<string>4;
 1839                         switch (cleanup_hash_string(portset.parameters.mysql.rsaChecksum)) {
 1840                                 case 32:
 1841                                         portset.parameters.mysql.rsaChecksumType = Hash_Md5;
 1842                                         break;
 1843                                 case 40:
 1844                                         portset.parameters.mysql.rsaChecksumType = Hash_Sha1;
 1845                                         break;
 1846                                 default:
 1847                                         yyerror2("Unknown checksum type: [%s] is not MD5 nor SHA1", portset.parameters.mysql.rsaChecksum);
 1848                         }
 1849                   }
 1850                 | RSAKEY CHECKSUM MD5HASH checksumoperator STRING {
 1851                         portset.parameters.mysql.rsaChecksum = $<string>5;
 1852                         if (cleanup_hash_string(portset.parameters.mysql.rsaChecksum) != 32)
 1853                                 yyerror2("Unknown checksum type: [%s] is not MD5", portset.parameters.mysql.rsaChecksum);
 1854                         portset.parameters.mysql.rsaChecksumType = Hash_Md5;
 1855                   }
 1856                 | RSAKEY CHECKSUM SHA1HASH checksumoperator STRING {
 1857                         portset.parameters.mysql.rsaChecksum = $<string>5;
 1858                         if (cleanup_hash_string(portset.parameters.mysql.rsaChecksum) != 40)
 1859                                 yyerror2("Unknown checksum type: [%s] is not SHA1", portset.parameters.mysql.rsaChecksum);
 1860                         portset.parameters.mysql.rsaChecksumType = Hash_Sha1;
 1861                   }
 1862                 ;
 1863                 ;
 1864 
 1865 target          : TARGET MAILADDR {
 1866                         $<string>$ = $2;
 1867                   }
 1868                 | TARGET STRING {
 1869                         $<string>$ = $2;
 1870                   }
 1871                 ;
 1872 
 1873 maxforward      : MAXFORWARD NUMBER {
 1874                         $<number>$ = verifyMaxForward($2);
 1875                   }
 1876                 ;
 1877 
 1878 siplist         : /* EMPTY */
 1879                 | siplist sip
 1880                 ;
 1881 
 1882 sip             : target {
 1883                         portset.parameters.sip.target = $<string>1;
 1884                   }
 1885                 | maxforward {
 1886                         portset.parameters.sip.maxforward = $<number>1;
 1887                   }
 1888                 ;
 1889 
 1890 httplist        : /* EMPTY */
 1891                 | httplist http
 1892                 ;
 1893 
 1894 http            : username {
 1895                         portset.parameters.http.username = $<string>1;
 1896                   }
 1897                 | password {
 1898                         portset.parameters.http.password = $<string>1;
 1899                   }
 1900                 | request
 1901                 | responsesum
 1902                 | status
 1903                 | method
 1904                 | hostheader
 1905                 | '[' httpheaderlist ']'
 1906                 ;
 1907 
 1908 status          : STATUS operator NUMBER {
 1909                         if ($<number>3 < 0) {
 1910                                 yyerror2("The status value must be greater or equal to 0");
 1911                         }
 1912                         portset.parameters.http.operator = $<number>2;
 1913                         portset.parameters.http.status = $<number>3;
 1914                         portset.parameters.http.hasStatus = true;
 1915                   }
 1916                 ;
 1917 
 1918 method          : METHOD GET {
 1919                         portset.parameters.http.method = Http_Get;
 1920                   }
 1921                 | METHOD HEAD {
 1922                         portset.parameters.http.method = Http_Head;
 1923                   }
 1924                 ;
 1925 
 1926 request         : REQUEST PATH {
 1927                         portset.parameters.http.request = Util_urlEncode($2, false);
 1928                         FREE($2);
 1929                   }
 1930                 | REQUEST STRING {
 1931                         portset.parameters.http.request = Util_urlEncode($2, false);
 1932                         FREE($2);
 1933                   }
 1934                 ;
 1935 
 1936 responsesum     : CHECKSUM STRING {
 1937                         portset.parameters.http.checksum = $2;
 1938                   }
 1939                 ;
 1940 
 1941 hostheader      : HOSTHEADER STRING {
 1942                         addhttpheader(&portset, Str_cat("Host:%s", $2));
 1943                         FREE($2);
 1944                   }
 1945                 ;
 1946 
 1947 httpheaderlist  : /* EMPTY */
 1948                 | httpheaderlist HTTPHEADER {
 1949                         addhttpheader(&portset, $2);
 1950                  }
 1951                 ;
 1952 
 1953 secret          : SECRET STRING {
 1954                         $<string>$ = $2;
 1955                   }
 1956                 ;
 1957 
 1958 radiuslist      : /* EMPTY */
 1959                 | radiuslist radius
 1960                 ;
 1961 
 1962 radius          : secret {
 1963                         portset.parameters.radius.secret = $<string>1;
 1964                   }
 1965                 ;
 1966 
 1967 apache_stat_list: apache_stat
 1968                 | apache_stat_list apache_stat
 1969                 ;
 1970 
 1971 apache_stat     : username {
 1972                         portset.parameters.apachestatus.username = $<string>1;
 1973                   }
 1974                 | password {
 1975                         portset.parameters.apachestatus.password = $<string>1;
 1976                   }
 1977                 | PATHTOK PATH {
 1978                         portset.parameters.apachestatus.path = $<string>2;
 1979                   }
 1980                 | LOGLIMIT operator NUMBER PERCENT {
 1981                         portset.parameters.apachestatus.loglimitOP = $<number>2;
 1982                         portset.parameters.apachestatus.loglimit = $<number>3;
 1983                   }
 1984                 | CLOSELIMIT operator NUMBER PERCENT {
 1985                         portset.parameters.apachestatus.closelimitOP = $<number>2;
 1986                         portset.parameters.apachestatus.closelimit = $<number>3;
 1987                   }
 1988                 | DNSLIMIT operator NUMBER PERCENT {
 1989                         portset.parameters.apachestatus.dnslimitOP = $<number>2;
 1990                         portset.parameters.apachestatus.dnslimit = $<number>3;
 1991                   }
 1992                 | KEEPALIVELIMIT operator NUMBER PERCENT {
 1993                         portset.parameters.apachestatus.keepalivelimitOP = $<number>2;
 1994                         portset.parameters.apachestatus.keepalivelimit = $<number>3;
 1995                   }
 1996                 | REPLYLIMIT operator NUMBER PERCENT {
 1997                         portset.parameters.apachestatus.replylimitOP = $<number>2;
 1998                         portset.parameters.apachestatus.replylimit = $<number>3;
 1999                   }
 2000                 | REQUESTLIMIT operator NUMBER PERCENT {
 2001                         portset.parameters.apachestatus.requestlimitOP = $<number>2;
 2002                         portset.parameters.apachestatus.requestlimit = $<number>3;
 2003                   }
 2004                 | STARTLIMIT operator NUMBER PERCENT {
 2005                         portset.parameters.apachestatus.startlimitOP = $<number>2;
 2006                         portset.parameters.apachestatus.startlimit = $<number>3;
 2007                   }
 2008                 | WAITLIMIT operator NUMBER PERCENT {
 2009                         portset.parameters.apachestatus.waitlimitOP = $<number>2;
 2010                         portset.parameters.apachestatus.waitlimit = $<number>3;
 2011                   }
 2012                 | GRACEFULLIMIT operator NUMBER PERCENT {
 2013                         portset.parameters.apachestatus.gracefullimitOP = $<number>2;
 2014                         portset.parameters.apachestatus.gracefullimit = $<number>3;
 2015                   }
 2016                 | CLEANUPLIMIT operator NUMBER PERCENT {
 2017                         portset.parameters.apachestatus.cleanuplimitOP = $<number>2;
 2018                         portset.parameters.apachestatus.cleanuplimit = $<number>3;
 2019                   }
 2020                 ;
 2021 
 2022 exist           : IF NOT EXIST rate1 THEN action1 recovery_success {
 2023                         addeventaction(&(nonexistset).action, $<number>6, $<number>7);
 2024                         addnonexist(&nonexistset);
 2025                   }
 2026                 | IF EXIST rate1 THEN action1 recovery_success {
 2027                         addeventaction(&(existset).action, $<number>5, $<number>6);
 2028                         addexist(&existset);
 2029                   }
 2030                 ;
 2031 
 2032 
 2033 pid             : IF CHANGED PID rate1 THEN action1 {
 2034                         addeventaction(&(pidset).action, $<number>6, Action_Ignored);
 2035                         addpid(&pidset);
 2036                   }
 2037                 ;
 2038 
 2039 ppid            : IF CHANGED PPID rate1 THEN action1 {
 2040                         addeventaction(&(ppidset).action, $<number>6, Action_Ignored);
 2041                         addppid(&ppidset);
 2042                   }
 2043                 ;
 2044 
 2045 uptime          : IF UPTIME operator NUMBER time rate1 THEN action1 recovery_success {
 2046                         uptimeset.operator = $<number>3;
 2047                         uptimeset.uptime = ((unsigned long long)$4 * $<number>5);
 2048                         addeventaction(&(uptimeset).action, $<number>8, $<number>9);
 2049                         adduptime(&uptimeset);
 2050                   }
 2051                 ;
 2052 
 2053 responsetime    : RESPONSETIME operator NUMBER MILLISECOND {
 2054                         responsetimeset.operator = $<number>2;
 2055                         responsetimeset.limit = $3;
 2056                   }
 2057                 | RESPONSETIME operator NUMBER SECOND {
 2058                         responsetimeset.operator = $<number>2;
 2059                         responsetimeset.limit = $3 * 1000;
 2060                   }
 2061                 ;
 2062 
 2063 icmpcount       : COUNT NUMBER {
 2064                         icmpset.count = $<number>2;
 2065                  }
 2066                 ;
 2067 
 2068 icmpsize        : SIZE NUMBER {
 2069                         icmpset.size = $<number>2;
 2070                         if (icmpset.size < 8) {
 2071                                 yyerror2("The minimum ping size is 8 bytes");
 2072                         } else if (icmpset.size > 1492) {
 2073                                 yyerror2("The maximum ping size is 1492 bytes");
 2074                         }
 2075                  }
 2076                 ;
 2077 
 2078 icmptimeout     : TIMEOUT NUMBER SECOND {
 2079                         icmpset.timeout = $<number>2 * 1000; // timeout is in milliseconds internally
 2080                     }
 2081                   ;
 2082 
 2083 icmpoutgoing    : ADDRESS STRING {
 2084                         _parseOutgoingAddress($<string>2, &(icmpset.outgoing));
 2085                   }
 2086                 ;
 2087 
 2088 stoptimeout     : /* EMPTY */ {
 2089                         $<number>$ = Run.limits.stopTimeout;
 2090                   }
 2091                 | TIMEOUT NUMBER SECOND {
 2092                         $<number>$ = $2 * 1000; // milliseconds internally
 2093                   }
 2094                 ;
 2095 
 2096 starttimeout    : /* EMPTY */ {
 2097                         $<number>$ = Run.limits.startTimeout;
 2098                   }
 2099                 | TIMEOUT NUMBER SECOND {
 2100                         $<number>$ = $2 * 1000; // milliseconds internally
 2101                   }
 2102                 ;
 2103 
 2104 restarttimeout  : /* EMPTY */ {
 2105                         $<number>$ = Run.limits.restartTimeout;
 2106                   }
 2107                 | TIMEOUT NUMBER SECOND {
 2108                         $<number>$ = $2 * 1000; // milliseconds internally
 2109                   }
 2110                 ;
 2111 
 2112 programtimeout  : /* EMPTY */ {
 2113                         $<number>$ = Run.limits.programTimeout;
 2114                   }
 2115                 | TIMEOUT NUMBER SECOND {
 2116                         $<number>$ = $2 * 1000; // milliseconds internally
 2117                   }
 2118                 ;
 2119 
 2120 nettimeout      : /* EMPTY */ {
 2121                         $<number>$ = Run.limits.networkTimeout;
 2122                   }
 2123                 | TIMEOUT NUMBER SECOND {
 2124                         $<number>$ = $2 * 1000; // net timeout is in milliseconds internally
 2125                   }
 2126                 ;
 2127 
 2128 connectiontimeout : TIMEOUT NUMBER SECOND {
 2129                         portset.timeout = $<number>2 * 1000; // timeout is in milliseconds internally
 2130                     }
 2131                   ;
 2132 
 2133 retry           : RETRY NUMBER {
 2134                         portset.retry = $2;
 2135                   }
 2136                 ;
 2137 
 2138 actionrate      : IF NUMBER RESTART NUMBER CYCLE THEN action1 {
 2139                         actionrateset.count = $2;
 2140                         actionrateset.cycle = $4;
 2141                         addeventaction(&(actionrateset).action, $<number>7, Action_Alert);
 2142                         addactionrate(&actionrateset);
 2143                   }
 2144                 | IF NUMBER RESTART NUMBER CYCLE THEN TIMEOUT {
 2145                         actionrateset.count = $2;
 2146                         actionrateset.cycle = $4;
 2147                         addeventaction(&(actionrateset).action, Action_Unmonitor, Action_Alert);
 2148                         addactionrate(&actionrateset);
 2149                   }
 2150                 ;
 2151 
 2152 urloption       : CONTENT urloperator STRING {
 2153                         seturlrequest($<number>2, $<string>3);
 2154                         FREE($3);
 2155                   }
 2156                 ;
 2157 
 2158 urloperator     : EQUAL    { $<number>$ = Operator_Equal; }
 2159                 | NOTEQUAL { $<number>$ = Operator_NotEqual; }
 2160                 ;
 2161 
 2162 alert           : alertmail formatlist reminder {
 2163                         mailset.events = Event_All;
 2164                         addmail($<string>1, &mailset, &current->maillist);
 2165                   }
 2166                 | alertmail '{' eventoptionlist '}' formatlist reminder {
 2167                         addmail($<string>1, &mailset, &current->maillist);
 2168                   }
 2169                 | alertmail NOT '{' eventoptionlist '}' formatlist reminder {
 2170                         mailset.events = ~mailset.events;
 2171                         addmail($<string>1, &mailset, &current->maillist);
 2172                   }
 2173                 | noalertmail {
 2174                         addmail($<string>1, &mailset, &current->maillist);
 2175                   }
 2176                 ;
 2177 
 2178 alertmail       : ALERT MAILADDR { $<string>$ = $2; }
 2179                 ;
 2180 
 2181 noalertmail     : NOALERT MAILADDR { $<string>$ = $2; }
 2182                 ;
 2183 
 2184 eventoptionlist : eventoption
 2185                 | eventoptionlist eventoption
 2186                 ;
 2187 
 2188 eventoption     : ACTION          { mailset.events |= Event_Action; }
 2189                 | BYTEIN          { mailset.events |= Event_ByteIn; }
 2190                 | BYTEOUT         { mailset.events |= Event_ByteOut; }
 2191                 | CHECKSUM        { mailset.events |= Event_Checksum; }
 2192                 | CONNECTION      { mailset.events |= Event_Connection; }
 2193                 | CONTENT         { mailset.events |= Event_Content; }
 2194                 | DATA            { mailset.events |= Event_Data; }
 2195                 | EXEC            { mailset.events |= Event_Exec; }
 2196                 | EXIST           { mailset.events |= Event_Exist; }
 2197                 | FSFLAG          { mailset.events |= Event_FsFlag; }
 2198                 | GID             { mailset.events |= Event_Gid; }
 2199                 | ICMP            { mailset.events |= Event_Icmp; }
 2200                 | INSTANCE        { mailset.events |= Event_Instance; }
 2201                 | INVALID         { mailset.events |= Event_Invalid; }
 2202                 | LINK            { mailset.events |= Event_Link; }
 2203                 | NONEXIST        { mailset.events |= Event_NonExist; }
 2204                 | PACKETIN        { mailset.events |= Event_PacketIn; }
 2205                 | PACKETOUT       { mailset.events |= Event_PacketOut; }
 2206                 | PERMISSION      { mailset.events |= Event_Permission; }
 2207                 | PID             { mailset.events |= Event_Pid; }
 2208                 | PPID            { mailset.events |= Event_PPid; }
 2209                 | RESOURCE        { mailset.events |= Event_Resource; }
 2210                 | SATURATION      { mailset.events |= Event_Saturation; }
 2211                 | SIZE            { mailset.events |= Event_Size; }
 2212                 | SPEED           { mailset.events |= Event_Speed; }
 2213                 | STATUS          { mailset.events |= Event_Status; }
 2214                 | TIMEOUT         { mailset.events |= Event_Timeout; }
 2215                 | TIME            { mailset.events |= Event_Timestamp; }
 2216                 | UID             { mailset.events |= Event_Uid; }
 2217                 | UPTIME          { mailset.events |= Event_Uptime; }
 2218                 ;
 2219 
 2220 formatlist      : /* EMPTY */
 2221                 | MAILFORMAT '{' formatoptionlist '}'
 2222                 ;
 2223 
 2224 formatoptionlist: formatoption
 2225                 | formatoptionlist formatoption
 2226                 ;
 2227 
 2228 formatoption    : MAILFROM ADDRESSOBJECT { mailset.from = $<address>1; }
 2229                 | MAILREPLYTO ADDRESSOBJECT { mailset.replyto = $<address>1; }
 2230                 | MAILSUBJECT { mailset.subject = $1; }
 2231                 | MAILBODY { mailset.message = $1; }
 2232                 ;
 2233 
 2234 every           : EVERY NUMBER CYCLE {
 2235                         current->every.type = Every_SkipCycles;
 2236                         current->every.spec.cycle.counter = current->every.spec.cycle.number = $2;
 2237                  }
 2238                 | EVERY TIMESPEC {
 2239                         current->every.type = Every_Cron;
 2240                         current->every.spec.cron = $2;
 2241                  }
 2242                 | NOTEVERY TIMESPEC {
 2243                         current->every.type = Every_NotInCron;
 2244                         current->every.spec.cron = $2;
 2245                  }
 2246                 ;
 2247 
 2248 mode            : MODE ACTIVE {
 2249                         current->mode = Monitor_Active;
 2250                   }
 2251                 | MODE PASSIVE {
 2252                         current->mode = Monitor_Passive;
 2253                   }
 2254                 | MODE MANUAL {
 2255                         // Deprecated since monit 5.18
 2256                         current->onreboot = Onreboot_Laststate;
 2257                   }
 2258                 ;
 2259 
 2260 onreboot        : ONREBOOT START {
 2261                         current->onreboot = Onreboot_Start;
 2262                   }
 2263                 | ONREBOOT NOSTART {
 2264                         current->onreboot = Onreboot_Nostart;
 2265                         current->monitor = Monitor_Not;
 2266                   }
 2267                 | ONREBOOT LASTSTATE {
 2268                         current->onreboot = Onreboot_Laststate;
 2269                   }
 2270                 ;
 2271 
 2272 group           : GROUP STRINGNAME {
 2273                         addservicegroup($2);
 2274                         FREE($2);
 2275                   }
 2276                 ;
 2277 
 2278 
 2279 depend          : DEPENDS dependlist
 2280                 ;
 2281 
 2282 dependlist      : dependant
 2283                 | dependlist dependant
 2284                 ;
 2285 
 2286 dependant       : SERVICENAME { adddependant($<string>1); }
 2287                 ;
 2288 
 2289 statusvalue     : IF STATUS operator NUMBER rate1 THEN action1 recovery_success {
 2290                         statusset.initialized = true;
 2291                         statusset.operator = $<number>3;
 2292                         statusset.return_value = $<number>4;
 2293                         addeventaction(&(statusset).action, $<number>7, $<number>8);
 2294                         addstatus(&statusset);
 2295                    }
 2296                 | IF CHANGED STATUS rate1 THEN action1 {
 2297                         statusset.initialized = false;
 2298                         statusset.operator = Operator_Changed;
 2299                         statusset.return_value = 0;
 2300                         addeventaction(&(statusset).action, $<number>6, Action_Ignored);
 2301                         addstatus(&statusset);
 2302                    }
 2303                 ;
 2304 
 2305 resourceprocess : IF resourceprocesslist rate1 THEN action1 recovery_success {
 2306                         addeventaction(&(resourceset).action, $<number>5, $<number>6);
 2307                         addresource(&resourceset);
 2308                    }
 2309                 ;
 2310 
 2311 resourceprocesslist : resourceprocessopt
 2312                     | resourceprocesslist resourceprocessopt
 2313                     ;
 2314 
 2315 resourceprocessopt  : resourcecpuproc
 2316                     | resourcememproc
 2317                     | resourcethreads
 2318                     | resourcechild
 2319                     | resourceload
 2320                     | resourceread
 2321                     | resourcewrite
 2322                     ;
 2323 
 2324 resourcesystem  : IF resourcesystemlist rate1 THEN action1 recovery_success {
 2325                         addeventaction(&(resourceset).action, $<number>5, $<number>6);
 2326                         addresource(&resourceset);
 2327                    }
 2328                 ;
 2329 
 2330 resourcesystemlist : resourcesystemopt
 2331                    | resourcesystemlist resourcesystemopt
 2332                    ;
 2333 
 2334 resourcesystemopt  : resourceload
 2335                    | resourcemem
 2336                    | resourceswap
 2337                    | resourcecpu
 2338                    ;
 2339 
 2340 resourcecpuproc : CPU operator value PERCENT {
 2341                         resourceset.resource_id = Resource_CpuPercent;
 2342                         resourceset.operator = $<number>2;
 2343                         resourceset.limit = $<real>3;
 2344                   }
 2345                 | TOTALCPU operator value PERCENT {
 2346                         resourceset.resource_id = Resource_CpuPercentTotal;
 2347                         resourceset.operator = $<number>2;
 2348                         resourceset.limit = $<real>3;
 2349                   }
 2350                 ;
 2351 
 2352 resourcecpu     : resourcecpuid operator value PERCENT {
 2353                         resourceset.resource_id = $<number>1;
 2354                         resourceset.operator = $<number>2;
 2355                         resourceset.limit = $<real>3;
 2356                   }
 2357                 ;
 2358 
 2359 resourcecpuid   : CPUUSER {
 2360                         if (systeminfo.statisticsAvailable & Statistics_CpuUser)
 2361                                 $<number>$ = Resource_CpuUser;
 2362                         else
 2363                                 yywarning2("The CPU user usage statistics is not available on this system\n");
 2364                   }
 2365                 | CPUSYSTEM {
 2366                         if (systeminfo.statisticsAvailable & Statistics_CpuSystem)
 2367                                 $<number>$ = Resource_CpuSystem;
 2368                         else
 2369                                 yywarning2("The CPU system usage statistics is not available on this system\n");
 2370                   }
 2371                 | CPUWAIT {
 2372                         if (systeminfo.statisticsAvailable & Statistics_CpuIOWait)
 2373                                 $<number>$ = Resource_CpuWait;
 2374                         else
 2375                                 yywarning2("The CPU I/O wait usage statistics is not available on this system\n");
 2376                   }
 2377                 | CPUNICE {
 2378                         if (systeminfo.statisticsAvailable & Statistics_CpuNice)
 2379                                 $<number>$ = Resource_CpuNice;
 2380                         else
 2381                                 yywarning2("The CPU nice usage statistics is not available on this system\n");
 2382                   }
 2383                 | CPUHARDIRQ {
 2384                         if (systeminfo.statisticsAvailable & Statistics_CpuHardIRQ)
 2385                                 $<number>$ = Resource_CpuHardIRQ;
 2386                         else
 2387                                 yywarning2("The CPU hardware IRQ usage statistics is not available on this system\n");
 2388                   }
 2389                 | CPUSOFTIRQ {
 2390                         if (systeminfo.statisticsAvailable & Statistics_CpuSoftIRQ)
 2391                                 $<number>$ = Resource_CpuSoftIRQ;
 2392                         else
 2393                                 yywarning2("The CPU software IRQ usage statistics is not available on this system\n");
 2394                   }
 2395                 | CPUSTEAL {
 2396                         if (systeminfo.statisticsAvailable & Statistics_CpuSteal)
 2397                                 $<number>$ = Resource_CpuSteal;
 2398                         else
 2399                                 yywarning2("The CPU steal usage statistics is not available on this system\n");
 2400                   }
 2401                 | CPUGUEST {
 2402                         if (systeminfo.statisticsAvailable & Statistics_CpuGuest)
 2403                                 $<number>$ = Resource_CpuGuest;
 2404                         else
 2405                                 yywarning2("The CPU guest usage statistics is not available on this system\n");
 2406                   }
 2407                 | CPUGUESTNICE {
 2408                         if (systeminfo.statisticsAvailable & Statistics_CpuGuestNice)
 2409                                 $<number>$ = Resource_CpuGuestNice;
 2410                         else
 2411                                 yywarning2("The CPU guest nice usage statistics is not available on this system\n");
 2412                   }
 2413                 | CPU {
 2414                         $<number>$ = Resource_CpuPercent;
 2415                   }
 2416                 ;
 2417 
 2418 resourcemem     : MEMORY operator value unit {
 2419                         resourceset.resource_id = Resource_MemoryKbyte;
 2420                         resourceset.operator = $<number>2;
 2421                         resourceset.limit = $<real>3 * $<number>4;
 2422                   }
 2423                 | MEMORY operator value PERCENT {
 2424                         resourceset.resource_id = Resource_MemoryPercent;
 2425                         resourceset.operator = $<number>2;
 2426                         resourceset.limit = $<real>3;
 2427                   }
 2428                 ;
 2429 
 2430 resourcememproc : MEMORY operator value unit {
 2431                         resourceset.resource_id = Resource_MemoryKbyte;
 2432                         resourceset.operator = $<number>2;
 2433                         resourceset.limit = $<real>3 * $<number>4;
 2434                   }
 2435                 | MEMORY operator value PERCENT {
 2436                         resourceset.resource_id = Resource_MemoryPercent;
 2437                         resourceset.operator = $<number>2;
 2438                         resourceset.limit = $<real>3;
 2439                   }
 2440                 | TOTALMEMORY operator value unit {
 2441                         resourceset.resource_id = Resource_MemoryKbyteTotal;
 2442                         resourceset.operator = $<number>2;
 2443                         resourceset.limit = $<real>3 * $<number>4;
 2444                   }
 2445                 | TOTALMEMORY operator value PERCENT  {
 2446                         resourceset.resource_id = Resource_MemoryPercentTotal;
 2447                         resourceset.operator = $<number>2;
 2448                         resourceset.limit = $<real>3;
 2449                   }
 2450                 ;
 2451 
 2452 resourceswap    : SWAP operator value unit {
 2453                         resourceset.resource_id = Resource_SwapKbyte;
 2454                         resourceset.operator = $<number>2;
 2455                         resourceset.limit = $<real>3 * $<number>4;
 2456                   }
 2457                 | SWAP operator value PERCENT {
 2458                         resourceset.resource_id = Resource_SwapPercent;
 2459                         resourceset.operator = $<number>2;
 2460                         resourceset.limit = $<real>3;
 2461                   }
 2462                 ;
 2463 
 2464 resourcethreads : THREADS operator NUMBER {
 2465                         resourceset.resource_id = Resource_Threads;
 2466                         resourceset.operator = $<number>2;
 2467                         resourceset.limit = $<number>3;
 2468                   }
 2469                 ;
 2470 
 2471 resourcechild   : CHILDREN operator NUMBER {
 2472                         resourceset.resource_id = Resource_Children;
 2473                         resourceset.operator = $<number>2;
 2474                         resourceset.limit = $<number>3;
 2475                   }
 2476                 ;
 2477 
 2478 resourceload    : resourceloadavg coremultiplier operator value {
 2479                         switch ($<number>1) {
 2480                                 case Resource_LoadAverage1m:
 2481                                         resourceset.resource_id = $<number>2 > 1 ? Resource_LoadAveragePerCore1m : $<number>1;
 2482                                         break;
 2483                                 case Resource_LoadAverage5m:
 2484                                         resourceset.resource_id = $<number>2 > 1 ? Resource_LoadAveragePerCore5m : $<number>1;
 2485                                         break;
 2486                                 case Resource_LoadAverage15m:
 2487                                         resourceset.resource_id = $<number>2 > 1 ? Resource_LoadAveragePerCore15m : $<number>1;
 2488                                         break;
 2489                                 default:
 2490                                         resourceset.resource_id = $<number>1;
 2491                                         break;
 2492                         }
 2493                         resourceset.operator = $<number>3;
 2494                         resourceset.limit = $<real>4;
 2495                   }
 2496                 ;
 2497 
 2498 resourceloadavg : LOADAVG1  { $<number>$ = Resource_LoadAverage1m; }
 2499                 | LOADAVG5  { $<number>$ = Resource_LoadAverage5m; }
 2500                 | LOADAVG15 { $<number>$ = Resource_LoadAverage15m; }
 2501                 ;
 2502 
 2503 coremultiplier  : /* EMPTY */ { $<number>$ = 1; }
 2504                 | CORE        { $<number>$ = systeminfo.cpu.count; }
 2505                 ;
 2506 
 2507 
 2508 resourceread    : READ operator value unit currenttime {
 2509                         resourceset.resource_id = Resource_ReadBytes;
 2510                         resourceset.operator = $<number>2;
 2511                         resourceset.limit = $<real>3 * $<number>4;
 2512                   }
 2513                 | DISK READ operator value unit currenttime {
 2514                         resourceset.resource_id = Resource_ReadBytesPhysical;
 2515                         resourceset.operator = $<number>3;
 2516                         resourceset.limit = $<real>4 * $<number>5;
 2517                   }
 2518                 | DISK READ operator NUMBER OPERATION {
 2519                         resourceset.resource_id = Resource_ReadOperations;
 2520                         resourceset.operator = $<number>3;
 2521                         resourceset.limit = $<number>4;
 2522                   }
 2523                 ;
 2524 
 2525 resourcewrite   : WRITE operator value unit currenttime {
 2526                         resourceset.resource_id = Resource_WriteBytes;
 2527                         resourceset.operator = $<number>2;
 2528                         resourceset.limit = $<real>3 * $<number>4;
 2529                   }
 2530                 | DISK WRITE operator value unit currenttime {
 2531                         resourceset.resource_id = Resource_WriteBytesPhysical;
 2532                         resourceset.operator = $<number>3;
 2533                         resourceset.limit = $<real>4 * $<number>5;
 2534                   }
 2535                 | DISK WRITE operator NUMBER OPERATION {
 2536                         resourceset.resource_id = Resource_WriteOperations;
 2537                         resourceset.operator = $<number>3;
 2538                         resourceset.limit = $<number>4;
 2539                   }
 2540                 ;
 2541 
 2542 value           : REAL { $<real>$ = $1; }
 2543                 | NUMBER { $<real>$ = (float) $1; }
 2544                 ;
 2545 
 2546 timestamptype   : TIME  { $<number>$ = Timestamp_Default; }
 2547                 | ATIME { $<number>$ = Timestamp_Access; }
 2548                 | CTIME { $<number>$ = Timestamp_Change; }
 2549                 | MTIME { $<number>$ = Timestamp_Modification; }
 2550                 ;
 2551 
 2552 timestamp       : IF timestamptype operator NUMBER time rate1 THEN action1 recovery_success {
 2553                         timestampset.type = $<number>2;
 2554                         timestampset.operator = $<number>3;
 2555                         timestampset.time = ($4 * $<number>5);
 2556                         addeventaction(&(timestampset).action, $<number>8, $<number>9);
 2557                         addtimestamp(&timestampset);
 2558                   }
 2559                 | IF CHANGED timestamptype rate1 THEN action1 {
 2560                         timestampset.type = $<number>3;
 2561                         timestampset.test_changes = true;
 2562                         addeventaction(&(timestampset).action, $<number>6, Action_Ignored);
 2563                         addtimestamp(&timestampset);
 2564                   }
 2565                 ;
 2566 
 2567 operator        : /* EMPTY */    { $<number>$ = Operator_Equal; }
 2568                 | GREATER        { $<number>$ = Operator_Greater; }
 2569                 | GREATEROREQUAL { $<number>$ = Operator_GreaterOrEqual; }
 2570                 | LESS           { $<number>$ = Operator_Less; }
 2571                 | LESSOREQUAL    { $<number>$ = Operator_LessOrEqual; }
 2572                 | EQUAL          { $<number>$ = Operator_Equal; }
 2573                 | NOTEQUAL       { $<number>$ = Operator_NotEqual; }
 2574                 | CHANGED        { $<number>$ = Operator_Changed; }
 2575                 ;
 2576 
 2577 time            : /* EMPTY */ { $<number>$ = Time_Second; }
 2578                 | SECOND      { $<number>$ = Time_Second; }
 2579                 | MINUTE      { $<number>$ = Time_Minute; }
 2580                 | HOUR        { $<number>$ = Time_Hour; }
 2581                 | DAY         { $<number>$ = Time_Day; }
 2582                 | MONTH       { $<number>$ = Time_Month; }
 2583                 ;
 2584 
 2585 totaltime       : MINUTE      { $<number>$ = Time_Minute; }
 2586                 | HOUR        { $<number>$ = Time_Hour; }
 2587                 | DAY         { $<number>$ = Time_Day; }
 2588 
 2589 currenttime     : /* EMPTY */ { $<number>$ = Time_Second; }
 2590                 | SECOND      { $<number>$ = Time_Second; }
 2591 
 2592 repeat          : /* EMPTY */ {
 2593                         repeat = 0;
 2594                   }
 2595                 | REPEAT EVERY CYCLE {
 2596                         repeat = 1;
 2597                   }
 2598                 | REPEAT EVERY NUMBER CYCLE {
 2599                         if ($<number>3 < 0) {
 2600                                 yyerror2("The number of repeat cycles must be greater or equal to 0");
 2601                         }
 2602                         repeat = $<number>3;
 2603                   }
 2604                 ;
 2605 
 2606 action          : ALERT {
 2607                         $<number>$ = Action_Alert;
 2608                   }
 2609                 | EXEC argumentlist repeat {
 2610                         $<number>$ = Action_Exec;
 2611                   }
 2612                 | EXEC argumentlist useroptionlist repeat
 2613                   {
 2614                         $<number>$ = Action_Exec;
 2615                   }
 2616                 | RESTART {
 2617                         $<number>$ = Action_Restart;
 2618                   }
 2619                 | START {
 2620                         $<number>$ = Action_Start;
 2621                   }
 2622                 | STOP {
 2623                         $<number>$ = Action_Stop;
 2624                   }
 2625                 | UNMONITOR {
 2626                         $<number>$ = Action_Unmonitor;
 2627                   }
 2628                 ;
 2629 
 2630 action1         : action {
 2631                         $<number>$ = $<number>1;
 2632                         if ($<number>1 == Action_Exec && command) {
 2633                                 repeat1 = repeat;
 2634                                 repeat = 0;
 2635                                 command1 = command;
 2636                                 command = NULL;
 2637                         }
 2638                   }
 2639                 ;
 2640 
 2641 action2         : action {
 2642                         $<number>$ = $<number>1;
 2643                         if ($<number>1 == Action_Exec && command) {
 2644                                 repeat2 = repeat;
 2645                                 repeat = 0;
 2646                                 command2 = command;
 2647                                 command = NULL;
 2648                         }
 2649                   }
 2650                 ;
 2651 
 2652 rateXcycles     : NUMBER CYCLE {
 2653                         if ($<number>1 < 1 || (unsigned long)$<number>1 > BITMAP_MAX) {
 2654                                 yyerror2("The number of cycles must be between 1 and %zu", BITMAP_MAX);
 2655                         } else {
 2656                                 rate.count  = $<number>1;
 2657                                 rate.cycles = $<number>1;
 2658                         }
 2659                   }
 2660                 ;
 2661 
 2662 rateXYcycles    : NUMBER NUMBER CYCLE {
 2663                         if ($<number>2 < 1 || (unsigned long)$<number>2 > BITMAP_MAX) {
 2664                                 yyerror2("The number of cycles must be between 1 and %zu", BITMAP_MAX);
 2665                         } else if ($<number>1 < 1 || $<number>1 > $<number>2) {
 2666                                 yyerror2("The number of events must be between 1 and less then poll cycles");
 2667                         } else {
 2668                                 rate.count  = $<number>1;
 2669                                 rate.cycles = $<number>2;
 2670                         }
 2671                   }
 2672                 ;
 2673 
 2674 rate1           : /* EMPTY */
 2675                 | rateXcycles {
 2676                         rate1.count = rate.count;
 2677                         rate1.cycles = rate.cycles;
 2678                         reset_rateset(&rate);
 2679                   }
 2680                 | rateXYcycles {
 2681                         rate1.count = rate.count;
 2682                         rate1.cycles = rate.cycles;
 2683                         reset_rateset(&rate);
 2684                 }
 2685                 ;
 2686 
 2687 rate2           : /* EMPTY */
 2688                 | rateXcycles {
 2689                         rate2.count = rate.count;
 2690                         rate2.cycles = rate.cycles;
 2691                         reset_rateset(&rate);
 2692                   }
 2693                 | rateXYcycles {
 2694                         rate2.count = rate.count;
 2695                         rate2.cycles = rate.cycles;
 2696                         reset_rateset(&rate);
 2697                 }
 2698                 ;
 2699 
 2700 recovery_success : /* EMPTY */ {
 2701                         $<number>$ = Action_Alert;
 2702                   }
 2703                 | ELSE action2 {
 2704                         $<number>$ = $<number>2;
 2705                   }
 2706                 | ELSE IF RECOVERED rate2 THEN action2 {
 2707                         $<number>$ = $<number>6;
 2708                   }
 2709                 | ELSE IF PASSED rate2 THEN action2 {
 2710                         $<number>$ = $<number>6;
 2711                   }
 2712                 | ELSE IF SUCCEEDED rate2 THEN action2 {
 2713                         $<number>$ = $<number>6;
 2714                   }
 2715                 ;
 2716 
 2717 recovery_failure : /* EMPTY */ {
 2718                         $<number>$ = Action_Alert;
 2719                   }
 2720                 | ELSE action2 {
 2721                         $<number>$ = $<number>2;
 2722                   }
 2723                 | ELSE IF FAILED rate2 THEN action2 {
 2724                         $<number>$ = $<number>6;
 2725                   }
 2726                 ;
 2727 
 2728 checksum        : IF FAILED hashtype CHECKSUM rate1 THEN action1 recovery_success {
 2729                         addeventaction(&(checksumset).action, $<number>7, $<number>8);
 2730                         addchecksum(&checksumset);
 2731                   }
 2732                 | IF FAILED hashtype CHECKSUM EXPECT STRING rate1 THEN action1
 2733                   recovery_success {
 2734                         snprintf(checksumset.hash, sizeof(checksumset.hash), "%s", $6);
 2735                         FREE($6);
 2736                         addeventaction(&(checksumset).action, $<number>9, $<number>10);
 2737                         addchecksum(&checksumset);
 2738                   }
 2739                 | IF CHANGED hashtype CHECKSUM rate1 THEN action1 {
 2740                         checksumset.test_changes = true;
 2741                         addeventaction(&(checksumset).action, $<number>7, Action_Ignored);
 2742                         addchecksum(&checksumset);
 2743                   }
 2744                 ;
 2745 hashtype        : /* EMPTY */ { checksumset.type = Hash_Unknown; }
 2746                 | MD5HASH     { checksumset.type = Hash_Md5; }
 2747                 | SHA1HASH    { checksumset.type = Hash_Sha1; }
 2748                 ;
 2749 
 2750 inode           : IF INODE operator NUMBER rate1 THEN action1 recovery_success {
 2751                         filesystemset.resource = Resource_Inode;
 2752                         filesystemset.operator = $<number>3;
 2753                         filesystemset.limit_absolute = $4;
 2754                         addeventaction(&(filesystemset).action, $<number>7, $<number>8);
 2755                         addfilesystem(&filesystemset);
 2756                   }
 2757                 | IF INODE operator value PERCENT rate1 THEN action1 recovery_success {
 2758                         filesystemset.resource = Resource_Inode;
 2759                         filesystemset.operator = $<number>3;
 2760                         filesystemset.limit_percent = $<real>4;
 2761                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2762                         addfilesystem(&filesystemset);
 2763                   }
 2764                 | IF INODE TFREE operator NUMBER rate1 THEN action1 recovery_success {
 2765                         filesystemset.resource = Resource_InodeFree;
 2766                         filesystemset.operator = $<number>4;
 2767                         filesystemset.limit_absolute = $5;
 2768                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2769                         addfilesystem(&filesystemset);
 2770                   }
 2771                 | IF INODE TFREE operator value PERCENT rate1 THEN action1 recovery_success {
 2772                         filesystemset.resource = Resource_InodeFree;
 2773                         filesystemset.operator = $<number>4;
 2774                         filesystemset.limit_percent = $<real>5;
 2775                         addeventaction(&(filesystemset).action, $<number>9, $<number>10);
 2776                         addfilesystem(&filesystemset);
 2777                   }
 2778                 ;
 2779 
 2780 space           : IF SPACE operator value unit rate1 THEN action1 recovery_success {
 2781                         filesystemset.resource = Resource_Space;
 2782                         filesystemset.operator = $<number>3;
 2783                         filesystemset.limit_absolute = $<real>4 * $<number>5;
 2784                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2785                         addfilesystem(&filesystemset);
 2786                   }
 2787                 | IF SPACE operator value PERCENT rate1 THEN action1 recovery_success {
 2788                         filesystemset.resource = Resource_Space;
 2789                         filesystemset.operator = $<number>3;
 2790                         filesystemset.limit_percent = $<real>4;
 2791                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2792                         addfilesystem(&filesystemset);
 2793                   }
 2794                 | IF SPACE TFREE operator value unit rate1 THEN action1 recovery_success {
 2795                         filesystemset.resource = Resource_SpaceFree;
 2796                         filesystemset.operator = $<number>4;
 2797                         filesystemset.limit_absolute = $<real>5 * $<number>6;
 2798                         addeventaction(&(filesystemset).action, $<number>9, $<number>10);
 2799                         addfilesystem(&filesystemset);
 2800                   }
 2801                 | IF SPACE TFREE operator value PERCENT rate1 THEN action1 recovery_success {
 2802                         filesystemset.resource = Resource_SpaceFree;
 2803                         filesystemset.operator = $<number>4;
 2804                         filesystemset.limit_percent = $<real>5;
 2805                         addeventaction(&(filesystemset).action, $<number>9, $<number>10);
 2806                         addfilesystem(&filesystemset);
 2807                   }
 2808                 ;
 2809 
 2810 read            : IF READ operator value unit currenttime rate1 THEN action1 recovery_success {
 2811                         filesystemset.resource = Resource_ReadBytes;
 2812                         filesystemset.operator = $<number>3;
 2813                         filesystemset.limit_absolute = $<real>4 * $<number>5;
 2814                         addeventaction(&(filesystemset).action, $<number>9, $<number>10);
 2815                         addfilesystem(&filesystemset);
 2816                   }
 2817                 | IF READ operator NUMBER OPERATION rate1 THEN action1 recovery_success {
 2818                         filesystemset.resource = Resource_ReadOperations;
 2819                         filesystemset.operator = $<number>3;
 2820                         filesystemset.limit_absolute = $<number>4;
 2821                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2822                         addfilesystem(&filesystemset);
 2823                   }
 2824                 ;
 2825 
 2826 write           : IF WRITE operator value unit currenttime rate1 THEN action1 recovery_success {
 2827                         filesystemset.resource = Resource_WriteBytes;
 2828                         filesystemset.operator = $<number>3;
 2829                         filesystemset.limit_absolute = $<real>4 * $<number>5;
 2830                         addeventaction(&(filesystemset).action, $<number>9, $<number>10);
 2831                         addfilesystem(&filesystemset);
 2832                   }
 2833                 | IF WRITE operator NUMBER OPERATION rate1 THEN action1 recovery_success {
 2834                         filesystemset.resource = Resource_WriteOperations;
 2835                         filesystemset.operator = $<number>3;
 2836                         filesystemset.limit_absolute = $<number>4;
 2837                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2838                         addfilesystem(&filesystemset);
 2839                   }
 2840                 ;
 2841 
 2842 servicetime     : IF SERVICETIME operator NUMBER MILLISECOND rate1 THEN action1 recovery_success {
 2843                         filesystemset.resource = Resource_ServiceTime;
 2844                         filesystemset.operator = $<number>3;
 2845                         filesystemset.limit_absolute = $<number>4;
 2846                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2847                         addfilesystem(&filesystemset);
 2848                   }
 2849                 | IF SERVICETIME operator value SECOND rate1 THEN action1 recovery_success {
 2850                         filesystemset.resource = Resource_ServiceTime;
 2851                         filesystemset.operator = $<number>3;
 2852                         filesystemset.limit_absolute = $<real>4 * 1000;
 2853                         addeventaction(&(filesystemset).action, $<number>8, $<number>9);
 2854                         addfilesystem(&filesystemset);
 2855                   }
 2856                 ;
 2857 
 2858 fsflag          : IF CHANGED FSFLAG rate1 THEN action1 {
 2859                         addeventaction(&(fsflagset).action, $<number>6, Action_Ignored);
 2860                         addfsflag(&fsflagset);
 2861                   }
 2862                 ;
 2863 
 2864 unit            : /* empty */  { $<number>$ = Unit_Byte; }
 2865                 | BYTE         { $<number>$ = Unit_Byte; }
 2866                 | KILOBYTE     { $<number>$ = Unit_Kilobyte; }
 2867                 | MEGABYTE     { $<number>$ = Unit_Megabyte; }
 2868                 | GIGABYTE     { $<number>$ = Unit_Gigabyte; }
 2869                 ;
 2870 
 2871 permission      : IF FAILED PERMISSION NUMBER rate1 THEN action1 recovery_success {
 2872                         permset.perm = check_perm($4);
 2873                         addeventaction(&(permset).action, $<number>7, $<number>8);
 2874                         addperm(&permset);
 2875                   }
 2876                 | IF CHANGED PERMISSION rate1 THEN action1 recovery_success {
 2877                         permset.test_changes = true;
 2878                         addeventaction(&(permset).action, $<number>6, Action_Ignored);
 2879                         addperm(&permset);
 2880                   }
 2881                 ;
 2882 
 2883 match           : IF CONTENT urloperator PATH rate1 THEN action1 {
 2884                         matchset.not = $<number>3 == Operator_Equal ? false : true;
 2885                         matchset.ignore = false;
 2886                         matchset.match_path = $4;
 2887                         matchset.match_string = NULL;
 2888                         addmatchpath(&matchset, $<number>7);
 2889                         FREE($4);
 2890                   }
 2891                 | IF CONTENT urloperator STRING rate1 THEN action1 {
 2892                         matchset.not = $<number>3 == Operator_Equal ? false : true;
 2893                         matchset.ignore = false;
 2894                         matchset.match_path = NULL;
 2895                         matchset.match_string = $4;
 2896                         addmatch(&matchset, $<number>7, 0);
 2897                   }
 2898                 | IGNORE CONTENT urloperator PATH {
 2899                         matchset.not = $<number>3 == Operator_Equal ? false : true;
 2900                         matchset.ignore = true;
 2901                         matchset.match_path = $4;
 2902                         matchset.match_string = NULL;
 2903                         addmatchpath(&matchset, Action_Ignored);
 2904                         FREE($4);
 2905                   }
 2906                 | IGNORE CONTENT urloperator STRING {
 2907                         matchset.not = $<number>3 == Operator_Equal ? false : true;
 2908                         matchset.ignore = true;
 2909                         matchset.match_path = NULL;
 2910                         matchset.match_string = $4;
 2911                         addmatch(&matchset, Action_Ignored, 0);
 2912                   }
 2913                 /* The below MATCH statement is deprecated (replaced by CONTENT) */
 2914                 | IF matchflagnot MATCH PATH rate1 THEN action1 {
 2915                         matchset.ignore = false;
 2916                         matchset.match_path = $4;
 2917                         matchset.match_string = NULL;
 2918                         addmatchpath(&matchset, $<number>7);
 2919                         FREE($4);
 2920                   }
 2921                 | IF matchflagnot MATCH STRING rate1 THEN action1 {
 2922                         matchset.ignore = false;
 2923                         matchset.match_path = NULL;
 2924                         matchset.match_string = $4;
 2925                         addmatch(&matchset, $<number>7, 0);
 2926                   }
 2927                 | IGNORE matchflagnot MATCH PATH {
 2928                         matchset.ignore = true;
 2929                         matchset.match_path = $4;
 2930                         matchset.match_string = NULL;
 2931                         addmatchpath(&matchset, Action_Ignored);
 2932                         FREE($4);
 2933                   }
 2934                 | IGNORE matchflagnot MATCH STRING {
 2935                         matchset.ignore = true;
 2936                         matchset.match_path = NULL;
 2937                         matchset.match_string = $4;
 2938                         addmatch(&matchset, Action_Ignored, 0);
 2939                   }
 2940                 ;
 2941 
 2942 matchflagnot    : /* EMPTY */ {
 2943                         matchset.not = false;
 2944                   }
 2945                 | NOT {
 2946                         matchset.not = true;
 2947                   }
 2948                 ;
 2949 
 2950 
 2951 size            : IF SIZE operator NUMBER unit rate1 THEN action1 recovery_success {
 2952                         sizeset.operator = $<number>3;
 2953                         sizeset.size = ((unsigned long long)$4 * $<number>5);
 2954                         addeventaction(&(sizeset).action, $<number>8, $<number>9);
 2955                         addsize(&sizeset);
 2956                   }
 2957                 | IF CHANGED SIZE rate1 THEN action1 {
 2958                         sizeset.test_changes = true;
 2959                         addeventaction(&(sizeset).action, $<number>6, Action_Ignored);
 2960                         addsize(&sizeset);
 2961                   }
 2962                 ;
 2963 
 2964 uid             : IF FAILED UID STRING rate1 THEN action1 recovery_success {
 2965                         uidset.uid = get_uid($4, 0);
 2966                         addeventaction(&(uidset).action, $<number>7, $<number>8);
 2967                         current->uid = adduid(&uidset);
 2968                         FREE($4);
 2969                   }
 2970                 | IF FAILED UID NUMBER rate1 THEN action1 recovery_success {
 2971                     uidset.uid = get_uid(NULL, $4);
 2972                     addeventaction(&(uidset).action, $<number>7, $<number>8);
 2973                     current->uid = adduid(&uidset);
 2974                   }
 2975                 ;
 2976 
 2977 euid            : IF FAILED EUID STRING rate1 THEN action1 recovery_success {
 2978                         uidset.uid = get_uid($4, 0);
 2979                         addeventaction(&(uidset).action, $<number>7, $<number>8);
 2980                         current->euid = adduid(&uidset);
 2981                         FREE($4);
 2982                   }
 2983                 | IF FAILED EUID NUMBER rate1 THEN action1 recovery_success {
 2984                         uidset.uid = get_uid(NULL, $4);
 2985                         addeventaction(&(uidset).action, $<number>7, $<number>8);
 2986                         current->euid = adduid(&uidset);
 2987                   }
 2988                 ;
 2989 
 2990 secattr         : IF FAILED SECURITY ATTRIBUTE STRING rate1 THEN action1 recovery_success {
 2991                         addsecurityattribute($5, $<number>8, $<number>9);
 2992                   }
 2993                 | IF FAILED SECURITY ATTRIBUTE PATH rate1 THEN action1 recovery_success {
 2994                         addsecurityattribute($5, $<number>8, $<number>9);
 2995                   }
 2996                 ;
 2997 
 2998 filedescriptorssystem : IF FILEDESCRIPTORS operator NUMBER rate1 THEN action1 recovery_success {
 2999                         if (systeminfo.statisticsAvailable & Statistics_FiledescriptorsPerSystem)
 3000                                 addfiledescriptors($<number>3, false, (long long)$4, -1., $<number>7, $<number>8);
 3001                         else
 3002                                 yywarning("The per-system filedescriptors statistics is not available on this system\n");
 3003                   }
 3004                 | IF FILEDESCRIPTORS operator value PERCENT rate1 THEN action1 recovery_success {
 3005                         if (systeminfo.statisticsAvailable & Statistics_FiledescriptorsPerSystem)
 3006                                 addfiledescriptors($<number>3, false, -1LL, $<real>4, $<number>8, $<number>9);
 3007                         else
 3008                                 yywarning("The per-system filedescriptors statistics is not available on this system\n");
 3009                   }
 3010                 ;
 3011 
 3012 filedescriptorsprocess : IF FILEDESCRIPTORS operator NUMBER rate1 THEN action1 recovery_success {
 3013                         if (systeminfo.statisticsAvailable & Statistics_FiledescriptorsPerProcess)
 3014                                 addfiledescriptors($<number>3, false, (long long)$4, -1., $<number>7, $<number>8);
 3015                         else
 3016                                 yywarning("The per-process filedescriptors statistics is not available on this system\n");
 3017                   }
 3018                 | IF FILEDESCRIPTORS operator value PERCENT rate1 THEN action1 recovery_success {
 3019                         if (systeminfo.statisticsAvailable & Statistics_FiledescriptorsPerProcessMax)
 3020                                 addfiledescriptors($<number>3, false, -1LL, $<real>4, $<number>8, $<number>9);
 3021                         else
 3022                                 yywarning("The per-process filedescriptors maximum is not exposed on this system, so we cannot compute usage %%, please use the test with absolute value\n");
 3023                   }
 3024                 ;
 3025 
 3026 filedescriptorsprocesstotal : IF TOTAL FILEDESCRIPTORS operator NUMBER rate1 THEN action1 recovery_success {
 3027                         if (systeminfo.statisticsAvailable & Statistics_FiledescriptorsPerProcess)
 3028                                 addfiledescriptors($<number>4, true, (long long)$5, -1., $<number>8, $<number>9);
 3029                         else
 3030                                 yywarning("The per-process filedescriptors statistics is not available on this system\n");
 3031                   }
 3032                 ;
 3033 
 3034 gid             : IF FAILED GID STRING rate1 THEN action1 recovery_success {
 3035                         gidset.gid = get_gid($4, 0);
 3036                         addeventaction(&(gidset).action, $<number>7, $<number>8);
 3037                         current->gid = addgid(&gidset);
 3038                         FREE($4);
 3039                   }
 3040                 | IF FAILED GID NUMBER rate1 THEN action1 recovery_success {
 3041                         gidset.gid = get_gid(NULL, $4);
 3042                         addeventaction(&(gidset).action, $<number>7, $<number>8);
 3043                         current->gid = addgid(&gidset);
 3044                   }
 3045                 ;
 3046 
 3047 linkstatus   : IF FAILED LINK rate1 THEN action1 recovery_success { /* Deprecated */
 3048                         addeventaction(&(linkstatusset).action, $<number>6, $<number>7);
 3049                         addlinkstatus(current, &linkstatusset);
 3050                   }
 3051              | IF LINK DOWN rate1 THEN action1 recovery_failure {
 3052                         linkstatusset.check_invers = false;
 3053                         addeventaction(&(linkstatusset).action, $<number>6, $<number>7);
 3054                         addlinkstatus(current, &linkstatusset);
 3055                   }
 3056              | IF LINK UP rate1 THEN action1 recovery_success {
 3057                         linkstatusset.check_invers = true;
 3058                         addeventaction(&(linkstatusset).action, $<number>6, $<number>7);
 3059                         addlinkstatus(current, &linkstatusset);
 3060                   }
 3061                 ;
 3062 
 3063 linkspeed    : IF CHANGED LINK rate1 THEN action1 recovery_success {
 3064                         addeventaction(&(linkspeedset).action, $<number>6, $<number>7);
 3065                         addlinkspeed(current, &linkspeedset);
 3066                   }
 3067 
 3068 linksaturation : IF SATURATION operator NUMBER PERCENT rate1 THEN action1 recovery_success {
 3069                         linksaturationset.operator = $<number>3;
 3070                         linksaturationset.limit = (unsigned long long)$4;
 3071                         addeventaction(&(linksaturationset).action, $<number>8, $<number>9);
 3072                         addlinksaturation(current, &linksaturationset);
 3073                   }
 3074                 ;
 3075 
 3076 upload          : IF UPLOAD operator NUMBER unit currenttime rate1 THEN action1 recovery_success {
 3077                         bandwidthset.operator = $<number>3;
 3078                         bandwidthset.limit = ((unsigned long long)$4 * $<number>5);
 3079                         bandwidthset.rangecount = 1;
 3080                         bandwidthset.range = $<number>6;
 3081                         addeventaction(&(bandwidthset).action, $<number>9, $<number>10);
 3082                         addbandwidth(&(current->uploadbyteslist), &bandwidthset);
 3083                   }
 3084                 | IF TOTAL UPLOAD operator NUMBER unit totaltime rate1 THEN action1 recovery_success {
 3085                         bandwidthset.operator = $<number>4;
 3086                         bandwidthset.limit = ((unsigned long long)$5 * $<number>6);
 3087                         bandwidthset.rangecount = 1;
 3088                         bandwidthset.range = $<number>7;
 3089                         addeventaction(&(bandwidthset).action, $<number>10, $<number>11);
 3090                         addbandwidth(&(current->uploadbyteslist), &bandwidthset);
 3091                   }
 3092                 | IF TOTAL UPLOAD operator NUMBER unit NUMBER totaltime rate1 THEN action1 recovery_success {
 3093                         bandwidthset.operator = $<number>4;
 3094                         bandwidthset.limit = ((unsigned long long)$5 * $<number>6);
 3095                         bandwidthset.rangecount = $7;
 3096                         bandwidthset.range = $<number>8;
 3097                         addeventaction(&(bandwidthset).action, $<number>11, $<number>12);
 3098                         addbandwidth(&(current->uploadbyteslist), &bandwidthset);
 3099                   }
 3100                 | IF UPLOAD operator NUMBER PACKET currenttime rate1 THEN action1 recovery_success {
 3101                         bandwidthset.operator = $<number>3;
 3102                         bandwidthset.limit = (unsigned long long)$4;
 3103                         bandwidthset.rangecount = 1;
 3104                         bandwidthset.range = $<number>6;
 3105                         addeventaction(&(bandwidthset).action, $<number>9, $<number>10);
 3106                         addbandwidth(&(current->uploadpacketslist), &bandwidthset);
 3107                   }
 3108                 | IF TOTAL UPLOAD operator NUMBER PACKET totaltime rate1 THEN action1 recovery_success {
 3109                         bandwidthset.operator = $<number>4;
 3110                         bandwidthset.limit = (unsigned long long)$5;
 3111                         bandwidthset.rangecount = 1;
 3112                         bandwidthset.range = $<number>7;
 3113                         addeventaction(&(bandwidthset).action, $<number>10, $<number>11);
 3114                         addbandwidth(&(current->uploadpacketslist), &bandwidthset);
 3115                   }
 3116                 | IF TOTAL UPLOAD operator NUMBER PACKET NUMBER totaltime rate1 THEN action1 recovery_success {
 3117                         bandwidthset.operator = $<number>4;
 3118                         bandwidthset.limit = (unsigned long long)$5;
 3119                         bandwidthset.rangecount = $7;
 3120                         bandwidthset.range = $<number>8;
 3121                         addeventaction(&(bandwidthset).action, $<number>11, $<number>12);
 3122                         addbandwidth(&(current->uploadpacketslist), &bandwidthset);
 3123                   }
 3124                 ;
 3125 
 3126 download        : IF DOWNLOAD operator NUMBER unit currenttime rate1 THEN action1 recovery_success {
 3127                         bandwidthset.operator = $<number>3;
 3128                         bandwidthset.limit = ((unsigned long long)$4 * $<number>5);
 3129                         bandwidthset.rangecount = 1;
 3130                         bandwidthset.range = $<number>6;
 3131                         addeventaction(&(bandwidthset).action, $<number>9, $<number>10);
 3132                         addbandwidth(&(current->downloadbyteslist), &bandwidthset);
 3133                   }
 3134                 | IF TOTAL DOWNLOAD operator NUMBER unit totaltime rate1 THEN action1 recovery_success {
 3135                         bandwidthset.operator = $<number>4;
 3136                         bandwidthset.limit = ((unsigned long long)$5 * $<number>6);
 3137                         bandwidthset.rangecount = 1;
 3138                         bandwidthset.range = $<number>7;
 3139                         addeventaction(&(bandwidthset).action, $<number>10, $<number>11);
 3140                         addbandwidth(&(current->downloadbyteslist), &bandwidthset);
 3141                   }
 3142                 | IF TOTAL DOWNLOAD operator NUMBER unit NUMBER totaltime rate1 THEN action1 recovery_success {
 3143                         bandwidthset.operator = $<number>4;
 3144                         bandwidthset.limit = ((unsigned long long)$5 * $<number>6);
 3145                         bandwidthset.rangecount = $7;
 3146                         bandwidthset.range = $<number>8;
 3147                         addeventaction(&(bandwidthset).action, $<number>11, $<number>12);
 3148                         addbandwidth(&(current->downloadbyteslist), &bandwidthset);
 3149                   }
 3150                 | IF DOWNLOAD operator NUMBER PACKET currenttime rate1 THEN action1 recovery_success {
 3151                         bandwidthset.operator = $<number>3;
 3152                         bandwidthset.limit = (unsigned long long)$4;
 3153                         bandwidthset.rangecount = 1;
 3154                         bandwidthset.range = $<number>6;
 3155                         addeventaction(&(bandwidthset).action, $<number>9, $<number>10);
 3156                         addbandwidth(&(current->downloadpacketslist), &bandwidthset);
 3157                   }
 3158                 | IF TOTAL DOWNLOAD operator NUMBER PACKET totaltime rate1 THEN action1 recovery_success {
 3159                         bandwidthset.operator = $<number>4;
 3160                         bandwidthset.limit = (unsigned long long)$5;
 3161                         bandwidthset.rangecount = 1;
 3162                         bandwidthset.range = $<number>7;
 3163                         addeventaction(&(bandwidthset).action, $<number>10, $<number>11);
 3164                         addbandwidth(&(current->downloadpacketslist), &bandwidthset);
 3165                   }
 3166                 | IF TOTAL DOWNLOAD operator NUMBER PACKET NUMBER totaltime rate1 THEN action1 recovery_success {
 3167                         bandwidthset.operator = $<number>4;
 3168                         bandwidthset.limit = (unsigned long long)$5;
 3169                         bandwidthset.rangecount = $7;
 3170                         bandwidthset.range = $<number>8;
 3171                         addeventaction(&(bandwidthset).action, $<number>11, $<number>12);
 3172                         addbandwidth(&(current->downloadpacketslist), &bandwidthset);
 3173                   }
 3174                 ;
 3175 
 3176 icmptype        : TYPE ICMPECHO { $<number>$ = ICMP_ECHO; }
 3177                 ;
 3178 
 3179 reminder        : /* EMPTY */           { mailset.reminder = 0; }
 3180                 | REMINDER NUMBER       { mailset.reminder = $<number>2; }
 3181                 | REMINDER NUMBER CYCLE { mailset.reminder = $<number>2; }
 3182                 ;
 3183 
 3184 %%
 3185 
 3186 
 3187 /* -------------------------------------------------------- Parser interface */
 3188 
 3189 
 3190 /**
 3191  * Syntactic error routine
 3192  *
 3193  * This routine is automatically called by the lexer!
 3194  */
 3195 void yyerror(const char *s, ...) {
 3196         ASSERT(s);
 3197         char *msg = NULL;
 3198         va_list ap;
 3199         va_start(ap, s);
 3200         msg = Str_vcat(s, ap);
 3201         va_end(ap);
 3202         Log_error("%s:%i: %s '%s'\n", currentfile, lineno, msg, yytext);
 3203         cfg_errflag++;
 3204         FREE(msg);
 3205 }
 3206 
 3207 
 3208 /**
 3209  * Syntactical warning routine
 3210  */
 3211 void yywarning(const char *s, ...) {
 3212         ASSERT(s);
 3213         char *msg = NULL;
 3214         va_list ap;
 3215         va_start(ap, s);
 3216         msg = Str_vcat(s, ap);
 3217         va_end(ap);
 3218         Log_warning("%s:%i: %s '%s'\n", currentfile, lineno, msg, yytext);
 3219         FREE(msg);
 3220 }
 3221 
 3222 
 3223 /**
 3224  * Argument error routine
 3225  */
 3226 void yyerror2(const char *s, ...) {
 3227         ASSERT(s);
 3228         char *msg = NULL;
 3229         va_list ap;
 3230         va_start(ap, s);
 3231         msg = Str_vcat(s, ap);
 3232         va_end(ap);
 3233         Log_error("%s:%i: %s '%s'\n", argcurrentfile, arglineno, msg, argyytext);
 3234         cfg_errflag++;
 3235         FREE(msg);
 3236 }
 3237 
 3238 
 3239 /**
 3240  * Argument warning routine
 3241  */
 3242 void yywarning2(const char *s, ...) {
 3243         ASSERT(s);
 3244         char *msg = NULL;
 3245         va_list ap;
 3246         va_start(ap, s);
 3247         msg = Str_vcat(s, ap);
 3248         va_end(ap);
 3249         Log_warning("%s:%i: %s '%s'\n", argcurrentfile, arglineno, msg, argyytext);
 3250         FREE(msg);
 3251 }
 3252 
 3253 
 3254 /*
 3255  * The Parser hook - start parsing the control file
 3256  * Returns true if parsing succeeded, otherwise false
 3257  */
 3258 bool parse(char *controlfile) {
 3259         ASSERT(controlfile);
 3260 
 3261         if ((yyin = fopen(controlfile,"r")) == (FILE *)NULL) {
 3262                 Log_error("Cannot open the control file '%s' -- %s\n", controlfile, STRERROR);
 3263                 return false;
 3264         }
 3265 
 3266         currentfile = Str_dup(controlfile);
 3267 
 3268         available_statistics(&systeminfo);
 3269 
 3270         /*
 3271          * Creation of the global service list is synchronized
 3272          */
 3273         LOCK(Run.mutex)
 3274         {
 3275                 preparse();
 3276                 yyparse();
 3277                 fclose(yyin);
 3278                 postparse();
 3279         }
 3280         END_LOCK;
 3281 
 3282         FREE(currentfile);
 3283 
 3284         if (argyytext != NULL)
 3285                 FREE(argyytext);
 3286 
 3287         /*
 3288          * Secure check the monitrc file. The run control file must have the
 3289          * same uid as the REAL uid of this process, it must have permissions
 3290          * no greater than 700 and it must not be a symbolic link.
 3291          */
 3292         if (! file_checkStat(controlfile, "control file", S_IRUSR|S_IWUSR|S_IXUSR))
 3293                 return false;
 3294 
 3295         return cfg_errflag == 0;
 3296 }
 3297 
 3298 
 3299 /* ----------------------------------------------------------------- Private */
 3300 
 3301 
 3302 /**
 3303  * Initialize objects used by the parser.
 3304  */
 3305 static void preparse() {
 3306         servicelist = tail = current = NULL;
 3307         /* Set instance incarnation ID */
 3308         time(&Run.incarnation);
 3309         /* Reset lexer */
 3310         buffer_stack_ptr            = 0;
 3311         lineno                      = 1;
 3312         arglineno                   = 1;
 3313         argcurrentfile              = NULL;
 3314         argyytext                   = NULL;
 3315         /* Reset parser */
 3316         Run.limits.sendExpectBuffer  = LIMIT_SENDEXPECTBUFFER;
 3317         Run.limits.fileContentBuffer = LIMIT_FILECONTENTBUFFER;
 3318         Run.limits.httpContentBuffer = LIMIT_HTTPCONTENTBUFFER;
 3319         Run.limits.programOutput     = LIMIT_PROGRAMOUTPUT;
 3320         Run.limits.networkTimeout    = LIMIT_NETWORKTIMEOUT;
 3321         Run.limits.programTimeout    = LIMIT_PROGRAMTIMEOUT;
 3322         Run.limits.stopTimeout       = LIMIT_STOPTIMEOUT;
 3323         Run.limits.startTimeout      = LIMIT_STARTTIMEOUT;
 3324         Run.limits.restartTimeout    = LIMIT_RESTARTTIMEOUT;
 3325         Run.onreboot                 = Onreboot_Start;
 3326         Run.mmonitcredentials        = NULL;
 3327         Run.httpd.flags              = Httpd_Disabled | Httpd_Signature;
 3328         Run.httpd.credentials        = NULL;
 3329         memset(&(Run.httpd.socket), 0, sizeof(Run.httpd.socket));
 3330         Run.mailserver_timeout       = SMTP_TIMEOUT;
 3331         Run.eventlist_dir            = NULL;
 3332         Run.eventlist_slots          = -1;
 3333         Run.system                   = NULL;
 3334         Run.mmonits                  = NULL;
 3335         Run.maillist                 = NULL;
 3336         Run.mailservers              = NULL;
 3337         Run.MailFormat.from          = NULL;
 3338         Run.MailFormat.replyto       = NULL;
 3339         Run.MailFormat.subject       = NULL;
 3340         Run.MailFormat.message       = NULL;
 3341         depend_list                  = NULL;
 3342         Run.flags |= Run_HandlerInit | Run_MmonitCredentials;
 3343         for (int i = 0; i <= Handler_Max; i++)
 3344                 Run.handler_queue[i] = 0;
 3345 
 3346         /*
 3347          * Initialize objects
 3348          */
 3349         reset_uidset();
 3350         reset_gidset();
 3351         reset_statusset();
 3352         reset_sizeset();
 3353         reset_mailset();
 3354         reset_sslset();
 3355         reset_mailserverset();
 3356         reset_mmonitset();
 3357         reset_responsetimeset();
 3358         reset_portset();
 3359         reset_permset();
 3360         reset_icmpset();
 3361         reset_linkstatusset();
 3362         reset_linkspeedset();
 3363         reset_linksaturationset();
 3364         reset_bandwidthset();
 3365         reset_rateset(&rate);
 3366         reset_rateset(&rate1);
 3367         reset_rateset(&rate2);
 3368         reset_filesystemset();
 3369         reset_resourceset();
 3370         reset_checksumset();
 3371         reset_timestampset();
 3372         reset_actionrateset();
 3373 }
 3374 
 3375 
 3376 /*
 3377  * Check that values are reasonable after parsing
 3378  */
 3379 static void postparse() {
 3380         if (cfg_errflag)
 3381                 return;
 3382 
 3383         /* If defined - add the last service to the service list */
 3384         if (current) {
 3385                 addservice(current);
 3386                 current = NULL;
 3387         }
 3388 
 3389         /* Check that we do not start monit in daemon mode without having a poll time */
 3390         if (! Run.polltime && ((Run.flags & Run_Daemon) || (Run.flags & Run_Foreground))) {
 3391                 Log_error("Poll time is invalid or not defined. Please define poll time in the control file\nas a number (> 0)  or use the -d option when starting monit\n");
 3392                 cfg_errflag++;
 3393         }
 3394 
 3395         if (Run.files.log)
 3396                 Run.flags |= Run_Log;
 3397 
 3398         /* Add the default general system service if not specified explicitly: service name default to hostname */
 3399         if (! Run.system) {
 3400                 char hostname[STRLEN];
 3401                 if (gethostname(hostname, sizeof(hostname))) {
 3402                         Log_error("Cannot get system hostname -- please add 'check system <name>'\n");
 3403                         cfg_errflag++;
 3404                 }
 3405                 if (Util_existService(hostname)) {
 3406                         Log_error("'check system' not defined in control file, failed to add automatic configuration (service name %s is used already) -- please add 'check system <name>' manually\n", hostname);
 3407                         cfg_errflag++;
 3408                 }
 3409                 Run.system = createservice(Service_System, Str_dup(hostname), NULL, check_system);
 3410                 addservice(Run.system);
 3411         }
 3412         addeventaction(&(Run.system->action_MONIT_START), Action_Start, Action_Ignored);
 3413         addeventaction(&(Run.system->action_MONIT_STOP), Action_Stop,  Action_Ignored);
 3414 
 3415         if (Run.mmonits) {
 3416                 if (Run.httpd.flags & Httpd_Net) {
 3417                         if (Run.flags & Run_MmonitCredentials) {
 3418                                 Auth_T c;
 3419                                 for (c = Run.httpd.credentials; c; c = c->next) {
 3420                                         if (c->digesttype == Digest_Cleartext && ! c->is_readonly) {
 3421                                                 Run.mmonitcredentials = c;
 3422                                                 break;
 3423                                         }
 3424                                 }
 3425                                 if (! Run.mmonitcredentials)
 3426                                         Log_warning("M/Monit registration with credentials enabled, but no suitable credentials found in monit configuration file -- please add 'allow user:password' option to 'set httpd' statement\n");
 3427                         }
 3428                 } else if (Run.httpd.flags & Httpd_Unix) {
 3429                         Log_warning("M/Monit enabled but Monit httpd is using unix socket -- please change 'set httpd' statement to use TCP port in order to be able to manage services on Monit\n");
 3430                 } else {
 3431                         Log_warning("M/Monit enabled but no httpd allowed -- please add 'set httpd' statement\n");
 3432                 }
 3433         }
 3434 
 3435         /* Check the sanity of any dependency graph */
 3436         check_depend();
 3437 
 3438 #if defined HAVE_OPENSSL && defined OPENSSL_FIPS
 3439         Ssl_setFipsMode(Run.flags & Run_FipsEnabled);
 3440 #endif
 3441 
 3442         Processor_setHttpPostLimit();
 3443 }
 3444 
 3445 
 3446 static bool _parseOutgoingAddress(const char *ip, Outgoing_T *outgoing) {
 3447         struct addrinfo *result, hints = {.ai_flags = AI_NUMERICHOST};
 3448         int status = getaddrinfo(ip, NULL, &hints, &result);
 3449         if (status == 0) {
 3450                 outgoing->ip = (char *)ip;
 3451                 outgoing->addrlen = result->ai_addrlen;
 3452                 memcpy(&(outgoing->addr), result->ai_addr, result->ai_addrlen);
 3453                 freeaddrinfo(result);
 3454                 return true;
 3455         } else {
 3456                 yyerror2("IP address parsing failed for %s -- %s", ip, status == EAI_SYSTEM ? STRERROR : gai_strerror(status));
 3457         }
 3458         return false;
 3459 }
 3460 
 3461 
 3462 /*
 3463  * Create a new service object and add any current objects to the
 3464  * service list.
 3465  */
 3466 static Service_T createservice(Service_Type type, char *name, char *value, State_Type (*check)(Service_T s)) {
 3467         ASSERT(name);
 3468 
 3469         check_name(name);
 3470 
 3471         if (current)
 3472                 addservice(current);
 3473 
 3474         NEW(current);
 3475         current->type = type;
 3476         switch (type) {
 3477                 case Service_Directory:
 3478                         NEW(current->inf.directory);
 3479                         break;
 3480                 case Service_Fifo:
 3481                         NEW(current->inf.fifo);
 3482                         break;
 3483                 case Service_File:
 3484                         NEW(current->inf.file);
 3485                         break;
 3486                 case Service_Filesystem:
 3487                         NEW(current->inf.filesystem);
 3488                         break;
 3489                 case Service_Net:
 3490                         NEW(current->inf.net);
 3491                         break;
 3492                 case Service_Process:
 3493                         NEW(current->inf.process);
 3494                         break;
 3495                 default:
 3496                         break;
 3497         }
 3498         Util_resetInfo(current);
 3499 
 3500         if (type == Service_Program) {
 3501                 NEW(current->program);
 3502                 current->program->args = command;
 3503                 command = NULL;
 3504                 current->program->timeout = Run.limits.programTimeout;
 3505         }
 3506 
 3507         /* Set default values */
 3508         current->onrebootRestored = false;
 3509         current->mode     = Monitor_Active;
 3510         current->monitor  = Monitor_Init;
 3511         current->onreboot = Run.onreboot;
 3512         current->name     = name;
 3513         current->name_urlescaped = Util_urlEncode(name, false);
 3514         current->name_htmlescaped = escapeHTML(StringBuffer_create(16), name);
 3515         current->check    = check;
 3516         current->path     = value;
 3517 
 3518         /* Initialize general event handlers */
 3519         addeventaction(&(current)->action_DATA,     Action_Alert,     Action_Alert);
 3520         addeventaction(&(current)->action_EXEC,     Action_Alert,     Action_Alert);
 3521         addeventaction(&(current)->action_INVALID,  Action_Restart,   Action_Alert);
 3522 
 3523         /* Initialize internal event handlers */
 3524         addeventaction(&(current)->action_ACTION,       Action_Alert, Action_Ignored);
 3525 
 3526         gettimeofday(&current->collected, NULL);
 3527 
 3528         return current;
 3529 }
 3530 
 3531 
 3532 /*
 3533  * Add a service object to the servicelist
 3534  */
 3535 static void addservice(Service_T s) {
 3536         ASSERT(s);
 3537 
 3538         // Test sanity check
 3539         switch (s->type) {
 3540                 case Service_Host:
 3541                         // Verify that a remote service has a port or an icmp list
 3542                         if (! s->portlist && ! s->icmplist) {
 3543                                 Log_error("'check host' statement is incomplete: Please specify a port number to test\n or an icmp test at the remote host: '%s'\n", s->name);
 3544                                 cfg_errflag++;
 3545                         }
 3546                         break;
 3547                 case Service_Program:
 3548                         // Verify that a program test has a status test
 3549                         if (! s->statuslist) {
 3550                                 Log_error("'check program %s' is incomplete: Please add an 'if status != n' test\n", s->name);
 3551                                 cfg_errflag++;
 3552                         }
 3553                         char program[PATH_MAX];
 3554                         strncpy(program, s->program->args->arg[0], sizeof(program) - 1);
 3555                         // Require that the program exist before creating the Command object
 3556                         if (File_isExecutable(program)) {
 3557                                 s->program->C = Command_new(program, NULL);
 3558                                 for (int i = 1; i < s->program->args->length; i++) {
 3559                                         Command_appendArgument(s->program->C, s->program->args->arg[i]);
 3560                                         snprintf(program + strlen(program), sizeof(program) - strlen(program) - 1, " %s", s->program->args->arg[i]);
 3561                                 }
 3562                                 s->path = Str_dup(program);
 3563                                 if (s->program->args->has_uid)
 3564                                         Command_setUid(s->program->C, s->program->args->uid);
 3565                                 if (s->program->args->has_gid)
 3566                                         Command_setGid(s->program->C, s->program->args->gid);
 3567                                 // Set environment
 3568                                 Command_setEnv(s->program->C, "MONIT_SERVICE", s->name);
 3569                         } else {
 3570                                 Log_error("A 'check program' statement requires the program to exist '%s'\n", program);
 3571                                 cfg_errflag++;
 3572                         }
 3573                         break;
 3574                 case Service_Net:
 3575                         if (! s->linkstatuslist) {
 3576                                 // Add link status test if not defined
 3577                                 addeventaction(&(linkstatusset).action, Action_Alert, Action_Alert);
 3578                                 addlinkstatus(s, &linkstatusset);
 3579                         }
 3580                         break;
 3581                 case Service_Filesystem:
 3582                         if (! s->nonexistlist && ! s->existlist) {
 3583                                 // Add non-existence test if not defined
 3584                                 addeventaction(&(nonexistset).action, Action_Restart, Action_Alert);
 3585                                 addnonexist(&nonexistset);
 3586                         }
 3587                         if (! s->fsflaglist) {
 3588                                 // Add filesystem flags change test if not defined
 3589                                 addeventaction(&(fsflagset).action, Action_Alert, Action_Ignored);
 3590                                 addfsflag(&fsflagset);
 3591                         }
 3592                         break;
 3593                 case Service_Directory:
 3594                 case Service_Fifo:
 3595                 case Service_File:
 3596                 case Service_Process:
 3597                         if (! s->nonexistlist && ! s->existlist) {
 3598                                 // Add existence test if not defined
 3599                                 addeventaction(&(nonexistset).action, Action_Restart, Action_Alert);
 3600                                 addnonexist(&nonexistset);
 3601                         }
 3602                         break;
 3603                 default:
 3604                         break;
 3605         }
 3606 
 3607         /* Add the service to the end of the service list */
 3608         if (tail != NULL) {
 3609                 tail->next = s;
 3610                 tail->next_conf = s;
 3611         } else {
 3612                 servicelist = s;
 3613                 servicelist_conf = s;
 3614         }
 3615         tail = s;
 3616 }
 3617 
 3618 
 3619 /*
 3620  * Add entry to service group list
 3621  */
 3622 static void addservicegroup(char *name) {
 3623         ServiceGroup_T g;
 3624 
 3625         ASSERT(name);
 3626 
 3627         /* Check if service group with the same name is defined already */
 3628         for (g = servicegrouplist; g; g = g->next)
 3629                 if (IS(g->name, name))
 3630                         break;
 3631 
 3632         if (! g) {
 3633                 NEW(g);
 3634                 g->name = Str_dup(name);
 3635                 g->members = List_new();
 3636                 g->next = servicegrouplist;
 3637                 servicegrouplist = g;
 3638         }
 3639 
 3640         List_append(g->members, current);
 3641 }
 3642 
 3643 
 3644 /*
 3645  * Add a dependant entry to the current service dependant list
 3646  */
 3647 static void adddependant(char *dependant) {
 3648         Dependant_T d;
 3649 
 3650         ASSERT(dependant);
 3651 
 3652         NEW(d);
 3653 
 3654         if (current->dependantlist)
 3655                 d->next = current->dependantlist;
 3656 
 3657         d->dependant = dependant;
 3658         d->dependant_urlescaped = Util_urlEncode(dependant, false);
 3659         d->dependant_htmlescaped = escapeHTML(StringBuffer_create(16), dependant);
 3660         current->dependantlist = d;
 3661 
 3662 }
 3663 
 3664 
 3665 /*
 3666  * Add the given mailaddress with the appropriate alert notification
 3667  * values and mail attributes to the given mailinglist.
 3668  */
 3669 static void addmail(char *mailto, Mail_T f, Mail_T *l) {
 3670         Mail_T m;
 3671 
 3672         ASSERT(mailto);
 3673 
 3674         NEW(m);
 3675         m->to       = mailto;
 3676         m->from     = f->from;
 3677         m->replyto  = f->replyto;
 3678         m->subject  = f->subject;
 3679         m->message  = f->message;
 3680         m->events   = f->events;
 3681         m->reminder = f->reminder;
 3682 
 3683         m->next = *l;
 3684         *l = m;
 3685 
 3686         reset_mailset();
 3687 }
 3688 
 3689 
 3690 /*
 3691  * Add the given portset to the current service's portlist
 3692  */
 3693 static void addport(Port_T *list, Port_T port) {
 3694         ASSERT(port);
 3695 
 3696         if (port->protocol->check == check_radius && port->type != Socket_Udp)
 3697                 yyerror("Radius protocol test supports UDP only");
 3698 
 3699         Port_T p;
 3700         NEW(p);
 3701         p->is_available       = Connection_Init;
 3702         p->check_invers       = port->check_invers;
 3703         p->type               = port->type;
 3704         p->socket             = port->socket;
 3705         p->family             = port->family;
 3706         p->action             = port->action;
 3707         p->timeout            = port->timeout;
 3708         p->retry              = port->retry;
 3709         p->protocol           = port->protocol;
 3710         p->hostname           = port->hostname;
 3711         p->url_request        = port->url_request;
 3712         p->outgoing           = port->outgoing;
 3713 
 3714         if (p->family == Socket_Unix) {
 3715                 p->target.unix.pathname = port->target.unix.pathname;
 3716         } else {
 3717                 p->target.net.port = port->target.net.port;
 3718                 if (sslset.flags) {
 3719 #ifdef HAVE_OPENSSL
 3720                         p->target.net.ssl.certificate.minimumDays = port->target.net.ssl.certificate.minimumDays;
 3721                         if (sslset.flags && (p->target.net.port == 25 || p->target.net.port == 143 || p->target.net.port == 587))
 3722                                 sslset.flags = SSL_StartTLS;
 3723                         _setSSLOptions(&(p->target.net.ssl.options));
 3724 #else
 3725                         yyerror("SSL check cannot be activated -- Monit was not built with SSL support");
 3726 #endif
 3727                 }
 3728         }
 3729         memcpy(&p->parameters, &port->parameters, sizeof(port->parameters));
 3730 
 3731         if (p->protocol->check == check_http) {
 3732                 if (p->parameters.http.checksum) {
 3733                         cleanup_hash_string(p->parameters.http.checksum);
 3734                         if (strlen(p->parameters.http.checksum) == 32)
 3735                                 p->parameters.http.hashtype = Hash_Md5;
 3736                         else if (strlen(p->parameters.http.checksum) == 40)
 3737                                 p->parameters.http.hashtype = Hash_Sha1;
 3738                         else
 3739                                 yyerror2("invalid checksum [%s]", p->parameters.http.checksum);
 3740                 } else {
 3741                         p->parameters.http.hashtype = Hash_Unknown;
 3742                 }
 3743                 if (! p->parameters.http.method) {
 3744                         p->parameters.http.method = Http_Get;
 3745                 } else if (p->parameters.http.method == Http_Head) {
 3746                         // Sanity check: if content or checksum test is used, the method Http_Head is not allowed, as we need the content
 3747                         if ((p->url_request && p->url_request->regex) || p->parameters.http.checksum) {
 3748                                 yyerror2("if response content or checksum test is enabled, the HEAD method is not allowed");
 3749                         }
 3750                 }
 3751         } else if (p->protocol->check == check_mysql) {
 3752                 if (p->parameters.mysql.rsaChecksum) {
 3753                         if (! p->parameters.mysql.username)
 3754                                 yyerror2("the rsakey checksum test requires credentials to be defined");
 3755                         if (p->target.net.ssl.options.flags != SSL_Disabled)
 3756                                 yyerror2("the rsakey checksum test can be used just with unsecured mysql protocol");
 3757                 }
 3758         }
 3759 
 3760         p->responsetime.limit    = responsetimeset.limit;
 3761         p->responsetime.current  = responsetimeset.current;
 3762         p->responsetime.operator = responsetimeset.operator;
 3763 
 3764         p->next = *list;
 3765         *list = p;
 3766 
 3767         reset_sslset();
 3768         reset_responsetimeset();
 3769         reset_portset();
 3770 
 3771 }
 3772 
 3773 
 3774 static void addhttpheader(Port_T port, const char *header) {
 3775         if (! port->parameters.http.headers) {
 3776                 port->parameters.http.headers = List_new();
 3777         }
 3778         if (Str_startsWith(header, "Connection:") && ! Str_sub(header, "close")) {
 3779                 yywarning("We don't recommend setting the Connection header. Monit will always close the connection even if 'keep-alive' is set\n");
 3780         }
 3781         List_append(port->parameters.http.headers, (char *)header);
 3782 }
 3783 
 3784 
 3785 /*
 3786  * Add a new resource object to the current service resource list
 3787  */
 3788 static void addresource(Resource_T rr) {
 3789         ASSERT(rr);
 3790         if (Run.flags & Run_ProcessEngineEnabled) {
 3791                 Resource_T r;
 3792                 NEW(r);
 3793                 r->resource_id = rr->resource_id;
 3794                 r->limit       = rr->limit;
 3795                 r->action      = rr->action;
 3796                 r->operator    = rr->operator;
 3797                 r->next        = current->resourcelist;
 3798                 current->resourcelist = r;
 3799         } else {
 3800                 yywarning("Cannot activate service check. The process status engine was disabled. On certain systems you must run monit as root to utilize this feature)\n");
 3801         }
 3802         reset_resourceset();
 3803 }
 3804 
 3805 
 3806 /*
 3807  * Add a new file object to the current service timestamp list
 3808  */
 3809 static void addtimestamp(Timestamp_T ts) {
 3810         ASSERT(ts);
 3811 
 3812         Timestamp_T t;
 3813         NEW(t);
 3814         t->type         = ts->type;
 3815         t->operator     = ts->operator;
 3816         t->time         = ts->time;
 3817         t->action       = ts->action;
 3818         t->test_changes = ts->test_changes;
 3819 
 3820         t->next = current->timestamplist;
 3821         current->timestamplist = t;
 3822 
 3823         reset_timestampset();
 3824 }
 3825 
 3826 
 3827 /*
 3828  * Add a new object to the current service actionrate list
 3829  */
 3830 static void addactionrate(ActionRate_T ar) {
 3831         ActionRate_T a;
 3832 
 3833         ASSERT(ar);
 3834 
 3835         if (ar->count > ar->cycle)
 3836                 yyerror2("The number of restarts must be less than poll cycles");
 3837         if (ar->count <= 0 || ar->cycle <= 0)
 3838                 yyerror2("Zero or negative values not allowed in a action rate statement");
 3839 
 3840         NEW(a);
 3841         a->count  = ar->count;
 3842         a->cycle  = ar->cycle;
 3843         a->action = ar->action;
 3844 
 3845         a->next = current->actionratelist;
 3846         current->actionratelist = a;
 3847 
 3848         reset_actionrateset();
 3849 }
 3850 
 3851 
 3852 
 3853 /*
 3854  * Add a new Size object to the current service size list
 3855  */
 3856 static void addsize(Size_T ss) {
 3857         Size_T s;
 3858         struct stat buf;
 3859 
 3860         ASSERT(ss);
 3861 
 3862         NEW(s);
 3863         s->operator     = ss->operator;
 3864         s->size         = ss->size;
 3865         s->action       = ss->action;
 3866         s->test_changes = ss->test_changes;
 3867         /* Get the initial size for future comparison, if the file exists */
 3868         if (s->test_changes) {
 3869                 s->initialized = ! stat(current->path, &buf);
 3870                 if (s->initialized)
 3871                         s->size = (unsigned long long)buf.st_size;
 3872         }
 3873 
 3874         s->next = current->sizelist;
 3875         current->sizelist = s;
 3876 
 3877         reset_sizeset();
 3878 }
 3879 
 3880 
 3881 /*
 3882  * Add a new Uptime object to the current service uptime list
 3883  */
 3884 static void adduptime(Uptime_T uu) {
 3885         Uptime_T u;
 3886 
 3887         ASSERT(uu);
 3888 
 3889         NEW(u);
 3890         u->operator = uu->operator;
 3891         u->uptime = uu->uptime;
 3892         u->action = uu->action;
 3893 
 3894         u->next = current->uptimelist;
 3895         current->uptimelist = u;
 3896 
 3897         reset_uptimeset();
 3898 }
 3899 
 3900 
 3901 /*
 3902  * Add a new Pid object to the current service pid list
 3903  */
 3904 static void addpid(Pid_T pp) {
 3905         ASSERT(pp);
 3906 
 3907         Pid_T p;
 3908         NEW(p);
 3909         p->action = pp->action;
 3910 
 3911         p->next = current->pidlist;
 3912         current->pidlist = p;
 3913 
 3914         reset_pidset();
 3915 }
 3916 
 3917 
 3918 /*
 3919  * Add a new PPid object to the current service ppid list
 3920  */
 3921 static void addppid(Pid_T pp) {
 3922         ASSERT(pp);
 3923 
 3924         Pid_T p;
 3925         NEW(p);
 3926         p->action = pp->action;
 3927 
 3928         p->next = current->ppidlist;
 3929         current->ppidlist = p;
 3930 
 3931         reset_ppidset();
 3932 }
 3933 
 3934 
 3935 /*
 3936  * Add a new Fsflag object to the current service fsflag list
 3937  */
 3938 static void addfsflag(FsFlag_T ff) {
 3939         ASSERT(ff);
 3940 
 3941         FsFlag_T f;
 3942         NEW(f);
 3943         f->action = ff->action;
 3944 
 3945         f->next = current->fsflaglist;
 3946         current->fsflaglist = f;
 3947 
 3948         reset_fsflagset();
 3949 }
 3950 
 3951 
 3952 /*
 3953  * Add a new Nonexist object to the current service list
 3954  */
 3955 static void addnonexist(NonExist_T ff) {
 3956         ASSERT(ff);
 3957 
 3958         NonExist_T f;
 3959         NEW(f);
 3960         f->action = ff->action;
 3961 
 3962         f->next = current->nonexistlist;
 3963         current->nonexistlist = f;
 3964 
 3965         reset_nonexistset();
 3966 }
 3967 
 3968 
 3969 static void addexist(Exist_T rule) {
 3970         ASSERT(rule);
 3971         Exist_T r;
 3972         NEW(r);
 3973         r->action = rule->action;
 3974         r->next = current->existlist;
 3975         current->existlist = r;
 3976         reset_existset();
 3977 }
 3978 
 3979 
 3980 /*
 3981  * Set Checksum object in the current service
 3982  */
 3983 static void addchecksum(Checksum_T cs) {
 3984         ASSERT(cs);
 3985 
 3986         cs->initialized = true;
 3987 
 3988         if (STR_UNDEF(cs->hash)) {
 3989                 if (cs->type == Hash_Unknown)
 3990                         cs->type = Hash_Default;
 3991                 if (! (Checksum_getChecksum(current->path, cs->type, cs->hash, sizeof(cs->hash)))) {
 3992                         /* If the file doesn't exist, set dummy value */
 3993                         snprintf(cs->hash, sizeof(cs->hash), cs->type == Hash_Md5 ? "00000000000000000000000000000000" : "0000000000000000000000000000000000000000");
 3994                         cs->initialized = false;
 3995                         yywarning2("Cannot compute a checksum for file %s", current->path);
 3996                 }
 3997         }
 3998 
 3999         int len = cleanup_hash_string(cs->hash);
 4000         if (cs->type == Hash_Unknown) {
 4001                 if (len == 32) {
 4002                         cs->type = Hash_Md5;
 4003                 } else if (len == 40) {
 4004                         cs->type = Hash_Sha1;
 4005                 } else {
 4006                         yyerror2("Unknown checksum type [%s] for file %s", cs->hash, current->path);
 4007                         reset_checksumset();
 4008                         return;
 4009                 }
 4010         } else if ((cs->type == Hash_Md5 && len != 32) || (cs->type == Hash_Sha1 && len != 40)) {
 4011                 yyerror2("Invalid checksum [%s] for file %s", cs->hash, current->path);
 4012                 reset_checksumset();
 4013                 return;
 4014         }
 4015 
 4016         Checksum_T c;
 4017         NEW(c);
 4018         c->type         = cs->type;
 4019         c->test_changes = cs->test_changes;
 4020         c->initialized  = cs->initialized;
 4021         c->action       = cs->action;
 4022         snprintf(c->hash, sizeof(c->hash), "%s", cs->hash);
 4023 
 4024         current->checksum = c;
 4025 
 4026         reset_checksumset();
 4027 
 4028 }
 4029 
 4030 
 4031 /*
 4032  * Set Perm object in the current service
 4033  */
 4034 static void addperm(Perm_T ps) {
 4035         ASSERT(ps);
 4036 
 4037         Perm_T p;
 4038         NEW(p);
 4039         p->action = ps->action;
 4040         p->test_changes = ps->test_changes;
 4041         if (p->test_changes) {
 4042                 if (! File_exist(current->path))
 4043                         DEBUG("The path '%s' used in the PERMISSION statement refer to a non-existing object\n", current->path);
 4044                 else if ((p->perm = File_mod(current->path)) < 0)
 4045                         yyerror2("Cannot get the timestamp for '%s'", current->path);
 4046                 else
 4047                         p->perm &= 07777;
 4048         } else {
 4049                 p->perm = ps->perm;
 4050         }
 4051         current->perm = p;
 4052         reset_permset();
 4053 }
 4054 
 4055 
 4056 static void addlinkstatus(Service_T s, LinkStatus_T L) {
 4057         ASSERT(L);
 4058 
 4059         LinkStatus_T l;
 4060 
 4061         // Sanity check: we don't support link up/down tests mix
 4062         for (l = s->linkstatuslist; l; l = l->next) {
 4063                 if (l->check_invers != L->check_invers)
 4064                         yyerror2("Mixing link up and down tests is not supported");
 4065         }
 4066                         
 4067         if (L->check_invers)
 4068                 s->inverseStatus = true;
 4069 
 4070         NEW(l);
 4071         l->check_invers = L->check_invers;
 4072         l->action = L->action;
 4073 
 4074         l->next = s->linkstatuslist;
 4075         s->linkstatuslist = l;
 4076 
 4077         reset_linkstatusset();
 4078 }
 4079 
 4080 
 4081 static void addlinkspeed(Service_T s, LinkSpeed_T L) {
 4082         ASSERT(L);
 4083 
 4084         LinkSpeed_T l;
 4085         NEW(l);
 4086         l->action = L->action;
 4087 
 4088         l->next = s->linkspeedlist;
 4089         s->linkspeedlist = l;
 4090 
 4091         reset_linkspeedset();
 4092 }
 4093 
 4094 
 4095 static void addlinksaturation(Service_T s, LinkSaturation_T L) {
 4096         ASSERT(L);
 4097 
 4098         LinkSaturation_T l;
 4099         NEW(l);
 4100         l->operator = L->operator;
 4101         l->limit = L->limit;
 4102         l->action = L->action;
 4103 
 4104         l->next = s->linksaturationlist;
 4105         s->linksaturationlist = l;
 4106 
 4107         reset_linksaturationset();
 4108 }
 4109 
 4110 
 4111 /*
 4112  * Return Bandwidth object
 4113  */
 4114 static void addbandwidth(Bandwidth_T *list, Bandwidth_T b) {
 4115         ASSERT(list);
 4116         ASSERT(b);
 4117 
 4118         if (b->rangecount * b->range > 24 * Time_Hour) {
 4119                 yyerror2("Maximum range for total test is 24 hours");
 4120         } else if (b->range == Time_Minute && b->rangecount > 60) {
 4121                 yyerror2("Maximum value for [minute(s)] unit is 60");
 4122         } else if (b->range == Time_Hour && b->rangecount > 24) {
 4123                 yyerror2("Maximum value for [hour(s)] unit is 24");
 4124         } else if (b->range == Time_Day && b->rangecount > 1) {
 4125                 yyerror2("Maximum value for [day(s)] unit is 1");
 4126         } else {
 4127                 if (b->range == Time_Day) {
 4128                         // translate last day -> last 24 hours
 4129                         b->rangecount = 24;
 4130                         b->range = Time_Hour;
 4131                 }
 4132                 Bandwidth_T bandwidth;
 4133                 NEW(bandwidth);
 4134                 bandwidth->operator = b->operator;
 4135                 bandwidth->limit = b->limit;
 4136                 bandwidth->rangecount = b->rangecount;
 4137                 bandwidth->range = b->range;
 4138                 bandwidth->action = b->action;
 4139                 bandwidth->next = *list;
 4140                 *list = bandwidth;
 4141         }
 4142         reset_bandwidthset();
 4143 }
 4144 
 4145 
 4146 static void appendmatch(Match_T *list, Match_T item) {
 4147         if (*list) {
 4148                 /* Find the end of the list (keep the same patterns order as in the config file) */
 4149                 Match_T last;
 4150                 for (last = *list; last->next; last = last->next)
 4151                         ;
 4152                 last->next = item;
 4153         } else {
 4154                 *list = item;
 4155         }
 4156 }
 4157 
 4158 
 4159 /*
 4160  * Set Match object in the current service
 4161  */
 4162 static void addmatch(Match_T ms, int actionnumber, int linenumber) {
 4163         Match_T m;
 4164 
 4165         ASSERT(ms);
 4166 
 4167         NEW(m);
 4168         NEW(m->regex_comp);
 4169 
 4170         m->match_string = ms->match_string;
 4171         m->match_path   = ms->match_path ? Str_dup(ms->match_path) : NULL;
 4172         m->action       = ms->action;
 4173         m->not          = ms->not;
 4174         m->ignore       = ms->ignore;
 4175         m->next         = NULL;
 4176 
 4177         addeventaction(&(m->action), actionnumber, Action_Ignored);
 4178 
 4179         int reg_return = regcomp(m->regex_comp, ms->match_string, REG_NOSUB|REG_EXTENDED);
 4180 
 4181         if (reg_return != 0) {
 4182                 char errbuf[STRLEN];
 4183                 regerror(reg_return, ms->regex_comp, errbuf, STRLEN);
 4184                 if (m->match_path != NULL)
 4185                         yyerror2("Regex parsing error: %s on line %i of", errbuf, linenumber);
 4186                 else
 4187                         yyerror2("Regex parsing error: %s", errbuf);
 4188         }
 4189         appendmatch(m->ignore ? &current->matchignorelist : &current->matchlist, m);
 4190 }
 4191 
 4192 
 4193 static void addmatchpath(Match_T ms, Action_Type actionnumber) {
 4194         ASSERT(ms->match_path);
 4195 
 4196         FILE *handle = fopen(ms->match_path, "r");
 4197         if (handle == NULL) {
 4198                 yyerror2("Cannot read regex match file (%s)", ms->match_path);
 4199                 return;
 4200         }
 4201 
 4202         // The addeventaction() called from addmatch() will reset the command1 to NULL, but we need to duplicate the command for each line, thus need to save it here
 4203         command_t savecommand = command1;
 4204         for (int linenumber = 1; ! feof(handle); linenumber++) {
 4205                 char buf[2048];
 4206 
 4207                 if (! fgets(buf, sizeof(buf), handle))
 4208                         continue;
 4209 
 4210                 size_t len = strlen(buf);
 4211 
 4212                 if (len == 0 || buf[0] == '\n')
 4213                         continue;
 4214 
 4215                 if (buf[len - 1] == '\n')
 4216                         buf[len - 1] = 0;
 4217 
 4218                 ms->match_string = Str_dup(buf);
 4219 
 4220                 if (actionnumber == Action_Exec) {
 4221                         if (command1 == NULL) {
 4222                                 ASSERT(savecommand);
 4223                                 command1 = copycommand(savecommand);
 4224                         }
 4225                 }
 4226 
 4227                 addmatch(ms, actionnumber, linenumber);
 4228         }
 4229         if (actionnumber == Action_Exec && savecommand)
 4230                 gccmd(&savecommand);
 4231 
 4232         fclose(handle);
 4233 }
 4234 
 4235 
 4236 /*
 4237  * Set exit status test object in the current service
 4238  */
 4239 static void addstatus(Status_T status) {
 4240         Status_T s;
 4241         ASSERT(status);
 4242         NEW(s);
 4243         s->initialized = status->initialized;
 4244         s->return_value = status->return_value;
 4245         s->operator = status->operator;
 4246         s->action = status->action;
 4247         s->next = current->statuslist;
 4248         current->statuslist = s;
 4249 
 4250         reset_statusset();
 4251 }
 4252 
 4253 
 4254 /*
 4255  * Set Uid object in the current service
 4256  */
 4257 static Uid_T adduid(Uid_T u) {
 4258         ASSERT(u);
 4259 
 4260         Uid_T uid;
 4261         NEW(uid);
 4262         uid->uid = u->uid;
 4263         uid->action = u->action;
 4264         reset_uidset();
 4265         return uid;
 4266 }
 4267 
 4268 
 4269 /*
 4270  * Set Gid object in the current service
 4271  */
 4272 static Gid_T addgid(Gid_T g) {
 4273         ASSERT(g);
 4274 
 4275         Gid_T gid;
 4276         NEW(gid);
 4277         gid->gid = g->gid;
 4278         gid->action = g->action;
 4279         reset_gidset();
 4280         return gid;
 4281 }
 4282 
 4283 
 4284 /*
 4285  * Add a new filesystem to the current service's filesystem list
 4286  */
 4287 static void addfilesystem(FileSystem_T ds) {
 4288         FileSystem_T dev;
 4289 
 4290         ASSERT(ds);
 4291 
 4292         NEW(dev);
 4293         dev->resource           = ds->resource;
 4294         dev->operator           = ds->operator;
 4295         dev->limit_absolute     = ds->limit_absolute;
 4296         dev->limit_percent      = ds->limit_percent;
 4297         dev->action             = ds->action;
 4298 
 4299         dev->next               = current->filesystemlist;
 4300         current->filesystemlist = dev;
 4301 
 4302         reset_filesystemset();
 4303 
 4304 }
 4305 
 4306 
 4307 /*
 4308  * Add a new icmp object to the current service's icmp list
 4309  */
 4310 static void addicmp(Icmp_T is) {
 4311         Icmp_T icmp;
 4312 
 4313         ASSERT(is);
 4314 
 4315         NEW(icmp);
 4316         icmp->family        = is->family;
 4317         icmp->type          = is->type;
 4318         icmp->size          = is->size;
 4319         icmp->count         = is->count;
 4320         icmp->timeout       = is->timeout;
 4321         icmp->action        = is->action;
 4322         icmp->outgoing      = is->outgoing;
 4323         icmp->check_invers  = is->check_invers;
 4324         icmp->is_available  = Connection_Init;
 4325 
 4326         icmp->responsetime.limit    = responsetimeset.limit;
 4327         icmp->responsetime.current  = responsetimeset.current;
 4328         icmp->responsetime.operator = responsetimeset.operator;
 4329 
 4330         icmp->next          = current->icmplist;
 4331         current->icmplist   = icmp;
 4332 
 4333         reset_responsetimeset();
 4334         reset_icmpset();
 4335 }
 4336 
 4337 
 4338 /*
 4339  * Set EventAction object
 4340  */
 4341 static void addeventaction(EventAction_T *_ea, Action_Type failed, Action_Type succeeded) {
 4342         EventAction_T ea;
 4343 
 4344         ASSERT(_ea);
 4345 
 4346         NEW(ea);
 4347         NEW(ea->failed);
 4348         NEW(ea->succeeded);
 4349 
 4350         ea->failed->id = failed;
 4351         ea->failed->repeat = repeat1;
 4352         ea->failed->count = rate1.count;
 4353         ea->failed->cycles = rate1.cycles;
 4354         if (failed == Action_Exec) {
 4355                 ASSERT(command1);
 4356                 ea->failed->exec = command1;
 4357                 command1 = NULL;
 4358         }
 4359 
 4360         ea->succeeded->id = succeeded;
 4361         ea->succeeded->repeat = repeat2;
 4362         ea->succeeded->count = rate2.count;
 4363         ea->succeeded->cycles = rate2.cycles;
 4364         if (succeeded == Action_Exec) {
 4365                 ASSERT(command2);
 4366                 ea->succeeded->exec = command2;
 4367                 command2 = NULL;
 4368         }
 4369         *_ea = ea;
 4370         reset_rateset(&rate);
 4371         reset_rateset(&rate1);
 4372         reset_rateset(&rate2);
 4373         repeat = repeat1 = repeat2 = 0;
 4374 }
 4375 
 4376 
 4377 /*
 4378  * Add a generic protocol handler to
 4379  */
 4380 static void addgeneric(Port_T port, char *send, char *expect) {
 4381         Generic_T g = port->parameters.generic.sendexpect;
 4382         if (! g) {
 4383                 NEW(g);
 4384                 port->parameters.generic.sendexpect = g;
 4385         } else {
 4386                 while (g->next)
 4387                         g = g->next;
 4388                 NEW(g->next);
 4389                 g = g->next;
 4390         }
 4391         if (send) {
 4392                 g->send = send;
 4393                 g->expect = NULL;
 4394         } else if (expect) {
 4395                 int reg_return;
 4396                 NEW(g->expect);
 4397                 reg_return = regcomp(g->expect, expect, REG_NOSUB|REG_EXTENDED);
 4398                 FREE(expect);
 4399                 if (reg_return != 0) {
 4400                         char errbuf[STRLEN];
 4401                         regerror(reg_return, g->expect, errbuf, STRLEN);
 4402                         yyerror2("Regex parsing error: %s", errbuf);
 4403                 }
 4404                 g->send = NULL;
 4405         }
 4406 }
 4407 
 4408 
 4409 /*
 4410  * Add the current command object to the current service object's
 4411  * start or stop program.
 4412  */
 4413 static void addcommand(int what, unsigned int timeout) {
 4414 
 4415         switch (what) {
 4416                 case START:   current->start = command; break;
 4417                 case STOP:    current->stop = command; break;
 4418                 case RESTART: current->restart = command; break;
 4419         }
 4420 
 4421         command->timeout = timeout;
 4422 
 4423         command = NULL;
 4424 
 4425 }
 4426 
 4427 
 4428 /*
 4429  * Add a new argument to the argument list
 4430  */
 4431 static void addargument(char *argument) {
 4432 
 4433         ASSERT(argument);
 4434 
 4435         if (! command) {
 4436                 check_exec(argument);
 4437                 NEW(command);
 4438         }
 4439 
 4440         command->arg[command->length++] = argument;
 4441         command->arg[command->length] = NULL;
 4442 
 4443         if (command->length >= ARGMAX)
 4444                 yyerror("Exceeded maximum number of program arguments");
 4445 
 4446 }
 4447 
 4448 
 4449 /*
 4450  * Setup a url request for the current port object
 4451  */
 4452 static void prepare_urlrequest(URL_T U) {
 4453 
 4454         ASSERT(U);
 4455 
 4456         /* Only the HTTP protocol is supported for URLs currently. See also the lexer if this is to be changed in the future */
 4457         portset.protocol = Protocol_get(Protocol_HTTP);
 4458 
 4459         if (urlrequest == NULL)
 4460                 NEW(urlrequest);
 4461         urlrequest->url = U;
 4462         portset.hostname = Str_dup(U->hostname);
 4463         portset.target.net.port = U->port;
 4464         portset.url_request = urlrequest;
 4465         portset.type = Socket_Tcp;
 4466         portset.parameters.http.request = Str_cat("%s%s%s", U->path, U->query ? "?" : "", U->query ? U->query : "");
 4467         if (IS(U->protocol, "https"))
 4468                 sslset.flags = SSL_Enabled;
 4469 }
 4470 
 4471 
 4472 /*
 4473  * Set the url request for a port
 4474  */
 4475 static void  seturlrequest(int operator, char *regex) {
 4476 
 4477         ASSERT(regex);
 4478 
 4479         if (! urlrequest)
 4480                 NEW(urlrequest);
 4481         urlrequest->operator = operator;
 4482         int reg_return;
 4483         NEW(urlrequest->regex);
 4484         reg_return = regcomp(urlrequest->regex, regex, REG_NOSUB|REG_EXTENDED);
 4485         if (reg_return != 0) {
 4486                 char errbuf[STRLEN];
 4487                 regerror(reg_return, urlrequest->regex, errbuf, STRLEN);
 4488                 yyerror2("Regex parsing error: %s", errbuf);
 4489         }
 4490 }
 4491 
 4492 
 4493 /*
 4494  * Add a new data recipient server to the mmonit server list
 4495  */
 4496 static void addmmonit(Mmonit_T mmonit) {
 4497         ASSERT(mmonit->url);
 4498 
 4499         Mmonit_T c;
 4500         NEW(c);
 4501         c->url = mmonit->url;
 4502         c->compress = MmonitCompress_Init;
 4503         _setSSLOptions(&(c->ssl));
 4504         if (IS(c->url->protocol, "https")) {
 4505 #ifdef HAVE_OPENSSL
 4506                 c->ssl.flags = SSL_Enabled;
 4507 #else
 4508                 yyerror("SSL check cannot be activated -- SSL disabled");
 4509 #endif
 4510         }
 4511         c->timeout = mmonit->timeout;
 4512         c->next = NULL;
 4513 
 4514         if (Run.mmonits) {
 4515                 Mmonit_T C;
 4516                 for (C = Run.mmonits; C->next; C = C->next)
 4517                         /* Empty */ ;
 4518                 C->next = c;
 4519         } else {
 4520                 Run.mmonits = c;
 4521         }
 4522         reset_sslset();
 4523         reset_mmonitset();
 4524 }
 4525 
 4526 
 4527 /*
 4528  * Add a new smtp server to the mail server list
 4529  */
 4530 static void addmailserver(MailServer_T mailserver) {
 4531 
 4532         MailServer_T s;
 4533 
 4534         ASSERT(mailserver->host);
 4535 
 4536         NEW(s);
 4537         s->host        = mailserver->host;
 4538         s->port        = mailserver->port;
 4539         s->username    = mailserver->username;
 4540         s->password    = mailserver->password;
 4541 
 4542         if (sslset.flags && (mailserver->port == 25 || mailserver->port == 587))
 4543                 sslset.flags = SSL_StartTLS;
 4544         _setSSLOptions(&(s->ssl));
 4545 
 4546         s->next = NULL;
 4547 
 4548         if (Run.mailservers) {
 4549                 MailServer_T l;
 4550                 for (l = Run.mailservers; l->next; l = l->next)
 4551                         /* empty */;
 4552                 l->next = s;
 4553         } else {
 4554                 Run.mailservers = s;
 4555         }
 4556         reset_mailserverset();
 4557 }
 4558 
 4559 
 4560 /*
 4561  * Return uid if found on the system. If the parameter user is NULL
 4562  * the uid parameter is used for looking up the user id on the system,
 4563  * otherwise the user parameter is used.
 4564  */
 4565 static uid_t get_uid(char *user, uid_t uid) {
 4566         char buf[4096];
 4567         struct passwd pwd, *result = NULL;
 4568         if (user) {
 4569                 if (getpwnam_r(user, &pwd, buf, sizeof(buf), &result) != 0 || ! result) {
 4570                         yyerror2("Requested user not found on the system");
 4571                         return(0);
 4572                 }
 4573         } else {
 4574                 if (getpwuid_r(uid, &pwd, buf, sizeof(buf), &result) != 0 || ! result) {
 4575                         yyerror2("Requested uid not found on the system");
 4576                         return(0);
 4577                 }
 4578         }
 4579         return(pwd.pw_uid);
 4580 }
 4581 
 4582 
 4583 /*
 4584  * Return gid if found on the system. If the parameter group is NULL
 4585  * the gid parameter is used for looking up the group id on the system,
 4586  * otherwise the group parameter is used.
 4587  */
 4588 static gid_t get_gid(char *group, gid_t gid) {
 4589         struct group *grd;
 4590 
 4591         if (group) {
 4592                 grd = getgrnam(group);
 4593 
 4594                 if (! grd) {
 4595                         yyerror2("Requested group not found on the system");
 4596                         return(0);
 4597                 }
 4598 
 4599         } else {
 4600 
 4601                 if (! (grd = getgrgid(gid))) {
 4602                         yyerror2("Requested gid not found on the system");
 4603                         return(0);
 4604                 }
 4605 
 4606         }
 4607 
 4608         return(grd->gr_gid);
 4609 
 4610 }
 4611 
 4612 
 4613 /*
 4614  * Add a new user id to the current command object.
 4615  */
 4616 static void addeuid(uid_t uid) {
 4617         if (! getuid()) {
 4618                 command->has_uid = true;
 4619                 command->uid = uid;
 4620         } else {
 4621                 yyerror("UID statement requires root privileges");
 4622         }
 4623 }
 4624 
 4625 
 4626 /*
 4627  * Add a new group id to the current command object.
 4628  */
 4629 static void addegid(gid_t gid) {
 4630         if (! getuid()) {
 4631                 command->has_gid = true;
 4632                 command->gid = gid;
 4633         } else {
 4634                 yyerror("GID statement requires root privileges");
 4635         }
 4636 }
 4637 
 4638 
 4639 /*
 4640  * Reset the logfile if changed
 4641  */
 4642 static void setlogfile(char *logfile) {
 4643         if (Run.files.log) {
 4644                 if (IS(Run.files.log, logfile)) {
 4645                         FREE(logfile);
 4646                         return;
 4647                 } else {
 4648                         FREE(Run.files.log);
 4649                 }
 4650         }
 4651         Run.files.log = logfile;
 4652 }
 4653 
 4654 
 4655 /*
 4656  * Reset the pidfile if changed
 4657  */
 4658 static void setpidfile(char *pidfile) {
 4659         if (Run.files.pid) {
 4660                 if (IS(Run.files.pid, pidfile)) {
 4661                         FREE(pidfile);
 4662                         return;
 4663                 } else {
 4664                         FREE(Run.files.pid);
 4665                 }
 4666         }
 4667         Run.files.pid = pidfile;
 4668 }
 4669 
 4670 
 4671 /*
 4672  * Read a apache htpasswd file and add credentials found for username
 4673  */
 4674 static void addhtpasswdentry(char *filename, char *username, Digest_Type dtype) {
 4675         char *ht_username = NULL;
 4676         char *ht_passwd = NULL;
 4677         char buf[STRLEN];
 4678         FILE *handle = NULL;
 4679         int credentials_added = 0;
 4680 
 4681         ASSERT(filename);
 4682 
 4683         handle = fopen(filename, "r");
 4684 
 4685         if (handle == NULL) {
 4686                 if (username != NULL)
 4687                         yyerror2("Cannot read htpasswd (%s) for user %s", filename, username);
 4688                 else
 4689                         yyerror2("Cannot read htpasswd (%s)", filename);
 4690                 return;
 4691         }
 4692 
 4693         while (! feof(handle)) {
 4694                 char *colonindex = NULL;
 4695 
 4696                 if (! fgets(buf, STRLEN, handle))
 4697                         continue;
 4698 
 4699                 Str_rtrim(buf);
 4700                 Str_curtail(buf, "#");
 4701 
 4702                 if (NULL == (colonindex = strchr(buf, ':')))
 4703                 continue;
 4704 
 4705                 ht_passwd = Str_dup(colonindex+1);
 4706                 *colonindex = '\0';
 4707 
 4708                 /* In case we have a file in /etc/passwd or /etc/shadow style we
 4709                  *  want to remove ":.*$" and Crypt and MD5 hashed dont have a colon
 4710                  */
 4711 
 4712                 if ((NULL != (colonindex = strchr(ht_passwd, ':'))) && (dtype != Digest_Cleartext))
 4713                         *colonindex = '\0';
 4714 
 4715                 ht_username = Str_dup(buf);
 4716 
 4717                 if (username == NULL) {
 4718                         if (addcredentials(ht_username, ht_passwd, dtype, false))
 4719                                 credentials_added++;
 4720                 } else if (Str_cmp(username, ht_username) == 0)  {
 4721                         if (addcredentials(ht_username, ht_passwd, dtype, false))
 4722                                 credentials_added++;
 4723                 } else {
 4724                         FREE(ht_passwd);
 4725                         FREE(ht_username);
 4726                 }
 4727         }
 4728 
 4729         if (credentials_added == 0) {
 4730                 if (username == NULL)
 4731                         yywarning2("htpasswd file (%s) has no usable credentials", filename);
 4732                 else
 4733                         yywarning2("htpasswd file (%s) has no usable credentials for user %s", filename, username);
 4734         }
 4735         fclose(handle);
 4736 }
 4737 
 4738 
 4739 #ifdef HAVE_LIBPAM
 4740 static void addpamauth(char* groupname, int readonly) {
 4741         Auth_T prev = NULL;
 4742 
 4743         ASSERT(groupname);
 4744 
 4745         if (! Run.httpd.credentials)
 4746                 NEW(Run.httpd.credentials);
 4747 
 4748         Auth_T c = Run.httpd.credentials;
 4749         do {
 4750                 if (c->groupname != NULL && IS(c->groupname, groupname)) {
 4751                         yywarning2("PAM group %s was added already, entry ignored", groupname);
 4752                         FREE(groupname);
 4753                         return;
 4754                 }
 4755                 prev = c;
 4756                 c = c->next;
 4757         } while (c != NULL);
 4758 
 4759         NEW(prev->next);
 4760         c = prev->next;
 4761 
 4762         c->next        = NULL;
 4763         c->uname       = NULL;
 4764         c->passwd      = NULL;
 4765         c->groupname   = groupname;
 4766         c->digesttype  = Digest_Pam;
 4767         c->is_readonly = readonly;
 4768 
 4769         DEBUG("Adding PAM group '%s'\n", groupname);
 4770 
 4771         return;
 4772 }
 4773 #endif
 4774 
 4775 
 4776 /*
 4777  * Add Basic Authentication credentials
 4778  */
 4779 static bool addcredentials(char *uname, char *passwd, Digest_Type dtype, bool readonly) {
 4780         Auth_T c;
 4781 
 4782         ASSERT(uname);
 4783         ASSERT(passwd);
 4784 
 4785         if (strlen(passwd) > Str_compareConstantTimeStringLength) {
 4786                 yyerror2("Password for user %s is too long, maximum %d allowed", uname, Str_compareConstantTimeStringLength);
 4787                 FREE(uname);
 4788                 FREE(passwd);
 4789                 return false;
 4790         }
 4791 
 4792         if (! Run.httpd.credentials) {
 4793                 NEW(Run.httpd.credentials);
 4794                 c = Run.httpd.credentials;
 4795         } else {
 4796                 if (Util_getUserCredentials(uname) != NULL) {
 4797                         yywarning2("Credentials for user %s were already added, entry ignored", uname);
 4798                         FREE(uname);
 4799                         FREE(passwd);
 4800                         return false;
 4801                 }
 4802                 c = Run.httpd.credentials;
 4803                 while (c->next != NULL)
 4804                         c = c->next;
 4805                 NEW(c->next);
 4806                 c = c->next;
 4807         }
 4808 
 4809         c->next        = NULL;
 4810         c->uname       = uname;
 4811         c->passwd      = passwd;
 4812         c->groupname   = NULL;
 4813         c->digesttype  = dtype;
 4814         c->is_readonly = readonly;
 4815 
 4816         DEBUG("Adding credentials for user '%s'\n", uname);
 4817 
 4818         return true;
 4819 
 4820 }
 4821 
 4822 
 4823 /*
 4824  * Set the syslog and the facilities to be used
 4825  */
 4826 static void setsyslog(char *facility) {
 4827 
 4828         if (! Run.files.log || ihp.logfile) {
 4829                 ihp.logfile = true;
 4830                 setlogfile(Str_dup("syslog"));
 4831                 Run.flags |= Run_UseSyslog;
 4832                 Run.flags |= Run_Log;
 4833         }
 4834 
 4835         if (facility) {
 4836                 if (IS(facility,"log_local0"))
 4837                         Run.facility = LOG_LOCAL0;
 4838                 else if (IS(facility, "log_local1"))
 4839                         Run.facility = LOG_LOCAL1;
 4840                 else if (IS(facility, "log_local2"))
 4841                         Run.facility = LOG_LOCAL2;
 4842                 else if (IS(facility, "log_local3"))
 4843                         Run.facility = LOG_LOCAL3;
 4844                 else if (IS(facility, "log_local4"))
 4845                         Run.facility = LOG_LOCAL4;
 4846                 else if (IS(facility, "log_local5"))
 4847                         Run.facility = LOG_LOCAL5;
 4848                 else if (IS(facility, "log_local6"))
 4849                         Run.facility = LOG_LOCAL6;
 4850                 else if (IS(facility, "log_local7"))
 4851                         Run.facility = LOG_LOCAL7;
 4852                 else if (IS(facility, "log_daemon"))
 4853                         Run.facility = LOG_DAEMON;
 4854                 else
 4855                         yyerror2("Invalid syslog facility");
 4856         } else {
 4857                 Run.facility = LOG_USER;
 4858         }
 4859 
 4860 }
 4861 
 4862 
 4863 /*
 4864  * Reset the current sslset for reuse
 4865  */
 4866 static void reset_sslset() {
 4867         memset(&sslset, 0, sizeof(struct SslOptions_T));
 4868         sslset.version = sslset.verify = sslset.allowSelfSigned = -1;
 4869 }
 4870 
 4871 
 4872 /*
 4873  * Reset the current mailset for reuse
 4874  */
 4875 static void reset_mailset() {
 4876         memset(&mailset, 0, sizeof(struct Mail_T));
 4877 }
 4878 
 4879 
 4880 /*
 4881  * Reset the mailserver set to default values
 4882  */
 4883 static void reset_mailserverset() {
 4884         memset(&mailserverset, 0, sizeof(struct MailServer_T));
 4885         mailserverset.port = PORT_SMTP;
 4886 }
 4887 
 4888 
 4889 /*
 4890  * Reset the mmonit set to default values
 4891  */
 4892 static void reset_mmonitset() {
 4893         memset(&mmonitset, 0, sizeof(struct Mmonit_T));
 4894         mmonitset.timeout = Run.limits.networkTimeout;
 4895 }
 4896 
 4897 
 4898 /*
 4899  * Reset the Port set to default values
 4900  */
 4901 static void reset_portset() {
 4902         memset(&portset, 0, sizeof(struct Port_T));
 4903         portset.check_invers = false;
 4904         portset.socket = -1;
 4905         portset.type = Socket_Tcp;
 4906         portset.family = Socket_Ip;
 4907         portset.timeout = Run.limits.networkTimeout;
 4908         portset.retry = 1;
 4909         portset.protocol = Protocol_get(Protocol_DEFAULT);
 4910         urlrequest = NULL;
 4911 }
 4912 
 4913 
 4914 /*
 4915  * Reset the Proc set to default values
 4916  */
 4917 static void reset_resourceset() {
 4918         resourceset.resource_id = 0;
 4919         resourceset.limit = 0;
 4920         resourceset.action = NULL;
 4921         resourceset.operator = Operator_Equal;
 4922 }
 4923 
 4924 
 4925 /*
 4926  * Reset the Timestamp set to default values
 4927  */
 4928 static void reset_timestampset() {
 4929         timestampset.type = Timestamp_Default;
 4930         timestampset.operator = Operator_Equal;
 4931         timestampset.time = 0;
 4932         timestampset.test_changes = false;
 4933         timestampset.initialized = false;
 4934         timestampset.action = NULL;
 4935 }
 4936 
 4937 
 4938 /*
 4939  * Reset the ActionRate set to default values
 4940  */
 4941 static void reset_actionrateset() {
 4942         actionrateset.count = 0;
 4943         actionrateset.cycle = 0;
 4944         actionrateset.action = NULL;
 4945 }
 4946 
 4947 
 4948 /*
 4949  * Reset the Size set to default values
 4950  */
 4951 static void reset_sizeset() {
 4952         sizeset.operator = Operator_Equal;
 4953         sizeset.size = 0;
 4954         sizeset.test_changes = false;
 4955         sizeset.action = NULL;
 4956 }
 4957 
 4958 
 4959 /*
 4960  * Reset the Uptime set to default values
 4961  */
 4962 static void reset_uptimeset() {
 4963         uptimeset.operator = Operator_Equal;
 4964         uptimeset.uptime = 0;
 4965         uptimeset.action = NULL;
 4966 }
 4967 
 4968 
 4969 static void reset_responsetimeset() {
 4970         responsetimeset.operator = Operator_Less;
 4971         responsetimeset.current = 0.;
 4972         responsetimeset.limit = -1.;
 4973 }
 4974 
 4975 
 4976 static void reset_linkstatusset() {
 4977         linkstatusset.check_invers = false;
 4978         linkstatusset.action = NULL;
 4979 }
 4980 
 4981 
 4982 static void reset_linkspeedset() {
 4983         linkspeedset.action = NULL;
 4984 }
 4985 
 4986 
 4987 static void reset_linksaturationset() {
 4988         linksaturationset.limit = 0.;
 4989         linksaturationset.operator = Operator_Equal;
 4990         linksaturationset.action = NULL;
 4991 }
 4992 
 4993 
 4994 /*
 4995  * Reset the Bandwidth set to default values
 4996  */
 4997 static void reset_bandwidthset() {
 4998         bandwidthset.operator = Operator_Equal;
 4999         bandwidthset.limit = 0ULL;
 5000         bandwidthset.action = NULL;
 5001 }
 5002 
 5003 
 5004 /*
 5005  * Reset the Pid set to default values
 5006  */
 5007 static void reset_pidset() {
 5008         pidset.action = NULL;
 5009 }
 5010 
 5011 
 5012 /*
 5013  * Reset the PPid set to default values
 5014  */
 5015 static void reset_ppidset() {
 5016         ppidset.action = NULL;
 5017 }
 5018 
 5019 
 5020 /*
 5021  * Reset the Fsflag set to default values
 5022  */
 5023 static void reset_fsflagset() {
 5024         fsflagset.action = NULL;
 5025 }
 5026 
 5027 
 5028 /*
 5029  * Reset the Nonexist set to default values
 5030  */
 5031 static void reset_nonexistset() {
 5032         nonexistset.action = NULL;
 5033 }
 5034 
 5035 
 5036 static void reset_existset() {
 5037         existset.action = NULL;
 5038 }
 5039 
 5040 
 5041 /*
 5042  * Reset the Checksum set to default values
 5043  */
 5044 static void reset_checksumset() {
 5045         checksumset.type         = Hash_Unknown;
 5046         checksumset.test_changes = false;
 5047         checksumset.action       = NULL;
 5048         *checksumset.hash        = 0;
 5049 }
 5050 
 5051 
 5052 /*
 5053  * Reset the Perm set to default values
 5054  */
 5055 static void reset_permset() {
 5056         permset.test_changes = false;
 5057         permset.perm = 0;
 5058         permset.action = NULL;
 5059 }
 5060 
 5061 
 5062 /*
 5063  * Reset the Status set to default values
 5064  */
 5065 static void reset_statusset() {
 5066         statusset.initialized = false;
 5067         statusset.return_value = 0;
 5068         statusset.operator = Operator_Equal;
 5069         statusset.action = NULL;
 5070 }
 5071 
 5072 
 5073 /*
 5074  * Reset the Uid set to default values
 5075  */
 5076 static void reset_uidset() {
 5077         uidset.uid = 0;
 5078         uidset.action = NULL;
 5079 }
 5080 
 5081 
 5082 /*
 5083  * Reset the Gid set to default values
 5084  */
 5085 static void reset_gidset() {
 5086         gidset.gid = 0;
 5087         gidset.action = NULL;
 5088 }
 5089 
 5090 
 5091 /*
 5092  * Reset the Filesystem set to default values
 5093  */
 5094 static void reset_filesystemset() {
 5095         filesystemset.resource = 0;
 5096         filesystemset.operator = Operator_Equal;
 5097         filesystemset.limit_absolute = -1;
 5098         filesystemset.limit_percent = -1.;
 5099         filesystemset.action = NULL;
 5100 }
 5101 
 5102 
 5103 /*
 5104  * Reset the ICMP set to default values
 5105  */
 5106 static void reset_icmpset() {
 5107         icmpset.type = ICMP_ECHO;
 5108         icmpset.size = ICMP_SIZE;
 5109         icmpset.count = ICMP_ATTEMPT_COUNT;
 5110         icmpset.timeout = Run.limits.networkTimeout;
 5111         icmpset.check_invers = false;
 5112         icmpset.action = NULL;
 5113 }
 5114 
 5115 
 5116 /*
 5117  * Reset the Rate set to default values
 5118  */
 5119 static void reset_rateset(struct rate_t *r) {
 5120         r->count = 1;
 5121         r->cycles = 1;
 5122 }
 5123 
 5124 
 5125 /* ---------------------------------------------------------------- Checkers */
 5126 
 5127 
 5128 /*
 5129  * Check for unique service name
 5130  */
 5131 static void check_name(char *name) {
 5132         ASSERT(name);
 5133 
 5134         if (Util_existService(name) || (current && IS(name, current->name)))
 5135                 yyerror2("Service name conflict, %s already defined", name);
 5136         if (name && *name == '/')
 5137                 yyerror2("Service name '%s' must not start with '/' -- ", name);
 5138 }
 5139 
 5140 
 5141 /*
 5142  * Permission statement semantic check
 5143  */
 5144 static int check_perm(int perm) {
 5145         int result;
 5146         char *status;
 5147         char buf[STRLEN];
 5148 
 5149         snprintf(buf, STRLEN, "%d", perm);
 5150 
 5151         result = (int)strtol(buf, &status, 8);
 5152 
 5153         if (*status != '\0' || result < 0 || result > 07777)
 5154                 yyerror2("Permission statements must have an octal value between 0 and 7777");
 5155 
 5156         return result;
 5157 }
 5158 
 5159 
 5160 /*
 5161  * Check the dependency graph for errors
 5162  * by doing a topological sort, thereby finding any cycles.
 5163  * Assures that graph is a Directed Acyclic Graph (DAG).
 5164  */
 5165 static void check_depend() {
 5166         Service_T depends_on = NULL;
 5167         Service_T* dlt = &depend_list; /* the current tail of it                                 */
 5168         bool done;                /* no unvisited nodes left?                               */
 5169         bool found_some;          /* last iteration found anything new ?                    */
 5170         depend_list = NULL;            /* depend_list will be the topological sorted servicelist */
 5171 
 5172         do {
 5173                 done = true;
 5174                 found_some = false;
 5175                 for (Service_T s = servicelist; s; s = s->next) {
 5176                         Dependant_T d;
 5177                         if (s->visited)
 5178                                 continue;
 5179                         done = false; // still unvisited nodes
 5180                         depends_on = NULL;
 5181                         for (d = s->dependantlist; d; d = d->next) {
 5182                                 Service_T dp = Util_getService(d->dependant);
 5183                                 if (! dp) {
 5184                                         Log_error("Depending service '%s' is not defined in the control file\n", d->dependant);
 5185                                         exit(1);
 5186                                 }
 5187                                 if (! dp->visited) {
 5188                                         depends_on = dp;
 5189                                 }
 5190                         }
 5191 
 5192                         if (! depends_on) {
 5193                                 s->visited = true;
 5194                                 found_some = true;
 5195                                 *dlt = s;
 5196                                 dlt = &s->next_depend;
 5197                         }
 5198                 }
 5199         } while (found_some && ! done);
 5200 
 5201         if (! done) {
 5202                 ASSERT(depends_on);
 5203                 Log_error("Found a depend loop in the control file involving the service '%s'\n", depends_on->name);
 5204                 exit(1);
 5205         }
 5206 
 5207         ASSERT(depend_list);
 5208         servicelist = depend_list;
 5209 
 5210         for (Service_T s = depend_list; s; s = s->next_depend)
 5211                 s->next = s->next_depend;
 5212 }
 5213 
 5214 
 5215 // Check and warn if the executable does not exist
 5216 static void check_exec(char *exec) {
 5217         if (! File_exist(exec))
 5218                 yywarning2("Program does not exist:");
 5219         else if (! File_isExecutable(exec))
 5220                 yywarning2("Program is not executable:");
 5221 }
 5222 
 5223 
 5224 /* Return a valid max forward value for SIP header */
 5225 static int verifyMaxForward(int mf) {
 5226         if (mf == 0) {
 5227                 return INT_MAX; // Differentiate uninitialized (0) and explicit zero
 5228         } else if (mf > 0 && mf <= 255) {
 5229                 return mf;
 5230         }
 5231         yywarning2("SIP max forward is outside the range [0..255]. Setting max forward to 70");
 5232         return 70;
 5233 }
 5234 
 5235 
 5236 /* -------------------------------------------------------------------- Misc */
 5237 
 5238 
 5239 /*
 5240  * Cleans up a hash string, tolower and remove byte separators
 5241  */
 5242 static int cleanup_hash_string(char *hashstring) {
 5243         int i = 0, j = 0;
 5244 
 5245         ASSERT(hashstring);
 5246 
 5247         while (hashstring[i]) {
 5248                 if (isxdigit((int)hashstring[i])) {
 5249                         hashstring[j] = tolower((int)hashstring[i]);
 5250                         j++;
 5251                 }
 5252                 i++;
 5253         }
 5254         hashstring[j] = 0;
 5255         return j;
 5256 }
 5257 
 5258 
 5259 /* Return deep copy of the command */
 5260 static command_t copycommand(command_t source) {
 5261         int i;
 5262         command_t copy = NULL;
 5263 
 5264         NEW(copy);
 5265         copy->length = source->length;
 5266         copy->has_uid = source->has_uid;
 5267         copy->uid = source->uid;
 5268         copy->has_gid = source->has_gid;
 5269         copy->gid = source->gid;
 5270         copy->timeout = source->timeout;
 5271         for (i = 0; i < copy->length; i++)
 5272                 copy->arg[i] = Str_dup(source->arg[i]);
 5273         copy->arg[copy->length] = NULL;
 5274 
 5275         return copy;
 5276 }
 5277 
 5278 
 5279 static void _setPEM(char **store, char *path, const char *description, bool isFile) {
 5280         if (*store) {
 5281                 yyerror2("Duplicate %s", description);
 5282                 FREE(path);
 5283         } else if (! File_exist(path)) {
 5284                 yyerror2("%s doesn't exist", description);
 5285                 FREE(path);
 5286         } else if (! (isFile ? File_isFile(path) : File_isDirectory(path))) {
 5287                 yyerror2("%s is not a %s", description, isFile ? "file" : "directory");
 5288                 FREE(path);
 5289         } else if (! File_isReadable(path)) {
 5290                 yyerror2("Cannot read %s", description);
 5291                 FREE(path);
 5292         } else {
 5293                 sslset.flags = SSL_Enabled;
 5294                 *store = path;
 5295         }
 5296 }
 5297 
 5298 
 5299 static void _setSSLOptions(SslOptions_T options) {
 5300         options->allowSelfSigned = sslset.allowSelfSigned;
 5301         options->CACertificateFile = sslset.CACertificateFile;
 5302         options->CACertificatePath = sslset.CACertificatePath;
 5303         options->checksum = sslset.checksum;
 5304         options->checksumType = sslset.checksumType;
 5305         options->ciphers = sslset.ciphers;
 5306         options->clientpemfile = sslset.clientpemfile;
 5307         options->flags = sslset.flags;
 5308         options->pemfile = sslset.pemfile;
 5309         options->pemchain = sslset.pemchain;
 5310         options->pemkey = sslset.pemkey;
 5311         options->verify = sslset.verify;
 5312         options->version = sslset.version;
 5313         reset_sslset();
 5314 }
 5315 
 5316 
 5317 #ifdef HAVE_OPENSSL
 5318 static void _setSSLVersion(short version) {
 5319         sslset.flags = SSL_Enabled;
 5320         if (sslset.version == -1)
 5321                 sslset.version = version;
 5322         else
 5323                 sslset.version |= version;
 5324 }
 5325 #endif
 5326 
 5327 
 5328 static void _unsetSSLVersion(short version) {
 5329         if (sslset.version != -1)
 5330                 sslset.version &= ~version;
 5331 }
 5332 
 5333 
 5334 static void addsecurityattribute(char *value, Action_Type failed, Action_Type succeeded) {
 5335         SecurityAttribute_T attr;
 5336         NEW(attr);
 5337         addeventaction(&(attr->action), failed, succeeded);
 5338         attr->attribute = value;
 5339         attr->next = current->secattrlist;
 5340         current->secattrlist = attr;
 5341 }
 5342 
 5343 static void addfiledescriptors(Operator_Type operator, bool total, long long value_absolute, float value_percent, Action_Type failed, Action_Type succeeded) {
 5344         Filedescriptors_T fds;
 5345         NEW(fds);
 5346         addeventaction(&(fds->action), failed, succeeded);
 5347         fds->total = total;
 5348         fds->limit_absolute = value_absolute;
 5349         fds->limit_percent = value_percent;
 5350         fds->operator = operator;
 5351         fds->next = current->filedescriptorslist;
 5352         current->filedescriptorslist = fds;
 5353 }
 5354