Ignore:
Timestamp:
Nov 21, 2008, 10:33:04 PM (16 years ago)
Author:
katerina
Message:

Rewrite of code for conditionals in configuration file, supports more tests now (ticket #129).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/sh_readconf.c

    r196 r197  
    4343#include "sh_prelink.h"
    4444#include "sh_extern.h"
     45#include "sh_tools.h"
    4546
    4647#ifdef WITH_DATABASE
     
    135136};
    136137
     138enum {
     139  SH_RC_ANY        = 0,
     140  SH_RC_HOST       = 1,
     141  SH_RC_SYSTEM     = 2,
     142  SH_RC_FILE       = 3,
     143  SH_RC_IFACE      = 4,
     144  SH_RC_CMD        = 5
     145};
     146
     147
     148static int sh_readconf_cond_match(char * str, int line)
     149{
     150  int    match  = 0;
     151  int    negate = 1;
     152  int    cond_type = SH_RC_ANY;
     153  char   myident[3*SH_MINIBUF+3];
     154  struct stat buf;
     155
     156  char * p = str;
     157
     158  if (*p == '!') { negate = 0; ++p; }
     159  if (*p == '$') {
     160    cond_type = SH_RC_SYSTEM; ++p; /* [!]$system */
     161  }
     162  else { /* *p == '@' */
     163
     164    ++p; while (isspace((int)*p)) ++p;
     165
     166    if (0 != strncmp(p, _("if "),   3)) {
     167      cond_type = SH_RC_HOST; /* [!]$host */
     168    }
     169
     170    else {
     171
     172      p += 3; while (isspace((int)*p)) ++p; /* skip the 'if\s+' */
     173
     174      if (0 == strncmp(p, _("not "), 4))
     175        {
     176          p += 4; while (isspace((int)*p)) ++p;
     177          negate = 0;
     178        }
     179      else if (0 == strncmp(p, _("!"), 1))
     180        {
     181          ++p; while (isspace((int)*p)) ++p;
     182          negate = 0;
     183        }
     184 
     185      if (0 == strncmp(p, _("file_exists "), 12))
     186        {
     187          p += 12; cond_type = SH_RC_FILE;
     188        }
     189      else if (0 == strncmp(p, _("interface_exists "), 17))
     190        {
     191          p += 17; cond_type = SH_RC_IFACE;
     192        }
     193      else if (0 == strncmp(p, _("hostname_matches "), 17))
     194        {
     195          p += 17; cond_type = SH_RC_HOST;
     196        }
     197      else if (0 == strncmp(p, _("system_matches "), 15))
     198        {
     199          p += 15; cond_type = SH_RC_SYSTEM;
     200        }
     201      else if (0 == strncmp(p, _("command_succeeds "), 17))
     202        {
     203          p += 17; cond_type = SH_RC_CMD;
     204        }
     205      else
     206        {
     207          char errbuf[SH_ERRBUF_SIZE];
     208          sl_snprintf(errbuf, sizeof(errbuf),
     209                      _("Unsupported test at line %d of configuration file"),
     210                      line);
     211          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     212                          errbuf,
     213                          _("sh_readconf_cond_match"));
     214          return 0;
     215        }
     216    }
     217  }
     218
     219  while (isspace((int)*p)) ++p;
     220
     221  switch (cond_type)
     222    {
     223    case SH_RC_HOST:
     224      if  (sl_strncmp (p,  sh.host.name, strlen(sh.host.name)) == 0
     225#ifdef HAVE_REGEX_H
     226           || sh_util_regcmp (p, sh.host.name) == 0
     227#endif
     228           )
     229        match = negate;
     230      break;
     231    case SH_RC_SYSTEM:
     232      /*
     233       * The system type, release, and machine.
     234       */
     235      sl_snprintf(myident, sizeof(myident), _("%s:%s:%s"), 
     236                  sh.host.system, /* flawfinder: ignore */
     237                  sh.host.release, sh.host.machine);
     238     
     239      if  (sl_strncmp (p,  myident, sl_strlen(myident)) == 0
     240#ifdef HAVE_REGEX_H
     241           || sh_util_regcmp (p, myident) == 0
     242#endif
     243           )
     244        match = negate;
     245      break;
     246    case SH_RC_FILE:
     247      if (0 == retry_lstat(FIL__, __LINE__, p, &buf))
     248        match = negate;
     249      break;
     250    case SH_RC_IFACE:
     251      if (sh_tools_iface_is_present(p))
     252        match = negate;
     253      break;
     254    case SH_RC_CMD:
     255      if (0 == sh_unix_run_command(p))
     256        match = negate;
     257      break;
     258    default:
     259      match = 0;
     260    }
     261  return match;
     262}
     263
     264static int sh_readconf_is_end (char * str)
     265{
     266  int retval = 0;
     267
     268  if (str[0] == '@' || str[0] == '$')
     269    {
     270      char * p = str;
     271      ++p; while (isspace((int)*p)) ++p;
     272      if (0 == strcmp (p, _("end")     ) ||
     273          0 == strncmp(p, _("end "),  4) || /* Comment to follow */
     274          0 == strcmp (p, _("endif")   ) ||
     275          0 == strncmp(p, _("endif "),6) ||
     276          0 == strcmp (p, _("fi")      ) ||
     277          0 == strncmp(p, _("fi "),   3)
     278          )
     279        {
     280          return 1;
     281        }
     282    }
     283  return retval;
     284}
    137285   
    138286static int sh_readconfig_line (char * line);
     
    160308#endif
    161309  char * tmp;
    162   char * lptr;
    163310
    164311  char   line_in[512+2];
    165312  char * line;
    166   int    line_int;
    167 
    168   char   myident[3*SH_MINIBUF+3];
    169313
    170314  /* This is for nested conditionals.
    171315   */
    172   int    some_other_host[16]   = { 0 };
    173   int    some_other_system[16] = { 0 };
    174   int    seen_host   = 0;
    175   int    seen_system = 0;
    176   int    host_int    = 0;
    177   int    sys_int     = 0;
    178 
    179   int    invert = 0;
    180   int    length = sl_strlen(sh.host.name);
    181 
     316  int    cond_depth  = 0;
     317  int    cond_excl   = 0;
     318 
    182319  int    local_file = 1;
    183320  char   local_flag = 'R';
     
    288425  sl_rewind (fd);
    289426#endif
    290 
    291   /* The system type, release, and machine.
    292    */
    293   sl_snprintf(myident, sizeof(myident), _("%s:%s:%s"), 
    294               sh.host.system, /* flawfinder: ignore */
    295               sh.host.release, sh.host.machine);
    296427
    297428
     
    345476    /* Skip leading white space.
    346477     */
    347     while (*line)
    348       {
    349         line_int = *line;
    350         if (!isspace(line_int))
    351           break;
    352         ++line;
    353       }
     478    while (isspace((int)*line)) ++line;
     479
    354480
    355481    /* Skip header etc.
     
    365491
    366492
     493    /* ---  an @host/@if/$system directive -------------- */
     494
     495    if (line[0] == '@' || (line[0] == '!' && line[1] == '@') ||
     496        line[0] == '$' || (line[0] == '!' && line[1] == '$'))
     497      {
     498        if (sh_readconf_is_end(line))
     499          {
     500            if (0 == cond_depth) {
     501              sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALD,
     502                               _("config file"),
     503                               (long) conf_line);
     504            }
     505            else {
     506              if (cond_excl == cond_depth)
     507                cond_excl = 0;
     508              --cond_depth;
     509            }
     510          }
     511        else
     512          {
     513            if (sh_readconf_cond_match(line, conf_line)) {
     514              ++cond_depth;
     515            }
     516            else {
     517              ++cond_depth;
     518              if (cond_excl == 0)
     519                cond_excl = cond_depth;
     520            }
     521          }
     522        continue;
     523      }
     524
     525    /****************************************************
     526     *
     527     * Only carry on if this section is intended for us
     528     *
     529     ****************************************************/
     530   
     531    if (cond_excl != 0) {
     532      continue;
     533    }
     534
    367535    /* -------  starts a section  ------------  */
    368536   
    369     if (line[0] == '['                       &&
    370         some_other_host[seen_host] == 0      &&
    371         some_other_system[seen_system] == 0)
     537    else if (line[0] == '[')
    372538      {
    373539        read_mode = SH_SECTION_NONE;
    374540
    375         if (sl_strncmp (line,  _("[EOF]"),
    376                           5) == 0)
    377           {
    378             goto nopel;
    379           }
     541        if (0 == sl_strncmp (line,  _("[EOF]"), 5)) {
     542          goto nopel;
     543        }
    380544
    381545        i = 0;
     
    410574      }
    411575
    412     /* ---  an @host directive -------------- */
    413 
    414     else if (line[0] == '@' || (line[0] == '!' && line[1] == '@'))
    415       {
    416         if (line[0] == '!')
    417           {
    418             lptr   = &line[2];
    419             invert = 1;
    420           }
    421         else
    422           {
    423             lptr   = &line[1];
    424             invert = 0;
    425           }
    426 
    427         if (sl_strncmp (lptr, _("end"), 3) == 0)
    428           {
    429             if (0 == seen_host)
    430               sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALD,
    431                                _("config file"),
    432                                (long) conf_line);
    433 
    434             else if (host_int == 0)
    435               {
    436                 /* end  of an @host directive
    437                  */
    438                 some_other_host[seen_host] = 0;
    439                 --seen_host;
    440                 seen_host = (seen_host < 0) ? 0 : seen_host;
    441               }
    442 
    443             else
    444               {
    445                 --host_int;
    446                 host_int = (host_int < 0) ? 0 : host_int;
    447               }
    448           }
    449         else if (some_other_host[seen_host] == 0      &&
    450                  some_other_system[seen_system] == 0  &&
    451                  seen_host < 15)
    452           {
    453             if  (sl_strncmp (lptr,  sh.host.name, length) == 0
    454 #ifdef HAVE_REGEX_H
    455                  || sh_util_regcmp (lptr, sh.host.name) == 0
    456 #endif
    457                  )
    458               {
    459                 /* if match and '@',  set some_other_host = 0;
    460                  * if match and '!@', set some_other_host = 1;
    461                  */
    462                 ++seen_host;
    463                 some_other_host[seen_host] = invert;
    464               }
    465             else
    466               {
    467                 /* if no match and '@',  set some_other_host = 1;
    468                  * if no match and '!@', set some_other_host = 0;
    469                  */
    470                 ++seen_host;
    471                 some_other_host[seen_host] = (invert == 0) ? 1 : 0;
    472               }
    473           }
    474         else
    475           ++host_int;
    476       }
    477 
    478576    /* ---  an %schedule directive ------------ */
    479577
     
    489587#endif
    490588      }
    491          
    492     /* ---  an $system directive -------------- */
    493 
    494     else if (line[0] == '$' || (line[0] == '!' && line[1] == '$'))
    495       {
    496         if (line[0] == '!')
    497           {
    498             lptr   = &line[2];
    499             invert = 1;
    500           }
    501         else
    502           {
    503             lptr   = &line[1];
    504             invert = 0;
    505           }
    506 
    507         if (sl_strncmp (lptr, _("end"), 3) == 0)
    508           {
    509             if (0 == seen_system)
    510               sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALD,
    511                                _("config file"),
    512                                (long) conf_line);
    513 
    514             else if (sys_int == 0)
    515               {
    516                 /* end  of an $system directive
    517                  */
    518                 some_other_system[seen_system] = 0;
    519                 --seen_system;
    520                 seen_system = (seen_system < 0) ? 0 : seen_system;
    521               }
    522             else
    523               {
    524                 --sys_int;
    525                 sys_int = (sys_int < 0) ? 0 : sys_int;
    526               }
    527           }
    528         else if (some_other_host[seen_host] == 0      &&
    529                  some_other_system[seen_system] == 0  &&
    530                  seen_system < 15)
    531           {
    532             if  (sl_strncmp (lptr,  myident, sl_strlen(myident)) == 0
    533 #ifdef HAVE_REGEX_H
    534                  || sh_util_regcmp (lptr, myident) == 0
    535 #endif
    536                  )
    537               {
    538                 ++seen_system;
    539                 some_other_system[seen_system] = invert;
    540               }
    541             else
    542               {
    543                 ++seen_system;
    544                 some_other_system[seen_system] = (invert == 0) ? 1 : 0;
    545               }
    546           }
    547         else
    548           ++sys_int;
    549       }
    550589
    551590    /* ------  no new section -------------- */
    552591
    553592
    554     else if (some_other_host[seen_host] == 0          &&
    555              some_other_system[seen_system] == 0      &&
    556              read_mode != SH_SECTION_NONE)
     593    else if (read_mode != SH_SECTION_NONE)
    557594      {
    558595        if (0 != sh_readconfig_line (line))
     
    562599          }
    563600      }
    564 
    565   }
     601  } /* while getline() */
    566602
    567603 nopel:
    568604           
    569   if (0 != seen_host || 0 != seen_system)
     605  if (0 != cond_depth)
    570606    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALDD,
    571607                     _("config file"),
Note: See TracChangeset for help on using the changeset viewer.