aboutsummaryrefslogtreecommitdiff
path: root/web/apache/service.cxx
blob: 6b73e029292ac97f9b73f02766de191e29845955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// file      : web/apache/service.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#include <web/apache/service>

#include <unistd.h> // getppid()
#include <signal.h> // kill()

#include <httpd/httpd.h>
#include <httpd/http_config.h>

#include <memory> // unique_ptr
#include <string>
#include <exception>

using namespace std;

namespace web
{
  namespace apache
  {
    void service::
    init_directives()
    {
      assert(cmds == nullptr);

      // Fill apache module directive definitions. Directives share
      // common name space in apache configuration file, so to prevent name
      // clash have to form directive name as a combination of module and
      // option names: <module name>-<option name>. This why for option
      // bar of module foo the corresponding directive will appear in apache
      // configuration file as foo-bar.
      //
      unique_ptr<command_rec[]> directives (
        new command_rec[option_names_.size () + 1]);

      command_rec* d (directives.get ());

      for (auto& o: option_names_)
      {
        o = name_ + "-" + o;

        *d++ =
          {
            o.c_str (),
            reinterpret_cast<cmd_func> (add_option),
            this,
            RSRC_CONF,
            TAKE1,
            nullptr
          };
      }

      *d = {};

      cmds = directives.release ();
    }

    const char* service::
    add_option (cmd_parms *parms, void *mconfig, const char *value) noexcept
    {
      service& srv (*reinterpret_cast<service*> (parms->cmd->cmd_data));
      string name (parms->cmd->name + srv.name_.length () + 1);

      for (auto& v: srv.options_)
        if (v.name == name)
        {
          v.value = value;
          return 0;
        }

      srv.options_.emplace_back (name, value);
      return 0;
    }

    void service::
    init_worker(log& l) noexcept
    {
      static const string func_name (
        "web::apache::service<" + name_ + ">::init_worker");

      try
      {
        exemplar_.init (options_, l);
      }
      catch (const exception& e)
      {
        l.write (nullptr, 0, func_name.c_str (), APLOG_EMERG, e.what ());

        // Terminate the root apache process.
        //
        ::kill (::getppid (), SIGTERM);
      }
      catch (...)
      {
        l.write (nullptr,
                 0,
                 func_name.c_str (),
                 APLOG_EMERG,
                 "unknown error");

        // Terminate the root apache process.
        //
        ::kill (::getppid (), SIGTERM);
      }
    }
  }
}