/*
 * Copyright (c) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2018 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 *
 * author Alexander Demeshko <ademeshko@cloudlinux.com>
 *
 */

#include <lscapi_util.h>
#include <string.h>
#include <unixd.h>
#include <apr_hash.h>
#include <apr_strings.h>
#include <apr_signal.h>
#include <mpm_common.h>
#include <ap_mpm.h>

#ifdef WITH_BLACKLIST
#include <json-c/json.h>  // Include json-c library
#include <sys/stat.h>     // Include for stat()

#define LSAPI_BLACKLIST_DIR     "/var/cloudlinux/cl.selector/uids/"
#define LSAPI_BLACKLIST_FLAG    "/opt/cloudlinux/flags/enabled-flags.d/lsapi-php-restrictions.flag"

// Will be activated on apache restart if LSAPI_BLACKLIST_FLAG exists
static int use_handler_blacklist = 0;

static void lsapi_clear_handler_blacklist(lsapi_svr_conf_t *dircfg);
static int lsapi_check_and_load_handler_blacklist(request_rec *r, lsapi_svr_conf_t *dircfg, uint32_t uid);
static int lsapi_is_handler_blacklisted(request_rec *r, lsapi_svr_conf_t *dircfg, uint32_t uid);
int lscapi_conn_failed_cb(lsphp_conn_t *conn);
#endif

#define PREFIX "mod_lsapi: "
#define MOD_LSAPI_VERSION MOD_LSAPI_VERSION_MAJOR "." MOD_LSAPI_VERSION_MINOR "-" MOD_LSAPI_VERSION_RELEASE

/* LSAPI_PRO_ONLY:BEGIN */
#ifdef WITH_CRIU
static int reset_criu_on_apache_restart = 0;
#endif
/* LSAPI_PRO_ONLY:END */

module AP_MODULE_DECLARE_DATA lsapi_module;

APLOG_USE_MODULE(lsapi);

lsapi_svr_conf_t *lsapi_get_svr_config(server_rec *s)
{
    return ap_get_module_config(s->module_config, &lsapi_module);
}


static void* alloc_by_pool(size_t sz, void *user_data)
{
    return apr_palloc((apr_pool_t*)user_data, sz);
}

/* LSAPI_PRO_ONLY:BEGIN */
static int check_connection_pool_condition(request_rec *r, lscapi_rec *lscapi, lsapi_svr_conf_t *svrcfg)
{
    int rc = 1;
    static const unsigned bodyLen_threshold = 10240;
    unsigned bodyLen = (unsigned) lscapi_get_body_len(lscapi);
    if (r->chunked)
    {
        lscapi_notice(svrcfg, 0, r->server, "Connection pool mode is switched off for the request due to chunked mode");
        rc = 0;
    }
    else if (r->method_number == M_POST)
    {
        if (bodyLen == 0)
        {
            lscapi_notice(svrcfg, 0, r->server,
                            "Connection pool mode is switched off for the request due to POST method with unknown body length");
            rc = 0;
        }
        else if (bodyLen >= bodyLen_threshold)
        {
            lscapi_notice(svrcfg, 0, r->server,
                          "Connection pool mode is switched off for the request due to POST method with too large body (%u more than %u)",
                          bodyLen, bodyLen_threshold );
            rc = 0;
        }
    }
    return rc;
}

static int
connect_with_connection_pool(lsphp_conn_t *backend, request_rec *r, lscapi_rec *lscapi,
                             lsapi_svr_conf_t *svrcfg, lsapi_connslot_info_t* slotInfoPtr,
                             unsigned *eventMaskPtr, char *errbuf, size_t errlen)
{
    const char *sock_name = lscapi_conn_get_socket_name(backend);
    lscapi_notice(svrcfg, 0, r->server, "will try to grab the slot, as connection pool mode is in use");
    if (lscapi_grab_sock_slot(r->server, svrcfg, sock_name, slotInfoPtr) != 0)
    {
        // something wrong with connection pool, so will use conventional mode
        lscapi_notice(svrcfg, 0, r->server, "grab the slot failed, so will not use connection pool mode");
        return -1;
    }

    if (slotInfoPtr->slot->is_open)
    {
        lscapi_lsphp_use_sock_ext(backend, slotInfoPtr->slot->sock, slotInfoPtr->slot->worker_pid, errbuf, sizeof errbuf);
        if (lscapi_is_conn_closed(backend))
        {
            lscapi_notice(svrcfg, 0, r->server, "Opened socket in the grabbed slot became close - mark it as closed");
            slotInfoPtr->slot->sock = 0;
            slotInfoPtr->slot->worker_pid = 0;
            slotInfoPtr->slot->is_open = 0;
        }
    }

    if (slotInfoPtr->slot->is_open == 0)
    {
        lscapi_notice(svrcfg, 0, r->server, "Will ty to connect to backend for the allocated slot");
        if (lscapi_connect_backend(backend, eventMaskPtr, errbuf, errlen) != 0)
        {
            lscapi_notice(svrcfg, 0, r->server, "connect to backend failed, so will ungrab the slot and return with error");
            lscapi_ungrab_sock_slot(r->server, slotInfoPtr);
            return -1;
        }

        lscapi_notice(svrcfg, 0, r->server, "connect to backend succedeed, will write its sock into the grabbed slot");
        slotInfoPtr->slot->sock = lscapi_lsphp_conn_get_socket(backend);
        slotInfoPtr->slot->worker_pid = lscapi_conn_get_worker_pid(backend);
        slotInfoPtr->slot->is_open = 1;
    }
    return 0;
}

/* LSAPI_PRO_ONLY:END */

// Return codes:
//   -1: error occured
/* LSAPI_PRO_ONLY:BEGIN */
//    1: connection established in connection pool mode
/* LSAPI_PRO_ONLY:END */
//    0: connection estableshed
static apr_status_t
connect_to_backend(lsphp_conn_t *backend, request_rec *r, lscapi_rec *lscapi,
/* LSAPI_PRO_ONLY:BEGIN */
                   lsapi_connslot_info_t* slotInfoPtr,
/* LSAPI_PRO_ONLY:END */
                   unsigned *eventMaskPtr, char *errbuf, size_t errlen)
{
    lsapi_svr_conf_t *svrcfg = ap_get_module_config(r->server->module_config, &lsapi_module);
    lsapi_dir_conf_t *dircfg = (lsapi_dir_conf_t*) ap_get_module_config(r->per_dir_config, &lsapi_module);

/* LSAPI_PRO_ONLY:BEGIN */
    int with_connpool = svrcfg->with_connection_pool ? check_connection_pool_condition(r, lscapi, svrcfg) : 0;

    if (with_connpool
        && connect_with_connection_pool(backend, r, lscapi, svrcfg, slotInfoPtr, eventMaskPtr, errbuf, errlen) != 0)
    {
        with_connpool = 0;
    }

    if (with_connpool == 0)
/* LSAPI_PRO_ONLY:END */
    {
        lscapi_notice(svrcfg, 0, r->server, "will connect to backend");
        if (lscapi_connect_backend_ex(backend, eventMaskPtr, errbuf, errlen, r->chunked) != 0)
        {
            return -1;
        }
    }

    if (dircfg->measure_time)
    {
        lscapi_write_measured_time(r, LSCAPI_MEASURE_CONN_ESTABLISHED);
    }
/* LSAPI_PRO_ONLY:BEGIN */
    if (with_connpool != 0)
    {
        return 1;
    }
    else
/* LSAPI_PRO_ONLY:END */
        return 0;
}


#define SET_STATUS_WITH_LINE(r, st)  do { (r)->status = (st); (r)->status_line = lsapi_get_status_line((r)->status); } while (0)

/*
 * Backend communications occur in scope of this function and it's callees
 */
