LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - opt_serv.c
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 910
Code covered: 70.0 % Executed lines: 637

       1                 : #define _GNU_SOURCE 1 /* strsignal() */
       2                 : 
       3                 : #include "opt_serv.h"
       4                 : 
       5                 : #define EX_UTILS_NO_FUNCS 1
       6                 : #include "ex_utils.h"
       7                 : 
       8                 : #include "opt_policy.h"
       9                 : 
      10                 : #include "mk.h"
      11                 : 
      12                 : #include "opt_conf.h"
      13                 : 
      14                 : #include <stddef.h> /* offsetof */
      15                 : 
      16                 : #include <sys/resource.h>
      17                 : #include <signal.h>
      18                 : 
      19                 : #include <sys/utsname.h>
      20                 : 
      21                 : #ifndef CONF_FULL_STATIC
      22                 : # include <pwd.h>
      23                 : # include <grp.h>
      24                 : # include <sys/types.h>
      25                 : #endif
      26                 : 
      27                 : #ifndef HAVE_STRSIGNAL
      28                 : # define strsignal(x) ""
      29                 : #endif
      30                 : 
      31                 : #ifdef RLIMIT_AS /* not sure how portable this one is,
      32                 :                   * modern stuff seems to have it */
      33                 : # define USE_RLIMIT_AS TRUE
      34                 : #else
      35                 : # define USE_RLIMIT_AS FALSE
      36                 : # define RLIMIT_AS 0
      37                 : #endif
      38                 : 
      39                 : #include <syslog.h>
      40                 : 
      41                 : static Vlg *vlg = NULL;
      42                 : 
      43                 : 
      44                 : /* only called the first time, so that it can easily be used from req conf */
      45                 : int opt_serv_sc_append_hostname(Vstr_base *s1, size_t pos)
      46             102 : {
      47                 :   static char buf[256];
      48                 :   static size_t len = 0;
      49                 : 
      50             102 :   if (!len)
      51                 :   {
      52              64 :     if (gethostname(buf, sizeof(buf)) == -1)
      53               0 :       err(EXIT_FAILURE, "gethostname");
      54                 :   
      55              64 :     buf[sizeof(buf) - 1] = 0;
      56              64 :     len = strlen(buf);
      57                 :   }
      58                 :   
      59             102 :   return (vstr_add_ptr(s1, pos, buf, len));
      60                 : }
      61                 : static int opt_serv__init_append_hostname(void)
      62              64 : {
      63              64 :   Vstr_base *tmp = vstr_make_base(NULL);
      64                 : 
      65              64 :   if (!tmp)
      66               0 :     return (FALSE);
      67                 : 
      68              64 :   opt_serv_sc_append_hostname(tmp, 0); /* ignore error */
      69                 :   
      70              64 :   vstr_free_base(tmp);
      71                 : 
      72              64 :   return (TRUE);
      73                 : }
      74                 : 
      75                 : int opt_serv_sc_append_cwd(Vstr_base *s1, size_t pos)
      76               4 : {
      77                 :   static size_t sz = PATH_MAX;
      78               4 :   char *ptr = MK(sz);
      79               4 :   int ret = FALSE;
      80                 : 
      81               4 :   if (ptr)
      82                 :   {
      83               4 :     const size_t maxsz = 8 * PATH_MAX; /* FIXME: config. */
      84               4 :     char *tmp = NULL;
      85                 :     
      86               4 :     tmp = getcwd(ptr, sz);
      87               8 :     while (!tmp && (errno == ERANGE) && (sz < maxsz))
      88                 :     {
      89               0 :       sz += PATH_MAX;
      90               0 :       if (!MV(ptr, tmp, sz))
      91                 :         break;
      92               0 :       tmp = getcwd(ptr, sz);
      93                 :     }
      94                 :   
      95               4 :     if (!tmp) 
      96               0 :       ret = vstr_add_cstr_ptr(s1, pos, "/");
      97                 :     else
      98               4 :       ret = vstr_add_cstr_buf(s1, pos, tmp);
      99                 :   }
     100                 :   
     101               4 :   F(ptr);
     102                 :   
     103               4 :   return (ret);
     104                 : }
     105                 : 
     106                 : static int opt_serv_sc_append_env(Vstr_base *s1, size_t pos,
     107                 :                                   const Conf_parse *conf, Conf_token *token)
     108              60 : {
     109              60 :   const Vstr_sect_node *pv = NULL;
     110              60 :   const char *env_name = NULL;
     111              60 :   const char *env_data = NULL;
     112                 :   
     113              60 :   CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     114              60 :   if (!(pv = conf_token_value(token)))
     115               0 :     return (FALSE);
     116                 :   
     117              60 :   if (!(env_name = vstr_export_cstr_ptr(conf->data, pv->pos, pv->len)))
     118               0 :     return (FALSE);
     119                 :   
     120              60 :   env_data = getenv(env_name);
     121              60 :   if (!env_data) env_data = "";
     122                 :   
     123              60 :   return (vstr_add_cstr_buf(s1, pos, env_data));
     124                 : }
     125                 : 
     126                 : #ifdef CONF_FULL_STATIC /* just ignore it, if using full-static */
     127                 : # define OPT_SERV_SC_APPEND_HOMEDIR(w, x, y, z) CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE)
     128                 : #else
     129                 : static int opt_serv_sc_append_homedir(Vstr_base *s1, size_t pos,
     130                 :                                       const Conf_parse *conf, Conf_token *token)
     131               4 : {
     132               4 :   const Vstr_sect_node *pv = NULL;
     133               4 :   const char *usr_name = NULL;
     134               4 :   const char *usr_data = "";
     135               4 :   struct passwd *pw = NULL;
     136                 :   
     137               4 :   CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     138               4 :   if (!(pv = conf_token_value(token)))
     139               0 :     return (FALSE);
     140               4 :   if (!(usr_name = vstr_export_cstr_ptr(conf->data, pv->pos, pv->len)))
     141               0 :     return (FALSE);
     142                 :   
     143               4 :   if ((pw = getpwnam(usr_name)))
     144               4 :     usr_data = pw->pw_dir;
     145                 :   
     146               4 :   return (vstr_add_cstr_buf(s1, pos, usr_data));
     147                 : }
     148                 : # define OPT_SERV_SC_APPEND_HOMEDIR(w, x, y, z) \
     149                 :     opt_serv_sc_append_homedir(w, x, y, z)
     150                 : #endif
     151                 : 
     152                 : #define OPT_SERV_SC_APPEND_UNAME(x) do {                                \
     153                 :       if (!vstr_add_cstr_buf(conf->tmp, conf->tmp->len, utsname-> x))   \
     154                 :         return (FALSE);                                                 \
     155                 :     } while (FALSE)
     156                 : 
     157                 : 
     158                 : int opt_serv_sc_tst(Conf_parse *conf, Conf_token *token,
     159                 :                     int *matches, int prev_match,
     160                 :                     int (*tst_func)(Conf_parse *, Conf_token *,
     161                 :                                     int *, int, void *), void *data)
     162           45260 : {
     163                 :   if (0) { }
     164                 :   
     165           45456 :   else if (OPT_SERV_SYM_EQ("else")  || OPT_SERV_SYM_EQ("ELSE"))
     166             196 :     *matches = !prev_match;
     167           48036 :   else if (OPT_SERV_SYM_EQ("true")  || OPT_SERV_SYM_EQ("TRUE"))
     168            2972 :     *matches = TRUE;
     169           43664 :   else if (OPT_SERV_SYM_EQ("false") || OPT_SERV_SYM_EQ("FALSE"))
     170            1572 :     *matches = FALSE;
     171                 :   
     172           49584 :   else if (OPT_SERV_SYM_EQ("not") || OPT_SERV_SYM_EQ("NOT") ||
     173                 :            OPT_SERV_SYM_EQ("!"))
     174                 :   {
     175            9064 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     176            9064 :     if (!(*tst_func)(conf, token, matches, prev_match, data))
     177               0 :       return (FALSE);
     178            9064 :     *matches = !*matches;
     179                 :   }
     180           55052 :   else if (OPT_SERV_SYM_EQ("or") || OPT_SERV_SYM_EQ("OR") ||
     181                 :            OPT_SERV_SYM_EQ("||"))
     182                 :   {
     183           31452 :     unsigned int depth = token->depth_num;
     184                 : 
     185          134220 :     while (conf_token_list_num(token, depth))
     186                 :     {
     187           79172 :       int or_matches = TRUE;
     188                 :     
     189           79172 :       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     190           79172 :       if (!(*tst_func)(conf, token, &or_matches, prev_match, data))
     191               0 :         return (FALSE);
     192                 : 
     193           79172 :       if (or_matches)
     194                 :       {
     195            7856 :         int ret = conf_parse_end_token(conf, token, depth);
     196            3928 :         ASSERT(ret);
     197            7856 :         return (TRUE);
     198                 :       }
     199                 :     }
     200                 : 
     201           23596 :     *matches = FALSE;
     202                 :   }
     203               6 :   else if (OPT_SERV_SYM_EQ("and") || OPT_SERV_SYM_EQ("AND") ||
     204                 :            OPT_SERV_SYM_EQ("&&"))
     205                 :   {
     206               4 :     unsigned int depth = token->depth_num;
     207                 : 
     208              12 :     while (conf_token_list_num(token, depth))
     209                 :     {
     210               4 :       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     211               4 :       if (!(*tst_func)(conf, token, matches, prev_match, data))
     212               0 :         return (FALSE);
     213                 : 
     214               4 :       if (!*matches)
     215                 :       {
     216               0 :         int ret = conf_parse_end_token(conf, token, depth);
     217               0 :         ASSERT(ret);
     218               0 :         return (TRUE);
     219                 :       }
     220                 :     }
     221                 :   }
     222                 :   
     223                 :   else
     224               0 :     return (FALSE);
     225                 :   
     226           37404 :   return (TRUE);
     227                 : }
     228                 : 
     229                 : #define OPT_SERV__IOLIM_VAL(x) do {                                     \
     230                 :                                                                         \
     231                 :       OPT_SERV_X_SYM_ULONG_BEG(x);                                      \
     232                 :       else if (OPT_SERV_SYM_EQ("<unlimited>")) (x) = 0;                 \
     233                 :       else if (OPT_SERV_SYM_EQ("<default>"))   (x) = 0;                 \
     234                 :       OPT_SERV_X_SYM_NUM_END();                                         \
     235                 :     } while (FALSE)
     236                 : 
     237                 : static int opt_serv__conf_main_policy_d1(Opt_serv_policy_opts *opts,
     238                 :                                          Conf_parse *conf, Conf_token *token,
     239                 :                                          int clist)
     240              28 : {
     241                 :   unsigned int dummy;
     242                 :   
     243                 :   if (0) { }
     244              28 :   else if (OPT_SERV_SYM_EQ("match-init"))
     245               0 :     OPT_SERV_SC_MATCH_INIT(opts->beg,
     246                 :                            opt_serv__conf_main_policy_d1(opts, conf, token,
     247                 :                                                          clist));
     248                 :   
     249              28 :   else if (OPT_SERV_SYM_EQ("timeout"))
     250                 :   {
     251              72 :     CONF_SC_MAKE_CLIST_BEG(timeout, clist);
     252                 :     
     253              24 :     else if (OPT_SERV_SYM_EQ("idle"))
     254              24 :       OPT_SERV_X_UINT(opts->idle_timeout);
     255               0 :     else if (OPT_SERV_SYM_EQ("total"))
     256               0 :       OPT_SERV_X_SINGLE_UINT(dummy);
     257                 :   
     258               0 :     CONF_SC_MAKE_CLIST_END();
     259                 :   }
     260               4 :   else if (OPT_SERV_SYM_EQ("instant-close"))
     261               0 :     OPT_SERV_X_TOGGLE(opts->use_insta_close);
     262               4 :   else if (OPT_SERV_SYM_EQ("lingering-close"))
     263               0 :     OPT_SERV_X_NEG_TOGGLE(opts->use_insta_close);
     264               4 :   else if (OPT_SERV_SYM_EQ("limit"))
     265                 :   {
     266              12 :     CONF_SC_MAKE_CLIST_BEG(limit, clist);
     267                 :     
     268               4 :     else if (OPT_SERV_SYM_EQ("connections"))
     269               0 :       OPT_SERV_X_UINT(opts->max_connections);
     270               4 :     else if (OPT_SERV_SYM_EQ("io"))
     271                 :     {
     272               4 :       unsigned int clist_ioo = FALSE; /* io outer */
     273               4 :       unsigned int clist_ioi = FALSE; /* io inner */
     274                 :       
     275              16 :       CONF_SC_MAKE_CLIST_BEG(limit_ioo, clist_ioo);
     276                 :       
     277              10 :       else if (OPT_SERV_SYM_EQ("policy-process/s") ||
     278                 :                OPT_SERV_SYM_EQ("policy-process-per-second"))
     279                 :       {
     280              12 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     281                 :         
     282               4 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     283               0 :           OPT_SERV__IOLIM_VAL(opts->io_limit.io_r_max);
     284               6 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     285               4 :           OPT_SERV__IOLIM_VAL(opts->io_limit.io_w_max);
     286                 :         
     287               0 :         CONF_SC_MAKE_CLIST_END();      
     288                 :       }
     289               6 :       else if (OPT_SERV_SYM_EQ("policy-connection/s") ||
     290                 :                OPT_SERV_SYM_EQ("policy-connection-per-second"))
     291                 :       {
     292              12 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     293                 :         
     294               4 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     295               0 :           OPT_SERV__IOLIM_VAL(opts->io_nslimit.io_r_max);
     296               6 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     297               4 :           OPT_SERV__IOLIM_VAL(opts->io_nslimit.io_w_max);
     298                 :         
     299               0 :         CONF_SC_MAKE_CLIST_END();      
     300                 :       }
     301                 :       
     302               0 :       CONF_SC_MAKE_CLIST_END();    
     303                 :     }
     304                 :   
     305               0 :     CONF_SC_MAKE_CLIST_END();
     306                 :   }
     307                 :   else
     308               0 :     return (FALSE);
     309                 :   
     310              28 :   return (TRUE);
     311                 : }
     312                 : 
     313                 : static int opt_serv__conf_main_policy(Opt_serv_opts *opts,
     314                 :                                       Conf_parse *conf, Conf_token *token)
     315              40 : {
     316              40 :   Opt_serv_policy_opts *popts = NULL;
     317              40 :   Conf_token *ntoken = NULL;
     318                 :   unsigned int cur_depth = opt_policy_sc_conf_parse(opts, conf, token,
     319              40 :                                                     &popts, &ntoken);
     320                 :   
     321              40 :   if (!cur_depth)
     322               0 :     return (FALSE);
     323                 :   
     324                 :   do
     325                 :   {
     326              40 :     int clist = FALSE;
     327                 :     
     328             108 :     CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
     329                 :     
     330              28 :     else if (opt_serv__conf_main_policy_d1(popts, conf, token, clist))
     331                 :     { }
     332                 :     
     333               0 :     CONF_SC_MAKE_CLIST_END();
     334                 :   } while (ntoken &&
     335                 :            (cur_depth = opt_policy_sc_conf_parse(opts, conf, token,
     336              40 :                                                  &popts, &ntoken)));
     337                 :   
     338              40 :   return (TRUE);
     339                 : }
     340                 : 
     341                 : static int opt_serv__match_init_tst_d1(struct Opt_serv_opts *,
     342                 :                                        Conf_parse *, Conf_token *,
     343                 :                                        int *, int);
     344                 : static int opt_serv__match_init_tst_op_d1(Conf_parse *conf, Conf_token *token,
     345                 :                                           int *matches, int prev_match,
     346                 :                                           void *passed_data)
     347              32 : {
     348              32 :   struct Opt_serv_opts *opts = passed_data;
     349                 : 
     350              32 :   return (opt_serv__match_init_tst_d1(opts, conf, token, matches, prev_match));
     351                 : }
     352                 : 
     353                 : static int opt_serv__match_init_tst_d1(struct Opt_serv_opts *opts,
     354                 :                                        Conf_parse *conf, Conf_token *token,
     355                 :                                        int *matches, int prev_match)
     356              92 : {
     357              92 :   int clist = FALSE;
     358                 :   
     359              46 :   ASSERT(matches);
     360                 :   
     361              92 :   CONF_SC_TOGGLE_CLIST_VAR(clist);
     362                 : 
     363                 :   if (0) {}
     364                 : 
     365              96 :   else if (OPT_SERV_SYM_EQ("version<=") || OPT_SERV_SYM_EQ("vers<="))
     366                 :   {
     367               4 :     OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     368               4 :     *matches = (vstr_cmp_vers_buf(conf->tmp, 1, conf->tmp->len,
     369                 :                                   opts->vers_cstr, opts->vers_len) >= 0);
     370                 :   }
     371              92 :   else if (OPT_SERV_SYM_EQ("version>=") || OPT_SERV_SYM_EQ("vers>="))
     372                 :   {
     373               4 :     OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     374               4 :     *matches = (vstr_cmp_vers_buf(conf->tmp, 1, conf->tmp->len,
     375                 :                                   opts->vers_cstr, opts->vers_len) <= 0);
     376                 :   }
     377              88 :   else if (OPT_SERV_SYM_EQ("version-eq") || OPT_SERV_SYM_EQ("vers=="))
     378                 :   {
     379               4 :     OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     380               4 :     *matches = (vstr_cmp_vers_buf(conf->tmp, 1, conf->tmp->len,
     381                 :                                   opts->vers_cstr, opts->vers_len) == 0);
     382                 :   }
     383                 : 
     384              84 :   else if (OPT_SERV_SYM_EQ("name-eq") || OPT_SERV_SYM_EQ("name=="))
     385                 :   {
     386               4 :     OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     387               4 :     *matches = vstr_cmp_buf_eq(conf->tmp, 1, conf->tmp->len,
     388                 :                                opts->name_cstr, opts->name_len);
     389                 :   }
     390                 : 
     391              78 :   else if (OPT_SERV_SYM_EQ("hostname-eq") ||
     392                 :            OPT_SERV_SYM_EQ("hostname=="))
     393                 :   {
     394               4 :     size_t lpos = 0;
     395                 :     
     396               4 :     OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     397                 : 
     398               4 :     lpos = conf->tmp->len;
     399               4 :     if (!opt_serv_sc_append_hostname(conf->tmp, lpos))
     400               0 :       return (FALSE);
     401                 :     
     402               4 :     if (lpos == conf->tmp->len)
     403               0 :       *matches = !!conf->tmp->len; /* if they are both blank, they match */
     404                 :     else
     405                 :     {
     406               4 :       size_t len = vstr_sc_posdiff(lpos + 1, conf->tmp->len);
     407               4 :       *matches = vstr_cmp_case_eq(conf->tmp, 1, lpos, conf->tmp, lpos + 1, len);
     408                 :     }
     409                 :   }
     410                 : 
     411              76 :   else if (OPT_SERV_SYM_EQ("uid-eq") ||
     412                 :            OPT_SERV_SYM_EQ("uid=="))
     413                 :   {
     414               4 :     unsigned int dummy = 0;
     415               4 :     OPT_SERV_X_SINGLE_UINT(dummy);
     416               4 :     *matches = (dummy == getuid());
     417                 :   }
     418              72 :   else if (OPT_SERV_SYM_EQ("euid-eq") ||
     419                 :            OPT_SERV_SYM_EQ("euid=="))
     420                 :   {
     421               4 :     unsigned int dummy = 0;
     422               4 :     OPT_SERV_X_SINGLE_UINT(dummy);
     423               4 :     *matches = (dummy == geteuid());
     424                 :   }
     425                 : 
     426              64 :   else if (OPT_SERV_SYM_EQ("debug"))
     427              12 :     *matches = COMPILE_DEBUG;
     428                 :   
     429                 :   else
     430              52 :     return (opt_serv_sc_tst(conf, token, matches, prev_match,
     431                 :                             opt_serv__match_init_tst_op_d1, opts));
     432                 : 
     433              40 :   return (TRUE);
     434                 : }
     435                 : 
     436                 : int opt_serv_match_init(struct Opt_serv_opts *opts,
     437                 :                         Conf_parse *conf, Conf_token *token)
     438              60 : {
     439                 :   static int prev_match = TRUE;
     440              60 :   int matches = TRUE;
     441              60 :   unsigned int depth = token->depth_num;
     442                 : 
     443              60 :   CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     444              60 :   ++depth;
     445             180 :   while (conf_token_list_num(token, depth))
     446                 :   {
     447              60 :     CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     448                 : 
     449              60 :     if (!opt_serv__match_init_tst_d1(opts, conf, token, &matches, prev_match))
     450               0 :       return (FALSE);
     451                 : 
     452              60 :     if (!matches)
     453              10 :       conf_parse_end_token(conf, token, depth - 1);
     454                 :   }
     455                 : 
     456              60 :   prev_match = matches;
     457                 :   
     458              60 :   return (TRUE);
     459                 : }
     460                 : 
     461                 : #define OPT_SERV__RLIM_VAL(x, y) do {                                   \
     462                 :       (y) = TRUE;                                                       \
     463                 :                                                                         \
     464                 :       OPT_SERV_X_SYM_ULONG_BEG(x);                                      \
     465                 :       else if (OPT_SERV_SYM_EQ("<infinity>"))  (x) = RLIM_INFINITY;     \
     466                 :       else if (OPT_SERV_SYM_EQ("<unlimited>")) (x) = RLIM_INFINITY;     \
     467                 :       else if (OPT_SERV_SYM_EQ("<default>"))   (y) = FALSE;             \
     468                 :       OPT_SERV_X_SYM_NUM_END();                                         \
     469                 :     } while (FALSE)
     470                 : 
     471                 : #define OPT_SERV__TMP_EQ(x) vstr_cmp_cstr_eq(conf->tmp, 1, conf->tmp->len, x)
     472                 : 
     473                 : #define OPT_SERV_ADDR_DUP_VSTR(x, y, z)                                 \
     474                 :     (((x)-> z) = vstr_dup_vstr((y)-> z ->conf ,                         \
     475                 :                                (y)-> z , 1, (y)-> z ->len,              \
     476                 :                                VSTR_TYPE_SUB_BUF_REF))
     477                 : 
     478                 : static void opt_serv__free_addr(Opt_serv_addr_opts *addr)
     479             130 : {
     480             130 :   if (!addr)
     481               0 :     return;
     482                 :   
     483             130 :   vstr_free_base(addr->acpt_filter_file);
     484             130 :   vstr_free_base(addr->acpt_address);
     485             130 :   vstr_free_base(addr->acpt_cong);
     486             130 :   vstr_free_base(addr->def_policy);
     487             130 :   F(addr);
     488                 : }
     489                 : 
     490                 : static Opt_serv_addr_opts *opt_serv_make_addr(Opt_serv_opts *)
     491                 :     COMPILE_ATTR_NONNULL_A() COMPILE_ATTR_WARN_UNUSED_RET();
     492                 : static Opt_serv_addr_opts *opt_serv_make_addr(Opt_serv_opts *opts)
     493              84 : {
     494              84 :   Opt_serv_addr_opts *addr = NULL;
     495                 : 
     496              42 :   ASSERT(opts && opts->addr_beg);
     497                 :   
     498              84 :   if (opts->no_conf_listen)
     499                 :   { /* use the initial one to start with */
     500               0 :     opts->no_conf_listen = FALSE;
     501               0 :     return (opts->addr_beg);
     502                 :   }
     503                 : 
     504                 :   /* duplicate the currnet one */
     505              84 :   if (!(addr = MK(sizeof(Opt_serv_addr_opts))))
     506               0 :     goto mk_addr_fail;
     507                 :     
     508              84 :   OPT_SERV_ADDR_DUP_VSTR(addr, opts->addr_beg, acpt_filter_file);
     509              84 :   OPT_SERV_ADDR_DUP_VSTR(addr, opts->addr_beg, acpt_address);
     510              84 :   OPT_SERV_ADDR_DUP_VSTR(addr, opts->addr_beg, acpt_cong);
     511              84 :   OPT_SERV_ADDR_DUP_VSTR(addr, opts->addr_beg, def_policy);
     512                 :   
     513              84 :   if (!addr->acpt_filter_file ||
     514                 :       !addr->acpt_address     ||
     515                 :       !addr->acpt_cong        ||
     516                 :       !addr->def_policy       ||
     517                 :       FALSE)
     518                 :     goto addr_init_fail;
     519                 :   
     520              84 :   addr->next = NULL;
     521                 :   
     522              84 :   addr->tcp_port        = opts->addr_beg->tcp_port;
     523              84 :   addr->defer_accept    = opts->addr_beg->defer_accept;
     524              84 :   addr->q_listen_len    = opts->addr_beg->q_listen_len;
     525              84 :   addr->max_connections = opts->addr_beg->max_connections;
     526                 : 
     527              84 :   addr->next = opts->addr_beg;
     528              84 :   opts->addr_beg = addr;
     529                 : 
     530              84 :   return (addr);
     531                 : 
     532               0 :  addr_init_fail:
     533               0 :   F(addr);
     534               0 :  mk_addr_fail:
     535               0 :   return (FALSE);
     536                 : }
     537                 : 
     538                 : static Opt_serv_addr_opts *opt_serv__srch_addr(Opt_serv_addr_opts *scan,
     539                 :                                                Opt_serv_addr_opts *addr)
     540              86 : {
     541             674 :   while (scan)
     542                 :   {
     543             506 :     if ((scan->tcp_port == addr->tcp_port) &&
     544                 :         vstr_cmp_eq(scan->acpt_address, 1, scan->acpt_address->len,
     545                 :                     addr->acpt_address, 1, addr->acpt_address->len))
     546               4 :       break;
     547                 : 
     548             502 :     scan = scan->next;
     549                 :   }
     550                 : 
     551              86 :   return (scan);
     552                 : }
     553                 : 
     554                 : #define OPT_SERV__ADDR_MERGE_VSTR(z) do {                               \
     555                 :       if (!vstr_sub_vstr(oaddr-> z, 1, oaddr-> z ->len,                 \
     556                 :                          naddr-> z, 1, naddr-> z ->len, VSTR_TYPE_SUB_DEF)) \
     557                 :         return (FALSE);                                                 \
     558                 :     } while (FALSE)
     559                 :   
     560                 : static int opt_serv_merge_addrs(Opt_serv_opts *)
     561                 :     COMPILE_ATTR_NONNULL_A() COMPILE_ATTR_WARN_UNUSED_RET();
     562                 : static int opt_serv_merge_addrs(Opt_serv_opts *opts)
     563              84 : {
     564              84 :   Opt_serv_addr_opts *oaddr = NULL;
     565              84 :   Opt_serv_addr_opts *naddr = NULL;
     566                 : 
     567              42 :   ASSERT(opts && opts->addr_beg);
     568                 :   
     569              84 :   naddr = opts->addr_beg;
     570              84 :   oaddr = opt_serv__srch_addr(naddr->next, naddr);
     571                 : 
     572              84 :   if (!oaddr)
     573              80 :     return (TRUE);
     574                 :   
     575                 :   /* can't match more than one */
     576               2 :   ASSERT(!opt_serv__srch_addr(oaddr->next, naddr));
     577                 : 
     578               4 :   OPT_SERV__ADDR_MERGE_VSTR(acpt_filter_file);
     579               2 :   ASSERT(vstr_cmp_eq(oaddr->acpt_address, 1, oaddr->acpt_address->len,
     580                 :                      naddr->acpt_address, 1, naddr->acpt_address->len));
     581               4 :   OPT_SERV__ADDR_MERGE_VSTR(acpt_cong);
     582               4 :   OPT_SERV__ADDR_MERGE_VSTR(def_policy);
     583                 : 
     584               2 :   ASSERT(oaddr->tcp_port == naddr->tcp_port);
     585               4 :   oaddr->defer_accept    = naddr->defer_accept;
     586               4 :   oaddr->q_listen_len    = naddr->q_listen_len;
     587               4 :   oaddr->max_connections = naddr->max_connections;
     588                 :   
     589               4 :   opts->addr_beg = naddr->next;
     590               4 :   opt_serv__free_addr(naddr);
     591                 : 
     592               4 :   return (TRUE);
     593                 : }
     594                 : 
     595                 : static int opt_serv__conf_d1(struct Opt_serv_opts *opts,
     596                 :                              Conf_parse *conf, Conf_token *token,
     597                 :                              int clist)
     598             328 : {
     599                 :   if (0) { }
     600                 : 
     601             328 :   else if (OPT_SERV_SYM_EQ("match-init"))
     602               8 :     OPT_SERV_SC_MATCH_INIT(opts, opt_serv__conf_d1(opts, conf, token, clist));
     603                 :   
     604             320 :   else if (OPT_SERV_SYM_EQ("policy"))
     605                 :   {
     606              40 :     if (!opt_serv__conf_main_policy(opts, conf, token))
     607               0 :       return (FALSE);
     608                 :   }
     609                 :   
     610             280 :   else if (OPT_SERV_SYM_EQ("chroot"))
     611               4 :     return (opt_serv_sc_make_static_path(opts, conf, token, opts->chroot_dir));
     612             276 :   else if (OPT_SERV_SYM_EQ("cntl-file") ||
     613                 :            OPT_SERV_SYM_EQ("control-file"))
     614              52 :     return (opt_serv_sc_make_static_path(opts, conf, token, opts->cntl_file));
     615             232 :   else if (OPT_SERV_SYM_EQ("daemonize") || OPT_SERV_SYM_EQ("daemonise"))
     616               8 :     OPT_SERV_X_TOGGLE(opts->become_daemon);
     617             216 :   else if (OPT_SERV_SYM_EQ("drop-privs"))
     618                 :   {
     619               8 :     unsigned int depth = token->depth_num;
     620               8 :     int val = opts->drop_privs;
     621               8 :     int ern = conf_sc_token_parse_toggle(conf, token, &val);
     622               8 :     unsigned int num = conf_token_list_num(token, token->depth_num);
     623                 :     
     624               8 :     if (ern == CONF_SC_TYPE_RET_ERR_NO_MATCH)
     625               0 :       return (FALSE);
     626               8 :     if (!val && num)
     627               0 :       return (FALSE);
     628                 : 
     629               8 :     opts->drop_privs = val;
     630              36 :     CONF_SC_MAKE_CLIST_MID(depth, clist);
     631                 : 
     632              20 :     else if (OPT_SERV_SYM_EQ("uid"))
     633               4 :       OPT_SERV_X_SINGLE_UINT(opts->priv_uid);
     634              18 :     else if (OPT_SERV_SYM_EQ("usrname") ||
     635                 :              OPT_SERV_SYM_EQ("username"))
     636               4 :       OPT_SERV_X_VSTR(opts, opts->vpriv_uid);
     637              12 :     else if (OPT_SERV_SYM_EQ("gid"))
     638               4 :       OPT_SERV_X_SINGLE_UINT(opts->priv_gid);
     639              10 :     else if (OPT_SERV_SYM_EQ("grpname") ||
     640                 :              OPT_SERV_SYM_EQ("groupname"))
     641               4 :       OPT_SERV_X_VSTR(opts, opts->vpriv_gid);
     642               8 :     else if (OPT_SERV_SYM_EQ("keep-CAP_FOWNER") ||
     643                 :              OPT_SERV_SYM_EQ("keep-cap-fowner"))
     644               4 :       OPT_SERV_X_TOGGLE(opts->keep_cap_fowner);
     645                 : 
     646               0 :     CONF_SC_MAKE_CLIST_END();
     647                 :   }
     648             208 :   else if (OPT_SERV_SYM_EQ("dumpable"))
     649               0 :     OPT_SERV_X_TOGGLE(opts->make_dumpable);
     650             208 :   else if (OPT_SERV_SYM_EQ("listen"))
     651                 :   {
     652              84 :     Opt_serv_addr_opts *addr = opt_serv_make_addr(opts);
     653             312 :     CONF_SC_MAKE_CLIST_BEG(listen, clist);
     654                 : 
     655             144 :     else if (!addr) return (FALSE);
     656                 :     
     657             144 :     else if (OPT_SERV_SYM_EQ("defer-accept"))
     658               8 :       OPT_SERV_X_UINT(addr->defer_accept);
     659             136 :     else if (OPT_SERV_SYM_EQ("port"))
     660               4 :       OPT_SERV_X_UINT(addr->tcp_port);
     661             174 :     else if (OPT_SERV_SYM_EQ("addr") || OPT_SERV_SYM_EQ("address"))
     662              84 :       OPT_SERV_X_VSTR(opts, addr->acpt_address);
     663              48 :     else if (OPT_SERV_SYM_EQ("cong") || OPT_SERV_SYM_EQ("congestion"))
     664               0 :       OPT_SERV_X_VSTR(opts, addr->acpt_cong);
     665              48 :     else if (OPT_SERV_SYM_EQ("policy"))
     666              20 :       OPT_SERV_X_VSTR(opts, addr->def_policy);
     667              28 :     else if (OPT_SERV_SYM_EQ("queue-length"))
     668                 :     {
     669              12 :       OPT_SERV_X_SYM_UINT_BEG(addr->q_listen_len);
     670               4 :       else if (OPT_SERV_SYM_EQ("<max>")) addr->q_listen_len = SOMAXCONN;
     671               0 :       OPT_SERV_X_SYM_NUM_END();
     672                 :     }
     673              16 :     else if (OPT_SERV_SYM_EQ("filter"))
     674                 :     {
     675               8 :       if (!opt_serv_sc_make_static_path(opts, conf, token,
     676                 :                                         addr->acpt_filter_file))
     677               0 :         return (FALSE);
     678                 :     }
     679               8 :     else if (OPT_SERV_SYM_EQ("max-connections"))
     680               8 :       OPT_SERV_X_UINT(addr->max_connections);
     681                 : 
     682               0 :     CONF_SC_MAKE_CLIST_END();
     683                 : 
     684              84 :     if (!opt_serv_merge_addrs(opts))
     685               0 :       return (FALSE);
     686                 :   }
     687             124 :   else if (OPT_SERV_SYM_EQ("parent-death-signal"))
     688               0 :     OPT_SERV_X_TOGGLE(opts->use_pdeathsig);
     689             124 :   else if (OPT_SERV_SYM_EQ("pid-file"))
     690              32 :     return (opt_serv_sc_make_static_path(opts, conf, token, opts->pid_file));
     691             100 :   else if (OPT_SERV_SYM_EQ("processes") ||
     692                 :            OPT_SERV_SYM_EQ("procs"))
     693                 :   {
     694              16 :     OPT_SERV_X_SYM_UINT_BEG(opts->num_procs);
     695                 :     
     696               0 :     else if (OPT_SERV_SYM_EQ("<sysconf-number-processors-configured>") ||
     697                 :              OPT_SERV_SYM_EQ("<sysconf-num-procs-configured>") ||
     698                 :              OPT_SERV_SYM_EQ("<sysconf-num-procs-conf>"))
     699               0 :       opts->num_procs = sysconf(_SC_NPROCESSORS_CONF);
     700               0 :     else if (OPT_SERV_SYM_EQ("<sysconf-number-processors-online>") ||
     701                 :              OPT_SERV_SYM_EQ("<sysconf-num-procs-online>") ||
     702                 :              OPT_SERV_SYM_EQ("<sysconf-num-procs-onln>"))
     703               0 :       opts->num_procs = sysconf(_SC_NPROCESSORS_ONLN);
     704                 :     
     705               0 :     OPT_SERV_X_SYM_NUM_END();    
     706                 :   }
     707              76 :   else if (OPT_SERV_SYM_EQ("logging"))
     708                 :   {
     709              12 :     CONF_SC_MAKE_CLIST_BEG(logging_main, clist);
     710                 :     
     711               4 :     else if (OPT_SERV_SYM_EQ("syslog"))
     712                 :     {
     713             116 :       CONF_SC_MAKE_CLIST_BEG(logging_syslog, clist);
     714             108 :       else if (OPT_SERV_SYM_EQ("native"))
     715               0 :         OPT_SERV_X_TOGGLE(opts->vlg_syslog_native);
     716             108 :       else if (OPT_SERV_SYM_EQ("limit"))
     717                 :       {
     718               0 :         CONF_SC_MAKE_CLIST_BEG(logging_limit, clist);
     719                 :         
     720               0 :         else if (OPT_SERV_SYM_EQ("size"))
     721                 :         {
     722               0 :           opts->vlg_tweaked_size = TRUE;
     723               0 :           OPT_SERV_X_ULONG(opts->vlg_size);
     724                 :         }
     725                 :     
     726               0 :         CONF_SC_MAKE_CLIST_END();
     727                 :       }
     728             108 :       else if (OPT_SERV_SYM_EQ("facility"))
     729                 :       {
     730             108 :         OPT_SERV_X_SINGLE_VSTR(conf->tmp);
     731                 :         if (0) { }
     732                 :         
     733             116 :         else if (OPT_SERV__TMP_EQ("AUTHPRIV") ||
     734                 :                  OPT_SERV__TMP_EQ("AUTH"))
     735               8 :           opts->syslog_facility = LOG_AUTHPRIV;
     736             100 :         else if (OPT_SERV__TMP_EQ("CRON"))   opts->syslog_facility = LOG_CRON;
     737              96 :         else if (OPT_SERV__TMP_EQ("DAEMON")) opts->syslog_facility = LOG_DAEMON;
     738              92 :         else if (OPT_SERV__TMP_EQ("FTP"))    opts->syslog_facility = LOG_FTP;
     739              84 :         else if (OPT_SERV__TMP_EQ("LOCAL"))
     740                 :         {
     741              32 :           unsigned int num = 0;
     742                 :           
     743              32 :           OPT_SERV_X_SINGLE_UINT(num);
     744              32 :           switch (num)
     745                 :           {
     746               0 :             default: return (FALSE);
     747               4 :             case 0: opts->syslog_facility = LOG_LOCAL0;
     748               8 :             case 1: opts->syslog_facility = LOG_LOCAL1;
     749              12 :             case 2: opts->syslog_facility = LOG_LOCAL2;
     750              16 :             case 3: opts->syslog_facility = LOG_LOCAL3;
     751              20 :             case 4: opts->syslog_facility = LOG_LOCAL4;
     752              24 :             case 5: opts->syslog_facility = LOG_LOCAL5;
     753              28 :             case 6: opts->syslog_facility = LOG_LOCAL6;
     754              32 :             case 7: opts->syslog_facility = LOG_LOCAL7;
     755                 :           }
     756                 :         }
     757              52 :         else if (OPT_SERV__TMP_EQ("LOCAL0")) opts->syslog_facility = LOG_LOCAL0;
     758              48 :         else if (OPT_SERV__TMP_EQ("LOCAL1")) opts->syslog_facility = LOG_LOCAL1;
     759              44 :         else if (OPT_SERV__TMP_EQ("LOCAL2")) opts->syslog_facility = LOG_LOCAL2;
     760              40 :         else if (OPT_SERV__TMP_EQ("LOCAL3")) opts->syslog_facility = LOG_LOCAL3;
     761              36 :         else if (OPT_SERV__TMP_EQ("LOCAL4")) opts->syslog_facility = LOG_LOCAL4;
     762              32 :         else if (OPT_SERV__TMP_EQ("LOCAL5")) opts->syslog_facility = LOG_LOCAL5;
     763              28 :         else if (OPT_SERV__TMP_EQ("LOCAL6")) opts->syslog_facility = LOG_LOCAL6;
     764              24 :         else if (OPT_SERV__TMP_EQ("LOCAL7")) opts->syslog_facility = LOG_LOCAL7;
     765              20 :         else if (OPT_SERV__TMP_EQ("LPR"))    opts->syslog_facility = LOG_LPR;
     766              16 :         else if (OPT_SERV__TMP_EQ("MAIL"))   opts->syslog_facility = LOG_MAIL;
     767              12 :         else if (OPT_SERV__TMP_EQ("NEWS"))   opts->syslog_facility = LOG_NEWS;
     768               8 :         else if (OPT_SERV__TMP_EQ("USER"))   opts->syslog_facility = LOG_USER;
     769               4 :         else if (OPT_SERV__TMP_EQ("UUCP"))   opts->syslog_facility = LOG_UUCP;
     770                 :         
     771                 :         else
     772               0 :           return (FALSE);
     773                 : 
     774                 :       }
     775               0 :       CONF_SC_MAKE_CLIST_END();
     776                 :     }
     777                 :     
     778               0 :     CONF_SC_MAKE_CLIST_END();
     779                 :   }
     780             104 :   else if (OPT_SERV_SYM_EQ("resource-limits") ||
     781                 :            OPT_SERV_SYM_EQ("rlimit"))
     782                 :   {
     783             192 :     CONF_SC_MAKE_CLIST_BEG(rlimit, clist);
     784                 : 
     785              64 :     else if (OPT_SERV_SYM_EQ("AS")     || OPT_SERV_SYM_EQ("address-space"))
     786               0 :       OPT_SERV__RLIM_VAL(opts->rlim_as_num, opts->rlim_as_call);
     787              96 :     else if (OPT_SERV_SYM_EQ("CORE")   || OPT_SERV_SYM_EQ("core"))
     788              64 :       OPT_SERV__RLIM_VAL(opts->rlim_core_num, opts->rlim_core_call);
     789               0 :     else if (OPT_SERV_SYM_EQ("NOFILE") || OPT_SERV_SYM_EQ("fd-num") ||
     790                 :              OPT_SERV_SYM_EQ("file-descriptor-number"))
     791               0 :       OPT_SERV__RLIM_VAL(opts->rlim_file_num, opts->rlim_file_call);
     792                 :       
     793               0 :     CONF_SC_MAKE_CLIST_END();
     794                 :   }
     795                 :   /*  else if (OPT_SERV_SYM_EQ("priority"))
     796                 :       OPT_SERV_X_UINT(opts->sys_priority); */
     797               8 :   else if (OPT_SERV_SYM_EQ("cache-limits"))
     798                 :   {
     799               0 :     CONF_SC_MAKE_CLIST_BEG(cache_limits, clist);
     800                 :     
     801               0 :     else if (OPT_SERV_SYM_EQ("spare-vstr-bases"))
     802               0 :       OPT_SERV_X_UINT(opts->max_spare_bases);
     803               0 :     else if (OPT_SERV_SYM_EQ("spare-vstr-nodes-buf"))
     804               0 :       OPT_SERV_X_UINT(opts->max_spare_buf_nodes);
     805               0 :     else if (OPT_SERV_SYM_EQ("spare-vstr-nodes-ptr"))
     806               0 :       OPT_SERV_X_UINT(opts->max_spare_ptr_nodes);
     807               0 :     else if (OPT_SERV_SYM_EQ("spare-vstr-nodes-ref"))
     808               0 :       OPT_SERV_X_UINT(opts->max_spare_ref_nodes);
     809                 :     
     810               0 :     CONF_SC_MAKE_CLIST_END();
     811                 :   }
     812               8 :   else if (OPT_SERV_SYM_EQ("limit"))
     813                 :   {
     814              12 :     CONF_SC_MAKE_CLIST_BEG(limit, clist);
     815                 :     
     816               4 :     else if (OPT_SERV_SYM_EQ("io"))
     817                 :     {
     818               4 :       unsigned int clist_ioo = FALSE; /* io outer */
     819               4 :       unsigned int clist_ioi = FALSE; /* io inner */
     820                 :       
     821              16 :       CONF_SC_MAKE_CLIST_BEG(limit_ioo, clist_ioo);
     822                 :       
     823              10 :       else if (OPT_SERV_SYM_EQ("process/s") ||
     824                 :                OPT_SERV_SYM_EQ("process-per-second"))
     825                 :       {
     826              12 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     827                 :         
     828               4 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     829               0 :           OPT_SERV__IOLIM_VAL(opts->io_limit.io_r_max);
     830               6 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     831               4 :           OPT_SERV__IOLIM_VAL(opts->io_limit.io_w_max);
     832                 :         
     833               0 :         CONF_SC_MAKE_CLIST_END();      
     834                 :       }
     835               4 :       else if (OPT_SERV_SYM_EQ("policy-process/s") ||
     836                 :                OPT_SERV_SYM_EQ("policy-process-per-second"))
     837                 :       {
     838               0 :         Opt_serv_policy_opts *popts = NULL;
     839                 :         
     840               0 :         if (!(popts = opt_policy_conf_find(opts, conf, token)))
     841               0 :           return (FALSE);
     842                 :         
     843               0 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     844                 :         
     845               0 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     846               0 :           OPT_SERV__IOLIM_VAL(popts->io_limit.io_r_max);
     847               0 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     848               0 :           OPT_SERV__IOLIM_VAL(popts->io_limit.io_w_max);
     849                 :         
     850               0 :         CONF_SC_MAKE_CLIST_END();      
     851                 :       }
     852               4 :       else if (OPT_SERV_SYM_EQ("policy-connection/s") ||
     853                 :                OPT_SERV_SYM_EQ("policy-connection-per-second"))
     854                 :       {
     855               0 :         Opt_serv_policy_opts *popts = NULL;
     856                 :         
     857               0 :         if (!(popts = opt_policy_conf_find(opts, conf, token)))
     858               0 :           return (FALSE);
     859                 :         
     860               0 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     861                 :         
     862               0 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     863               0 :           OPT_SERV__IOLIM_VAL(popts->io_nslimit.io_r_max);
     864               0 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     865               0 :           OPT_SERV__IOLIM_VAL(popts->io_nslimit.io_w_max);
     866                 :         
     867               0 :         CONF_SC_MAKE_CLIST_END();      
     868                 :       }
     869               6 :       else if (OPT_SERV_SYM_EQ("connection/s") ||
     870                 :                OPT_SERV_SYM_EQ("connection-per-second"))
     871                 :       {
     872              12 :         CONF_SC_MAKE_CLIST_BEG(limit_ioi, clist_ioi);
     873                 :         
     874               4 :         else if (OPT_SERV_SYM_EQ("read") || OPT_SERV_SYM_EQ("recv"))
     875               0 :           OPT_SERV__IOLIM_VAL(opts->io_nslimit.io_r_max);
     876               6 :         else if (OPT_SERV_SYM_EQ("write") || OPT_SERV_SYM_EQ("send"))
     877               4 :           OPT_SERV__IOLIM_VAL(opts->io_nslimit.io_w_max);
     878                 :         
     879               0 :         CONF_SC_MAKE_CLIST_END();
     880                 :       }
     881                 :       
     882               0 :       CONF_SC_MAKE_CLIST_END();    
     883                 :     }
     884                 :   
     885               0 :     CONF_SC_MAKE_CLIST_END();
     886                 :   }
     887                 :   
     888                 :   else
     889               4 :     return (FALSE);
     890                 :   
     891             236 :   return (TRUE);
     892                 : }
     893                 : #undef OPT_SERV__RLIM_VAL
     894                 : 
     895                 : int opt_serv_conf(struct Opt_serv_opts *opts,
     896                 :                   Conf_parse *conf, Conf_token *token)
     897             108 : {
     898             108 :   unsigned int cur_depth = token->depth_num;
     899             108 :   int clist = FALSE;
     900                 :   
     901              54 :   ASSERT(opts && conf && token);
     902                 : 
     903             108 :   if (!conf_token_cmp_sym_cstr_eq(conf, token, "org.and.daemon-conf-1.0"))
     904               0 :     return (FALSE);
     905                 :   
     906             650 :   CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
     907                 :   
     908             328 :   else if (opt_serv__conf_d1(opts, conf, token, clist))
     909                 :   { }
     910                 :   
     911               4 :   CONF_SC_MAKE_CLIST_END();
     912                 :   
     913                 :   /* And they all live together ... dum dum */
     914             104 :   if (conf->data->conf->malloc_bad)
     915               0 :     return (FALSE);
     916                 : 
     917             104 :   return (TRUE);
     918                 : }
     919                 : 
     920                 : int opt_serv_conf_parse_cstr(Vstr_base *out,
     921                 :                              Opt_serv_opts *opts, const char *data)
     922              32 : {
     923              32 :   Conf_parse *conf    = conf_parse_make(NULL);
     924              32 :   Conf_token token[1] = {CONF_TOKEN_INIT};
     925                 : 
     926              16 :   ASSERT(opts && data);
     927                 :   
     928              32 :   if (!conf)
     929               0 :     goto conf_malloc_fail;
     930                 :   
     931              32 :   if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
     932                 :                          "(org.and.daemon-conf-1.0 "))
     933               0 :     goto read_malloc_fail;
     934              32 :   if (!vstr_add_cstr_ptr(conf->data, conf->data->len, data))
     935               0 :     goto read_malloc_fail;
     936              32 :   if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
     937                 :                          ")"))
     938               0 :     goto read_malloc_fail;
     939                 : 
     940              32 :   if (!conf_parse_lex(conf, 1, conf->data->len))
     941               0 :     goto conf_fail;
     942                 : 
     943              32 :   if (!conf_parse_token(conf, token))
     944               0 :     goto conf_fail;
     945                 :     
     946              32 :   if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
     947                 :     goto conf_fail;
     948                 :     
     949              32 :   if (!conf_parse_token(conf, token))
     950               0 :     goto conf_fail;
     951                 : 
     952              16 :   ASSERT(conf_token_cmp_sym_cstr_eq(conf, token, "org.and.daemon-conf-1.0"));
     953                 :   
     954              32 :   if (!opt_serv_conf(opts, conf, token))
     955               4 :     goto conf_fail;
     956              28 :   if (token->num != conf->sects->num)
     957               0 :     goto conf_fail;
     958                 : 
     959              28 :   conf_parse_free(conf);
     960              28 :   return (TRUE);
     961                 :   
     962               4 :  conf_fail:
     963               4 :   conf_parse_backtrace(out, data, conf, token);
     964               4 :  read_malloc_fail:
     965               4 :   conf_parse_free(conf);
     966               4 :  conf_malloc_fail:
     967               4 :   return (FALSE);
     968                 : }
     969                 : 
     970                 : int opt_serv_conf_parse_file(Vstr_base *out,
     971                 :                              Opt_serv_opts *opts, const char *fname)
     972               0 : {
     973               0 :   Conf_parse *conf    = conf_parse_make(NULL);
     974               0 :   Conf_token token[1] = {CONF_TOKEN_INIT};
     975                 : 
     976               0 :   ASSERT(opts && fname);
     977                 :   
     978               0 :   if (!conf)
     979               0 :     goto conf_malloc_fail;
     980                 :   
     981               0 :   if (!vstr_sc_read_len_file(conf->data, 0, fname, 0, 0, NULL))
     982               0 :     goto read_malloc_fail;
     983                 : 
     984               0 :   if (!conf_parse_lex(conf, 1, conf->data->len))
     985               0 :     goto conf_fail;
     986                 : 
     987               0 :   while (conf_parse_token(conf, token))
     988                 :   {
     989               0 :     if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
     990                 :       goto conf_fail;
     991                 : 
     992               0 :     if (!conf_parse_token(conf, token))
     993               0 :       goto conf_fail;
     994                 :     
     995               0 :     if (!conf_token_cmp_sym_cstr_eq(conf, token, "org.and.daemon-conf-1.0"))
     996               0 :       goto conf_fail;
     997                 :   
     998               0 :     if (!opt_serv_conf(opts, conf, token))
     999               0 :       goto conf_fail;
    1000                 :   }
    1001                 : 
    1002               0 :   conf_parse_free(conf);
    1003               0 :   return (TRUE);
    1004                 :   
    1005               0 :  conf_fail:
    1006               0 :   conf_parse_backtrace(out, fname, conf, token);
    1007               0 :   errno = 0;
    1008               0 :  read_malloc_fail:
    1009               0 :   if (errno && out) /* can't find config. file */
    1010               0 :     vstr_add_fmt(out, out->len, "open(%s): %m", fname);
    1011               0 :   conf_parse_free(conf);
    1012               0 :  conf_malloc_fail:
    1013               0 :   return (FALSE);
    1014                 : }
    1015                 : 
    1016                 : void opt_serv_conf_free_beg(struct Opt_serv_opts *opts)
    1017              88 : {
    1018              88 :   Opt_serv_addr_opts *scan = NULL;
    1019                 :   
    1020              88 :   if (!opts)
    1021               0 :     return;
    1022                 :   
    1023              88 :   vstr_free_base(opts->pid_file);         opts->pid_file         = NULL;
    1024              88 :   vstr_free_base(opts->cntl_file);        opts->cntl_file        = NULL;
    1025              88 :   vstr_free_base(opts->chroot_dir);       opts->chroot_dir       = NULL;
    1026              88 :   vstr_free_base(opts->vpriv_uid);        opts->vpriv_uid        = NULL;
    1027              88 :   vstr_free_base(opts->vpriv_gid);        opts->vpriv_gid        = NULL;
    1028                 : 
    1029              88 :   scan = opts->addr_beg;
    1030              88 :   opts->addr_beg = NULL;
    1031             302 :   while (scan)
    1032                 :   {
    1033             126 :     Opt_serv_addr_opts *scan_next = scan->next;
    1034                 : 
    1035             126 :     opt_serv__free_addr(scan);
    1036                 : 
    1037             126 :     scan = scan_next;
    1038                 :   }
    1039                 : }
    1040                 : 
    1041                 : void opt_serv_conf_free_end(struct Opt_serv_opts *opts)
    1042              44 : {
    1043              44 :   if (!opts)
    1044               0 :     return;
    1045                 : 
    1046              22 :   ASSERT( opts->ref_io_limit);
    1047              44 :   vstr_ref_del(opts->ref_io_limit);
    1048              22 :   ASSERT(!opts->ref_io_limit);
    1049                 : }
    1050                 : 
    1051                 : static void opt_serv__io_lim_ref_cb(struct Vstr_ref *ref)
    1052              44 : {
    1053              44 :   Opt_serv_opts *opts = NULL;
    1054              44 :   struct Evnt_limit *lim = NULL;
    1055                 : 
    1056              44 :   if (!ref)
    1057               0 :     return;
    1058                 :   
    1059              44 :   lim = ref->ptr;
    1060              22 :   ASSERT(lim);
    1061                 :   
    1062                 :   /* ISO C magic, converts a ptr to io_limit into a pointer to opts */
    1063              44 :   opts = (Opt_serv_opts *)(((char *)lim) - offsetof(Opt_serv_opts, io_limit));
    1064              44 :   opts->ref_io_limit = NULL; /* more magic */
    1065                 : }
    1066                 : 
    1067                 : int opt_serv_conf_init(Opt_serv_opts *opts)
    1068              64 : {
    1069              64 :   struct Opt_serv_policy_opts *popts = NULL;
    1070              64 :   Opt_serv_addr_opts *addr = MK(sizeof(Opt_serv_addr_opts));
    1071                 :   
    1072              32 :   ASSERT(opts && opts->make_policy && opts->copy_policy);
    1073                 : 
    1074              64 :   if (!addr)
    1075               0 :     goto mk_addr_fail;
    1076                 : 
    1077              64 :   if (!opt_serv__init_append_hostname())
    1078               0 :     goto mk_append_hostname_fail;
    1079                 :   
    1080              64 :   if (!(popts = (*opts->make_policy)(opts)))
    1081               0 :     goto mk_policy_fail;
    1082                 : 
    1083              64 :   opts->def_policy = popts;
    1084              64 :   vstr_add_cstr_ptr(popts->policy_name, 0, OPT_POLICY_CONF_DEF_POLICY_NAME);
    1085                 : 
    1086              64 :   if (popts->policy_name->conf->malloc_bad)
    1087               0 :     goto policy_init_fail;
    1088                 : 
    1089              64 :   opts->pid_file         = vstr_make_base(NULL);
    1090              64 :   opts->cntl_file        = vstr_make_base(NULL);
    1091              64 :   opts->chroot_dir       = vstr_make_base(NULL);
    1092              64 :   opts->vpriv_uid        = vstr_make_base(NULL);
    1093              64 :   opts->vpriv_gid        = vstr_make_base(NULL);
    1094              64 :   addr->acpt_filter_file = vstr_make_base(NULL);
    1095              64 :   addr->acpt_address     = vstr_make_base(NULL);
    1096              64 :   addr->acpt_cong        = vstr_make_base(NULL);
    1097              64 :   addr->def_policy       = vstr_make_base(NULL);
    1098              64 :   opts->ref_io_limit     = vstr_ref_make_ptr(&opts->io_limit,
    1099                 :                                              opt_serv__io_lim_ref_cb);
    1100                 :     
    1101              64 :   if (!opts->pid_file         ||
    1102                 :       !opts->cntl_file        ||
    1103                 :       !opts->chroot_dir       ||
    1104                 :       !opts->vpriv_uid        ||
    1105                 :       !opts->vpriv_gid        ||
    1106                 :       !addr->acpt_filter_file ||
    1107                 :       !addr->acpt_address     ||
    1108                 :       !addr->acpt_cong        ||
    1109                 :       !addr->def_policy       ||
    1110                 :       !opts->ref_io_limit     ||
    1111                 :       FALSE)
    1112                 :     goto opts_init_fail;
    1113                 : 
    1114              64 :   addr->next = NULL;
    1115                 :   
    1116              64 :   addr->tcp_port        = 0;
    1117              64 :   addr->defer_accept    = OPT_SERV_CONF_DEF_TCP_DEFER_ACCEPT;
    1118              64 :   addr->q_listen_len    = OPT_SERV_CONF_DEF_Q_LISTEN_LEN;
    1119              64 :   addr->max_connections = OPT_SERV_CONF_DEF_MAX_CONNECTIONS;
    1120                 :   
    1121              64 :   opts->addr_beg = addr;
    1122                 : 
    1123              64 :   opts->no_conf_listen = TRUE;
    1124                 :   
    1125              64 :   if (!opts->ref_io_limit) /* we can't have this succeed, while others fail */
    1126               0 :     goto opts_init_fail;
    1127                 :   
    1128              64 :   return (TRUE);
    1129                 : 
    1130               0 :  opts_init_fail:
    1131               0 :   opt_serv_conf_free_beg(opts);
    1132               0 :   opt_serv_conf_free_end(opts);
    1133               0 :  policy_init_fail:
    1134               0 :   vstr_ref_del(popts->ref);
    1135               0 :  mk_policy_fail:
    1136               0 :  mk_append_hostname_fail:
    1137               0 :   F(addr);
    1138               0 :  mk_addr_fail:
    1139               0 :   return (FALSE);
    1140                 : }
    1141                 : 
    1142                 : void opt_serv_logger(Vlg *passed_vlg)
    1143              64 : {
    1144              64 :   vlg = passed_vlg;
    1145              64 : }
    1146                 : 
    1147                 : void opt_serv_sc_drop_privs(Opt_serv_opts *opts)
    1148               0 : {
    1149               0 :   if (setgroups(1, &opts->priv_gid) == -1)
    1150               0 :     vlg_err(vlg, EXIT_FAILURE, "setgroups(%ld): %m\n", (long)opts->priv_gid);
    1151                 :       
    1152               0 :   if (setgid(opts->priv_gid) == -1)
    1153               0 :     vlg_err(vlg, EXIT_FAILURE, "setgid(%ld): %m\n", (long)opts->priv_gid);
    1154                 :   
    1155               0 :   if (setuid(opts->priv_uid) == -1)
    1156               0 :     vlg_err(vlg, EXIT_FAILURE, "setuid(%ld): %m\n", (long)opts->priv_uid);
    1157               0 : }
    1158                 : 
    1159                 : static void opt_serv__sc_rlim_num(const char *name, int resource,
    1160                 :                                   unsigned int num)
    1161              28 : {
    1162                 :   struct rlimit rlim[1];
    1163                 :     
    1164              28 :   if (getrlimit(resource, rlim) == -1)
    1165               0 :     vlg_err(vlg, EXIT_FAILURE, "getrlimit(RLIMIT_%s): %m\n", name);
    1166                 : 
    1167                 : 
    1168              28 :   if (num == RLIM_INFINITY) /* only attempt upwards, if we are privilaged */
    1169                 :   {
    1170              24 :     if ((rlim->rlim_max != RLIM_INFINITY) && !getuid())
    1171               0 :       rlim->rlim_max = num;
    1172                 :   }
    1173                 :   else
    1174                 :   {
    1175               4 :     if ((num > rlim->rlim_max) && !getuid())
    1176               0 :       rlim->rlim_max = num;
    1177                 :   
    1178               4 :     if (num < rlim->rlim_max) /* can always do this ? */
    1179               4 :       rlim->rlim_max = num;
    1180                 :   }
    1181                 :   
    1182              28 :   rlim->rlim_cur = rlim->rlim_max; /* upgrade soft to hard */
    1183                 :   
    1184              28 :   if (setrlimit(resource, rlim) == -1)
    1185               0 :     vlg_err(vlg, EXIT_FAILURE, "setrlimit(RLIMIT_%s): %m\n", name);
    1186              28 : }
    1187                 : 
    1188                 : void opt_serv_sc_rlim_as_num(unsigned int rlim_as_num)
    1189               0 : {
    1190                 :   if (USE_RLIMIT_AS)
    1191               0 :     opt_serv__sc_rlim_num("AS", RLIMIT_AS, rlim_as_num);
    1192               0 : }
    1193                 : 
    1194                 : void opt_serv_sc_rlim_core_num(unsigned int rlim_core_num)
    1195              28 : {
    1196              28 :   opt_serv__sc_rlim_num("CORE", RLIMIT_CORE, rlim_core_num);
    1197              28 : }
    1198                 : 
    1199                 : void opt_serv_sc_rlim_file_num(unsigned int rlim_file_num)
    1200               0 : {
    1201               0 :   opt_serv__sc_rlim_num("NOFILE", RLIMIT_NOFILE, rlim_file_num);
    1202               0 : }
    1203                 : 
    1204                 : int opt_serv_sc_acpt_end(const Opt_serv_policy_opts *popts,
    1205                 :                          struct Evnt *from_evnt, struct Evnt *evnt)
    1206           12052 : {
    1207           12052 :   Acpt_listener *acpt_listener = (Acpt_listener *)from_evnt;
    1208           12052 :   unsigned int acpt_num = acpt_listener->ref->ref - 1;  /* ref +1 for itself */
    1209           12052 :   unsigned int acpt_max = acpt_listener->max_connections;
    1210                 : 
    1211           12052 :   vlg_dbg1(vlg, "acpt: %u/%u\n", acpt_num, acpt_max);
    1212                 :   
    1213           12052 :   if (acpt_max && (acpt_num >= acpt_max))
    1214                 :   {
    1215             278 :     vlg_dbg1(vlg, "ACPT DEL ($<sa:%p>,%u,%u)\n", EVNT_SA(from_evnt),
    1216                 :              acpt_num, acpt_max);
    1217             278 :     evnt_wait_cntl_del(from_evnt, POLLIN);
    1218                 :   }
    1219                 :   
    1220           12052 :   if (popts->max_connections && (evnt_num_all() > popts->max_connections))
    1221                 :   {
    1222               0 :     vlg_info(vlg, "LIMIT-BLOCKED from[$<sa:%p>]: policy $<vstr.all:%p>\n",
    1223                 :              EVNT_SA(evnt), popts->policy_name);
    1224               0 :     return (FALSE);
    1225                 :   }
    1226                 :   
    1227           12052 :   vlg_info(vlg, "CONNECT from[$<sa:%p>]\n", EVNT_SA(evnt));
    1228                 :   
    1229           12052 :   return (TRUE);
    1230                 : }
    1231                 : 
    1232                 : void opt_serv_sc_free_beg(struct Evnt *evnt, const char *info_rep)
    1233           12284 : {
    1234           12284 :   if (EVNT_ACPT_EXISTS(evnt) && EVNT_ACPT_DATA(evnt)->evnt)
    1235                 :   {
    1236           12244 :     Acpt_data *acpt_data = EVNT_ACPT_DATA(evnt);
    1237           12244 :     Acpt_listener *acpt_listener = (Acpt_listener *)acpt_data->evnt;
    1238           12244 :     unsigned int acpt_num = acpt_listener->ref->ref - 1;
    1239           12244 :     unsigned int acpt_max = acpt_listener->max_connections;
    1240                 :   
    1241           12244 :     if (acpt_max && (acpt_num <= acpt_max)) /* note that we are going to -1 */
    1242                 :     {
    1243            2308 :       vlg_dbg1(vlg, "ACPT ADD ($<sa:%p>,%u,%u)\n", EVNT_SA(acpt_data->evnt),
    1244                 :                acpt_num, acpt_max);
    1245            2308 :       evnt_wait_cntl_add(acpt_data->evnt, POLLIN);
    1246                 :     }
    1247                 :     
    1248           12244 :     evnt_stats_add(acpt_data->evnt, evnt);
    1249                 :   }
    1250                 : 
    1251           12284 :   if (evnt->flag_fully_acpt)
    1252           12284 :     evnt_vlg_stats_info(evnt, info_rep);
    1253           12284 : }
    1254                 : 
    1255                 : #define OPT_SERV__SIG_OR_ERR(x)                 \
    1256                 :     if (sigaction(x, &sa, NULL) == -1)          \
    1257                 :       err(EXIT_FAILURE, "signal(%d:%s)", x, strsignal(x))
    1258                 : 
    1259                 : static void opt_serv__sig_crash(int s_ig_num)
    1260               0 : {
    1261               0 :   vlg_sig_abort(vlg, "SIG[%d]: %s\n", s_ig_num, strsignal(s_ig_num));
    1262               0 : }
    1263                 : 
    1264                 : static void opt_serv__sig_raise_cont(int s_ig_num)
    1265               0 : {
    1266                 :   struct sigaction sa;
    1267                 :   
    1268               0 :   if (sigemptyset(&sa.sa_mask) == -1)
    1269               0 :     err(EXIT_FAILURE, "signal init");
    1270                 : 
    1271               0 :   sa.sa_flags   = SA_RESTART;
    1272               0 :   sa.sa_handler = SIG_DFL;
    1273               0 :   OPT_SERV__SIG_OR_ERR(s_ig_num);
    1274                 : 
    1275               0 :   vlg_sig_warn(vlg, "SIG[%d]: %s\n", s_ig_num, strsignal(s_ig_num));
    1276               0 :   raise(s_ig_num);
    1277               0 : }
    1278                 : 
    1279                 : static void opt_serv__sig_cont(int s_ig_num)
    1280               0 : {
    1281                 :   if (0) /* s_ig_num == SIGCONT) */
    1282                 :   {
    1283                 :     struct sigaction sa;
    1284                 :   
    1285                 :     if (sigemptyset(&sa.sa_mask) == -1)
    1286                 :       err(EXIT_FAILURE, "signal init");
    1287                 : 
    1288                 :     sa.sa_flags   = SA_RESTART;
    1289                 :     sa.sa_handler = opt_serv__sig_raise_cont;
    1290                 :     OPT_SERV__SIG_OR_ERR(SIGTSTP);
    1291                 :   }
    1292                 :   
    1293               0 :   vlg_sig_info(vlg, "SIG[%d]: %s\n", s_ig_num, strsignal(s_ig_num));
    1294               0 : }
    1295                 : 
    1296                 : static void opt_serv__sig_child(int s_ig_num)
    1297               2 : {
    1298               1 :   ASSERT(s_ig_num == SIGCHLD);
    1299               2 :   evnt_child_exited = TRUE;
    1300               2 : }
    1301                 : 
    1302                 : void opt_serv_sc_signals(void)
    1303              64 : {
    1304                 :   struct sigaction sa;
    1305                 :   
    1306              64 :   if (sigemptyset(&sa.sa_mask) == -1)
    1307               0 :     err(EXIT_FAILURE, "signal init %s", "sigemptyset");
    1308                 :   
    1309                 :   /* don't use SA_RESTART ... */
    1310              64 :   sa.sa_flags   = 0;
    1311                 :   /* ignore it... we don't have a use for it */
    1312              64 :   sa.sa_handler = SIG_IGN;
    1313                 :   
    1314              64 :   OPT_SERV__SIG_OR_ERR(SIGPIPE);
    1315                 : 
    1316              64 :   sa.sa_handler = opt_serv__sig_crash;
    1317                 :   
    1318              64 :   OPT_SERV__SIG_OR_ERR(SIGSEGV);
    1319              64 :   OPT_SERV__SIG_OR_ERR(SIGBUS);
    1320              64 :   OPT_SERV__SIG_OR_ERR(SIGILL);
    1321              64 :   OPT_SERV__SIG_OR_ERR(SIGFPE);
    1322              64 :   OPT_SERV__SIG_OR_ERR(SIGXFSZ);
    1323                 : 
    1324              64 :   sa.sa_flags   = SA_RESTART;
    1325              64 :   sa.sa_handler = opt_serv__sig_child;
    1326              64 :   OPT_SERV__SIG_OR_ERR(SIGCHLD);
    1327                 :   
    1328              64 :   sa.sa_flags   = SA_RESTART;
    1329              64 :   sa.sa_handler = opt_serv__sig_cont; /* print, and do nothing */
    1330                 :   
    1331              64 :   OPT_SERV__SIG_OR_ERR(SIGUSR1);
    1332              64 :   OPT_SERV__SIG_OR_ERR(SIGUSR2);
    1333              64 :   OPT_SERV__SIG_OR_ERR(SIGHUP);
    1334              64 :   OPT_SERV__SIG_OR_ERR(SIGCONT);
    1335                 :   
    1336              64 :   sa.sa_handler = opt_serv__sig_raise_cont; /* queue print, and re-raise */
    1337                 :   
    1338              64 :   OPT_SERV__SIG_OR_ERR(SIGTSTP);
    1339              64 :   OPT_SERV__SIG_OR_ERR(SIGTERM);
    1340              64 : }
    1341                 : #undef SERV__SIG_OR_ERR
    1342                 : 
    1343                 : void opt_serv_sc_check_children(void)
    1344         9176339 : {
    1345         9176339 :   if (evnt_child_exited)
    1346                 :   {
    1347               1 :     vlg_warn(vlg, "Child exited.\n");
    1348               1 :     evnt_acpt_close_all();
    1349               1 :     evnt_scan_q_close();
    1350               1 :     evnt_child_exited = FALSE;
    1351                 :   }
    1352         9176339 : }
    1353                 : 
    1354                 : void opt_serv_sc_cntl_resources(const Opt_serv_opts *opts)
    1355         9176339 : { /* cap the amount of "wasted" resources we're using */
    1356                 :   
    1357         9176339 :   vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BASE,
    1358                 :                  0, opts->max_spare_bases);
    1359                 : 
    1360         9176339 :   vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF,
    1361                 :                  0, opts->max_spare_buf_nodes);
    1362         9176339 :   vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR,
    1363                 :                  0, opts->max_spare_ptr_nodes);
    1364         9176339 :   vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF,
    1365                 :                  0, opts->max_spare_ref_nodes);
    1366         9176339 : }
    1367                 : 
    1368                 : /* appends into conf->tmp */
    1369                 : int opt_serv_build_single_str(struct Opt_serv_opts *opts,
    1370                 :                               const Conf_parse *conf, Conf_token *token,
    1371                 :                               int clist, int doing_init)
    1372           10722 : {
    1373                 :   if (0) { }
    1374                 :     
    1375           10752 :   else if (OPT_SERV_SYM_EQ("ENV")   || OPT_SERV_SYM_EQ("ENVIRONMENT") ||
    1376                 :            OPT_SERV_SYM_EQ("<ENV>") || OPT_SERV_SYM_EQ("<ENVIRONMENT>"))
    1377                 :   {
    1378              60 :     if (!opt_serv_sc_append_env(conf->tmp, conf->tmp->len, conf, token))
    1379               0 :       return (FALSE);
    1380                 :   }
    1381           10664 :   else if (doing_init &&
    1382                 :            (OPT_SERV_SYM_EQ("HOME") || OPT_SERV_SYM_EQ("<HOME>")))
    1383                 :   {
    1384               4 :     if (!OPT_SERV_SC_APPEND_HOMEDIR(conf->tmp, conf->tmp->len, conf, token))
    1385               0 :       return (FALSE);
    1386                 :   }
    1387           10658 :   else if (OPT_SERV_SYM_EQ("<hostname>"))
    1388               4 :     opt_serv_sc_append_hostname(conf->tmp, conf->tmp->len);
    1389           10654 :   else if (OPT_SERV_SYM_EQ("<cwd>"))
    1390               4 :     opt_serv_sc_append_cwd(conf->tmp, conf->tmp->len);
    1391           10650 :   else if (OPT_SERV_SYM_EQ("<uname>"))
    1392                 :   {
    1393                 :     static struct utsname utsname[1];
    1394                 :     static int done = FALSE;
    1395                 :     
    1396               0 :     if (!done && (uname(utsname) == -1)) return (FALSE);
    1397               0 :     done = TRUE;
    1398                 :     
    1399               0 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
    1400               0 :     CONF_SC_TOGGLE_CLIST_VAR(clist);
    1401                 :     
    1402                 :     if (0) { }
    1403                 :     
    1404               0 :     else if (OPT_SERV_SYM_EQ("sysname"))  OPT_SERV_SC_APPEND_UNAME(sysname);
    1405               0 :     else if (OPT_SERV_SYM_EQ("nodename")) OPT_SERV_SC_APPEND_UNAME(nodename);
    1406               0 :     else if (OPT_SERV_SYM_EQ("release"))  OPT_SERV_SC_APPEND_UNAME(release);
    1407               0 :     else if (OPT_SERV_SYM_EQ("version"))  OPT_SERV_SC_APPEND_UNAME(version);
    1408               0 :     else if (OPT_SERV_SYM_EQ("machine"))  OPT_SERV_SC_APPEND_UNAME(machine);
    1409                 :     
    1410                 :     else
    1411               0 :       return (FALSE);
    1412                 :   }
    1413           10650 :   else if (OPT_SERV_SYM_EQ("<version>") || OPT_SERV_SYM_EQ("<vers>"))
    1414                 :   {
    1415               0 :     if (!vstr_add_ptr(conf->tmp, conf->tmp->len,
    1416                 :                       opts->vers_cstr, opts->vers_len))
    1417               0 :       return (FALSE);
    1418                 :   }
    1419           10650 :   else if (OPT_SERV_SYM_EQ("<program-name>"))
    1420                 :   {
    1421               0 :     if (!vstr_add_ptr(conf->tmp, conf->tmp->len,
    1422                 :                       opts->name_cstr, opts->name_len))
    1423               0 :       return (FALSE);
    1424                 :   }
    1425           10650 :   else if (!clist)
    1426                 :   { /* unknown symbol or string */
    1427           10650 :     size_t pos = conf->tmp->len + 1;
    1428           10650 :     const Vstr_sect_node *pv = conf_token_value(token);
    1429                 :     
    1430           10650 :     if (!pv || !vstr_add_vstr(conf->tmp, conf->tmp->len,
    1431                 :                               conf->data, pv->pos, pv->len,
    1432                 :                               VSTR_TYPE_ADD_BUF_REF))
    1433               0 :       return (FALSE);
    1434                 :     
    1435           10650 :     OPT_SERV_X__ESC_VSTR(conf->tmp, pos, pv->len);
    1436                 :   }
    1437                 :   
    1438                 :   else
    1439               0 :     return (FALSE);
    1440                 : 
    1441           10722 :   return (TRUE);
    1442                 : }
    1443                 : 
    1444                 : static int opt_serv__build_str(struct Opt_serv_opts *opts,
    1445                 :                                Conf_parse *conf, Conf_token *token,
    1446                 :                                int doing_init)
    1447             718 : {
    1448             718 :   unsigned int cur_depth = token->depth_num;
    1449             718 :   int clist = FALSE;
    1450                 :   
    1451             718 :   vstr_del(conf->tmp, 1, conf->tmp->len);
    1452             718 :   while (conf_token_list_num(token, cur_depth))
    1453                 :   {
    1454            2082 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
    1455            2082 :     CONF_SC_TOGGLE_CLIST_VAR(clist);
    1456                 : 
    1457            2082 :     if (!opt_serv_build_single_str(opts, conf, token, clist, doing_init))
    1458               0 :       return (FALSE);
    1459                 :   }
    1460                 :   
    1461             718 :   return (!conf->tmp->conf->malloc_bad);
    1462                 : }
    1463                 : 
    1464                 : static int opt_serv__sc_make_str(struct Opt_serv_opts *opts,
    1465                 :                                  Conf_parse *conf, Conf_token *token,
    1466                 :                                  Vstr_base *s1, size_t pos, size_t len,
    1467                 :                                  int doing_init)
    1468           16972 : {
    1469           16972 :   int clist = FALSE;
    1470                 : 
    1471            8489 :   ASSERT(s1 != conf->tmp);
    1472                 :   
    1473           16972 :   CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
    1474           16972 :   CONF_SC_TOGGLE_CLIST_VAR(clist);
    1475                 : 
    1476                 :   if (0) { }
    1477                 :   
    1478           16972 :   else if (OPT_SERV_SYM_EQ("<none>") || OPT_SERV_SYM_EQ("<empty>"))
    1479                 :   {
    1480               4 :     return (vstr_del(s1, pos, len));
    1481                 :   }
    1482           16968 :   else if (OPT_SERV_SYM_EQ("assign") || OPT_SERV_SYM_EQ("="))
    1483                 :   {
    1484             128 :     if (!opt_serv__build_str(opts, conf, token, doing_init))
    1485               0 :       return (FALSE);
    1486                 :     
    1487             128 :     return (vstr_sub_vstr(s1, pos, len,
    1488                 :                           conf->tmp, 1, conf->tmp->len, VSTR_TYPE_SUB_BUF_REF));
    1489                 :   }
    1490           16840 :   else if (OPT_SERV_SYM_EQ("append") || OPT_SERV_SYM_EQ("+=") ||
    1491                 :            OPT_SERV_SYM_EQ(".=") || OPT_SERV_SYM_EQ(">>="))
    1492                 :   {
    1493             590 :     if (!opt_serv__build_str(opts, conf, token, doing_init))
    1494               0 :       return (FALSE);
    1495                 : 
    1496             590 :     return (vstr_add_vstr(s1, vstr_sc_poslast(pos, len),
    1497                 :                           conf->tmp, 1, conf->tmp->len, VSTR_TYPE_ADD_BUF_REF));
    1498                 :   }
    1499           16250 :   else if (OPT_SERV_SYM_EQ("prepend") || OPT_SERV_SYM_EQ("<<="))
    1500                 :   {
    1501               0 :     if (!opt_serv__build_str(opts, conf, token, doing_init))
    1502               0 :       return (FALSE);
    1503                 : 
    1504               0 :     return (vstr_add_vstr(s1, pos - 1,
    1505                 :                           conf->tmp, 1, conf->tmp->len, VSTR_TYPE_ADD_BUF_REF));
    1506                 :   }
    1507           16250 :   else if (!clist)
    1508                 :   {
    1509           16250 :     const Vstr_sect_node *pv = conf_token_value(token);
    1510                 :       
    1511           16250 :     if (!pv || !vstr_sub_vstr(s1, pos, len, conf->data, pv->pos, pv->len,
    1512                 :                               VSTR_TYPE_SUB_BUF_REF))
    1513               0 :       return (FALSE);
    1514           16250 :     OPT_SERV_X__ESC_VSTR(s1, pos, pv->len);
    1515                 : 
    1516           16250 :     return (TRUE);
    1517                 :   }
    1518                 : 
    1519               0 :   return (FALSE);  
    1520                 : }
    1521                 : 
    1522                 : int opt_serv_sc_make_str(struct Opt_serv_opts *opts,
    1523                 :                          Conf_parse *conf, Conf_token *token,
    1524                 :                          Vstr_base *s1, size_t pos, size_t len)
    1525           16660 : {
    1526           16660 :   return (opt_serv__sc_make_str(opts, conf, token, s1, pos, len, FALSE));
    1527                 : }
    1528                 : 
    1529                 : int opt_serv_sc_make_static_path(struct Opt_serv_opts *opts,
    1530                 :                                  Conf_parse *conf, Conf_token *token,
    1531                 :                                  Vstr_base *s1)
    1532             312 : {
    1533             312 :   return (opt_serv__sc_make_str(opts, conf, token, s1, 1, s1->len, TRUE));
    1534                 : }
    1535                 : 
    1536                 : static int opt_serv__build_uintmax(Conf_parse *conf, Conf_token *token,
    1537                 :                                    uintmax_t num, uintmax_t *ret)
    1538              28 : {
    1539              14 :   ASSERT(ret);
    1540                 :   
    1541              28 :   OPT_SERV_X_SYM_SINGLE_UINTMAX_BEG(*ret);
    1542                 : 
    1543               8 :   else if (OPT_SERV_SYM_EQ("<num>")) *ret = num;
    1544                 : 
    1545               0 :   OPT_SERV_X_SYM_NUM_END();
    1546                 :   
    1547              28 :   return (TRUE);
    1548                 : }
    1549                 : 
    1550                 : int opt_serv_sc_make_uintmax(Conf_parse *conf, Conf_token *token,
    1551                 :                              uintmax_t *num)
    1552           58484 : {
    1553           58484 :   OPT_SERV_X_SYM_SINGLE_UINTMAX_BEG(*num);
    1554                 : 
    1555           13724 :   else if (OPT_SERV_SYM_EQ("none")   || OPT_SERV_SYM_EQ("zero")   ||
    1556                 :            OPT_SERV_SYM_EQ("NONE")   || OPT_SERV_SYM_EQ("ZERO")   ||
    1557                 :            OPT_SERV_SYM_EQ("<none>") || OPT_SERV_SYM_EQ("<zero>") ||
    1558                 :            OPT_SERV_SYM_EQ("<NONE>") || OPT_SERV_SYM_EQ("<ZERO>"))
    1559                 :   {
    1560               4 :     *num = 0;
    1561                 :   }
    1562           13718 :   else if (OPT_SERV_SYM_EQ("assign") || OPT_SERV_SYM_EQ("="))
    1563                 :   {
    1564               4 :     if (!opt_serv__build_uintmax(conf, token, *num, num))
    1565               0 :       return (FALSE);
    1566                 :   }
    1567           13720 :   else if (OPT_SERV_SYM_EQ("add") || OPT_SERV_SYM_EQ("+="))
    1568                 :   {
    1569               8 :     uintmax_t tmp = 0;
    1570                 :     
    1571               8 :     if (!opt_serv__build_uintmax(conf, token, *num, &tmp))
    1572               0 :       return (FALSE);
    1573                 : 
    1574               8 :     if ((tmp + *num) < tmp)
    1575               0 :       return (FALSE);
    1576                 :     
    1577               8 :     *num += tmp;
    1578                 :   }
    1579           13708 :   else if (OPT_SERV_SYM_EQ("remove") || OPT_SERV_SYM_EQ("-="))
    1580                 :   {
    1581               4 :     uintmax_t tmp = 0;
    1582                 :     
    1583               4 :     if (!opt_serv__build_uintmax(conf, token, *num, &tmp))
    1584               0 :       return (FALSE);
    1585                 : 
    1586               4 :     if (tmp > *num)
    1587               0 :       return (FALSE);
    1588                 :     
    1589               4 :     *num -= tmp;
    1590                 :   }
    1591           13704 :   else if (OPT_SERV_SYM_EQ("multiply") || OPT_SERV_SYM_EQ("*="))
    1592                 :   {
    1593               4 :     uintmax_t tmp = 0;
    1594                 :     
    1595               4 :     if (!opt_serv__build_uintmax(conf, token, *num, &tmp))
    1596               0 :       return (FALSE);
    1597                 : 
    1598                 :     /* FIXME: this doesn't actually work, but it's better than nothing */
    1599               4 :     if ((tmp * *num) < tmp)
    1600               0 :       return (FALSE);
    1601                 :     
    1602               4 :     *num *= tmp;
    1603                 :   }
    1604           13700 :   else if (OPT_SERV_SYM_EQ("divide") || OPT_SERV_SYM_EQ("/="))
    1605                 :   {
    1606               4 :     uintmax_t tmp = 0;
    1607                 :     
    1608               4 :     if (!opt_serv__build_uintmax(conf, token, *num, &tmp))
    1609               0 :       return (FALSE);
    1610                 : 
    1611               4 :     if (!tmp)
    1612               0 :       return (FALSE);
    1613                 :     
    1614               4 :     *num /= tmp;
    1615                 :   }
    1616           13696 :   else if (OPT_SERV_SYM_EQ("modulus") || OPT_SERV_SYM_EQ("%="))
    1617                 :   {
    1618               4 :     uintmax_t tmp = 0;
    1619                 :     
    1620               4 :     if (!opt_serv__build_uintmax(conf, token, *num, &tmp))
    1621               0 :       return (FALSE);
    1622                 : 
    1623               4 :     if (!tmp)
    1624               0 :       return (FALSE);
    1625                 :     
    1626               4 :     *num %= tmp;
    1627                 :   }
    1628                 :   
    1629           13688 :   OPT_SERV_X_SYM_NUM_END();
    1630                 : 
    1631           44796 :   return (TRUE);  
    1632                 : }
    1633                 : 
    1634                 : int opt_serv_sc_make_uint(Conf_parse *conf, Conf_token *token,
    1635                 :                           unsigned int *num)
    1636           58404 : {
    1637                 : 
    1638           58404 :   uintmax_t tmp = *num;
    1639                 : 
    1640           58404 :   if (!opt_serv_sc_make_uintmax(conf, token, &tmp))
    1641           13660 :     return (FALSE);
    1642                 : 
    1643           44744 :   if (tmp > UINT_MAX)
    1644               0 :     return (FALSE);
    1645           44744 :   *num = tmp;
    1646                 : 
    1647           44744 :   return (TRUE);
    1648                 : }
    1649                 : 
    1650                 : int opt_serv_sc_make_ulong(Conf_parse *conf, Conf_token *token,
    1651                 :                            unsigned long *num)
    1652              80 : {
    1653                 : 
    1654              80 :   uintmax_t tmp = *num;
    1655                 : 
    1656              80 :   if (!opt_serv_sc_make_uintmax(conf, token, &tmp))
    1657              28 :     return (FALSE);
    1658                 : 
    1659              52 :   if (tmp > ULONG_MAX)
    1660               0 :     return (FALSE);
    1661              52 :   *num = tmp;
    1662                 : 
    1663              52 :   return (TRUE);
    1664                 : }
    1665                 : 
    1666                 : #ifndef CONF_FULL_STATIC
    1667                 : void opt_serv_sc_resolve_uid(struct Opt_serv_opts *opts,
    1668                 :                              const char *program_name,
    1669                 :                              void (*usage)(const char *, int, const char *))
    1670               0 : {
    1671               0 :   const char *name  = NULL;
    1672               0 :   struct passwd *pw = NULL;
    1673                 :   
    1674               0 :   if (!opts->vpriv_uid->len)
    1675               0 :     return;
    1676                 :   
    1677               0 :   OPT_SC_EXPORT_CSTR(name, opts->vpriv_uid, TRUE, "privilage uid");
    1678                 :   
    1679               0 :   if (!(pw = getpwnam(name)))
    1680                 :   {
    1681               0 :     Vstr_base *s1 = vstr_make_base(NULL);
    1682               0 :     const char *msg = NULL;
    1683                 :     
    1684               0 :     if (s1 &&
    1685                 :         vstr_add_fmt(s1, s1->len, " Username -- %s -- can't be found.\n",
    1686                 :                      name) &&
    1687                 :         (msg = vstr_export_cstr_ptr(s1, 1, s1->len)))
    1688               0 :       usage(program_name, EXIT_FAILURE, msg);
    1689               0 :     usage(program_name, EXIT_FAILURE, " Username can't be found.\n");
    1690                 :   }
    1691                 :   
    1692               0 :   opts->priv_uid = pw->pw_uid;
    1693                 : }
    1694                 : 
    1695                 : void opt_serv_sc_resolve_gid(struct Opt_serv_opts *opts,
    1696                 :                              const char *program_name,
    1697                 :                              void (*usage)(const char *, int, const char *))
    1698               0 : {
    1699               0 :   const char *name = NULL;
    1700               0 :   struct group *gr = NULL;
    1701                 : 
    1702               0 :   if (!opts->vpriv_gid->len)
    1703               0 :     return;
    1704                 :   
    1705               0 :   OPT_SC_EXPORT_CSTR(name, opts->vpriv_gid, FALSE, "privilage gid");
    1706                 :   
    1707               0 :   if (!(gr = getgrnam(name)))
    1708                 :   {
    1709               0 :     Vstr_base *s1 = vstr_make_base(NULL);
    1710               0 :     const char *msg = NULL;
    1711                 :     
    1712               0 :     if (s1 &&
    1713                 :         vstr_add_fmt(s1, s1->len, " Groupname -- %s -- can't be found.\n",
    1714                 :                      name) &&
    1715                 :         (msg = vstr_export_cstr_ptr(s1, 1, s1->len)))
    1716               0 :       usage(program_name, EXIT_FAILURE, msg);
    1717               0 :     usage(program_name, EXIT_FAILURE, " Groupname can't be found.\n");
    1718                 :   }
    1719                 : 
    1720               0 :   opts->priv_gid = gr->gr_gid;
    1721                 : }
    1722                 : #endif
    1723                 : 
    1724                 : int opt_serv_sc_config_dir(Vstr_base *s1, void *data, const char *dir,
    1725                 :                            int (*func)(Vstr_base *, void *, const char *))
    1726               6 : {
    1727               6 :   struct dirent **dents = NULL;
    1728               6 :   int num = -1;
    1729               6 :   int scan = 0;
    1730               6 :   int ret = TRUE;
    1731               6 :   Vstr_base *bld = vstr_make_base(s1->conf);
    1732                 : 
    1733               6 :   if (!bld || bld->conf->malloc_bad)
    1734                 :   {
    1735               0 :     errno = ENOMEM;
    1736               0 :     goto fail;
    1737                 :   }
    1738                 : 
    1739               6 :   num = opt_conf_sc_scan_dir(dir, &dents);
    1740               6 :   if (num == -1)
    1741               4 :     goto fail;
    1742                 : 
    1743                 :   /* *******************************************************************
    1744                 :    * These free's are for malloc's done inside scandir, so we __MUST__
    1745                 :    * use the normal free().
    1746                 :    * ***************************************************************** */
    1747              29 :   while (scan < num)
    1748                 :   {
    1749              26 :     if (ret)
    1750                 :     { /* create the full path... */
    1751              26 :       const char *fname = NULL;
    1752              26 :       const struct dirent *dent = dents[scan];
    1753                 :       
    1754              26 :       vstr_del(bld, 1, bld->len);
    1755              26 :       vstr_add_cstr_ptr(bld, bld->len, dir);
    1756              26 :       vstr_add_cstr_ptr(bld, bld->len, "/");
    1757              26 :       vstr_add_ptr(bld, bld->len, dent->d_name, _D_EXACT_NAMLEN(dent));
    1758                 : 
    1759              26 :       if (bld->conf->malloc_bad)
    1760                 :       {
    1761               0 :         bld->conf->malloc_bad = FALSE;
    1762               0 :         ret = FALSE;
    1763                 :       }
    1764                 :       
    1765              26 :       if (ret && !(fname = vstr_export_cstr_ptr(bld, 1, bld->len)))
    1766               0 :         ret = FALSE;
    1767              26 :       if (ret && !(*func)(s1, data, fname))
    1768               0 :         ret = FALSE;
    1769                 :     }
    1770                 :     
    1771              26 :     free(dents[scan]);
    1772              26 :     ++scan;
    1773                 :   }
    1774                 : 
    1775               2 :   free(dents);
    1776               2 :   vstr_free_base(bld);
    1777               2 :   return (ret);
    1778                 : 
    1779               4 :  fail:
    1780               4 :   vstr_add_fmt(s1, s1->len, "scandir(%s): %m", dir);
    1781               4 :   vstr_free_base(bld);
    1782               4 :   return (FALSE);
    1783                 : }

Generated by: LTP GCOV extension version 1.4