changeset 1069:e6fc18f1a032

env
author Igor Sysoev <igor@sysoev.ru>
date Sat, 20 Jan 2007 19:26:48 +0000
parents b88395feb707
children b54a1e283d6d
files src/core/nginx.c src/core/ngx_cycle.h src/http/modules/perl/ngx_http_perl_module.c src/os/unix/ngx_process_cycle.c
diffstat 4 files changed, 217 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -16,6 +16,7 @@ static ngx_int_t ngx_save_argv(ngx_cycle
 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -128,6 +129,13 @@ static ngx_command_t  ngx_core_commands[
       offsetof(ngx_core_conf_t, working_directory),
       NULL },
 
+    { ngx_string("env"),
+      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
+      ngx_set_env,
+      0,
+      0,
+      NULL },
+
 #if (NGX_THREADS)
 
     { ngx_string("worker_threads"),
@@ -178,7 +186,7 @@ ngx_uint_t  ngx_max_module;
 static ngx_uint_t  ngx_show_version;
 static ngx_uint_t  ngx_show_configure;
 
-static char  *ngx_null_environ = NULL;
+static char **ngx_os_environ;
 
 
 int ngx_cdecl
@@ -275,8 +283,6 @@ main(int argc, char *const *argv)
         return 1;
     }
 
-    environ = &ngx_null_environ;
-
     ngx_max_module = 0;
     for (i = 0; ngx_modules[i]; i++) {
         ngx_modules[i]->index = ngx_max_module++;
@@ -407,21 +413,128 @@ ngx_add_inherited_sockets(ngx_cycle_t *c
 }
 
 
+char **
+ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
+{
+    char             **p, **env;
+    ngx_str_t         *var;
+    ngx_uint_t         i, n;
+    ngx_core_conf_t   *ccf;
+
+    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
+
+    if (last) {
+        n = *last;
+
+    } else {
+        if (ccf->environment) {
+            return ccf->environment;
+        }
+
+        n = 0;
+    }
+
+    var = ccf->env.elts;
+
+    for (i = 0; i < ccf->env.nelts; i++) {
+        if (ngx_strcmp(var[i].data, "TZ") == 0
+            || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
+        {
+            goto tz_found;
+        }
+    }
+
+    var = ngx_array_push(&ccf->env);
+
+    var->len = 2;
+    var->data = (u_char *) "TZ";
+
+    var = ccf->env.elts;
+
+tz_found:
+
+    for (i = 0; i < ccf->env.nelts; i++) {
+
+        if (var[i].data[var[i].len] == '=') {
+            n++;
+            continue;
+        }
+
+        for (p = ngx_os_environ; *p; p++) {
+
+            if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
+                && (*p)[var[i].len] == '=')
+            {
+                n++;
+                break;
+            }
+        }
+    }
+
+    if (last) {
+        *last = n;
+        env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
+
+    } else {
+        env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
+    }
+
+    if (env == NULL) {
+        return NULL;
+    }
+
+    n = 0;
+
+    for (i = 0; i < ccf->env.nelts; i++) {
+
+        if (var[i].data[var[i].len] == '=') {
+            env[n++] = (char *) var[i].data;
+            continue;
+        }
+
+        for (p = ngx_os_environ; *p; p++) {
+
+            if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
+                && (*p)[var[i].len] == '=')
+            {
+                env[n++] = *p;
+                break;
+            }
+        }
+    }
+
+    env[n] = NULL;
+
+    if (last == NULL) {
+        ccf->environment = env;
+        environ = env;
+    }
+
+    return env;
+}
+
+
 ngx_pid_t
 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
 {
-    char             *env[3], *var;
-    u_char           *p;
-    ngx_uint_t        i;
-    ngx_pid_t         pid;
-    ngx_exec_ctx_t    ctx;
-    ngx_core_conf_t  *ccf;
-    ngx_listening_t  *ls;
+    char             **env, *var;
+    u_char            *p;
+    ngx_uint_t         i, n;
+    ngx_pid_t          pid;
+    ngx_exec_ctx_t     ctx;
+    ngx_core_conf_t   *ccf;
+    ngx_listening_t   *ls;
 
     ctx.path = argv[0];
     ctx.name = "new binary process";
     ctx.argv = argv;
 
+    n = 2;
+    env = ngx_set_environment(cycle, &n);
+    if (env == NULL) {
+        return NGX_INVALID_PID;
+    }
+
     var = ngx_alloc(sizeof(NGINX_VAR)
                     + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
                     cycle->log);
@@ -435,40 +548,42 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, 
 
     *p = '\0';
 
-    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "inherited: %s", var);
-
-    env[0] = var;
+    env[n++] = var;
 
 #if (NGX_SETPROCTITLE_USES_ENV)
 
     /* allocate the spare 300 bytes for the new binary process title */
 
-    env[1] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
-
-    env[2] = NULL;
-
-#else
-
-    env[1] = NULL;
+    env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 
 #endif
 
-    ctx.envp = (char *const *) &env;
+    env[n] = NULL;
+
+#if (NGX_DEBUG)
+    {
+    char  **e;
+    for (e = env; *e; e++) {
+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
+    }
+    }
+#endif
+
+    ctx.envp = (char *const *) env;
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
-    if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data)
-        != NGX_OK)
-    {
+    if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) {
         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                       ngx_rename_file_n " %s to %s failed "
                       "before executing new binary process \"%s\"",
                       ccf->pid.data, ccf->oldpid.data, argv[0]);
 
+        ngx_free(env);
         ngx_free(var);
 
         return NGX_INVALID_PID;