static apr_status_t talk_to_backend_impl(lsphp_conn_t *backend, request_rec *r,
/* LSAPI_PRO_ONLY:BEGIN */
                                         lsapi_connslot_info_t* slotInfoPtr,
/* LSAPI_PRO_ONLY:END */
                                         lscapi_rec *lscapi)
{
    apr_status_t status;
/* LSAPI_PRO_ONLY:BEGIN */
    int with_connpool = (slotInfoPtr != NULL);
/* LSAPI_PRO_ONLY:END */
    lsapi_svr_conf_t *svrcfg = ap_get_module_config(r->server->module_config, &lsapi_module);
    lsapi_dir_conf_t *dircfg = (lsapi_dir_conf_t*) ap_get_module_config(r->per_dir_config, &lsapi_module);

/* LSAPI_PRO_ONLY:BEGIN */
    if (with_connpool)
    {
        lscapi_remove_stale_data_from_socket(backend);
    }
/* LSAPI_PRO_ONLY:END */

    unsigned eventMask = 0;
    char errbuf[512];


/* LSAPI_PRO_ONLY:BEGIN */
    // Sometimes, particularly in connection pool mode, we need to reconnect connection and send request again

    // On successful send_request - break from the loop
    // On send_request error:
    //                        with CONNECT_RESET error flag and connection pool switched on - reconnect and continue to the loop
    //                        otherwise: return form the function with error code
/* LSAPI_PRO_ONLY:END */
    while (1)
    {
        int rc = lscapi_send_request(backend, &eventMask, errbuf, sizeof errbuf);
        if (rc == 0)
        {
            status = 0;
            break;
        }

        if (eventMask & LSCAPI_SENDREQ_INTERNAL_ERROR)
        {
            lscapi_rlog(APLOG_ERR, 0, r, "Internal error on sending request(%s); uri(%s) content-length(%s): %s",
                        r->the_request, r->unparsed_uri, apr_table_get(r->headers_in, "Content-Length"), errbuf);
            SET_STATUS_WITH_LINE(r, dircfg->err_lsapi_internal); //HTTP_SERVICE_UNAVAILABLE
        }
        else if (eventMask & LSCAPI_SENDREQ_BACKEND_ERROR)
        {
            lscapi_rlog(APLOG_ERR, 0, r, "Backend error on sending request(%s); uri(%s) content-length(%s) (lsphp is killed?): %s",
                        r->the_request, r->unparsed_uri, apr_table_get(r->headers_in, "Content-Length"), errbuf);
            SET_STATUS_WITH_LINE(r, dircfg->err_backend_sendreq); //HTTP_SERVICE_UNAVAILABLE
        }
        else if (eventMask & LSCAPI_SENDREQ_CLIENT_ERROR)
        {
            lscapi_rlog(APLOG_ERR, 0, r, "Client error on sending request(%s); uri(%s) content-length(%s): %s",
                        r->the_request, r->unparsed_uri, apr_table_get(r->headers_in, "Content-Length"), errbuf);
            SET_STATUS_WITH_LINE(r, dircfg->err_client_setup); //HTTP_BAD_REQUEST
        }
        else if (eventMask & LSCAPI_CONNECT_REJECTED)
        {
            lscapi_rlog(APLOG_ERR, 0, r, "Connect to backend rejected on sending request(%s); uri(%s)"
/* LSAPI_PRO_ONLY:BEGIN */
            ", check %s"
/* LSAPI_PRO_ONLY:END */
 , r->the_request, r->unparsed_uri
/* LSAPI_PRO_ONLY:BEGIN */
 , troubleshooting
/* LSAPI_PRO_ONLY:END */
            );
            SET_STATUS_WITH_LINE(r, dircfg->err_backend_reject); //HTTP_INSUFFICIENT_STORAGE
        }
        else if (eventMask & LSCAPI_CONNECT_GENERIC_ERROR)
        {
            lscapi_rlog(APLOG_ERR, 0, r, "Connect to backend failed on sending request(%s); uri(%s): %s",
                        r->the_request, r->unparsed_uri, errbuf);
            SET_STATUS_WITH_LINE(r, dircfg->err_backend_connect); //HTTP_SERVICE_UNAVAILABLE
        }
        else if (eventMask & LSCAPI_CONNECT_RESET_ERROR)
        {
/* LSAPI_PRO_ONLY:BEGIN */
            if (with_connpool)
            {
                lscapi_rlog(APLOG_ERR, 0, r, "Connect to backend failed with CONNECTION_RESET on sending request(%s); uri(%s): %s",
                            r->the_request, r->unparsed_uri, errbuf);
                slotInfoPtr->slot->sock = 0;
                slotInfoPtr->slot->worker_pid = 0;
                lscapi_release_lsphp_conn(backend);
                lscapi_reset_internal_error_state(lscapi);
                lscapi_notice(svrcfg, 0, r->server, "Will ty to re-connect to backend for the allocated slot");
                if (lscapi_connect_backend(backend, &eventMask, errbuf, sizeof errbuf) != 0)
                {
                    lscapi_notice(svrcfg, 0, r->server, "connect to backend failed, so will ungrab the slot and return with error");
                    lscapi_ungrab_sock_slot(r->server, slotInfoPtr);


                    if (eventMask & LSCAPI_CONNECT_REJECTED)
                    {
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                      PREFIX "[host %s] [req %s] Connect to backend rejected",
                                      r->hostname, r->the_request);
                        return dircfg->err_backend_reject;  // HTTP_INSUFFICIENT_STORAGE
                    }
                    else
                    {
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                      PREFIX "[host %s] [req %s] Connect to backend failed: %s",
                                      r->hostname, r->the_request, errbuf );
                        return dircfg->err_backend_connect; //HTTP_SERVICE_UNAVAILABLE
                    }
                }
                lscapi_notice(svrcfg, 0, r->server, "re-connect to backend succedeed, will write its sock into the grabbed slot");
                slotInfoPtr->slot->sock = lscapi_lsphp_conn_get_socket(backend);
                slotInfoPtr->slot->worker_pid = lscapi_conn_get_worker_pid(backend);
                slotInfoPtr->slot->is_open = 1;
                if (dircfg->measure_time)
                {
                    lscapi_write_measured_time(r, LSCAPI_MEASURE_CONN_ESTABLISHED);
                }
                continue;
            }
            else
/* LSAPI_PRO_ONLY:END */
            {
                lscapi_rlog(APLOG_ERR, 0, r, "Connect to backend failed with CONNECTION_RESET on sending request(%s); uri(%s): %s",
                            r->the_request, r->unparsed_uri, errbuf);
                SET_STATUS_WITH_LINE(r, dircfg->err_lsapi_internal); //HTTP_SERVICE_UNAVAILABLE
            }
        }
        else
        {
            // Unknown error?
            lscapi_rlog(APLOG_ERR, 0, r, "Error on sending request(%s); uri(%s) content-length(%s): %s",
                        r->the_request, r->unparsed_uri, apr_table_get(r->headers_in, "Content-Length"), errbuf);
            SET_STATUS_WITH_LINE(r, dircfg->err_lsapi_internal); //HTTP_SERVICE_UNAVAILABLE
        }
        lscapi_set_error(lscapi);

        status = r->status;
        // TODO: Dump request info in case of error
        return status;

    } //while (1)

    if (dircfg->measure_time)
    {
        lscapi_write_measured_time(r, LSCAPI_MEASURE_REQUEST_SENT);
    }


    status = lscapi_do_request(lscapi, backend, r, &eventMask, svrcfg, dircfg);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                  PREFIX "lscapi_do_request() status = %d", status);

/* LSAPI_PRO_ONLY:BEGIN */
    if(with_connpool) {
        lscapi_remove_stale_data_from_socket(backend);
        lscapi_ungrab_sock_slot(r->server, slotInfoPtr);
    } else {
/* LSAPI_PRO_ONLY:END */
        lscapi_release_lsphp_conn(backend);
        //ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
        //              PREFIX "lscapi_release_lsphp_conn() finished");
/* LSAPI_PRO_ONLY:BEGIN */
    }
/* LSAPI_PRO_ONLY:END */

    return status;
}

static apr_status_t talk_to_backend(lsphp_conn_t *backend, request_rec *r,
                                    lscapi_rec *lscapi,
                                    lsapi_svr_conf_t *svrcfg,
                                    lsapi_dir_conf_t *dircfg)
{
    apr_status_t status;
/* LSAPI_PRO_ONLY:BEGIN */
    lsapi_connslot_info_t slotInfo;
/* LSAPI_PRO_ONLY:END */
    char errbuf[512];
    unsigned eventMask;

#ifdef WITH_BLACKLIST
    if (use_handler_blacklist) // Set failed callback only if blacklist is enabled
        lscapi_conn_set_failed_cb(backend, lscapi_conn_failed_cb, r);
#endif

    // lets connect backend
    status = connect_to_backend(backend, r, lscapi,
/* LSAPI_PRO_ONLY:BEGIN */
                                 &slotInfo,
/* LSAPI_PRO_ONLY:END */
                                 &eventMask, errbuf, sizeof errbuf);

    if(status < 0) {
        if(eventMask & LSCAPI_CONNECT_REJECTED)
        {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          PREFIX "[host %s] [req %s] Connect to backend rejected",
                          r->hostname, r->the_request);
            return dircfg->err_backend_reject;  // HTTP_INSUFFICIENT_STORAGE
        } else
        {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          PREFIX "[host %s] [req %s] Connect to backend failed: %s",
                          r->hostname, r->the_request, errbuf );
            return dircfg->err_backend_connect; //HTTP_SERVICE_UNAVAILABLE
        }
    }

/* LSAPI_PRO_ONLY:BEGIN */
    int with_connpool = (status > 0);
/* LSAPI_PRO_ONLY:END */
    status = talk_to_backend_impl(backend, r, 
/* LSAPI_PRO_ONLY:BEGIN */
                                  with_connpool ? &slotInfo : NULL, 
/* LSAPI_PRO_ONLY:END */
                                  lscapi);
    return status;
}

#ifdef WITH_BLACKLIST
static void lsapi_clear_handler_blacklist(lsapi_svr_conf_t *cfg)
{
    if (cfg->handler_blacklist != NULL)
    {
        json_object_put(cfg->handler_blacklist);
        cfg->handler_blacklist = NULL;
    }
}

static int lsapi_check_and_load_handler_blacklist(request_rec *r, lsapi_svr_conf_t *cfg, uint32_t uid)
{
    char json_file_path[128]; // Will be enough as the path is fixed
    snprintf(json_file_path, sizeof(json_file_path),
             "%s/%u/version_selection_conf.json", LSAPI_BLACKLIST_DIR, uid);

    struct stat file_stat;
    if (stat(json_file_path, &file_stat) != 0)
    {
        int saved_errno = errno;

        // Clear previous blacklist in case of error
        lsapi_clear_handler_blacklist(cfg);

        // Assume no blacklist if file does not exist
        if (saved_errno == ENOENT) return 0;

        if (saved_errno == EACCES)
        {
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
                          PREFIX "Permission denied to access to version selection file: %s",
                          json_file_path);
            return -1;
        }

        ap_log_rerror(APLOG_MARK, APLOG_WARNING, saved_errno, r,
            PREFIX "Error accessing version selection file: %s", json_file_path);
        return -1;
    }

    // Check last file modification time
    if (file_stat.st_mtime <= cfg->blacklist_last_mod_time &&
        cfg->handler_blacklist != NULL) return 0; // No change since last read

    // Clear previous blacklist
    lsapi_clear_handler_blacklist(cfg);

    json_object *root_obj = json_object_from_file(json_file_path);
    if (!root_obj)
    {
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
            PREFIX "Error parsing blacklist JSON: %s", json_file_path);
        return -1;
    }

    json_object *deny_phps;
    if (!json_object_object_get_ex(root_obj, "deny_phps", &deny_phps) ||
        !json_object_is_type(deny_phps, json_type_array))
    {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
            PREFIX "Error: deny_phps not found or not an array in JSON: %s", json_file_path);

        json_object_put(root_obj);
        return -1;
    }

    cfg->handler_blacklist = json_object_get(deny_phps); // Increase ref count to copy
    json_object_put(root_obj); // Free the root object, deny_phps is still available

    cfg->blacklist_last_mod_time = file_stat.st_mtime;
    return 0;
}

static int lsapi_is_handler_blacklisted(request_rec *r, lsapi_svr_conf_t *cfg, uint32_t uid)
{
    // Check last modification time of the blacklist and reload if necessary
    if (lsapi_check_and_load_handler_blacklist(r, cfg, uid) != 0) return -1;
    else if (cfg->handler_blacklist == NULL) return 0;

    json_object *deny_phps = cfg->handler_blacklist;
    int array_len = json_object_array_length(deny_phps);

    for (int i = 0; i < array_len; i++)
    {
        json_object *handler_obj = json_object_array_get_idx(deny_phps, i);
        const char *blacklisted = json_object_get_string(handler_obj);
        if (blacklisted != NULL && !strcmp(r->handler, blacklisted)) return 1;
    }

    return 0;
}

int lscapi_conn_failed_cb(lsphp_conn_t *conn)
{
    lscapi_rec *lscapi = lscapi_conn_get_lsapi_handle(conn);
    request_rec *r = (request_rec*)lscapi_conn_get_opaque(conn);

    uint32_t real_uid = lscapi_get_real_uid(lscapi);
    lsapi_svr_conf_t *cfg = ap_get_module_config(r->server->module_config, &lsapi_module);

    // Continue backend invocation if the current handler is not blacklisted
    int rc = lsapi_is_handler_blacklisted(r, cfg, real_uid);
    if (rc < 0)
    {
        ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, PREFIX "[host %s] [req %s] "
                       "Use LSPHP Handler %s for the user with UID: %u as could bot determine if it is blacklisted",
                       r->hostname, r->the_request, r->handler, real_uid);
        return 0;
    }
    if (!rc) return 0; // not blacklisted

    // blacklisted
    ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, PREFIX "[host %s] [req %s] "
                    "LSPHP Handler %s is blacklisted for the user with UID: %u",
                    r->hostname, r->the_request, r->handler, real_uid);

    // Continue with default handler if the current handler is blacklisted
    // No need to use lscapi_get_backend_heuristic for defaultHandler
    const char *backend_path = lscapi_get_backend(defaultHandler);
    if (!backend_path)
    {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, PREFIX "[host %s] [req %s] "
                        "Failed to get backend path for default handler: %s",
                        r->hostname, r->the_request, defaultHandler);

        return -1; // Stop connection
    }

    r->handler = defaultHandler;
    lscapi_set_backend_path(lscapi, r->handler, backend_path);

    apr_status_t status;
    char errbuf[512];

    status = lscapi_determine_conn_lsphp(conn, &(cfg->backend_info), errbuf, sizeof errbuf);
    if(status != 0)
    {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, PREFIX "[host %s] [req %s] "
                      "Could not determine lsphp connection: %s",
                      r->hostname, r->the_request, errbuf);

        return -1; // Stop connection
    }

    return 1; // Retry connection with default handler
}
#endif

