From 678fe256b3133f41132119e7ecd2f3ceae8b67e6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 15:42:58 +0200 Subject: Merging upstream version 2.4.59. Signed-off-by: Daniel Baumann --- server/NWGNUmakefile | 2 +- server/buildmark.c | 2 +- server/config.c | 3 +++ server/core.c | 69 +++++++++++++++++++++++++++++++++++++----------- server/core_filters.c | 62 +++++++++++++++++++++---------------------- server/log.c | 51 ++++++++++++++++++++++++++++------- server/main.c | 10 ++++--- server/mpm_unix.c | 16 ++++++----- server/scoreboard.c | 4 +-- server/util.c | 5 ++-- server/util_expr_eval.c | 16 +++++------ server/util_expr_parse.c | 2 ++ server/util_script.c | 54 +++++++++++++++++++------------------ server/util_time.c | 35 ++++++++++++++++++++---- 14 files changed, 220 insertions(+), 111 deletions(-) (limited to 'server') diff --git a/server/NWGNUmakefile b/server/NWGNUmakefile index 7f96e81..4917811 100644 --- a/server/NWGNUmakefile +++ b/server/NWGNUmakefile @@ -225,7 +225,7 @@ FILES_lib_objs = \ $(EOLIST) # -# implement targets and dependancies (leave this section alone) +# implement targets and dependencies (leave this section alone) # libs :: $(OBJDIR) $(TARGET_lib) diff --git a/server/buildmark.c b/server/buildmark.c index a9cd684..36bd713 100644 --- a/server/buildmark.c +++ b/server/buildmark.c @@ -23,7 +23,7 @@ static const char server_built[] = __DATE__ " " __TIME__; static const char server_built[] = "unknown"; #endif -AP_DECLARE(const char *) ap_get_server_built() +AP_DECLARE(const char *) ap_get_server_built(void) { return server_built; } diff --git a/server/config.c b/server/config.c index be889db..3d11ff5 100644 --- a/server/config.c +++ b/server/config.c @@ -2301,6 +2301,9 @@ AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp, if (s == NULL) { return s; } + if (ap_server_conf == NULL) { + ap_server_conf = s; + } init_config_globals(p); diff --git a/server/core.c b/server/core.c index e1493fd..e5e059e 100644 --- a/server/core.c +++ b/server/core.c @@ -95,6 +95,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(get_mgmt_items) APR_HOOK_LINK(insert_network_bucket) + APR_HOOK_LINK(get_pollfd_from_conn) ) AP_IMPLEMENT_HOOK_RUN_ALL(int, get_mgmt_items, @@ -106,6 +107,11 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, insert_network_bucket, apr_socket_t *socket), (c, bb, socket), AP_DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, get_pollfd_from_conn, + (conn_rec *c, struct apr_pollfd_t *pfd, + apr_interval_time_t *ptimeout), + (c, pfd, ptimeout), APR_ENOTIMPL) + /* Server core module... This module provides support for really basic * server operations, including options and commands which control the * operation of other modules. Consider this the bureaucracy module. @@ -489,6 +495,11 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) conf->flush_max_pipelined = AP_FLUSH_MAX_PIPELINED; } else { + /* Use main ErrorLogFormat while the vhost is loading */ + core_server_config *main_conf = + ap_get_core_module_config(ap_server_conf->module_config); + conf->error_log_format = main_conf->error_log_format; + conf->flush_max_pipelined = -1; } @@ -3951,24 +3962,26 @@ static const char *set_recursion_limit(cmd_parms *cmd, void *dummy, static void log_backtrace(const request_rec *r) { - const request_rec *top = r; + if (APLOGrdebug(r)) { + const request_rec *top = r; - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00121) - "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)"); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00121) + "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)"); - while (top && (top->prev || top->main)) { - if (top->prev) { - top = top->prev; - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00122) - "redirected from r->uri = %s", - top->uri ? top->uri : "(unexpectedly NULL)"); - } + while (top && (top->prev || top->main)) { + if (top->prev) { + top = top->prev; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00122) + "redirected from r->uri = %s", + top->uri ? top->uri : "(unexpectedly NULL)"); + } - if (!top->prev && top->main) { - top = top->main; - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00123) - "subrequested from r->uri = %s", - top->uri ? top->uri : "(unexpectedly NULL)"); + if (!top->prev && top->main) { + top = top->main; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00123) + "subrequested from r->uri = %s", + top->uri ? top->uri : "(unexpectedly NULL)"); + } } } } @@ -5597,6 +5610,28 @@ static int core_upgrade_storage(request_rec *r) return DECLINED; } +static apr_status_t core_get_pollfd_from_conn(conn_rec *c, + struct apr_pollfd_t *pfd, + apr_interval_time_t *ptimeout) +{ + if (c && !c->master) { + pfd->desc_type = APR_POLL_SOCKET; + pfd->desc.s = ap_get_conn_socket(c); + if (ptimeout) { + apr_socket_timeout_get(pfd->desc.s, ptimeout); + } + return APR_SUCCESS; + } + return APR_ENOTIMPL; +} + +AP_CORE_DECLARE(apr_status_t) ap_get_pollfd_from_conn(conn_rec *c, + struct apr_pollfd_t *pfd, + apr_interval_time_t *ptimeout) +{ + return ap_run_get_pollfd_from_conn(c, pfd, ptimeout); +} + static void register_hooks(apr_pool_t *p) { errorlog_hash = apr_hash_make(p); @@ -5640,7 +5675,9 @@ static void register_hooks(apr_pool_t *p) ap_hook_open_htaccess(ap_open_htaccess, NULL, NULL, APR_HOOK_REALLY_LAST); ap_hook_optional_fn_retrieve(core_optional_fn_retrieve, NULL, NULL, APR_HOOK_MIDDLE); - + ap_hook_get_pollfd_from_conn(core_get_pollfd_from_conn, NULL, NULL, + APR_HOOK_REALLY_LAST); + /* register the core's insert_filter hook and register core-provided * filters */ diff --git a/server/core_filters.c b/server/core_filters.c index d8a661f..c4ab603 100644 --- a/server/core_filters.c +++ b/server/core_filters.c @@ -719,41 +719,41 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s, if (!nvec) { apr_bucket_delete(bucket); } - continue; } - - /* Make sure that these new data fit in our iovec. */ - if (nvec == ctx->nvec) { - if (nvec == NVEC_MAX) { - sock_nopush(s, 1); - rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c); - if (rv != APR_SUCCESS) { - goto cleanup; - } - nbytes = 0; - nvec = 0; - } - else { - struct iovec *newvec; - apr_size_t newn = nvec * 2; - if (newn < NVEC_MIN) { - newn = NVEC_MIN; - } - else if (newn > NVEC_MAX) { - newn = NVEC_MAX; + else { + /* Make sure that these new data fit in our iovec. */ + if (nvec == ctx->nvec) { + if (nvec == NVEC_MAX) { + sock_nopush(s, 1); + rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c); + if (rv != APR_SUCCESS) { + goto cleanup; + } + nbytes = 0; + nvec = 0; } - newvec = apr_palloc(c->pool, newn * sizeof(struct iovec)); - if (nvec) { - memcpy(newvec, ctx->vec, nvec * sizeof(struct iovec)); + else { + struct iovec *newvec; + apr_size_t newn = nvec * 2; + if (newn < NVEC_MIN) { + newn = NVEC_MIN; + } + else if (newn > NVEC_MAX) { + newn = NVEC_MAX; + } + newvec = apr_palloc(c->pool, newn * sizeof(struct iovec)); + if (nvec) { + memcpy(newvec, ctx->vec, nvec * sizeof(struct iovec)); + } + ctx->vec = newvec; + ctx->nvec = newn; } - ctx->vec = newvec; - ctx->nvec = newn; } + nbytes += length; + ctx->vec[nvec].iov_base = (void *)data; + ctx->vec[nvec].iov_len = length; + nvec++; } - nbytes += length; - ctx->vec[nvec].iov_base = (void *)data; - ctx->vec[nvec].iov_len = length; - nvec++; /* Flush above max threshold, unless the brigade still contains in * memory buckets which we want to try writing in the same pass (if @@ -762,7 +762,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s, */ if (nbytes > conf->flush_max_threshold && next != APR_BRIGADE_SENTINEL(bb) - && !is_in_memory_bucket(next)) { + && next->length && !is_in_memory_bucket(next)) { sock_nopush(s, 1); rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c); if (rv != APR_SUCCESS) { diff --git a/server/log.c b/server/log.c index cc04c38..22d2f8d 100644 --- a/server/log.c +++ b/server/log.c @@ -55,7 +55,7 @@ #include "ap_mpm.h" #include "ap_listen.h" -#if HAVE_GETTID +#ifdef HAVE_SYS_GETTID #include #include #endif @@ -627,14 +627,18 @@ static int log_tid(const ap_errorlog_info *info, const char *arg, #if APR_HAS_THREADS int result; #endif -#if HAVE_GETTID +#if defined(HAVE_GETTID) || defined(HAVE_SYS_GETTID) if (arg && *arg == 'g') { +#ifdef HAVE_GETTID + pid_t tid = gettid(); +#else pid_t tid = syscall(SYS_gettid); +#endif if (tid == -1) return 0; return apr_snprintf(buf, buflen, "%"APR_PID_T_FMT, tid); } -#endif +#endif /* HAVE_GETTID || HAVE_SYS_GETTID */ #if APR_HAS_THREADS if (ap_mpm_query(AP_MPMQ_IS_THREADED, &result) == APR_SUCCESS && result != AP_MPMQ_NOT_SUPPORTED) @@ -652,14 +656,32 @@ static int log_ctime(const ap_errorlog_info *info, const char *arg, int time_len = buflen; int option = AP_CTIME_OPTION_NONE; - while (arg && *arg) { - switch (*arg) { - case 'u': option |= AP_CTIME_OPTION_USEC; - break; - case 'c': option |= AP_CTIME_OPTION_COMPACT; - break; + if (arg) { + if (arg[0] == 'u' && !arg[1]) { /* no ErrorLogFormat (fast path) */ + option |= AP_CTIME_OPTION_USEC; + } + else if (!ap_strchr_c(arg, '%')) { /* special "%{cuz}t" formats */ + while (*arg) { + switch (*arg++) { + case 'u': + option |= AP_CTIME_OPTION_USEC; + break; + case 'c': + option |= AP_CTIME_OPTION_COMPACT; + break; + case 'z': + option |= AP_CTIME_OPTION_GMTOFF; + break; + } + } + } + else { /* "%{strftime %-format}t" */ + apr_size_t len = 0; + apr_time_exp_t expt; + ap_explode_recent_localtime(&expt, apr_time_now()); + apr_strftime(buf, &len, buflen, arg, &expt); + return (int)len; } - arg++; } ap_recent_ctime_ex(buf, apr_time_now(), option, &time_len); @@ -1166,6 +1188,11 @@ static void log_error_core(const char *file, int line, int module_index, #endif logf = stderr_log; + + /* Use the main ErrorLogFormat if any */ + if (ap_server_conf) { + sconf = ap_get_core_module_config(ap_server_conf->module_config); + } } else { int configured_level = r ? ap_get_request_module_loglevel(r, module_index) : @@ -1219,6 +1246,10 @@ static void log_error_core(const char *file, int line, int module_index, } } } + else if (ap_server_conf) { + /* Use the main ErrorLogFormat if any */ + sconf = ap_get_core_module_config(ap_server_conf->module_config); + } } info.s = s; diff --git a/server/main.c b/server/main.c index 7da7aa2..fb23f01 100644 --- a/server/main.c +++ b/server/main.c @@ -678,8 +678,8 @@ int main(int argc, const char * const argv[]) if (temp_error_log) { ap_replace_stderr_log(process->pool, temp_error_log); } - ap_server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); - if (!ap_server_conf) { + ap_server_conf = NULL; /* set early by ap_read_config() for logging */ + if (!ap_read_config(process, ptemp, confname, &ap_conftree)) { if (showcompile) { /* Well, we tried. Show as much as we can, but exit nonzero to * indicate that something's not right. The cause should have @@ -688,6 +688,7 @@ int main(int argc, const char * const argv[]) } destroy_and_exit_process(process, 1); } + ap_assert(ap_server_conf != NULL); apr_pool_cleanup_register(pconf, &ap_server_conf, ap_pool_cleanup_set_null, apr_pool_cleanup_null); @@ -785,10 +786,11 @@ int main(int argc, const char * const argv[]) apr_pool_create(&ptemp, pconf); apr_pool_tag(ptemp, "ptemp"); ap_server_root = def_server_root; - ap_server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); - if (!ap_server_conf) { + ap_server_conf = NULL; /* set early by ap_read_config() for logging */ + if (!ap_read_config(process, ptemp, confname, &ap_conftree)) { destroy_and_exit_process(process, 1); } + ap_assert(ap_server_conf != NULL); apr_pool_cleanup_register(pconf, &ap_server_conf, ap_pool_cleanup_set_null, apr_pool_cleanup_null); /* sort hooks here to make sure pre_config hooks are sorted properly */ diff --git a/server/mpm_unix.c b/server/mpm_unix.c index 8c4d233..ed4555a 100644 --- a/server/mpm_unix.c +++ b/server/mpm_unix.c @@ -259,10 +259,12 @@ AP_DECLARE(void) ap_reclaim_child_processes(int terminate, while (cur_extra) { ap_generation_t old_gen; extra_process_t *next = cur_extra->next; + pid_t pid = cur_extra->pid; - if (reclaim_one_pid(cur_extra->pid, action_table[cur_action].action)) { - if (ap_unregister_extra_mpm_process(cur_extra->pid, &old_gen) == 1) { - mpm_callback(-1, cur_extra->pid, old_gen); + if (reclaim_one_pid(pid, action_table[cur_action].action)) { + if (ap_unregister_extra_mpm_process(pid, &old_gen) == 1) { + /* cur_extra dangling pointer from here. */ + mpm_callback(-1, pid, old_gen); } else { AP_DEBUG_ASSERT(1 == 0); @@ -307,10 +309,12 @@ AP_DECLARE(void) ap_relieve_child_processes(ap_reclaim_callback_fn_t *mpm_callba while (cur_extra) { ap_generation_t old_gen; extra_process_t *next = cur_extra->next; + pid_t pid = cur_extra->pid; - if (reclaim_one_pid(cur_extra->pid, DO_NOTHING)) { - if (ap_unregister_extra_mpm_process(cur_extra->pid, &old_gen) == 1) { - mpm_callback(-1, cur_extra->pid, old_gen); + if (reclaim_one_pid(pid, DO_NOTHING)) { + if (ap_unregister_extra_mpm_process(pid, &old_gen) == 1) { + /* cur_extra dangling pointer from here. */ + mpm_callback(-1, pid, old_gen); } else { AP_DEBUG_ASSERT(1 == 0); diff --git a/server/scoreboard.c b/server/scoreboard.c index 12dd56a..49d1600 100644 --- a/server/scoreboard.c +++ b/server/scoreboard.c @@ -653,7 +653,7 @@ AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status) } } -AP_DECLARE(int) ap_update_global_status() +AP_DECLARE(int) ap_update_global_status(void) { #ifdef HAVE_TIMES if (ap_scoreboard_image == NULL) { @@ -707,7 +707,7 @@ AP_DECLARE(process_score *) ap_get_scoreboard_process(int x) return &ap_scoreboard_image->parent[x]; } -AP_DECLARE(global_score *) ap_get_scoreboard_global() +AP_DECLARE(global_score *) ap_get_scoreboard_global(void) { return ap_scoreboard_image->global; } diff --git a/server/util.c b/server/util.c index 2015e43..45502b8 100644 --- a/server/util.c +++ b/server/util.c @@ -502,6 +502,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags) int ret = 1; apr_size_t l = 1, w = 1, n; int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0; + int merge_slashes = (flags & AP_NORMALIZE_MERGE_SLASHES) != 0; if (!IS_SLASH(path[0])) { /* Besides "OPTIONS *", a request-target should start with '/' @@ -546,7 +547,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags) if (w == 0 || IS_SLASH(path[w - 1])) { /* Collapse ///// sequences to / */ - if ((flags & AP_NORMALIZE_MERGE_SLASHES) && IS_SLASH(path[l])) { + if (merge_slashes && IS_SLASH(path[l])) { do { l++; } while (IS_SLASH(path[l])); @@ -3143,7 +3144,7 @@ AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb, static const char * const oom_message = "[crit] Memory allocation failed, " "aborting process." APR_EOL_STR; -AP_DECLARE(void) ap_abort_on_oom() +AP_DECLARE(void) ap_abort_on_oom(void) { int written, count = strlen(oom_message); const char *buf = oom_message; diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c index 7d6ae1e..db4be95 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -1271,7 +1271,7 @@ static int op_file_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *a APR_DECLARE_OPTIONAL_FN(int, http2_is_h2, (conn_rec *)); static APR_OPTIONAL_FN_TYPE(http2_is_h2) *is_http2 = NULL; -static const char *conn_var_names[] = { +static const char *const conn_var_names[] = { "HTTPS", /* 0 */ "IPV6", /* 1 */ "CONN_LOG_ID", /* 2 */ @@ -1321,7 +1321,7 @@ static const char *conn_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) } } -static const char *request_var_names[] = { +static const char *const request_var_names[] = { "REQUEST_METHOD", /* 0 */ "REQUEST_SCHEME", /* 1 */ "REQUEST_URI", /* 2 */ @@ -1449,7 +1449,7 @@ static const char *request_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) } } -static const char *req_header_var_names[] = { +static const char *const req_header_var_names[] = { "HTTP_USER_AGENT", /* 0 */ "HTTP_PROXY_CONNECTION", /* 1 */ "HTTP_REFERER", /* 2 */ @@ -1460,7 +1460,7 @@ static const char *req_header_var_names[] = { NULL }; -static const char *req_header_header_names[] = { +static const char *const req_header_header_names[] = { "User-Agent", "Proxy-Connection", "Referer", @@ -1472,7 +1472,7 @@ static const char *req_header_header_names[] = { static const char *req_header_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) { - const char **varname = (const char **)data; + const char **const varname = (const char **)data; int index = (varname - req_header_var_names); const char *name; @@ -1490,7 +1490,7 @@ static const char *req_header_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) return apr_table_get(ctx->r->headers_in, name); } -static const char *misc_var_names[] = { +static const char *const misc_var_names[] = { "TIME_YEAR", /* 0 */ "TIME_MON", /* 1 */ "TIME_DAY", /* 2 */ @@ -1647,7 +1647,7 @@ struct expr_provider_single { struct expr_provider_multi { const void *func; - const char **names; + const char *const *names; }; static const struct expr_provider_multi var_providers[] = { @@ -1716,7 +1716,7 @@ static int core_expr_lookup(ap_expr_lookup_parms *parms) case AP_EXPR_FUNC_VAR: { const struct expr_provider_multi *prov = var_providers; while (prov->func) { - const char **name = prov->names; + const char *const *name = prov->names; while (*name) { if (ap_cstr_casecmp(*name, parms->name) == 0) { *parms->func = prov->func; diff --git a/server/util_expr_parse.c b/server/util_expr_parse.c index bcf0173..ac4a323 100644 --- a/server/util_expr_parse.c +++ b/server/util_expr_parse.c @@ -1326,6 +1326,8 @@ YYSTYPE yylval; goto yysetstate; + /* TODO: comppiler warning that this is unused, and it seems to */ + (void)yynerrs; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ diff --git a/server/util_script.c b/server/util_script.c index 45c49d5..1fa4276 100644 --- a/server/util_script.c +++ b/server/util_script.c @@ -92,9 +92,21 @@ static void add_unless_null(apr_table_t *table, const char *name, const char *va } } -static void env2env(apr_table_t *table, const char *name) +/* Sets variable @name in table @dest from r->subprocess_env if + * available, else from the environment, else from @fallback if + * non-NULL. */ +static void env2env(apr_table_t *dest, request_rec *r, + const char *name, const char *fallback) { - add_unless_null(table, name, getenv(name)); + const char *val; + + val = apr_table_get(r->subprocess_env, name); + if (!val) + val = apr_pstrdup(r->pool, getenv(name)); + if (!val) + val = apr_pstrdup(r->pool, fallback); + if (val) + apr_table_addn(dest, name, val); } AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t) @@ -211,37 +223,29 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r) add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } - env_temp = apr_table_get(r->subprocess_env, "PATH"); - if (env_temp == NULL) { - env_temp = getenv("PATH"); - } - if (env_temp == NULL) { - env_temp = DEFAULT_PATH; - } - apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp)); - + env2env(e, r, "PATH", DEFAULT_PATH); #if defined(WIN32) - env2env(e, "SystemRoot"); - env2env(e, "COMSPEC"); - env2env(e, "PATHEXT"); - env2env(e, "WINDIR"); + env2env(e, r, "SystemRoot", NULL); + env2env(e, r, "COMSPEC", NULL); + env2env(e, r, "PATHEXT", NULL); + env2env(e, r, "WINDIR", NULL); #elif defined(OS2) - env2env(e, "COMSPEC"); - env2env(e, "ETC"); - env2env(e, "DPATH"); - env2env(e, "PERLLIB_PREFIX"); + env2env(e, r, "COMSPEC", NULL); + env2env(e, r, "ETC", NULL); + env2env(e, r, "DPATH", NULL); + env2env(e, r, "PERLLIB_PREFIX", NULL); #elif defined(BEOS) - env2env(e, "LIBRARY_PATH"); + env2env(e, r, "LIBRARY_PATH", NULL); #elif defined(DARWIN) - env2env(e, "DYLD_LIBRARY_PATH"); + env2env(e, r, "DYLD_LIBRARY_PATH", NULL); #elif defined(_AIX) - env2env(e, "LIBPATH"); + env2env(e, r, "LIBPATH", NULL); #elif defined(__HPUX__) /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */ - env2env(e, "SHLIB_PATH"); - env2env(e, "LD_LIBRARY_PATH"); + env2env(e, r, "SHLIB_PATH", NULL); + env2env(e, r, "LD_LIBRARY_PATH", NULL); #else /* Some Unix */ - env2env(e, "LD_LIBRARY_PATH"); + env2env(e, r, "LD_LIBRARY_PATH", NULL); #endif apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); diff --git a/server/util_time.c b/server/util_time.c index 3632d0d..299b53c 100644 --- a/server/util_time.c +++ b/server/util_time.c @@ -22,9 +22,11 @@ * */ #define AP_CTIME_USEC_LENGTH 7 -/* Length of ISO 8601 date/time */ +/* Length of ISO 8601 date/time (including trailing '\0') */ #define AP_CTIME_COMPACT_LEN 20 +/* Length of timezone offset from GMT ([+-]hhmm) plus leading space */ +#define AP_CTIME_GMTOFF_LEN 6 /* Cache for exploded values of recent timestamps */ @@ -181,7 +183,13 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, needed += AP_CTIME_USEC_LENGTH; } - /* Check the provided buffer length */ + if (option & AP_CTIME_OPTION_GMTOFF) { + needed += AP_CTIME_GMTOFF_LEN; + } + + /* Check the provided buffer length (note: above AP_CTIME_COMPACT_LEN + * and APR_CTIME_LEN include the trailing '\0'; so does 'needed' then). + */ if (len && *len >= needed) { *len = needed; } @@ -193,9 +201,10 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, } /* example without options: "Wed Jun 30 21:49:08 1993" */ - /* 123456789012345678901234 */ /* example for compact format: "1993-06-30 21:49:08" */ - /* 1234567890123456789 */ + /* example for compact+usec+gmtoff format: + * "1993-06-30 22:49:08.123456 +0100" + */ ap_explode_recent_localtime(&xt, t); real_year = 1900 + xt.tm_year; @@ -249,7 +258,23 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, *date_str++ = real_year % 100 / 10 + '0'; *date_str++ = real_year % 10 + '0'; } - *date_str++ = 0; + if (option & AP_CTIME_OPTION_GMTOFF) { + int off = xt.tm_gmtoff, off_hh, off_mm; + char sign = '+'; + if (off < 0) { + off = -off; + sign = '-'; + } + off_hh = off / 3600; + off_mm = off % 3600 / 60; + *date_str++ = ' '; + *date_str++ = sign; + *date_str++ = off_hh / 10 + '0'; + *date_str++ = off_hh % 10 + '0'; + *date_str++ = off_mm / 10 + '0'; + *date_str++ = off_mm % 10 + '0'; + } + *date_str = 0; return APR_SUCCESS; } -- cgit v1.2.3