@@ -477,16 +592,15 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, 
     pid = ngx_execute(cycle, &ctx);
 
     if (pid == NGX_INVALID_PID) {
-        if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
-            != NGX_OK)
-        {
+        if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
-                          ngx_rename_file_n " %s back to %s failed "
-                          "after try to executing new binary process \"%s\"",
+                          ngx_rename_file_n " %s back to %s failed after "
+                          "the try to execute the new binary process \"%s\"",
                           ccf->oldpid.data, ccf->pid.data, argv[0]);
         }
     }
 
+    ngx_free(env);
     ngx_free(var);
 
     return pid;
@@ -588,6 +702,8 @@ ngx_save_argv(ngx_cycle_t *cycle, int ar
 
 #endif
 
+    ngx_os_environ = environ;
+
     return NGX_OK;
 }
 
@@ -631,6 +747,12 @@ ngx_core_module_create_conf(ngx_cycle_t 
     ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;
 #endif
 
+    if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
+        != NGX_OK)
+    {
+        return NULL;
+    }
+
     return ccf;
 }
 
@@ -641,9 +763,9 @@ ngx_core_module_init_conf(ngx_cycle_t *c
     ngx_core_conf_t  *ccf = conf;
 
 #if !(NGX_WIN32)
-    ngx_str_t         lock_file;
-    struct passwd    *pwd;
-    struct group     *grp;
+    ngx_str_t       lock_file;
+    struct group   *grp;
+    struct passwd  *pwd;
 #endif
 
     ngx_conf_init_value(ccf->daemon, 1);
@@ -830,6 +952,36 @@ ngx_set_user(ngx_conf_t *cf, ngx_command
 
 
 static char *
+ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_core_conf_t  *ccf = conf;
+
+    ngx_str_t   *value, *var;
+    ngx_uint_t   i;
+
+    var = ngx_array_push(&ccf->env);
+    if (var == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+    *var = value[1];
+
+    for (i = 0; i < value[1].len; i++) {
+
+        if (value[1].data[i] == '=') {
+
+            var->len = i;
+
+            return NGX_CONF_OK;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
 ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_core_conf_t  *ccf = conf;
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -93,6 +93,9 @@ typedef struct {
      ngx_str_t                pid;
      ngx_str_t                oldpid;
 
+     ngx_array_t              env;
+     char                   **environment;
+
 #if (NGX_THREADS)
      ngx_int_t                worker_threads;
      size_t                   thread_stack_size;
@@ -113,6 +116,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log);
 void ngx_delete_pidfile(ngx_cycle_t *cycle);
 void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user);
+char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last);
 ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
 u_long ngx_get_cpu_affinity(ngx_uint_t n);
 ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -44,9 +44,8 @@ static ngx_int_t ngx_http_perl_ssi(ngx_h
 static void ngx_http_perl_sleep_handler(ngx_http_request_t *r);
 static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
     ngx_http_perl_main_conf_t *pmcf);
-static PerlInterpreter *
-    ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
-    ngx_log_t *log);
+static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
+    ngx_http_perl_main_conf_t *pmcf);
 static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
     ngx_log_t *log);
 static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
@@ -475,7 +474,7 @@ ngx_http_perl_init_interpreter(ngx_conf_
 
     PERL_SYS_INIT(&ngx_argc, &ngx_argv);
 
-    pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log);
+    pmcf->perl = ngx_http_perl_create_interpreter(cf, pmcf);
 
     if (pmcf->perl == NULL) {
         PERL_SYS_TERM();
@@ -500,8 +499,8 @@ ngx_http_perl_init_interpreter(ngx_conf_
 
 
 static PerlInterpreter *
-ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
-    ngx_log_t *log)
+ngx_http_perl_create_interpreter(ngx_conf_t *cf,
+    ngx_http_perl_main_conf_t *pmcf)
 {
     int                n;
     STRLEN             len;
@@ -509,11 +508,15 @@ ngx_http_perl_create_interpreter(ngx_htt
     char              *ver, *embedding[6];
     PerlInterpreter   *perl;
 
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter");
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter");
+
+    if (ngx_set_environment(cf->cycle, NULL) == NULL) {
+        return NULL;
+    }
 
     perl = perl_alloc();
     if (perl == NULL) {
-        ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed");
+        ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_alloc() failed");
         return NULL;
     }
 
@@ -546,7 +549,7 @@ ngx_http_perl_create_interpreter(ngx_htt
     n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL);
 
     if (n != 0) {
-        ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_parse() failed: %d", n);
+        ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_parse() failed: %d", n);
         goto fail;
     }
 
@@ -554,13 +557,13 @@ ngx_http_perl_create_interpreter(ngx_htt
     ver = SvPV(sv, len);
 
     if (ngx_strcmp(ver, NGINX_VERSION) != 0) {
-        ngx_log_error(NGX_LOG_ALERT, log, 0,
+        ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
                       "version " NGINX_VERSION " of nginx.pm is required, "
                       "but %s was found", ver);
         goto fail;
     }
 
-    if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) {
+    if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) {
         goto fail;
     }
 
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -757,15 +757,20 @@ ngx_worker_process_cycle(ngx_cycle_t *cy
 static void
 ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
 {
-    sigset_t           set;
-    ngx_int_t          n;
-    ngx_uint_t         i;
-    struct rlimit      rlmt;
-    ngx_core_conf_t   *ccf;
-    ngx_listening_t   *ls;
+    sigset_t          set;
+    ngx_int_t         n;
+    ngx_uint_t        i;
+    struct rlimit     rlmt;
+    ngx_core_conf_t  *ccf;
+    ngx_listening_t  *ls;
 
     ngx_process = NGX_PROCESS_WORKER;
 
+    if (ngx_set_environment(cycle, NULL) == NULL) {
+        /* fatal */
+        exit(2);
+    }
+
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
     if (geteuid() == 0) {