static apr_status_t lsapi_handler(request_rec * r)
{
    apr_status_t status;
    lscapi_rec *lscapi;
    lsphp_conn_t *backend;
    lsapi_svr_conf_t *svrcfg = ap_get_module_config(r->server->module_config, &lsapi_module);
    lsapi_dir_conf_t *dircfg = (lsapi_dir_conf_t*) ap_get_module_config(r->per_dir_config, &lsapi_module);

    if(dircfg->engine_off)
    {
        return DECLINED;
    }

    // use short-lived pool to possible memory allocation for handler determined by heuristic
    const char *backend_path = lscapi_get_backend_heuristic(r->handler, lsapi_alloc_from_pool, r->pool);
    if(!backend_path)
    {
        return DECLINED;
    }

    if(dircfg->measure_time)
    {
        lscapi_write_measured_time(r, LSCAPI_MEASURE_REQUEST_GOT);
    }

    unsigned flags = 0;
    char errbuf[512];
    lscapi = lscapi_create_connection(r, backend_path, &flags, &status,
                                      errbuf, sizeof errbuf, &lsapi_module);
    if(!lscapi) {
        if(status != HTTP_NOT_FOUND) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                            PREFIX "[host %s] [req %s]: %s",
                            r->hostname, r->the_request, errbuf);
        }
        return status;
    }

    backend = lscapi_acquire_lsphp_conn(lscapi, errbuf, sizeof errbuf );
    if(!backend) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      PREFIX "[host %s] [req %s] Could not acquire lsphp connection: %s",
                      r->hostname, r->the_request, errbuf);
        lscapi_destroy(lscapi);
        return dircfg->err_lsapi_conn_acquire; //HTTP_SERVICE_UNAVAILABLE
    }

    // will be ready to get deal with request body
    status = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
    if(status != OK) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
                      PREFIX "[host %s] [req %s] ap_client_block failed: %d",
                      r->hostname, r->the_request, status);
        lscapi_destroy(lscapi);
        return dircfg->err_client_setup; //HTTP_BAD_REQUEST
    }

/* LSAPI_PRO_ONLY:BEGIN */
    // No need to change cgroup of the backend processes in this case
    svrcfg->backend_info.change_cgroup = (svrcfg->terminate_backends_on_exit == 0);
/* LSAPI_PRO_ONLY:END */
    status = lscapi_determine_conn_lsphp(backend, &(svrcfg->backend_info), errbuf, sizeof errbuf);
    if(status != 0) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      PREFIX "[host %s] [req %s] Could not determine lsphp connection: %s",
                      r->hostname, r->the_request, errbuf );
        lscapi_destroy(lscapi);
        return dircfg->err_lsapi_conn_determine; //HTTP_SERVICE_UNAVAILABLE
    }
    status = talk_to_backend(backend, r, lscapi, svrcfg, dircfg);
    if(status == OK && dircfg->measure_time)
    {
        struct timeval tv_overall;
        struct timeval tv_connect;
        struct timeval tv_reqsent;
        struct timeval tv_hdrrecv;
        struct timeval tv_resprecv;

        apr_status_t st_overall;
        apr_status_t st_connect;
        apr_status_t st_reqsent;
        apr_status_t st_hdrrecv;
        apr_status_t st_resprecv;

        st_overall = lscapi_get_measured_timedelta(r, LSCAPI_MEASURE_REQUEST_GOT, LSCAPI_MEASURE_RESPONSE_GOT, &tv_overall);
        st_connect = lscapi_get_measured_timedelta(r, LSCAPI_MEASURE_REQUEST_GOT, LSCAPI_MEASURE_CONN_ESTABLISHED, &tv_connect);
        st_reqsent = lscapi_get_measured_timedelta(r, LSCAPI_MEASURE_CONN_ESTABLISHED, LSCAPI_MEASURE_REQUEST_SENT, &tv_reqsent);
        st_hdrrecv = lscapi_get_measured_timedelta(r, LSCAPI_MEASURE_REQUEST_SENT, LSCAPI_MEASURE_HEADER_GOT, &tv_hdrrecv);
        st_resprecv = lscapi_get_measured_timedelta(r, LSCAPI_MEASURE_HEADER_GOT, LSCAPI_MEASURE_RESPONSE_GOT, &tv_resprecv);

        if(st_overall == APR_SUCCESS
           && st_connect == APR_SUCCESS
           && st_reqsent == APR_SUCCESS
           && st_hdrrecv == APR_SUCCESS
           && st_resprecv == APR_SUCCESS)
        {
            ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
                            PREFIX "[host %s] [req %s] timings: backend connect:%ld.%ld; req sent: %ld.%ld; hdr recv %ld.%ld; resp recv: %ld.%ld; overall: %ld.%ld",
                            r->hostname, r->the_request,
                            tv_connect.tv_sec, tv_connect.tv_usec,
                            tv_reqsent.tv_sec, tv_reqsent.tv_usec,
                            tv_hdrrecv.tv_sec, tv_hdrrecv.tv_usec,
                            tv_resprecv.tv_sec, tv_resprecv.tv_usec,
                            tv_overall.tv_sec, tv_overall.tv_usec );
        }

    }

    lscapi_destroy(lscapi);

    return status;
}


static void lsapi_child_init(apr_pool_t *configpool, server_rec *s) {
    apr_status_t rc;

    lsapi_svr_conf_t *cfg = ap_get_module_config(s->module_config, &lsapi_module);

    apr_signal_unblock(SIGCHLD);
    apr_signal(SIGCHLD, SIG_IGN);
    lscapi_child_init(alloc_by_pool, s->process->pool);

/*
    rc = lscapi_util_child_init(configpool, s);
    if(rc != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_EMERG, rc, s,
                    PREFIX " Can't initialize self");
        return;
    }
*/
/* LSAPI_PRO_ONLY:BEGIN */
#ifndef WITHOUT_LVE
    if(!lscapi_is_lve_loaded())
#endif
/* LSAPI_PRO_ONLY:END */
        cfg->lve_enabled = 0;

    if ((rc = lscapi_starter_child_init(s, configpool, PREFIX)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_EMERG, rc, s,
                    PREFIX " Can't initialize selfstarter");
        return;
    }
    //ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
    //                  "in lsapi_child_init: lveEnabled:%d",
    //                  cfg->lveEnabled );


/* LSAPI_PRO_ONLY:BEGIN */
    rc = lscapi_connpool_child_init(PREFIX, s, configpool, cfg);
    if(rc != APR_SUCCESS) {

        ap_log_error(APLOG_MARK, APLOG_EMERG, rc, s,
                        PREFIX "Can't initialize connection pool");
        return;
    }
/* LSAPI_PRO_ONLY:END */
    return;
}

static apr_status_t lsapi_cleanup(void *data)
{
    lsapi_svr_conf_t *cfg = ap_get_module_config(((server_rec*)data)->module_config,
                                                    &lsapi_module);
    if(cfg->debug_enabled) {
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, (server_rec*)data, PREFIX "Cleanup");
    }

/* LSAPI_PRO_ONLY:BEGIN */
#ifdef WITH_CRIU
    if (reset_criu_on_apache_restart)
    {
        lscapi_terminate_backends_criu(cfg->socket_path, cfg->criu_imgs_dir_path);
    }
    else if (cfg->terminate_backends_on_exit)
    {
        lscapi_terminate_backends_ex(cfg->socket_path);
    }
#else
/* LSAPI_PRO_ONLY:END */
    if (cfg->terminate_backends_on_exit)
    {
        lscapi_terminate_backends_ex(cfg->socket_path);
    }
/* LSAPI_PRO_ONLY:BEGIN */
#endif // USE_CRIU
/* LSAPI_PRO_ONLY:END */

#if 0
    lscapi_cleanup_mutex(SULSPHP_HTTPD_USER);
#endif

    return APR_SUCCESS;
}

static int lsapi_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
{
    apr_status_t rc;

    rc = lscapi_starter_pre_config(pconf, plog, ptemp);
    if (rc != APR_SUCCESS) {
        return rc;
    }

    return OK;
}

static int lsapi_init(apr_pool_t * config_pool, apr_pool_t * plog, apr_pool_t * ptemp,
                      server_rec * main_server)
{
    const char *userdata_key = "lsapi_init";
    void *dummy = NULL;
    char errbuf[512];

    /* Initialize selfstarter only once */
    apr_pool_userdata_get(&dummy, userdata_key,
                          main_server->process->pool);
    if (dummy == NULL)
    {
        apr_pool_userdata_set((const void *)1, userdata_key,
                              apr_pool_cleanup_null,
                              main_server->process->pool);
        return APR_SUCCESS;
    }

/* LSAPI_PRO_ONLY:BEGIN */
    int max_daemons_limit;
    ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
    for (server_rec *s = main_server; s != NULL; s = s->next)
    {
        lsapi_svr_conf_t *cfg = ap_get_module_config(s->module_config, &lsapi_module);
        if (cfg->with_connection_pool != 0)
        {
            // This logic is duplicated by liblsapi processing on uninitialized backend_children
            int backend_children = (cfg->backend_info.backend_children == (uint32_t)-1) ? 120 : cfg->backend_info.backend_children;

            //TODO Should we change this calculation for MPM Prefork? Only 1 open connection for every socket name for every Apache worker

            int children_for_daemon = backend_children / max_daemons_limit;

            if (children_for_daemon <= 3)
            {
                ap_log_error (APLOG_MARK, APLOG_WARNING, 0, s,
                              PREFIX "Connection Pool Mode is forcibly turned off - too few backend children for %d MaxDaemons",
                              max_daemons_limit);
                ap_log_error (APLOG_MARK, APLOG_WARNING, 0, main_server,
                              PREFIX "please increase lsapi_backend_children to %d at least",
                              max_daemons_limit * 4);
                cfg->with_connection_pool = 0;
            }
            else
            {
                if (cfg->max_pool_size == 0)
                {
                    // no explicit value in config - set it here
                    cfg->max_pool_size = children_for_daemon - 1;
                }
                else if (cfg->max_pool_size > children_for_daemon - 1)
                {
                    ap_log_error (APLOG_MARK, APLOG_WARNING, 0, main_server,
                                PREFIX "lsapi_max_connection(%d) is too high for lsapi_backend_children(%d) and %d MaxDaemons Limit",
                                cfg->max_pool_size, backend_children, max_daemons_limit);
                    cfg->max_pool_size = children_for_daemon - 1;
                    ap_log_error (APLOG_MARK, APLOG_WARNING, 0, main_server,
                                    PREFIX "lsapi_max_connection is decreased to %d",
                                    cfg->max_pool_size);
                }
            }

        }
    }
/* LSAPI_PRO_ONLY:END */

    apr_status_t rc = lscapi_init(errbuf, sizeof errbuf);
    if (rc)
    {
        ap_log_error (APLOG_MARK, APLOG_ERR, 0, main_server,
                      PREFIX " version " MOD_LSAPI_VERSION ": initialization error: %s", errbuf );
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    rc = lscapi_util_init(main_server, config_pool, errbuf, sizeof errbuf);
    if (rc)
    {
        ap_log_error (APLOG_MARK, APLOG_ERR, 0, main_server,
                      PREFIX " version " MOD_LSAPI_VERSION ": initialization error: %s", errbuf );
        return HTTP_INTERNAL_SERVER_ERROR;
    }

/* LSAPI_PRO_ONLY:BEGIN */
#ifdef WITH_CRIU
    ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, main_server, PREFIX " version " MOD_LSAPI_VERSION " with CRIU support");
#else
/* LSAPI_PRO_ONLY:END */
    ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, main_server, PREFIX " version " MOD_LSAPI_VERSION );
