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

       1                 : /*
       2                 :  *  Copyright (C) 2004, 2005, 2006  James Antill
       3                 :  *
       4                 :  *  This library is free software; you can redistribute it and/or
       5                 :  *  modify it under the terms of the GNU Lesser General Public
       6                 :  *  License as published by the Free Software Foundation; either
       7                 :  *  version 2 of the License, or (at your option) any later version.
       8                 :  *
       9                 :  *  This library is distributed in the hope that it will be useful,
      10                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12                 :  *  Lesser General Public License for more details.
      13                 :  *
      14                 :  *  You should have received a copy of the GNU Lesser General Public
      15                 :  *  License along with this library; if not, write to the Free Software
      16                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17                 :  *
      18                 :  *  email: james@and.org
      19                 :  */
      20                 : /* conditionally compliant HTTP/1.1 server. */
      21                 : #define _GNU_SOURCE 1 /* strsignal() / posix_fadvise64 */
      22                 : #include <vstr.h>
      23                 : 
      24                 : #include <socket_poll.h>
      25                 : #include <timer_q.h>
      26                 : 
      27                 : #include <stdlib.h>
      28                 : #include <sys/types.h>
      29                 : #include <sys/socket.h>
      30                 : #include <unistd.h>
      31                 : #include <fcntl.h>
      32                 : #include <stdlib.h>
      33                 : #include <sys/types.h>
      34                 : #include <sys/socket.h>
      35                 : #include <errno.h>
      36                 : #include <err.h>
      37                 : #include <netinet/in.h>
      38                 : #include <netinet/tcp.h>
      39                 : #include <arpa/inet.h>
      40                 : 
      41                 : #include <grp.h>
      42                 : 
      43                 : #define EX_UTILS_NO_USE_INIT  1
      44                 : #define EX_UTILS_NO_USE_EXIT  1
      45                 : #define EX_UTILS_NO_USE_LIMIT 1
      46                 : #define EX_UTILS_NO_USE_OPEN  1
      47                 : #define EX_UTILS_NO_USE_GET   1
      48                 : #define EX_UTILS_NO_USE_IO_FD 1
      49                 : #define EX_UTILS_RET_FAIL     1
      50                 : #include "ex_utils.h"
      51                 : 
      52                 : #include "mk.h"
      53                 : 
      54                 : MALLOC_CHECK_DECL();
      55                 : 
      56                 : #include "cntl.h"
      57                 : #include "date.h"
      58                 : 
      59                 : #define HTTPD_HAVE_GLOBAL_OPTS 1
      60                 : 
      61                 : #include "httpd.h"
      62                 : #include "httpd_policy.h"
      63                 : 
      64                 : 
      65                 : #ifndef TCP_CONGESTION
      66                 : # ifdef __linux__
      67                 : #  define TCP_CONGESTION 13
      68                 : # else
      69                 : #  define TCP_CONGESTION 0
      70                 : # endif
      71                 : #endif
      72                 : 
      73                 : /* we get prctl.h from evnt.h */
      74                 : #if defined(HAVE_SYS_CAPABILITY_H) && defined(PR_SET_KEEPCAPS)
      75                 : # include <sys/capability.h>
      76                 : # define PROC_CNTL_KEEPCAPS(x1) prctl(PR_SET_KEEPCAPS, x1, 0, 0, 0)
      77                 : #else
      78                 : # define PROC_CNTL_KEEPCAPS(x1) (errno = ENOSYS, -1)
      79                 : # define cap_t void *
      80                 : # define cap_from_text(x) (errno = ENOSYS, NULL)
      81                 : # define cap_set_proc(x) (errno = ENOSYS, -1)
      82                 : # define cap_free(x) (errno = ENOSYS, -1)
      83                 : #endif
      84                 : 
      85                 : #ifdef PR_SET_DUMPABLE
      86                 : # define PROC_CNTL_DUMPABLE(x1) prctl(PR_SET_DUMPABLE, x1, 0, 0, 0)
      87                 : #else
      88                 : # define PROC_CNTL_DUMPABLE(x1) (errno = ENOSYS, -1)
      89                 : #endif
      90                 : 
      91                 : 
      92                 : 
      93                 : 
      94                 : #define CLEN COMPILE_STRLEN
      95                 : 
      96                 : /* is the cstr a prefix of the vstr */
      97                 : #define VPREFIX(vstr, p, l, cstr)                                       \
      98                 :     (((l) >= CLEN(cstr)) &&                                             \
      99                 :      vstr_cmp_buf_eq(vstr, p, CLEN(cstr), cstr, CLEN(cstr)))
     100                 : /* is the cstr a suffix of the vstr */
     101                 : #define VSUFFIX(vstr, p, l, cstr)                                       \
     102                 :     (((l) >= CLEN(cstr)) &&                                             \
     103                 :      vstr_cmp_eod_buf_eq(vstr, p, l, cstr, CLEN(cstr)))
     104                 : 
     105                 : /* is the cstr a prefix of the vstr, no case */
     106                 : #define VIPREFIX(vstr, p, l, cstr)                                      \
     107                 :     (((l) >= CLEN(cstr)) &&                                             \
     108                 :      vstr_cmp_case_buf_eq(vstr, p, CLEN(cstr), cstr, CLEN(cstr)))
     109                 : 
     110                 : /* for simplicity */
     111                 : #define VEQ(vstr, p, l, cstr) vstr_cmp_cstr_eq(vstr, p, l, cstr)
     112                 : 
     113                 : static Vlg *vlg = NULL;
     114                 : 
     115                 : static void usage(const char *program_name, int ret, const char *prefix)
     116               4 : {
     117               4 :   Vstr_base *out = vstr_make_base(NULL);
     118                 : 
     119               4 :   if (!out)
     120               0 :     errno = ENOMEM, err(EXIT_FAILURE, "usage");
     121                 : 
     122               4 :   vstr_add_fmt(out, 0, "%s\n\
     123                 :  Format: %s [options] <dir>\n\
     124                 :   Daemon options\n\
     125                 :     --configuration-file\n\
     126                 :     --config-file  -C - Load configuration file specified.\n\
     127                 :     --configuration-directory\n\
     128                 :     --config-dir      - Load <dir>/*.conf as configuration files.\n\
     129                 :     --default-configuration\n\
     130                 :     --def-configuration\n\
     131                 :                       - Do the default configuration, which is done if no\n\
     132                 :                         options are given.\n\
     133                 : \n\
     134                 :     --configuration-data-daemon\n\
     135                 :                       - Parse configuration given in the\n\
     136                 :                         org.and.daemon-conf-1.0 namespace.\n\
     137                 :     --daemon          - Toggle becoming a daemon%s.\n\
     138                 :     --chroot          - Change root.\n\
     139                 :     --drop-privs      - Toggle droping privilages%s.\n\
     140                 :     --priv-uid        - Drop privilages to this uid.\n\
     141                 :     --priv-gid        - Drop privilages to this gid.\n\
     142                 :     --pid-file        - Log pid to file.\n\
     143                 :     --cntl-file       - Create control file.\n\
     144                 :     --accept-filter-file\n\
     145                 :                       - Load Linux Socket Filter code for accept().\n\
     146                 :     --processes       - Number of processes to use (default: 1).\n\
     147                 :     --debug -d        - Raise debug level (can be used upto 3 times).\n\
     148                 :     --host -H         - IPv4 address to bind (default: \"all\").\n\
     149                 :     --help -h         - Print this message.\n\
     150                 :     --max-connections\n\
     151                 :                    -M - Max connections allowed (0 = no limit).\n\
     152                 :     --nagle -n        - Toggle usage of nagle TCP option%s.\n\
     153                 :     --port -P         - Port to bind to.\n\
     154                 :     --idle-timeout -t - Timeout (usecs) for connections that are idle.\n\
     155                 :     --defer-accept    - Time to defer dataless connections (default: 8s)\n\
     156                 :     --version -V      - Print the version string.\n\
     157                 : \n\
     158                 :   HTTPD options\n\
     159                 :     --configuration-data-httpd\n\
     160                 :                       - Parse configuration given in the\n\
     161                 :                         org.and.httpd-conf-main-1.0 namespace.\n\
     162                 :     --mmap            - Toggle use of mmap() to load files%s.\n\
     163                 :     --sendfile        - Toggle use of sendfile() to load files%s.\n\
     164                 :     --keep-alive      - Toggle use of Keep-Alive handling%s.\n\
     165                 :     --keep-alive-1.0  - Toggle use of Keep-Alive handling for HTTP/1.0%s.\n\
     166                 :     --virtual-hosts\n\
     167                 :     --vhosts          - Toggle use of directory virtual hostnames%s.\n\
     168                 :     --range           - Toggle use of partial responces%s.\n\
     169                 :     --range-1.0       - Toggle use of partial responces for HTTP/1.0%s.\n\
     170                 :     --public-only     - Toggle use of public only privilages%s.\n\
     171                 :     --directory-filename\n\
     172                 :     --dir-filename    - Filename to use when requesting directories.\n\
     173                 :     --server-name     - Contents of server header used in replies.\n\
     174                 :     --gzip-content-replacement\n\
     175                 :                       - Toggle use of gzip content replacement%s.\n\
     176                 :     --mime-types-main - Main mime types filename (default: /etc/mime.types).\n\
     177                 :     --mime-types-xtra - Additional mime types filename.\n\
     178                 :     --error-406       - Toggle sending 406 responses%s.\n\
     179                 :     --canonize-host   - Strip leading 'www.', strip trailing '.'%s.\n\
     180                 :     --error-host-400  - Give an 400 error for a bad host%s.\n\
     181                 :     --check-host      - Whether we check host headers at all%s.\n\
     182                 :     --unspecified-hostname\n\
     183                 :                       - Used for req with no Host header (default is hostname).\n\
     184                 :     --max-header-sz   - Max size of http header (0 = no limit).\n\
     185                 : ",
     186                 :                prefix, program_name,
     187                 :                opt_def_toggle(FALSE), opt_def_toggle(FALSE),
     188                 :                opt_def_toggle(EVNT_CONF_NAGLE),
     189                 :                opt_def_toggle(HTTPD_CONF_USE_MMAP),
     190                 :                opt_def_toggle(HTTPD_CONF_USE_SENDFILE),
     191                 :                opt_def_toggle(HTTPD_CONF_USE_KEEPA),
     192                 :                opt_def_toggle(HTTPD_CONF_USE_KEEPA_1_0),
     193                 :                opt_def_toggle(HTTPD_CONF_USE_VHOSTS_NAME),
     194                 :                opt_def_toggle(HTTPD_CONF_USE_RANGE),
     195                 :                opt_def_toggle(HTTPD_CONF_USE_RANGE_1_0),
     196                 :                opt_def_toggle(HTTPD_CONF_USE_PUBLIC_ONLY),
     197                 :                opt_def_toggle(HTTPD_CONF_USE_ENC_CONTENT_REPLACEMENT),
     198                 :                opt_def_toggle(HTTPD_CONF_USE_ERR_406),
     199                 :                opt_def_toggle(HTTPD_CONF_USE_CANONIZE_HOST),
     200                 :                opt_def_toggle(HTTPD_CONF_USE_HOST_ERR_400),
     201                 :                opt_def_toggle(HTTPD_CONF_USE_HOST_CHK));
     202                 : 
     203               4 :   if (io_put_all(out, ret ? STDERR_FILENO : STDOUT_FILENO) == IO_FAIL)
     204               0 :     err(EXIT_FAILURE, "write");
     205                 :   
     206               4 :   exit (ret);
     207                 : }
     208                 : 
     209                 : static void serv_init(void)
     210              64 : {
     211              64 :   if (!vstr_init()) /* init the library */
     212               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     213                 : 
     214              64 :   vlg_init();
     215                 : 
     216              64 :   if (!vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE,
     217                 :                       VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR))
     218               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     219                 : 
     220              64 :   if (!vstr_cntl_conf(NULL,
     221                 :                       VSTR_CNTL_CONF_SET_NUM_BUF_SZ, OPT_SERV_CONF_BUF_SZ))
     222               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     223                 :   
     224                 :   /* no passing of conf to evnt */
     225              64 :   if (!vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$') ||
     226                 :       !vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_SEP, "_") ||
     227                 :       !vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_GRP, "\3") ||
     228                 :       !vstr_sc_fmt_add_all(NULL) ||
     229                 :       !vlg_sc_fmt_add_all(NULL) ||
     230                 :       !VSTR_SC_FMT_ADD(NULL, http_fmt_add_vstr_add_vstr,
     231                 :                        "<http-esc.vstr", "p%zu%zu", ">") ||
     232                 :       !VSTR_SC_FMT_ADD(NULL, http_fmt_add_vstr_add_sect_vstr,
     233                 :                        "<http-esc.vstr.sect", "p%p%u", ">"))
     234               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     235                 : 
     236              64 :   if (!(vlg = vlg_make()))
     237               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     238                 : 
     239              64 :   if (!VSTR_SC_FMT_ADD(vlg->out_vstr->conf, http_fmt_add_vstr_add_vstr,
     240                 :                        "<http-esc.vstr", "p%zu%zu", ">") ||
     241                 :       !VSTR_SC_FMT_ADD(vlg->out_vstr->conf, http_fmt_add_vstr_add_sect_vstr,
     242                 :                        "<http-esc.vstr.sect", "p%p%u", ">"))
     243               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     244              64 :   if (!VSTR_SC_FMT_ADD(vlg->sig_out_vstr->conf, http_fmt_add_vstr_add_vstr,
     245                 :                        "<http-esc.vstr", "p%zu%zu", ">") ||
     246                 :       !VSTR_SC_FMT_ADD(vlg->sig_out_vstr->conf, http_fmt_add_vstr_add_sect_vstr,
     247                 :                        "<http-esc.vstr.sect", "p%p%u", ">"))
     248               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     249                 : 
     250              64 :   if (!socket_poll_init(0, SOCKET_POLL_TYPE_MAP_DIRECT))
     251               0 :       errno = ENOMEM, err(EXIT_FAILURE, "init");
     252                 :   
     253              64 :   evnt_logger(vlg);
     254              64 :   evnt_poll_init();
     255              64 :   evnt_timeout_init();
     256                 : 
     257              64 :   vlg_time_set(vlg, evnt_sc_time);
     258                 :   
     259              64 :   opt_serv_logger(vlg);
     260                 : 
     261              64 :   httpd_init(vlg);
     262                 :   
     263              64 :   opt_serv_sc_signals();
     264              64 : }
     265                 : 
     266                 : static int serv_cb_func_send(struct Evnt *evnt)
     267        17786860 : {
     268        17786860 :   struct Con *con = (struct Con *)evnt;
     269                 :   
     270                 :   assert(HTTPD_CONF_SEND_CALL_LIMIT >= 1);
     271        17786860 :   con->io_limit_num = HTTPD_CONF_SEND_CALL_LIMIT;
     272        17786860 :   return (httpd_serv_send(con));
     273                 : }
     274                 : 
     275                 : static int serv_cb_func_recv(struct Evnt *evnt)
     276           50488 : {
     277           50488 :   struct Con *con = (struct Con *)evnt;
     278                 :   
     279                 :   assert(HTTPD_CONF_RECV_CALL_LIMIT >= 1);
     280           50488 :   con->io_limit_num = HTTPD_CONF_RECV_CALL_LIMIT;
     281           50488 :   return (httpd_serv_recv(con));
     282                 : }
     283                 : 
     284                 : static void serv_cb_func_free(struct Evnt *evnt)
     285           12052 : {
     286           12052 :   struct Con *con = (struct Con *)evnt;
     287                 :   
     288           12052 :   httpd_fin_fd_close(con);
     289                 : 
     290           12052 :   opt_serv_sc_free_beg(evnt, "FREE");
     291                 : 
     292            6026 :   ASSERT(con->fs && !con->fs_num && !con->fs_off && (con->fs->fd == -1));
     293                 : 
     294           12052 :   vstr_free_base(con->mpbr_ct);
     295                 :   
     296           12052 :   if (con->fs_sz > 1)
     297                 :   {
     298              32 :     ASSERT(con->fs != con->fs_store);
     299              64 :     F(con->fs);
     300                 :   }
     301                 :   else
     302            5994 :     ASSERT(con->fs == con->fs_store);
     303                 : 
     304           12052 :   vstr_free_base(con->tag);
     305           12052 :   F(con);
     306           12052 : }
     307                 : 
     308                 : static struct Evnt *serv_cb_func_accept(struct Evnt *from_evnt, int fd,
     309                 :                                         struct sockaddr *sa, socklen_t len)
     310           12052 : {
     311           12052 :   struct Acpt_listener *acpt_listener = (struct Acpt_listener *)from_evnt;
     312           12052 :   struct Con *con = MK(sizeof(struct Con));
     313                 : 
     314           12052 :   if (sa->sa_family != AF_INET) /* only support IPv4 atm. */
     315               0 :     goto sa_fail;
     316                 :   
     317           12052 :   if (!(con->tag = vstr_dup_cstr_ptr(NULL, "<default>")))
     318               0 :     goto con_tag_fail;
     319                 :   
     320           12052 :   if (!con || !evnt_make_acpt_dup(con->evnt, fd, sa, len))
     321                 :     goto make_acpt_fail;
     322                 : 
     323           12052 :   con->evnt->cbs->cb_func_recv       = serv_cb_func_recv;
     324           12052 :   con->evnt->cbs->cb_func_send       = serv_cb_func_send;
     325           12052 :   con->evnt->cbs->cb_func_free       = serv_cb_func_free;
     326                 : 
     327           12052 :   if (!evnt_limit_dup(con->evnt, &httpd_opts->s->io_nslimit))
     328               0 :     goto evnt_fail; /* redone on policy changes... */
     329                 :   
     330           12052 :   if (!evnt_limit_add(con->evnt,  httpd_opts->s->ref_io_limit))
     331               0 :     goto evnt_fail; /* redone on policy changes... */
     332                 :   
     333           12052 :   if (!evnt_limit_dup(con->evnt, &httpd_opts->s->io_nslimit))
     334               0 :     goto evnt_fail;
     335                 :   
     336           12052 :   if (!evnt_limit_add(con->evnt,  httpd_opts->s->ref_io_limit))
     337               0 :     goto evnt_fail;
     338                 :   
     339           12052 :   if (!httpd_con_init(con, acpt_listener))
     340               0 :     goto evnt_fail;
     341                 : 
     342           12052 :   if (!evnt_sc_timeout_via_mtime(con->evnt,
     343                 :                                  con->policy->s->idle_timeout * 1000))
     344               0 :     VLG_WARNNOMEM_GOTO(evnt_fail, (vlg, "timeout: %m\n"));
     345                 : 
     346           12052 :   if (!opt_serv_sc_acpt_end(con->policy->s, from_evnt, con->evnt))
     347               0 :     goto evnt_fail;
     348                 : 
     349            6026 :   ASSERT(!con->evnt->flag_q_closed);
     350                 : 
     351           12052 :   vlg_dbg2(vlg, "con($<sa:%p>): congestion=$<sockopt.s:%d%d%d>\n",
     352                 :            CON_CEVNT_SA(con), evnt_fd(con->evnt), IPPROTO_TCP, TCP_CONGESTION);
     353                 :   
     354           12052 :   return (con->evnt);
     355                 :   
     356               0 :  evnt_fail:
     357               0 :   evnt_close(con->evnt);
     358               0 :   return (con->evnt);
     359                 :   
     360               0 :  make_acpt_fail:
     361               0 :   vstr_free_base(con->tag);
     362               0 :  con_tag_fail:
     363               0 :   F(con);
     364               0 :   VLG_WARNNOMEM_RET(NULL, (vlg, "%s: %m\n", "accept"));
     365                 :   
     366               0 :  sa_fail:
     367               0 :   F(con);
     368               0 :   VLG_WARNNOMEM_RET(NULL, (vlg, "%s: HTTPD sa == ipv4 fail\n", "accept"));
     369                 : }
     370                 : 
     371                 : static void serv_make_bind(const char *program_name)
     372              40 : {
     373              40 :   Opt_serv_addr_opts *addr = httpd_opts->s->addr_beg;
     374                 :   
     375             200 :   while (addr)
     376                 :   {
     377             120 :     const char *acpt_address = NULL;
     378             120 :     const char *acpt_filter_file = NULL;
     379             120 :     const char *acpt_cong = NULL;
     380             120 :     struct Evnt *evnt = NULL;
     381                 :     
     382             120 :     OPT_SC_EXPORT_CSTR(acpt_address,     addr->acpt_address,     FALSE,
     383                 :                        "accept address");
     384             120 :     OPT_SC_EXPORT_CSTR(acpt_filter_file, addr->acpt_filter_file, FALSE,
     385                 :                        "accept filter file");
     386             120 :     OPT_SC_EXPORT_CSTR(acpt_cong,        addr->acpt_cong,        FALSE,
     387                 :                        "accept congestion mode");
     388                 :     
     389             120 :     evnt = evnt_sc_serv_make_bind_ipv4(acpt_address, addr->tcp_port,
     390                 :                                        addr->q_listen_len,
     391                 :                                        addr->max_connections,
     392                 :                                        addr->defer_accept,
     393                 :                                        acpt_filter_file, acpt_cong);
     394                 : 
     395             120 :     if (addr->def_policy->len)
     396                 :     {
     397              16 :       Vstr_base *dp = addr->def_policy;
     398              16 :       Opt_serv_policy_opts *po = opt_policy_find(httpd_opts->s, dp, 1, dp->len);
     399              16 :       Acpt_listener *acpt_listener = (Acpt_listener *)evnt;
     400                 : 
     401              16 :       if (!po)
     402               0 :         usage(program_name, EXIT_FAILURE,
     403                 :               " The name of the accept policy isn't valid.\n");
     404                 :         
     405              16 :       acpt_listener->def_policy = vstr_ref_add(po->ref);
     406                 :     }
     407                 :     
     408             120 :     evnt->cbs->cb_func_accept = serv_cb_func_accept;
     409                 : 
     410             120 :     addr = addr->next;
     411                 :   }
     412              40 : }
     413                 : 
     414                 : #define VCMP_MT_EQ_ALL(x, y, z)               \
     415                 :     vstr_cmp_eq(x -> mime_types_ ## z, 1, x -> mime_types_ ## z ->len,  \
     416                 :                 y -> mime_types_ ## z, 1, y -> mime_types_ ## z ->len)
     417                 : static Httpd_policy_opts *serv__mime_types_eq(Httpd_policy_opts *node)
     418             138 : { /* compares both mime filenames ... */
     419             138 :   Opt_serv_policy_opts *scan = httpd_opts->s->def_policy;
     420                 : 
     421              69 :   ASSERT(node);
     422                 :   
     423             315 :   while (scan != node->s)
     424                 :   {
     425             176 :     Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan;
     426                 :     
     427             176 :     if (VCMP_MT_EQ_ALL(tmp, node, main) && VCMP_MT_EQ_ALL(tmp, node, xtra))
     428              68 :       return (tmp);
     429                 :     
     430             108 :     scan = scan->next;
     431                 :   }
     432                 :   
     433              70 :   return (NULL);
     434                 : }
     435                 : #undef VCMP_MT_EQ_ALL
     436                 : 
     437                 : static void serv_mime_types(const char *program_name)
     438              40 : {
     439              40 :   Opt_serv_policy_opts *scan = httpd_opts->s->def_policy;
     440                 :     
     441             218 :   while (scan)
     442                 :   {
     443             138 :     Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan;
     444             138 :     Httpd_policy_opts *prev = NULL;
     445                 :     
     446             138 :     if (!mime_types_init(tmp->mime_types,
     447                 :                          tmp->mime_types_def_ct, 1,
     448                 :                          tmp->mime_types_def_ct->len))
     449               0 :       errno = ENOMEM, err(EXIT_FAILURE, "init");
     450                 : 
     451             138 :     if ((prev = serv__mime_types_eq(tmp)))
     452              68 :       mime_types_combine_filedata(tmp->mime_types, prev->mime_types);
     453                 :     else
     454                 :     {
     455              70 :       const char *mime_types_main = NULL;
     456              70 :       const char *mime_types_xtra = NULL;
     457                 :   
     458              70 :       OPT_SC_EXPORT_CSTR(mime_types_main, tmp->mime_types_main, FALSE,
     459                 :                          "MIME types main file");
     460              70 :       OPT_SC_EXPORT_CSTR(mime_types_xtra, tmp->mime_types_xtra, FALSE,
     461                 :                          "MIME types extra file");
     462                 : 
     463              70 :       if (!mime_types_load_simple(tmp->mime_types, mime_types_main))
     464               0 :         err(EXIT_FAILURE, "load_mime(%s)", mime_types_main);
     465                 :   
     466              70 :       if (!mime_types_load_simple(tmp->mime_types, mime_types_xtra))
     467               0 :         err(EXIT_FAILURE, "load_mime(%s)", mime_types_xtra);
     468                 :     }
     469                 :     
     470             138 :     scan = scan->next;
     471                 :   }
     472                 : 
     473                 :   /* we don't need the filenames after we've loaded... */
     474              40 :   scan = httpd_opts->s->def_policy;
     475             218 :   while (scan)
     476                 :   {
     477             138 :     Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan;
     478                 :     
     479             138 :     vstr_free_base(tmp->mime_types_main); tmp->mime_types_main = NULL;
     480             138 :     vstr_free_base(tmp->mime_types_xtra); tmp->mime_types_xtra = NULL;
     481                 :     
     482             138 :     scan = scan->next;
     483                 :   }
     484              40 : }
     485                 : 
     486                 : static void serv_canon_policies(void)
     487              40 : {
     488              40 :   Opt_serv_policy_opts *scan = httpd_opts->s->def_policy;
     489                 :   
     490             218 :   while (scan)
     491                 :   { /* check variables for things which will screw us too much */
     492             138 :     Httpd_policy_opts *def_opt = (Httpd_policy_opts *)httpd_opts->s->def_policy;
     493             138 :     Httpd_policy_opts *opt = (Httpd_policy_opts *)scan;
     494             138 :     Vstr_base *def_doc_root = def_opt->document_root;
     495             138 :     Vstr_base *s1 = NULL;
     496             138 :     int ec = EXIT_FAILURE;
     497                 :     
     498              69 :     ASSERT(scan->beg == httpd_opts->s);
     499                 :     
     500             138 :     s1 = opt->document_root;
     501             138 :     if (!httpd_canon_dir_path(s1))
     502               0 :       VLG_ERRNOMEM((vlg, ec, "canon_dir_path($<vstr.all:%p>): %m\n", s1));
     503             138 :     if (!s1->len && !vstr_add_vstr(s1, 0, def_doc_root, 1, def_doc_root->len,
     504                 :                                    VSTR_TYPE_ADD_BUF_REF))
     505               0 :       VLG_ERRNOMEM((vlg, ec, "canon_dir_path(): %m\n"));
     506                 :     
     507             138 :     s1 = opt->req_conf_dir;
     508             138 :     if (!httpd_canon_dir_path(s1))
     509               0 :       VLG_ERRNOMEM((vlg, ec, "canon_dir_path($<vstr.all:%p>): %m\n", s1));
     510                 : 
     511             138 :     s1 = opt->req_err_dir;
     512             138 :     if (!httpd_canon_dir_path(s1))
     513               0 :       VLG_ERRNOMEM((vlg, ec, "canon_dir_path($<vstr.all:%p>): %m\n", s1));
     514                 : 
     515             138 :     if (!httpd_init_default_hostname(scan))
     516               0 :       VLG_ERRNOMEM((vlg, ec, "hostname(): %m\n"));
     517                 :     
     518             138 :     s1 = opt->dir_filename;
     519             138 :     if (!httpd_valid_url_filename(s1, 1, s1->len) &&
     520                 :         !vstr_sub_cstr_ptr(s1, 1, s1->len, HTTPD_CONF_DEF_DIR_FILENAME))
     521               0 :       VLG_ERRNOMEM((vlg, ec, "dir_filename(): %m\n"));
     522                 :     
     523             138 :     scan = scan->next;
     524                 :   }
     525              40 : }
     526                 : 
     527                 : static int serv_def_conf(Vstr_base *out)
     528               0 : { /* pretend we passed (if it works...):
     529                 :    * -C /etc/and-httpd/and-httpd.conf --conf-dir /etc/and-httpd/conf.d ... */
     530                 :   struct stat64 d_stat[1];
     531                 :   static const char pc_file[] = PATH_SYSCONFDIR "/and-httpd/and-httpd.conf";
     532                 :   static const char pc_dir[]  = PATH_SYSCONFDIR "/and-httpd/conf.d";
     533                 :   
     534               0 :   if ((stat64(pc_file, d_stat) != -1) &&
     535                 :       !httpd_conf_main_parse_file(out, httpd_opts, pc_file))
     536               0 :     return (FALSE);
     537               0 :   if ((stat64(pc_file, d_stat) != -1) &&
     538                 :       !opt_serv_sc_config_dir(out, httpd_opts, pc_dir,
     539                 :                               httpd_sc_conf_main_parse_dir_file))
     540               0 :     return (FALSE);
     541                 :   
     542               0 :   return (TRUE);
     543                 : }
     544                 : 
     545                 : #define POPT_TOGGLE_ARG(x) do {                                         \
     546                 :       Opt_serv_policy_opts *popt_scan = httpd_opts->s->def_policy;      \
     547                 :                                                                         \
     548                 :       while (popt_scan)                                                 \
     549                 :       {                                                                 \
     550                 :         Httpd_policy_opts *popt_tmp = (Httpd_policy_opts *)popt_scan;   \
     551                 :         OPT_TOGGLE_ARG(popt_tmp->x);                                    \
     552                 :         popt_scan = popt_scan->next;                                    \
     553                 :       }                                                                 \
     554                 :     } while (FALSE)
     555                 : 
     556                 : #define POPT_NUM_NR_ARG(x, y) do {                                      \
     557                 :       Opt_serv_policy_opts *popt_scan = httpd_opts->s->def_policy;      \
     558                 :                                                                         \
     559                 :       while (popt_scan)                                                 \
     560                 :       {                                                                 \
     561                 :         Httpd_policy_opts *popt_tmp = (Httpd_policy_opts *)popt_scan;   \
     562                 :         OPT_NUM_NR_ARG(popt_tmp->x, y);                                 \
     563                 :         popt_scan = popt_scan->next;                                    \
     564                 :       }                                                                 \
     565                 :     } while (FALSE)
     566                 : 
     567                 : #define POPT_VSTR_ARG(x) do {                                           \
     568                 :       Opt_serv_policy_opts *popt_scan = httpd_opts->s->def_policy;      \
     569                 :                                                                         \
     570                 :       while (popt_scan)                                                 \
     571                 :       {                                                                 \
     572                 :         Httpd_policy_opts *popt_tmp = (Httpd_policy_opts *)popt_scan;   \
     573                 :         OPT_VSTR_ARG(popt_tmp->x);                                      \
     574                 :         popt_scan = popt_scan->next;                                    \
     575                 :       }                                                                 \
     576                 :     } while (FALSE)
     577                 : 
     578                 : static void serv_cmd_line(int argc, char *argv[])
     579              64 : {
     580              64 :   int optchar = 0;
     581              64 :   const char *program_name = NULL;
     582                 :   struct option long_options[] =
     583                 :   {
     584                 :    OPT_SERV_DECL_GETOPTS(),
     585                 :    
     586                 :    {"configuration-file", required_argument, NULL, 'C'},
     587                 :    {"config-file",        required_argument, NULL, 'C'},
     588                 :    {"conf-file",          required_argument, NULL, 'C'},
     589                 :    {"configuration-directory", required_argument, NULL, 140},
     590                 :    {"config-dir",              required_argument, NULL, 140},
     591                 :    {"conf-dir",                required_argument, NULL, 140},
     592                 :    {"configuration-data-daemon", required_argument, NULL, 143},
     593                 :    {"config-data-daemon",        required_argument, NULL, 143},
     594                 :    {"configuration-data-httpd", required_argument, NULL, 144},
     595                 :    {"config-data-httpd",        required_argument, NULL, 144},
     596                 :    {"configuration-data-and-httpd", required_argument, NULL, 144},
     597                 :    {"config-data-and-httpd",        required_argument, NULL, 144},
     598                 :    {"default-configuration", no_argument, NULL, 149},
     599                 :    {"def-config",            no_argument, NULL, 149},
     600                 :    
     601                 :    {"sendfile", optional_argument, NULL, 31},
     602                 :    {"mmap", optional_argument, NULL, 30},
     603                 :    
     604                 :    {"max-header-sz", required_argument, NULL, 128},
     605                 :    {"keep-alive", optional_argument, NULL, 129},
     606                 :    {"keep-alive-1.0", optional_argument, NULL, 130},
     607                 :    {"vhosts", optional_argument, NULL, 131},
     608                 :    {"virtual-hosts", optional_argument, NULL, 131},
     609                 :    {"range", optional_argument, NULL, 132},
     610                 :    {"range-1.0", optional_argument, NULL, 133},
     611                 :    {"public-only", optional_argument, NULL, 134}, /* FIXME: rm ? */
     612                 :    {"dir-filename", required_argument, NULL, 135},
     613                 :    {"server-name", required_argument, NULL, 136},
     614                 :    {"gzip-content-replacement", optional_argument, NULL, 137},
     615                 :    /* 138 */
     616                 :    {"error-406", optional_argument, NULL, 139},
     617                 :    /* 140 -- config. dir above */
     618                 :    {"mime-types-main", required_argument, NULL, 141},
     619                 :    {"mime-types-extra", required_argument, NULL, 142},
     620                 :    {"mime-types-xtra", required_argument, NULL, 142},
     621                 :    /* 143 -- config data above */
     622                 :    /* 144 -- config data above */
     623                 :    {"unspecified-hostname", required_argument, NULL, 145},
     624                 :    {"canonize-host", optional_argument, NULL, 146},
     625                 :    {"error-host-400", optional_argument, NULL, 147},
     626                 :    {"check-host", optional_argument, NULL, 148},
     627                 :    /* 149 -- config data above */
     628                 :    /* {"404-file", required_argument, NULL, 0}, */
     629                 :    {NULL, 0, NULL, 0}
     630              64 :   };
     631              64 :   const char *chroot_dir = NULL;
     632              64 :   const char *document_root = NULL;
     633              64 :   Vstr_base *out = vstr_make_base(NULL);
     634              64 :   Httpd_policy_opts *popts = NULL;
     635                 : 
     636              64 :   if (!out)
     637               0 :     errno = ENOMEM, err(EXIT_FAILURE, "command line");
     638                 : 
     639              64 :   evnt_opt_nagle = TRUE;
     640                 :   
     641              64 :   program_name = opt_program_name(argv[0], PACKAGE);
     642              64 :   httpd_opts->s->name_cstr = program_name;
     643              64 :   httpd_opts->s->name_len  = strlen(program_name);
     644                 : 
     645              64 :   httpd_opts->s->make_policy = httpd_policy_make;
     646              64 :   httpd_opts->s->copy_policy = httpd_policy_copy;
     647                 : 
     648              64 :   if (!httpd_conf_main_init(httpd_opts))
     649               0 :     errno = ENOMEM, err(EXIT_FAILURE, "options");
     650                 : 
     651              64 :   if (!geteuid()) /* If root */
     652               0 :     httpd_opts->s->addr_beg->tcp_port = HTTPD_CONF_SERV_DEF_PORT;
     653                 :   else /* somewhat common unprived port */
     654              64 :     httpd_opts->s->addr_beg->tcp_port = 8008;
     655                 :     
     656              64 :   popts = (Httpd_policy_opts *)httpd_opts->s->def_policy;
     657             434 :   while ((optchar = getopt_long(argc, argv, "C:dhH:M:nP:t:V",
     658                 :                                 long_options, NULL)) != -1)
     659                 :   {
     660             330 :     switch (optchar)
     661                 :     {
     662               0 :       case '?': usage(program_name, EXIT_FAILURE, "");
     663               4 :       case 'h': usage(program_name, EXIT_SUCCESS, "");
     664                 :         
     665                 :       case 'V':
     666               4 :         vstr_add_fmt(out, 0, " %s version %s.\n", program_name, VERSION);
     667                 :         
     668               4 :         if (io_put_all(out, STDOUT_FILENO) == IO_FAIL)
     669               0 :           err(EXIT_FAILURE, "write");
     670                 :         
     671               4 :         exit (EXIT_SUCCESS);
     672                 :       
     673               3 :       OPT_SERV_GETOPTS(httpd_opts->s);
     674                 : 
     675                 :       case 'C':
     676              30 :         if (!httpd_conf_main_parse_file(out, httpd_opts, optarg))
     677               4 :           goto out_err_conf_msg;
     678              13 :         break;
     679                 :       case 140:
     680               6 :         if (!opt_serv_sc_config_dir(out, httpd_opts, optarg,
     681                 :                                     httpd_sc_conf_main_parse_dir_file))
     682               4 :           goto out_err_conf_msg;
     683               1 :         break;
     684                 :       case 143:
     685              32 :         if (!opt_serv_conf_parse_cstr(out, httpd_opts->s, optarg))
     686               4 :           goto out_err_conf_msg;
     687              14 :       break;
     688                 :       case 144:
     689              46 :         if (!httpd_conf_main_parse_cstr(out, httpd_opts, optarg))
     690               4 :           goto out_err_conf_msg;
     691              21 :         break;
     692                 :       case 149:
     693               0 :         if (!serv_def_conf(out))
     694               0 :           goto out_err_conf_msg;
     695               0 :         break;
     696                 :         
     697               2 :       case 128: POPT_NUM_NR_ARG(max_header_sz, "max header size"); break;
     698                 :         
     699               6 :       case  31: POPT_TOGGLE_ARG(use_sendfile);                     break;
     700               6 :       case  30: POPT_TOGGLE_ARG(use_mmap);                         break;
     701                 :         
     702               2 :       case 129: POPT_TOGGLE_ARG(use_keep_alive);                   break;
     703               0 :       case 130: POPT_TOGGLE_ARG(use_keep_alive_1_0);               break;
     704              10 :       case 131: POPT_TOGGLE_ARG(use_vhosts_name);                  break;
     705               2 :       case 132: POPT_TOGGLE_ARG(use_range);                        break;
     706               0 :       case 133: POPT_TOGGLE_ARG(use_range_1_0);                    break;
     707               2 :       case 134: POPT_TOGGLE_ARG(use_public_only);                  break;
     708               2 :       case 135: POPT_VSTR_ARG(dir_filename);                       break;
     709               2 :       case 136: POPT_VSTR_ARG(server_name);                        break;
     710               2 :       case 137: POPT_TOGGLE_ARG(use_enc_content_replacement);      break;
     711               2 :       case 139: POPT_TOGGLE_ARG(use_err_406);                      break;
     712                 :         /* case 140: */
     713              42 :       case 141: POPT_VSTR_ARG(mime_types_main);                    break;
     714              12 :       case 142: POPT_VSTR_ARG(mime_types_xtra);                    break;
     715                 :         /* case 143: */
     716                 :         /* case 144: */
     717              10 :       case 145: POPT_VSTR_ARG(default_hostname);                   break;
     718               2 :       case 146: POPT_TOGGLE_ARG(use_canonize_host);                break;
     719               2 :       case 147: POPT_TOGGLE_ARG(use_host_err_400);                 break;
     720               0 :       case 148: POPT_TOGGLE_ARG(use_host_chk);
     721                 :         
     722                 :       
     723               0 :       ASSERT_NO_SWITCH_DEF();
     724                 :     }
     725                 :   }
     726                 : 
     727              20 :   ASSERT(optind >= 1);
     728              40 :   if (optind <= 1) /* just program name, no options so use default... */
     729               0 :     if (!serv_def_conf(out))
     730               0 :       goto out_err_conf_msg;
     731              40 :   vstr_free_base(out); out = NULL;
     732                 :   
     733              40 :   argc -= optind;
     734              40 :   argv += optind;
     735                 : 
     736              40 :   if (argc > 1)
     737               0 :     usage(program_name, EXIT_FAILURE, " Too many arguments.\n");
     738                 : 
     739              40 :   if (argc == 1)
     740                 :   {
     741              40 :     Vstr_base *tmp = popts->document_root;
     742              40 :     vstr_sub_cstr_ptr(tmp, 1, tmp->len, argv[0]);
     743                 :   }
     744                 : 
     745              40 :   if (!popts->document_root->len)
     746               0 :     usage(program_name, EXIT_FAILURE, " Not specified a document root.\n");
     747                 : 
     748                 :   {
     749              40 :     const char *pid_file = NULL;
     750              40 :     Opt_serv_opts *opts = httpd_opts->s;
     751                 :     
     752              40 :     vlg_syslog_facility_set(vlg, opts->syslog_facility);
     753                 :     /* vlg_date_set(vlg, opts->vlg_date_fmt_type); */
     754              40 :     if (!opts->vlg_tweaked_size)
     755                 :     {
     756              40 :       if (opts->become_daemon)      
     757               0 :         opts->vlg_size = OPT_SERV_CONF_VLG_SIZE_UNTWEAKED_DAEMON;
     758                 :       else
     759              40 :         opts->vlg_size = OPT_SERV_CONF_VLG_SIZE_UNTWEAKED_CONSOLE;
     760                 :     }
     761              40 :     vlg_size_set(vlg, opts->vlg_size);
     762              40 :     vlg_syslog_native_set(vlg, opts->vlg_syslog_native);
     763                 :   
     764              40 :     OPT_SC_EXPORT_CSTR(pid_file,   opts->pid_file,   FALSE, "pid file");
     765              40 :     OPT_SC_EXPORT_CSTR(chroot_dir, opts->chroot_dir, FALSE, "chroot directory");
     766                 :     
     767              40 :     if (opts->drop_privs)
     768                 :     {
     769               0 :       OPT_SERV_SC_RESOLVE_UID(opts);
     770               0 :       OPT_SERV_SC_RESOLVE_GID(opts);
     771                 :     }
     772                 :   
     773              40 :     if (!httpd_init_default_hostname(opts->def_policy))
     774               0 :       errno = ENOMEM, err(EXIT_FAILURE, "default_hostname");
     775                 :   
     776              40 :     serv_make_bind(program_name);
     777                 : 
     778              40 :     serv_mime_types(program_name);
     779                 :     
     780              40 :     serv_canon_policies();
     781                 :   
     782              40 :     OPT_SC_EXPORT_CSTR(document_root, popts->document_root, TRUE,
     783                 :                        "document root");
     784                 :     
     785              40 :     if (opts->become_daemon)
     786                 :     {
     787               0 :       if (daemon(FALSE, FALSE) == -1)
     788               0 :         err(EXIT_FAILURE, "daemon");
     789               0 :       vlg_daemon(vlg, program_name);
     790                 :     }
     791                 :     
     792                 :     /* NOTE: after daemon so don't use err() anymore ... */
     793                 :     
     794              40 :     if (httpd_opts->s->rlim_as_call)
     795               0 :       opt_serv_sc_rlim_as_num(httpd_opts->s->rlim_as_num);
     796              40 :     if (httpd_opts->s->rlim_core_call)
     797              28 :       opt_serv_sc_rlim_core_num(httpd_opts->s->rlim_core_num);
     798              40 :     if (httpd_opts->s->rlim_file_call)
     799               0 :       opt_serv_sc_rlim_file_num(httpd_opts->s->rlim_file_num);
     800                 :   
     801              40 :     if (pid_file)
     802              20 :       vlg_pid_file(vlg, pid_file);
     803                 : 
     804              40 :     if (opts->cntl_file->len)
     805              40 :       cntl_make_file(vlg, opts->cntl_file);
     806                 : 
     807              40 :     if (chroot_dir)
     808                 :     { /* preload locale info. so syslog can log in localtime, this doesn't work
     809                 :        * with current glibc's as they re-stat ... maybe set the ENV somehow? */
     810               0 :       time_t now = time(NULL);
     811               0 :       (void)localtime(&now);
     812                 :       
     813               0 :       vlg_sc_bind_mount(chroot_dir);
     814                 :     }
     815                 :     
     816              40 :     if (chroot_dir && ((chroot(chroot_dir) == -1) || (chdir("/") == -1)))
     817               0 :       vlg_err(vlg, EXIT_FAILURE, "chroot(%s): %m\n", chroot_dir);
     818                 :     
     819              40 :     if (opts->drop_privs)
     820                 :     {
     821               0 :       if (opts->keep_cap_fowner && (PROC_CNTL_KEEPCAPS(TRUE) == -1))
     822                 :       {
     823               0 :         vlg_warn(vlg, "prctl(%s, %s): %m\n", "PR_SET_KEEPCAPS", "TRUE");
     824               0 :         opts->keep_cap_fowner = FALSE;
     825                 :       }
     826                 :       
     827               0 :       opt_serv_sc_drop_privs(opts);
     828                 :       
     829               0 :       if (opts->keep_cap_fowner)
     830                 :       { /* use + instead of = because that's how getpcaps prints it,
     831                 :          * however they do the same due to no input */
     832               0 :         cap_t caps = cap_from_text("cap_fowner+ep-i");
     833                 : 
     834               0 :         if (!caps)
     835               0 :           vlg_err(vlg, EXIT_FAILURE, "cap_from_text(%s): %m\n",
     836                 :                   "cap_fowner+pe-i");
     837                 :         
     838               0 :         if (PROC_CNTL_KEEPCAPS(FALSE) == -1)
     839               0 :           vlg_err(vlg, EXIT_FAILURE,
     840                 :                   "prctl(%s, %s): %m\n", "PR_SET_KEEPCAPS", "FALSE");
     841                 :         
     842               0 :         if (cap_set_proc(caps) == -1)
     843               0 :           vlg_err(vlg, EXIT_FAILURE, "cap_set_proc(%s): %m\n",
     844                 :                   "cap_fowner+ep-i");
     845               0 :         if (cap_free(caps) == -1)
     846               0 :           vlg_err(vlg, EXIT_FAILURE, "cap_free(): %m\n");
     847                 :       }
     848                 :     }
     849                 : 
     850              40 :     if (opts->num_procs > 1)
     851                 :     {
     852               4 :       int has_cntl = !!opts->cntl_file->len;
     853               4 :       cntl_sc_multiproc(vlg, opts->num_procs, has_cntl, opts->use_pdeathsig);
     854                 :     }
     855                 :     
     856              44 :     if (opts->make_dumpable && (PROC_CNTL_DUMPABLE(TRUE) == -1))
     857               0 :       vlg_warn(vlg, "prctl(%s, %s): %m\n", "PR_SET_DUMPABLE", "TRUE");
     858                 :   }
     859                 : 
     860              44 :   httpd_opts->beg_time = time(NULL);
     861                 :   
     862                 :   {
     863              44 :     struct Evnt *evnt = evnt_queue("accept");
     864                 :     
     865             254 :     while (evnt)
     866                 :     {
     867             166 :       vlg_info(vlg, "READY [$<sa:%p>]: %s%s%s\n", EVNT_SA(evnt),
     868                 :                chroot_dir ? chroot_dir : "",
     869                 :                chroot_dir ?        "/" : "",
     870                 :                document_root);
     871             166 :       evnt = evnt->next;
     872                 :     }
     873                 :   }
     874                 :   
     875              44 :   opt_serv_conf_free_beg(httpd_opts->s);
     876                 :   return;
     877                 : 
     878              16 :  out_err_conf_msg:
     879              16 :   vstr_add_cstr_ptr(out, out->len, "\n");
     880              16 :   if (io_put_all(out, STDERR_FILENO) == IO_FAIL)
     881               0 :     err(EXIT_FAILURE, "write");
     882              16 :   exit (EXIT_FAILURE);  
     883                 : }
     884                 : 
     885                 : int main(int argc, char *argv[])
     886              64 : {
     887                 :   if (sizeof(uintmax_t) != sizeof(VSTR_AUTOCONF_uintmax_t))
     888                 :     errx(EXIT_FAILURE, "uintmax_t size is different between program and Vstr");
     889                 : 
     890              32 :   assert((F(M0(1, 1)), 1)); /* for coverage */
     891                 :   
     892              64 :   serv_init();
     893                 : 
     894              64 :   serv_cmd_line(argc, argv);
     895                 : 
     896         9176427 :   while (evnt_waiting())
     897                 :   {
     898         9176339 :     evnt_sc_main_loop(HTTPD_CONF_MAX_WAIT_SEND);
     899         9176339 :     opt_serv_sc_check_children();
     900         9176339 :     opt_serv_sc_cntl_resources(httpd_opts->s);
     901                 :   }
     902              44 :   evnt_out_dbg3("E");
     903                 :   
     904              44 :   evnt_timeout_exit();
     905              44 :   cntl_child_free();
     906              44 :   evnt_close_all();
     907                 : 
     908              44 :   httpd_exit();
     909                 :   
     910              44 :   http_req_exit();
     911                 :   
     912              44 :   vlg_free(vlg);
     913              44 :   vlg_exit();
     914                 : 
     915              44 :   httpd_conf_main_free(httpd_opts);
     916                 :   
     917              44 :   timer_q_exit();
     918                 :   
     919              44 :   vstr_exit();
     920                 : 
     921              22 :   MALLOC_CHECK_EMPTY();
     922                 :   
     923              44 :   exit (EXIT_SUCCESS);
     924                 : }

Generated by: LTP GCOV extension version 1.4