/* LSAPI_PRO_ONLY:BEGIN */
#endif
/* LSAPI_PRO_ONLY:END */
    lsapi_svr_conf_t *main_cfg = ap_get_module_config(main_server->module_config, &lsapi_module);
    if (main_cfg->debug_enabled)
    {
        char signature[128];
        lscapi_get_module_signature(signature, sizeof(signature));
        ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, main_server, PREFIX " Module signature:(%s)", signature );
    }

    rc = lscapi_starter_init(PREFIX, main_server, config_pool);
    if (rc != APR_SUCCESS)
    {

        ap_log_error(APLOG_MARK, APLOG_EMERG, rc, main_server,
                        PREFIX "Can't initialize selfstarter");
        return rc;
    }

#ifdef WITH_BLACKLIST
    // Check if blacklist handler file flag exists
    struct stat file_stat;
    if (!stat(LSAPI_BLACKLIST_FLAG, &file_stat))
    {
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, main_server,
            PREFIX "Handler blacklist enabled: %s", LSAPI_BLACKLIST_FLAG);

        use_handler_blacklist = 1;
    }
#endif

    apr_pool_cleanup_register(config_pool, main_server,
                                lsapi_cleanup, apr_pool_cleanup_null);

    return APR_SUCCESS;
}

static void lsapi_dump_config(apr_pool_t *p, server_rec *main_s)
{
    apr_file_t *out = NULL;
/* LSAPI_PRO_ONLY:BEGIN */
#ifdef WITH_CRIU
    server_rec *s;
    unsigned int criu_count = 0;
#endif
/* LSAPI_PRO_ONLY:END */

    if (!ap_exists_config_define("DUMP_RUN_LSAPI"))
    {
        return;
    }

    apr_file_open_stdout(&out, p);

    apr_file_printf(out, "Version %s\n", MOD_LSAPI_VERSION);
/* LSAPI_PRO_ONLY:BEGIN */
    lsapi_svr_conf_t *cfg = ap_get_module_config(main_s->module_config, &lsapi_module);
    apr_file_printf(out, "lsapi_with_connection_pool %s\n", cfg->with_connection_pool ? "On" : "Off");

#ifdef WITH_CRIU
    for (s = main_s; s; s = s->next)
    {
        cfg = ap_get_module_config(s->module_config, &lsapi_module);

        if (cfg->backend_info.use_criu)
        {
            criu_count++;
        }
    }
    apr_file_printf(out, "lsapi_criu %s\n", criu_count > 0 ? "On" : "Off");
#endif
/* LSAPI_PRO_ONLY:END */
}

static void register_hooks(apr_pool_t * p)
{
    ap_hook_pre_config(lsapi_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_test_config(lsapi_dump_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_config(lsapi_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_child_init(lsapi_child_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_handler(lsapi_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

static const char *lsapi_debug_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->debug_enabled = ( strcasecmp(value, "on") == 0 );
    cfg->debug_enabled_was_set = 1;
    return NULL;
}

static const char *lsapi_terminate_backends_on_exit_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);

    cfg->terminate_backends_on_exit = ( strcasecmp(value, "off") != 0 );
    cfg->terminate_backends_on_exit_was_set = 1;

    return NULL;
}

static const char *lsapi_socket_path_handler(cmd_parms *cmd, void *dummy, const char *value) {
    const char *err = ap_check_cmd_context (cmd, (NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE));
    if (err != NULL)
    {
      return err;
    }

    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->socket_path = apr_pstrdup(cmd->pool, value);
    return NULL;
}

static const char *lsapi_phprc_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    if(strcasecmp(value, "no") == 0) {
        cfg->phprc = NULL;
        cfg->phprc_source = LSAPI_PHPRC_SOURCE_NO;
    } else if(strcasecmp(value, "auto") == 0) {
        cfg->phprc = NULL;
        cfg->phprc_source = LSAPI_PHPRC_SOURCE_AUTO;
    } else if(strcasecmp(value, "env") == 0) {
        cfg->phprc = NULL;
        cfg->phprc_source = LSAPI_PHPRC_SOURCE_ENV;
    } else if(strcasecmp(value, "docroot") == 0) {
        cfg->phprc = NULL;
        cfg->phprc_source = LSAPI_PHPRC_SOURCE_DOCROOT;
    } else {
        cfg->phprc = apr_pstrdup(cmd->pool, value);
        cfg->phprc_source = LSAPI_PHPRC_SOURCE_VAL;
    }
    cfg->phprc_source_was_set = 1;
    return NULL;
}

static const char *lsapi_target_perm_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->check_target_perm = ( strcasecmp(value, "on") == 0);
    cfg->check_target_perm_was_set = 1;
    return NULL;
}

static const char *lsapi_paranoid_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->paranoid = ( strcasecmp(value, "on") == 0);
    cfg->paranoid_was_set = 1;
    return NULL;
}

static const char *lsapi_check_document_root_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->skip_check_document_root = ( strcasecmp(value, "off") == 0);
    cfg->skip_check_document_root_was_set = 1;
    return NULL;
}

static const char *lsapi_use_default_uid_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->use_default_uid = ( strcasecmp(value, "off") != 0 );
    cfg->use_default_uid_was_set = 1;
    return NULL;
}

static const char *lsapi_backend_connect_timeout_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 0) {
        cfg->backend_info.connect_timeout = ival;
    }
    return NULL;
}

static const char *lsapi_backend_pgrp_max_idle_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    cfg->backend_info.backend_pgrp_max_idle = ival;
    return NULL;
}

static const char *lsapi_backend_max_idle_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    cfg->backend_info.backend_max_idle = ival;
    return NULL;
}

static const char *lsapi_backend_max_process_time_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 0) {
        cfg->backend_info.backend_max_process_time = ival;
    }
    return NULL;
}

static const char *lsapi_backend_max_reqs_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 0) {
        cfg->backend_info.backend_max_reqs = ival;
    }
    return NULL;
}

static const char *lsapi_backend_pgrp_max_reqs_handler(cmd_parms *cmd, void *dummy, const char *value)
{
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if (ival > 0)
    {
        cfg->backend_info.backend_pgrp_max_reqs = ival;
    }
    return NULL;
}

static const char *lsapi_backend_pgrp_max_crashes_handler(cmd_parms *cmd, void *dummy, const char *value)
{
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if (ival > 0)
    {
        cfg->backend_info.backend_pgrp_max_crashes = ival;
    }
    return NULL;
}

static const char *lsapi_backend_connect_tries_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 0) {
        cfg->backend_info.connect_tries = ival;
    }
    return NULL;
}


static const char *lsapi_backend_children_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 1) {
        cfg->backend_info.backend_children = ival;
    }
    return NULL;
}


static const char *lsapi_backend_oom_score_adj_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    int32_t ival = (int32_t) apr_atoi64 (value);
    if (ival < -1000) ival = -1000;
    else if (ival > 1000) ival = 1000;
    cfg->backend_info.backend_oom_score_adj = ival;
    return NULL;
}

static const char *lsapi_backend_initial_start(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival >= 1) {
        cfg->backend_info.backend_initial_start = ival;
    }
    return NULL;
}


static const char *lsapi_uid_gid_handler(cmd_parms *cmd, void* CFG,
                                           const char *arg1, const char *arg2)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    uint32_t uid = (uint32_t) apr_atoi64 (arg1);
    uint32_t gid = (uint32_t) apr_atoi64 (arg2);
    if(uid > 0 && gid > 0) {
        cfg->lsapi_uid = uid;
        cfg->lsapi_gid = gid;
    }

    return NULL;
}

static const char *lsapi_user_group_handler(cmd_parms *cmd, void* CFG,
                                           const char *arg1, const char *arg2)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    uint32_t uid = ap_uname2id(arg1);
    uint32_t gid = ap_gname2id(arg2);
    if(uid > 0 && gid > 0) {
        cfg->lsapi_uid = uid;
        cfg->lsapi_gid = gid;
    }

    return NULL;
}

static const char *lsapi_engine_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->engine_off = ( strcasecmp(value, "off") == 0 );
    cfg->engine_off_was_set = 1;

    return NULL;
}

static const char *lsapi_measure_time_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->measure_time = ( strcasecmp(value, "on") == 0 );
    cfg->measure_time_was_set = 1;

    return NULL;
}

/* LSAPI_PRO_ONLY:BEGIN */
static const char *lsapi_dump_request_info_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->dump_request_info = ( strcasecmp(value, "on") == 0 );
    cfg->dump_request_info_was_set = 1;

    return NULL;
}

/* LSAPI_PRO_ONLY:END */

static const char *lsapi_use_req_hostname_handler(cmd_parms *cmd, void *CFG, const char *value)
{
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->use_req_hostname = (strcasecmp(value, "on") == 0);
    cfg->use_req_hostname_was_set = 1;
    return NULL;
}

static const char *lsapi_selfstarter_handler(cmd_parms *cmd, void *dummy, const char *value) {
    return NULL;
}

static const char *lsapi_max_connection_handler(cmd_parms *cmd, void *dummy, const char *value) {
    const char *err = ap_check_cmd_context (cmd, GLOBAL_ONLY);
    if (err != NULL)
    {
      return err;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival > 0) {
        cfg->max_pool_size = ival;
    }
    return NULL;
}



#ifdef LSCAPI_WITH_DUMP_HEADER
static const char *lsapi_hostname_on_debug_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->hostname_on_debug = apr_pstrdup(cmd->pool, value);
    return NULL;
}
#endif

static const char *lsapi_set_env_handler(cmd_parms *cmd, void *dummy,
                                    const char *name, const char *value) {
    const char *err = ap_check_cmd_context (cmd, (NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE));
    if (err != NULL)
    {
      return err;
    }

    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    apr_table_set(cfg->envTable, name, value);
    return NULL;
}

static const char *lsapi_set_env_path_handler(cmd_parms *cmd, void *dummy,
                                                const char *value) {
    const char *err = ap_check_cmd_context (cmd, (NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE));
    if (err != NULL)
    {
      return err;
    }

    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_env_path = value;
    return NULL;
}


static const char *lsapi_backend_accept_notify_handler(cmd_parms *cmd, void *dummy, const char *value) {
    const char *err = ap_check_cmd_context (cmd, (NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE));
    if (err != NULL)
    {
      return err;
    }

    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->accept_notify = ( strcasecmp(value, "off") != 0 );
    cfg->accept_notify_was_set = 1;
    return NULL;
}

static const char *lsapi_sulsphp_log_path_handler(cmd_parms *cmd, void *CFG, const char *value) {
    const char *err = ap_check_cmd_context (cmd, GLOBAL_ONLY);
    if (err != NULL)
    {
        return err;
    }

    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->sulsphp_log_path = apr_pstrdup(cmd->pool, value);
    return NULL;
}

static const char *lsapi_backend_use_own_log_handler(cmd_parms *cmd, void *CFG, const char *value) {
    /*
       For backward compatibility of .htaccess files for previous versions of mod_lsapi
       we allow this directive in .htaccess but ignore it
    */
    const char *err = ap_check_cmd_context (cmd, NOT_IN_LIMIT);
    if (err != NULL)
    {
      return NULL;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.use_own_log = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.use_own_log_was_set = 1;
    return NULL;
}

static const char *lsapi_backend_loglevel_info_handler(cmd_parms *cmd, void *CFG, const char *value) {
    /*
       For backward compatibility of .htaccess files for previous versions of mod_lsapi
       we allow this directive in .htaccess but ignore it
    */
    const char *err = ap_check_cmd_context (cmd, NOT_IN_LIMIT);
    if (err != NULL)
    {
      return NULL;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.backend_loglevel_info = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.backend_loglevel_info_was_set = 1;
    return NULL;
}

static const char *lsapi_backend_common_own_log_handler(cmd_parms *cmd, void *CFG, const char *value) {
    /*
       For backward compatibility of .htaccess files for previous versions of mod_lsapi
       we allow this directive in .htaccess but ignore it
    */
    const char *err = ap_check_cmd_context (cmd, NOT_IN_LIMIT);
    if (err != NULL)
    {
      return NULL;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.common_own_log = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.common_own_log_was_set = 1;
    return NULL;
}

static const char *lsapi_disable_pwd_var_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.pwd_disabled = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.pwd_disabled_was_set = 1;
    return NULL;
}

static const char *lsapi_enable_user_ini_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.enable_user_ini = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.enable_user_ini_was_set = 1;
    return NULL;
}

static const char *lsapi_user_ini_homedir_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.user_ini_homedir = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.user_ini_homedir_was_set = 1;
    return NULL;
}

static const char *lsapi_per_user_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.per_user = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.per_user_was_set = 1;
    return NULL;
}


static const char *lsapi_protocol_logfile_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->protocol_log_file = apr_pstrdup(cmd->pool, value);
    return NULL;
}

static const char *lsapi_max_resend_buffer_handler(cmd_parms *cmd, void* CFG, const char *arg1)
{
    ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, cmd->server,
                  PREFIX " version " MOD_LSAPI_VERSION "lsapi_max_resend_buffer option is deprecated and unused. Please remove it from the Apache config");

    return NULL;
}

static const char *lsapi_error_code_handler(cmd_parms *cmd, void* CFG, const char *arg1, const char *arg2)
{
    uint32_t ival;
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;

    if(strcmp(arg1, "SERVER_DOCROOT") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_server_docroot = ival;
            cfg->err_server_docroot_was_set = 1;
        }
    } else if(strcmp(arg1, "SERVER_UID") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_server_uid = ival;
            cfg->err_server_uid_was_set = 1;
        }
    } else if(strcmp(arg1, "SCRIPT_PERMS") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_script_perms = ival;
            cfg->err_script_perms_was_set = 1;
        }
    } else if(strcmp(arg1, "LSAPI_CREATE") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_lsapi_create = ival;
            cfg->err_lsapi_create_was_set = 1;
        }
    } else if(strcmp(arg1, "LSAPI_INTERNAL") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_lsapi_internal = ival;
            cfg->err_lsapi_internal_was_set = 1;
        }
    } else if(strcmp(arg1, "LSAPI_CONN_ACQUIRE") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_lsapi_conn_acquire = ival;
            cfg->err_lsapi_conn_acquire_was_set = 1;
        }
    } else if(strcmp(arg1, "LSAPI_CONN_DETERMINE") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_lsapi_conn_determine = ival;
            cfg->err_lsapi_conn_determine_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_NOHDRS") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_nohdrs = ival;
            cfg->err_backend_nohdrs_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_ENDHDRS") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_endhdrs = ival;
            cfg->err_backend_endhdrs_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_SENDREQ") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_sendreq = ival;
            cfg->err_backend_sendreq_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_RECVHDR") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_recvhdr = ival;
            cfg->err_backend_recvhdr_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_RECVRSP") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_recvrsp = ival;
            cfg->err_backend_recvrsp_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_CONNECT") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_connect = ival;
            cfg->err_backend_connect_was_set = 1;
        }
    } else if(strcmp(arg1, "BACKEND_REJECT") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_backend_reject = ival;
            cfg->err_backend_reject_was_set = 1;
        }
    } else if(strcmp(arg1, "CLIENT_SETUP") == 0) {
        ival = (uint32_t) apr_atoi64 (arg2);
        if(ival >= 400 && ival < 600) {
            cfg->err_client_setup = ival;
            cfg->err_client_setup_was_set = 1;
        }
    }
    return NULL;
}


static const char *lsapi_backend_coredump_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.backend_coredump = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.backend_coredump_was_set = 1;
    return NULL;
}

static const char *lsapi_dump_debug_info_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.dump_backend_debug_info = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.dump_backend_debug_info_was_set = 1;
    return NULL;
}

static const char *lsapi_use_suexec_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.use_suexec = !( strcasecmp(value, "off") == 0 );
    cfg->backend_info.use_suexec_was_set = 1;
    return NULL;
}

static const char *lsapi_poll_timeout_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    uint32_t ival = (uint32_t) apr_atoi64 (value);
    if(ival >= 0) {
        cfg->backend_info.poll_timeout = ival;
    }
    return NULL;
}

static const char *lsapi_mutex_mech_handler(cmd_parms *cmd, void *dummy, const char *value) {
#if !LSCAPI_WITH_MUTEX_API
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);

    if(!strcmp(value, "default")) {
        cfg->mutex_mech = APR_LOCK_DEFAULT;

    } else if(!strcmp(value, "fcntl")) {
#if APR_HAS_FCNTL_SERIALIZE
        cfg->mutex_mech = APR_LOCK_FCNTL;
#endif // APR_HAS_FCNTL_SERIALIZE

    } else if(!strcmp(value, "flock")) {
#if APR_HAS_FLOCK_SERIALIZE
        cfg->mutex_mech = APR_LOCK_FLOCK;
#endif // APR_HAS_FLOCK_SERIALIZE

    } else if(!strcmp(value, "posixsem")) {
#if APR_HAS_POSIXSEM_SERIALIZE
        cfg->mutex_mech = APR_LOCK_POSIXSEM;
#endif // APR_HAS_POSIXSEM_SERIALIZE

    } else if(!strcmp(value, "pthread")) {
#if APR_HAS_PROC_PTHREAD_SERIALIZE
        cfg->mutex_mech = APR_LOCK_PROC_PTHREAD;
#endif // APR_HAS_PROC_PTHREAD_SERIALIZE

    } else if(!strcmp(value, "sysvsem")) {
#if APR_HAS_SYSVSEM_SERIALIZE
        cfg->mutex_mech = APR_LOCK_SYSVSEM;
#endif // APR_HAS_SYSVSEM_SERIALIZE
    }

#endif //!LSCAPI_WITH_MUTEX_API
    return NULL;
}

static const char *lsapi_mod_php_behaviour_handler(cmd_parms *cmd, void* CFG, const char *arg1)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->mod_php_behaviour_off = ( strcasecmp(arg1, "off") == 0 );
    cfg->mod_php_behaviour_off_was_set = 1;

    return NULL;
}

static const char *lsapi_suphp_usergroup_handler(cmd_parms *cmd, void* CFG,
                                           const char *arg1, const char *arg2)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    uint32_t uid = ap_uname2id(arg1);
    uint32_t gid = ap_gname2id(arg2);

    if(uid > 0 && gid > 0) {
        cfg->suphp_uid = uid;
        cfg->suphp_gid = gid;
    }

    return NULL;
}


static const char *lsapi_ruidgid_handler(cmd_parms *cmd, void* CFG,
                                           const char *arg1, const char *arg2)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    uint32_t uid = ap_uname2id(arg1);
    uint32_t gid = ap_gname2id(arg2);

    if(uid > 0 && gid > 0) {
        cfg->ruid = uid;
        cfg->rgid = gid;
    }

    return NULL;
}

static const char *lsapi_assign_user_id(cmd_parms *cmd, void* CFG,
                                           const char *arg1, const char *arg2)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    uint32_t uid = ap_uname2id(arg1);
    uint32_t gid = ap_gname2id(arg2);

    if(uid > 0 && gid > 0) {
        cfg->itk_uid = uid;
        cfg->itk_gid = gid;
    }

    return NULL;
}


static const char *php_value_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value) {
    int valueType = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0)
                ? LSCAPI_SPECIAL_ENV_PHPVAL_PERDIR : LSCAPI_SPECIAL_ENV_PHPVAL_SYSTEM;
    return lscapi_php_value_handler(cmd, cfg, name, value, 0, valueType);
}

static const char *php_admin_value_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value) {
    int valueType = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0)
                ? LSCAPI_SPECIAL_ENV_PHPVAL_PERDIR : LSCAPI_SPECIAL_ENV_PHPVAL_SYSTEM;
    return lscapi_php_value_handler(cmd, cfg, name, value, 1, valueType);
}

static const char *php_flag_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value) {
    int valueType = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0)
                ? LSCAPI_SPECIAL_ENV_PHPVAL_PERDIR : LSCAPI_SPECIAL_ENV_PHPVAL_SYSTEM;
    return lscapi_php_flag_handler(cmd, cfg, name, value, 0, valueType);
}

static const char *php_admin_flag_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value) {
    int valueType = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0)
                ? LSCAPI_SPECIAL_ENV_PHPVAL_PERDIR : LSCAPI_SPECIAL_ENV_PHPVAL_SYSTEM;
    return lscapi_php_flag_handler(cmd, cfg, name, value, 1, valueType);
}

static const char *lsapi_phpini_handler(cmd_parms *cmd, void *cfg,
                                    const char *value) {
    int valueType = LSCAPI_SPECIAL_ENV_ALTER_PHPINI;
    return lscapi_php_value_handler(cmd, cfg, "lsapi_phpini", value, 0, valueType);
}


static const char *lsapi_process_phpini_handler(cmd_parms *cmd, void* CFG, const char *arg1)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->process_phpini = ( strcasecmp(arg1, "on") == 0 );
    cfg->process_phpini_was_set = 1;

    return NULL;
}

static const char *lsapi_keep_http200_handler(cmd_parms *cmd, void* CFG, const char *arg1)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->keep_http200 = ( strcasecmp(arg1, "on") == 0 );
    cfg->keep_http200_was_set = 1;

    return NULL;
}

static const char *lsapi_output_buffering_handler(cmd_parms *cmd, void* CFG, const char *arg1)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    cfg->output_buffering = ( strcasecmp(arg1, "off") != 0 );
    cfg->output_buffering_was_set = 1;

    return NULL;
}

static const char *lsapi_lsapipath (cmd_parms * cmd, void *CFG, const char *regexp_data)
{
    lsapi_dir_conf_t* cfg = (lsapi_dir_conf_t*)CFG;
    if (regexp_data)
    {
        int right_param = 1;
        ap_regex_t rx;

        // Compile regex. Error ?
        if (ap_regcomp (&rx, regexp_data, AP_REG_EXTENDED))
        {
            right_param = 0;
        } else {
            cfg->path_regex = regexp_data;
            ap_regfree (&rx);
        }

        if (!right_param)
        {
            return apr_psprintf (cmd->pool,
                                "Wrong regexp expression %s in parameter LSAPIPath",
                                regexp_data);
        }
    }
    return NULL;
}

static const char *lsapi_tmpdir_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);

    cfg->tmpdir = apr_pstrdup(cmd->pool, value);
    return NULL;
}

static const char *lsapi_use_starter_hash_t_handler(cmd_parms *cmd, void *dummy, const char *value) {
    if (strcasecmp(value, "on") == 0)
        set_use_starter_hash_t_structures();
    return NULL;
}

#ifndef WITHOUT_SENTRY
static const char *lsapi_sentry_handler(cmd_parms *cmd, void *dummy, const char *value) {
/* LSAPI_PRO_ONLY:BEGIN */
    if (strcasecmp(value, "off") == 0)
        set_lsapi_sentry(0);
/* LSAPI_PRO_ONLY:END */
    return NULL;
}
#endif

static const char *lsapi_avoid_zombies_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.avoid_zombies = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.avoid_zombies_was_set = 1;
    return NULL;
}

static const char *lsapi_disable_reject_mode_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.disable_reject_mode = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.disable_reject_mode_was_set = 1;
    return NULL;
}

/* LSAPI_PRO_ONLY:BEGIN */
static const char *lsapi_with_connection_pool_handler(cmd_parms *cmd, void *dummy, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    if(strcasecmp(value, "off") == 0)
    {
        cfg->with_connection_pool = 0;
        cfg->with_connection_pool_was_set = 1;
    }
    else if(strcasecmp(value, "on") == 0)
    {
        cfg->with_connection_pool = 1;
        cfg->with_connection_pool_was_set = 1;
    }

    return NULL;
}

static const char *lsapi_mutex_tweak_handler(cmd_parms *cmd, void *dummy, const char *value) {
    const char *err = ap_check_cmd_context (cmd, GLOBAL_ONLY);
    if (err != NULL)
    {
      return err;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);

    if(strcasecmp(value, "off") == 0) {
        cfg->mutex_tweak = 0;
        cfg->mutex_tweak_was_set = 1;
    } else if(strcasecmp(value, "on") == 0) {
        cfg->mutex_tweak = 1;
        cfg->mutex_tweak_was_set = 1;
    }

    return NULL;
}

static const char *lsapi_backend_semtimedwait_handler(cmd_parms *cmd, void *CFG, const char *value) {
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.backend_semtimedwait = ( strcasecmp(value, "off") != 0 );
    cfg->backend_info.backend_semtimedwait_was_set = 1;
    return NULL;
}

static const char *lsapi_criu_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.use_criu = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.use_criu_was_set = 1;
#endif
    return NULL;
}

static const char *lsapi_criu_debug_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.criu_debug = ( strcasecmp(value, "on") == 0 );
    cfg->backend_info.criu_debug_was_set = 1;
#endif
    return NULL;
}

//Can by off, signals, pipes. Default off
static const char *lsapi_criu_signals_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->backend_info.use_criu_signals = 0;
    if ( !strcasecmp(value, "signals") ) {
        cfg->backend_info.use_criu_signals = 1;
    } else if ( !strcasecmp(value, "pipes") ) {
        cfg->backend_info.use_criu_signals = 2;
    }
    cfg->backend_info.use_criu_signals_was_set = 1;
#endif
    return NULL;
}

static const char *lsapi_criu_socket_path_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->criu_socket_path = apr_pstrdup(cmd->pool, value);
#endif
    return NULL;
}

static const char *lsapi_criu_imgs_dir_path_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);
    cfg->criu_imgs_dir_path = apr_pstrdup(cmd->pool, value);
#endif
    return NULL;
}

static const char *lsapi_reset_criu_on_apache_restart_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_CRIU
    if (strcasecmp(value, "on") == 0) {
        reset_criu_on_apache_restart = 1;
    }
#endif
    return NULL;
}

static const char *lsapi_use_perfcounters_handler(cmd_parms *cmd, void *dummy, const char *value) {
#ifdef WITH_LIBPERFLOG
    lsapi_use_perflog = ( strcasecmp(value, "on") == 0 );
    if(lsapi_use_perflog) lsapi_init_libperflog();
#endif
    return NULL;
}
/* LSAPI_PRO_ONLY:END */

static const char *lsapi_server_tweak_handler(cmd_parms *cmd, void *dummy, const char *value) {
    const char *err = ap_check_cmd_context (cmd, GLOBAL_ONLY);
    if (err != NULL)
    {
      return err;
    }
    lsapi_svr_conf_t *cfg = ap_get_module_config(cmd->server->module_config, &lsapi_module);

    if (strcasecmp(value, "off") == 0) {
        cfg->server_tweak = 0;
        cfg->server_tweak_was_set = 1;
    } else if (strcasecmp(value, "on") == 0) {
        cfg->server_tweak = 1;
        cfg->server_tweak_was_set = 1;
    }

    return NULL;
}

static const char *fake_TAKE1_handler(cmd_parms *cmd, void *dummy, const char *args) {
    return NULL;
}

static const char *fake_FLAG_handler(cmd_parms *cmd, void *dummy, int arg) {
    return NULL;
}

static const char *fake_TAKE2_handler(cmd_parms * cmd, void *dummy,
                                       const char *arg1, const char *arg2)
{
    return NULL;
}

static const char *fake_TAKE3_handler(cmd_parms * cmd, void *dummy,
                                       const char *arg1, const char *arg2, const char *arg3)
{
    return NULL;
}

static const command_rec config_directives[] = {
    AP_INIT_TAKE2("php_value", php_value_handler, NULL, OR_OPTIONS, "PHP Value"),
    AP_INIT_TAKE2("php_admin_value", php_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Admin Value"),
    AP_INIT_TAKE2("php_flag", php_flag_handler, NULL, OR_OPTIONS, "PHP Flag"),
    AP_INIT_TAKE2("php_admin_flag", php_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Admin Flag"),
    AP_INIT_TAKE1("lsapi_phpini", lsapi_phpini_handler, NULL, OR_OPTIONS, "To change php.ini on directory basis"),
    AP_INIT_TAKE1("lsapi_process_phpini", lsapi_process_phpini_handler, NULL, RSRC_CONF | ACCESS_CONF,
                  "Enable or disable phpini_* directive processing"),
    AP_INIT_TAKE1("lsapi_keep_http200", lsapi_keep_http200_handler, NULL, OR_OPTIONS,
                  "Keep (as mod_php) or not (as suphp) backend's HTTP_OK response status"),
    AP_INIT_TAKE1("lsapi_output_buffering", lsapi_output_buffering_handler, NULL, OR_OPTIONS, "Output buffering"),
    //AP_INIT_TAKE1("PHPINIDir", LSCAPI_PhpIniDirSetHandler, NULL, RSRC_CONF, "Directory with php.ini"),

    AP_INIT_TAKE1("lsapi_backend_connect_timeout", lsapi_backend_connect_timeout_handler, NULL, RSRC_CONF, "Backend connect timeout"),
    AP_INIT_TAKE1("lsapi_backend_connect_tries", lsapi_backend_connect_tries_handler, NULL, RSRC_CONF, "Backend connect try number"),
    AP_INIT_TAKE1("lsapi_backend_children", lsapi_backend_children_handler, NULL, RSRC_CONF, "LSAPI_CHILDREN"),
    AP_INIT_TAKE1("lsapi_backend_oom_score_adj", lsapi_backend_oom_score_adj_handler, NULL, RSRC_CONF, "oom_score_adj value for backend processes"),
    AP_INIT_TAKE1("lsapi_backend_pgrp_max_idle", lsapi_backend_pgrp_max_idle_handler, NULL, RSRC_CONF, "LSAPI_PGRP_MAX_IDLE"),
    AP_INIT_TAKE1("lsapi_backend_max_idle", lsapi_backend_max_idle_handler, NULL, RSRC_CONF, "LSAPI_MAX_IDLE"),
    AP_INIT_TAKE1("lsapi_backend_max_process_time", lsapi_backend_max_process_time_handler, NULL, RSRC_CONF, "LSAPI_MAX_PROCESS_TIME"),
    AP_INIT_TAKE1("lsapi_backend_max_reqs", lsapi_backend_max_reqs_handler, NULL, RSRC_CONF, "LSAPI_MAX_REQS"),
    AP_INIT_TAKE1("lsapi_backend_pgrp_max_reqs", lsapi_backend_pgrp_max_reqs_handler, NULL, RSRC_CONF, "LSAPI_PGRP_MAX_REQS"),
    AP_INIT_TAKE1("lsapi_backend_pgrp_max_crashes", lsapi_backend_pgrp_max_crashes_handler, NULL, RSRC_CONF, "LSAPI_PGRP_MAX_CRASHES"),
    AP_INIT_TAKE1("lsapi_backend_initial_start", lsapi_backend_initial_start, NULL, RSRC_CONF, "LSAPI_INITIAL_START"),
    AP_INIT_TAKE1("lsapi_debug", lsapi_debug_handler, NULL, RSRC_CONF, "Extended Debug"),
    AP_INIT_TAKE1("lsapi_terminate_backends_on_exit", lsapi_terminate_backends_on_exit_handler, NULL, RSRC_CONF, "Terminate backends processes on server stop/restart"),
    AP_INIT_TAKE1("lsapi_socket_path", lsapi_socket_path_handler, NULL, RSRC_CONF, "Path for backend sockets"),

    AP_INIT_TAKE1("lsapi_phprc", lsapi_phprc_handler, NULL, RSRC_CONF, "PHPRC value"),
    AP_INIT_TAKE1("lsapi_target_perm", lsapi_target_perm_handler, NULL, RSRC_CONF, "Check or not owning of target script"),
    AP_INIT_TAKE1("lsapi_paranoid", lsapi_paranoid_handler, NULL, RSRC_CONF, "Check or not permissions of target script"),
    AP_INIT_TAKE1("lsapi_check_document_root", lsapi_check_document_root_handler, NULL, RSRC_CONF, "Check or not owner of DOCUMENT_ROOT"),
    AP_INIT_TAKE1("lsapi_use_default_uid", lsapi_use_default_uid_handler, NULL, RSRC_CONF, "Use or not apache uid/gid for request as fallback"),
    AP_INIT_TAKE2("lsapi_uid_gid", lsapi_uid_gid_handler, NULL, RSRC_CONF | ACCESS_CONF, "uid/gid for requests"),
    AP_INIT_TAKE2("lsapi_user_group", lsapi_user_group_handler, NULL, RSRC_CONF | ACCESS_CONF, "user/group for requests"),

    AP_INIT_TAKE1("lsapi_selfstarter", lsapi_selfstarter_handler, NULL, RSRC_CONF, "Backward compatibilty option. Ignored."),

    /* In order to have a possibility to switch making coredumps on without restarting Apache,
       just by changing this options to On in .htaccess and killing all existing lsphp processes
    */
    AP_INIT_TAKE1("lsapi_backend_coredump", lsapi_backend_coredump_handler, NULL, OR_OPTIONS, "Backend core dump enabled or not"),

    AP_INIT_TAKE1("lsapi_dump_debug_info", lsapi_dump_debug_info_handler, NULL, RSRC_CONF, "Dump stacktrace and lsof before killing runaway backend"),
    AP_INIT_TAKE1("lsapi_use_suexec", lsapi_use_suexec_handler, NULL, RSRC_CONF, "Use or not suexec to target user"),
    AP_INIT_TAKE1("lsapi_poll_timeout", lsapi_poll_timeout_handler, NULL, OR_OPTIONS, "Timeout to poll backend"),
    AP_INIT_TAKE1("lsapi_mutex_mech", lsapi_mutex_mech_handler, NULL, RSRC_CONF, "Mutex mechanism to use"),
    AP_INIT_TAKE1("lsapi_mod_php_behaviour", lsapi_mod_php_behaviour_handler, NULL, RSRC_CONF | ACCESS_CONF,
                  "Enable or disable php_* directive processing"),
    AP_INIT_TAKE1("lsapi_backend_accept_notify", lsapi_backend_accept_notify_handler, NULL, RSRC_CONF, "LSAPI_ACCEPT_NOTIFY mode for lsphp enabled or not"),
    AP_INIT_TAKE1("lsapi_max_resend_buffer", lsapi_max_resend_buffer_handler, NULL, RSRC_CONF, "DEPRECATED, should not be used"),
    AP_INIT_TAKE2("lsapi_set_env", lsapi_set_env_handler, NULL, RSRC_CONF, "To set variable in backend environment"),
    AP_INIT_TAKE1("lsapi_set_env_path", lsapi_set_env_path_handler, NULL, RSRC_CONF, "To set PATH in backend environment"),
    AP_INIT_TAKE1("lsapi_max_connection", lsapi_max_connection_handler, NULL, RSRC_CONF, "Max simultaneous connections to lsphp in pool"),

    AP_INIT_TAKE1("lsapi_sulsphp_log_path", lsapi_sulsphp_log_path_handler, NULL, RSRC_CONF, "Use own file for sulsphp log"),

    /* OR_OPTIONS due to backward compatibility of configs, RSRC_CONF should be */
    AP_INIT_TAKE1("lsapi_backend_use_own_log", lsapi_backend_use_own_log_handler, NULL, OR_OPTIONS, "Use own file or Apache error log file for backend output"),

    /* OR_OPTIONS due to backward compatibility of configs, RSRC_CONF should be */
    AP_INIT_TAKE1("lsapi_backend_loglevel_info", lsapi_backend_loglevel_info_handler, NULL, OR_OPTIONS, "Use LOG_INFO level, instead of LOG_WARNING for non-fatal backend logs"),

    /* OR_OPTIONS due to backward compatibility of configs, RSRC_CONF should be */
    AP_INIT_TAKE1("lsapi_backend_common_own_log", lsapi_backend_common_own_log_handler, NULL, OR_OPTIONS, "Use dedicated log file or common log file for backend output"),

    AP_INIT_TAKE1("lsapi_disable_forced_pwd_var", lsapi_disable_pwd_var_handler, NULL, RSRC_CONF, "Disable forcing of PWD var in backend environment"),
    AP_INIT_TAKE1("lsapi_protocol_logfile", lsapi_protocol_logfile_handler, NULL, RSRC_CONF, "Filename to use for logging LSAPI protocol exchange"),
#ifdef LSCAPI_WITH_DUMP_HEADER
    // Not documented
    AP_INIT_TAKE1("lsapi_hostname_on_debug", lsapi_hostname_on_debug_handler, NULL, RSRC_CONF, "Dump or not failed response header"),
#endif
    AP_INIT_TAKE1("lsapi_enable_user_ini", lsapi_enable_user_ini_handler, NULL, RSRC_CONF, "Enable user ini files for backend"),
    AP_INIT_TAKE1("lsapi_user_ini_homedir", lsapi_user_ini_homedir_handler, NULL, RSRC_CONF, "Read user ini file from home direcotry"),
    AP_INIT_TAKE1("lsapi_per_user", lsapi_per_user_handler, NULL, RSRC_CONF, "Invoke backend not per VirtualHost but per account"),
    AP_INIT_TAKE1("lsapi_use_starter_hash_t_structures", lsapi_use_starter_hash_t_handler, NULL, RSRC_CONF,
                  "Use hashing structures in the starter against transmission over pipe"),
#ifndef WITHOUT_SENTRY
    AP_INIT_TAKE1("lsapi_sentry", lsapi_sentry_handler, NULL, RSRC_CONF,
                      "Enable sentry for mod_lsapi error reporting"),
#endif
    AP_INIT_TAKE1("lsapi_avoid_zombies", lsapi_avoid_zombies_handler, NULL, RSRC_CONF, "Enable mechanism to avoid creation of zombie process by lsphp processes"),
    AP_INIT_TAKE1("lsapi_disable_reject_mode", lsapi_disable_reject_mode_handler, NULL, RSRC_CONF, "Disable REJECT mode for lsphp processes"),
/* LSAPI_PRO_ONLY:BEGIN */
    AP_INIT_TAKE1("lsapi_with_connection_pool", lsapi_with_connection_pool_handler, NULL, RSRC_CONF, "Use or not connection pool mode."),
    AP_INIT_TAKE1("lsapi_mutex_tweak", lsapi_mutex_tweak_handler, NULL, RSRC_CONF, "Internal mode to tweak work with starter mutex"),
    AP_INIT_TAKE1("lsapi_backend_semtimedwait", lsapi_backend_semtimedwait_handler, NULL, RSRC_CONF, "Use lsapi_backend_connect_timeout together with POSIX semaphore"),
#ifdef WITH_CRIU
    AP_INIT_TAKE1("lsapi_criu", lsapi_criu_handler, NULL, RSRC_CONF, "Use or not criu"),
    AP_INIT_TAKE1("lsapi_criu_debug", lsapi_criu_debug_handler, NULL, RSRC_CONF, "Enable criu debug output"),
    AP_INIT_TAKE1("lsapi_criu_use_shm", lsapi_criu_signals_handler, NULL, RSRC_CONF, "Use shared memory or pipes for global counter"),
    AP_INIT_TAKE1("lsapi_criu_socket_path", lsapi_criu_socket_path_handler, NULL, RSRC_CONF, "Path to criu service socket"),
    AP_INIT_TAKE1("lsapi_criu_imgs_dir_path", lsapi_criu_imgs_dir_path_handler, NULL, RSRC_CONF, "Path to directory for criu images"),
    AP_INIT_TAKE1("lsapi_reset_criu_on_apache_restart", lsapi_reset_criu_on_apache_restart_handler, NULL, RSRC_CONF,
                  "Reset all criu images if apache restarts"),
#else
    AP_INIT_TAKE1("lsapi_criu_use_shm", lsapi_criu_signals_handler, NULL, RSRC_CONF, "Ignored as module compiled without CRIU support"),
    AP_INIT_TAKE1("lsapi_criu", lsapi_criu_handler, NULL, RSRC_CONF, "Ignored as module compiled without CRIU support"),
    AP_INIT_TAKE1("lsapi_criu_debug", lsapi_criu_debug_handler, NULL, RSRC_CONF, "Ignored as module compiled without CRIU support"),
    AP_INIT_TAKE1("lsapi_criu_socket_path", lsapi_criu_socket_path_handler, NULL, RSRC_CONF, "Ignored as module compiled wthout CRIU support"),
    AP_INIT_TAKE1("lsapi_criu_imgs_dir_path", lsapi_criu_imgs_dir_path_handler, NULL, RSRC_CONF, "Ignored as module compiled wthout CRIU support"),
    AP_INIT_TAKE1("lsapi_reset_criu_on_apache_restart", lsapi_reset_criu_on_apache_restart_handler, NULL, RSRC_CONF,
                  "Ignored as module compiled wthout CRIU support"),
#endif
    AP_INIT_TAKE1("lsapi_server_tweak", lsapi_server_tweak_handler, NULL, RSRC_CONF, "Internal mode to tweak work with Apache server_rec"),
#ifdef WITH_LIBPERFLOG
    AP_INIT_TAKE1("lsapi_use_perfcounters", lsapi_use_perfcounters_handler, NULL, RSRC_CONF, "Use or not performance counters"),
#else //WITH_LIBPERFLOG
    AP_INIT_TAKE1("lsapi_use_perfcounters", lsapi_use_perfcounters_handler, NULL, RSRC_CONF, "Ignored as module compiled without LIBPERFLOG support"),
#endif //WITH_LIBPERFLOG
/* LSAPI_PRO_ONLY:END */
    AP_INIT_TAKE1("LSAPIPath", lsapi_lsapipath, NULL, RSRC_CONF, "Set template of path"),
    AP_INIT_TAKE1("lsapi_tmpdir", lsapi_tmpdir_handler, NULL, RSRC_CONF, "Set tmpdir to create temporary files per request body in"),
    AP_INIT_TAKE2("lsapi_error_code", lsapi_error_code_handler, NULL, RSRC_CONF | ACCESS_CONF,
                  "Error codes used in response to client"),
    AP_INIT_TAKE1("lsapi_engine", lsapi_engine_handler, NULL, OR_OPTIONS, "Switching mod_lsapi handler on or off."),
    AP_INIT_TAKE1("lsapi_measure_time", lsapi_measure_time_handler, NULL, OR_OPTIONS, "Switching process time measurement on or off."),
    AP_INIT_TAKE1("lsapi_use_req_hostname", lsapi_use_req_hostname_handler, NULL, RSRC_CONF, "Use a hostname from the request_rec structure"),
/* LSAPI_PRO_ONLY:BEGIN */
    /*
        Undocumented, for dumping full info of requests. It is supposed that it will be switched on and off via .htaccess
    */
    AP_INIT_TAKE1("lsapi_dump_request_info", lsapi_dump_request_info_handler, NULL, OR_OPTIONS, "Dump full info about every HTTP request"),
/* LSAPI_PRO_ONLY:END */

    /*
     * SU PHP param will be used too as fallback
     */
    AP_INIT_TAKE2("suPHP_UserGroup", lsapi_suphp_usergroup_handler, NULL, RSRC_CONF | ACCESS_CONF,
                  "User and group scripts shall be run as"),

    /*
     * RUidGid param will be used too as fallback
     */
    AP_INIT_TAKE2 ("RUidGid", lsapi_ruidgid_handler, NULL, RSRC_CONF | ACCESS_CONF,
                "ruid2: Minimal uid or gid file/dir, else set[ug]id to default (User,Group)"),

    /*
     * AssignUserID param of itk module will be used too as fallback
     */
    AP_INIT_TAKE2("AssignUserID", lsapi_assign_user_id, NULL, RSRC_CONF|ACCESS_CONF,
                    "Tie a virtual host to a specific child process."),


    /*
     * Fake config directives to make fcgid-related configs compatible with mod_lsapi
     */
    AP_INIT_TAKE1("FcgidAccessChecker", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO,
                  "fcgid fake: a absolute access checker file path"),
    AP_INIT_FLAG("FcgidAccessCheckerAuthoritative",
                 fake_FLAG_handler, NULL, ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Set to 'off' to allow access control to be passed along to lower modules upon failure"),
    AP_INIT_TAKE1("FcgidAuthenticator", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO, "fcgid fake: a absolute authenticator file path"),
    AP_INIT_FLAG("FcgidAuthenticatorAuthoritative",
                 fake_FLAG_handler, NULL,
                 ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Set to 'off' to allow authentication to be passed along to lower modules upon failure"),
    AP_INIT_TAKE1("FcgidAuthorizer", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO,
                  "fcgid fake: a absolute authorizer file path"),
    AP_INIT_FLAG("FcgidAuthorizerAuthoritative",
                 fake_FLAG_handler, NULL,
                 ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Set to 'off' to allow authorization to be passed along to lower modules upon failure"),
    AP_INIT_TAKE1("FcgidBusyScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: scan interval for busy timeout process"),
    AP_INIT_TAKE1("FcgidBusyTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: a fastcgi application will be killed after handling a request for BusyTimeout"),
    AP_INIT_RAW_ARGS("FcgidCmdOptions", fake_TAKE1_handler, NULL, RSRC_CONF,
                     "set processing options for a FastCGI command"),
    AP_INIT_TAKE12("FcgidInitialEnv", fake_TAKE2_handler, NULL, RSRC_CONF,
                   "fcgid fake: an environment variable name and optional value to pass to FastCGI."),
    AP_INIT_TAKE1("FcgidMaxProcessesPerClass",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Max process count of one class of fastcgi application"),
    AP_INIT_TAKE1("FcgidMinProcessesPerClass",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Min process count of one class of fastcgi application"),
    AP_INIT_TAKE1("FcgidErrorScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: scan interval for exited process"),
    AP_INIT_TAKE1("FcgidIdleScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: scan interval for idle timeout process"),
    AP_INIT_TAKE1("FcgidIdleTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: an idle fastcgi application will be killed after IdleTimeout"),
    AP_INIT_TAKE1("FcgidIOTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Communication timeout to fastcgi server"),
    AP_INIT_TAKE1("FcgidConnectTimeout", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Connect timeout to fastcgi server"),
    AP_INIT_TAKE1("FcgidMaxProcesses", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Max total process count"),
    AP_INIT_TAKE1("FcgidMaxRequestInMem", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: The part of HTTP request which greater than this limit will swap to disk"),
    AP_INIT_TAKE1("FcgidMaxRequestLen", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Max HTTP request length in byte"),
    AP_INIT_TAKE1("FcgidMaxRequestsPerProcess", fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Max requests handled by each fastcgi application"),
    AP_INIT_TAKE1("FcgidOutputBufferSize", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: CGI output buffer size"),
    AP_INIT_TAKE1("FcgidPassHeader", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Header name which will be passed to FastCGI as environment variable."),
    AP_INIT_TAKE1("FcgidFixPathinfo",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Set 1, if cgi.fix_pathinfo=1 in php.ini"),
    AP_INIT_TAKE1("FcgidProcessLifeTime", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: fastcgi application lifetime"),
    AP_INIT_TAKE1("FcgidProcessTableFile", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: fastcgi shared memory file path"),
    AP_INIT_TAKE1("FcgidIPCDir", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: fastcgi socket file path"),
    AP_INIT_TAKE1("FcgidSpawnScore", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Score of spawn"),
    AP_INIT_TAKE1("FcgidSpawnScoreUpLimit", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Spawn score up limit"),
    AP_INIT_TAKE1("FcgidTerminationScore", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Score of termination"),
    AP_INIT_TAKE1("FcgidTimeScore", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Score of passage of time (in seconds)"),
    AP_INIT_TAKE123("FcgidWrapper", fake_TAKE3_handler, NULL,
                    RSRC_CONF | ACCESS_CONF | OR_FILEINFO,
                    "fcgid fake: The CGI wrapper file an optional URL suffix and an optional flag"),
    AP_INIT_TAKE1("FcgidZombieScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: scan interval for zombie process"),
    /*
     * Fake of deprecated fcgid config directives.
     */
    AP_INIT_TAKE1("BusyScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidBusyScanInterval' instead"),
    AP_INIT_TAKE1("BusyTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidBusyTimeout' instead"),
    AP_INIT_TAKE12("DefaultInitEnv", fake_TAKE2_handler, NULL, RSRC_CONF,
                   "fcgid fake: Deprecated - Use 'FcgidInitialEnv' instead"),
    AP_INIT_TAKE1("DefaultMaxClassProcessCount",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMaxProcessesPerClass' instead"),
    AP_INIT_TAKE1("DefaultMinClassProcessCount",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMinProcessesPerClass' instead"),
    AP_INIT_TAKE1("ErrorScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidErrorScanInterval' instead"),
    AP_INIT_TAKE1("FastCgiAccessChecker", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO,
                  "fcgid fake: Deprecated - Use 'FcgidAccessChecker' instead"),
    AP_INIT_FLAG("FastCgiAccessCheckerAuthoritative",
                 fake_FLAG_handler, NULL, ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Deprecated - Use 'FcgidAccessCheckerAuthoritative' instead"),
    AP_INIT_TAKE1("FastCgiAuthenticator", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO,
                  "fcgid fake: Deprecated - Use 'FcgidAuthenticator' instead"),
    AP_INIT_FLAG("FastCgiAuthenticatorAuthoritative",
                 fake_FLAG_handler, NULL,
                 ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Deprecated - Use 'FcgidAuthenticatorAuthoritative' instead"),
    AP_INIT_TAKE1("FastCgiAuthorizer", fake_TAKE1_handler, NULL,
                  ACCESS_CONF | OR_FILEINFO,
                  "fcgid fake: Deprecated - Use 'FcgidAuthorizer' instead"),
    AP_INIT_FLAG("FastCgiAuthorizerAuthoritative",
                 fake_FLAG_handler, NULL,
                 ACCESS_CONF | OR_FILEINFO,
                 "fcgid fake: Deprecated - Use 'FcgidAuthorizerAuthoritative' instead"),
    AP_INIT_TAKE123("FCGIWrapper", fake_TAKE3_handler, NULL,
                    RSRC_CONF | ACCESS_CONF | OR_FILEINFO,
                    "fcgid fake: Deprecated - Use 'FcgidWrapper' instead"),
    AP_INIT_TAKE1("IdleScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidIdleScanInterval' instead"),
    AP_INIT_TAKE1("IdleTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidIdleTimeout' instead"),
    AP_INIT_TAKE1("IPCCommTimeout", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidIOTimeout' instead"),
    AP_INIT_TAKE1("IPCConnectTimeout", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidConnectTimeout' instead"),
    AP_INIT_TAKE1("MaxProcessCount", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMaxProcesses' instead"),
    AP_INIT_TAKE1("MaxRequestInMem", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMaxRequestInMem' instead"),
    AP_INIT_TAKE1("MaxRequestLen", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMaxRequestLen' instead"),
    AP_INIT_TAKE1("MaxRequestsPerProcess", fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidMaxRequestsPerProcess' instead"),
    AP_INIT_TAKE1("OutputBufferSize", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidOutputBufferSize' instead"),
    AP_INIT_TAKE1("PassHeader", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidPassHeader' instead"),
    AP_INIT_TAKE1("PHP_Fix_Pathinfo_Enable",
                  fake_TAKE1_handler,
                  NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidFixPathinfo' instead"),
    AP_INIT_TAKE1("ProcessLifeTime", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidProcessLifeTime' instead"),
    AP_INIT_TAKE1("SharememPath", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidProcessTableFile' instead"),
    AP_INIT_TAKE1("SocketPath", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidIPCDir' instead"),
    AP_INIT_TAKE1("SpawnScore", fake_TAKE1_handler, NULL, RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidSpawnScore' instead"),
    AP_INIT_TAKE1("SpawnScoreUpLimit", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidSpawnScoreUpLimit' instead"),
    AP_INIT_TAKE1("TerminationScore", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidTerminationScore' instead"),
    AP_INIT_TAKE1("TimeScore", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidTimeScore' instead"),
    AP_INIT_TAKE1("ZombieScanInterval", fake_TAKE1_handler, NULL,
                  RSRC_CONF,
                  "fcgid fake: Deprecated - Use 'FcgidZombieScanInterval' instead"),

    /*
     * Fake config directives to make suphp configs compatible with mod_lsapi
     */
    AP_INIT_FLAG("suPHP_Engine", fake_FLAG_handler, NULL, RSRC_CONF | ACCESS_CONF,
                 "suPHP fake: Whether suPHP is on or off, default is off"),
    AP_INIT_TAKE1("suPHP_ConfigPath", fake_TAKE1_handler, NULL, OR_OPTIONS,
                  "suPHP fake: Wheres the php.ini resides, default is the PHP default"),
    AP_INIT_ITERATE("suPHP_AddHandler", fake_TAKE1_handler, NULL, RSRC_CONF | ACCESS_CONF, "suPHP fake: Tells mod_suphp to handle these MIME-types"),
    AP_INIT_ITERATE("suPHP_RemoveHandler", fake_TAKE1_handler, NULL, RSRC_CONF | ACCESS_CONF, "suPHP fake: Tells mod_suphp not to handle these MIME-types"),
    AP_INIT_TAKE1("suPHP_PHPPath", fake_TAKE1_handler, NULL, RSRC_CONF, "suPHP fake: Path to the PHP binary used to render source view"),

    /*
     * Fake config directives to make ruid2 configs compatible with mod_lsapi
     */
	AP_INIT_TAKE1 ("RMode", fake_TAKE1_handler, NULL, RSRC_CONF | ACCESS_CONF, "ruid2 fake: Set mode to config or stat (default: config)"),
	AP_INIT_ITERATE ("RGroups", fake_TAKE1_handler, NULL, RSRC_CONF | ACCESS_CONF, "ruid2 fake: Set additional groups"),
	AP_INIT_TAKE2 ("RDefaultUidGid", fake_TAKE2_handler, NULL, RSRC_CONF, "ruid2 fake: If uid or gid is < than RMinUidGid set[ug]id to this uid gid"),
	AP_INIT_TAKE2 ("RMinUidGid", fake_TAKE2_handler, NULL, RSRC_CONF, "ruid2 fake: Minimal uid or gid file/dir, else set[ug]id to default (RDefaultUidGid)"),
	AP_INIT_TAKE2 ("RDocumentChRoot", fake_TAKE2_handler, NULL, RSRC_CONF, "ruid2 fake: Set chroot directory and the document root inside"),

    {NULL}
};

module AP_MODULE_DECLARE_DATA lsapi_module = {
    STANDARD20_MODULE_STUFF,
    lscapi_create_dir_config,     /* create per-directory config structure */
    lscapi_merge_dir_config,      /* merge per-directory config structures */
    lscapi_create_svr_config,     /* create per-server config structure */
    lscapi_merge_svr_config,      /* merge per-server config structures */
    config_directives,            /* command apr_table_t */
    register_hooks                /* register hooks */
};
