Core: "-e" command line option.

When installing or running from a non-root user it is sometimes required to
override default, compiled in error log path. There was no way to do this
without rebuilding the binary (ticket #147).

This patch introduced "-e" command line option which allows one to override
compiled in error log path.
diff --git a/auto/configure b/auto/configure
index 7e6e33a..474d69e 100755
--- a/auto/configure
+++ b/auto/configure
@@ -87,6 +87,10 @@
 have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define
 have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define
 
+if [ ".$NGX_ERROR_LOG_PATH" = "." ]; then
+    have=NGX_ERROR_LOG_STDERR . auto/have
+fi
+
 have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" . auto/define
 have=NGX_HTTP_CLIENT_TEMP_PATH value="\"$NGX_HTTP_CLIENT_TEMP_PATH\""
 . auto/define
diff --git a/docs/man/nginx.8 b/docs/man/nginx.8
index 573d935..f2ed9f7 100644
--- a/docs/man/nginx.8
+++ b/docs/man/nginx.8
@@ -25,7 +25,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"
-.Dd December 5, 2019
+.Dd November 5, 2020
 .Dt NGINX 8
 .Os
 .Sh NAME
@@ -35,6 +35,7 @@
 .Nm
 .Op Fl ?hqTtVv
 .Op Fl c Ar file
+.Op Fl e Ar file
 .Op Fl g Ar directives
 .Op Fl p Ar prefix
 .Op Fl s Ar signal
@@ -54,6 +55,12 @@
 .It Fl c Ar file
 Use an alternative configuration
 .Ar file .
+.It Fl e Ar file
+Use an alternative error log
+.Ar file .
+Special value
+.Cm stderr
+indicates that the standard error output should be used.
 .It Fl g Ar directives
 Set global configuration directives.
 See
diff --git a/src/core/nginx.c b/src/core/nginx.c
index f73e559..48a20e9 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -183,6 +183,7 @@
 static ngx_uint_t   ngx_show_version;
 static ngx_uint_t   ngx_show_configure;
 static u_char      *ngx_prefix;
+static u_char      *ngx_error_log;
 static u_char      *ngx_conf_file;
 static u_char      *ngx_conf_params;
 static char        *ngx_signal;
@@ -230,7 +231,7 @@
     ngx_pid = ngx_getpid();
     ngx_parent = ngx_getppid();
 
-    log = ngx_log_init(ngx_prefix);
+    log = ngx_log_init(ngx_prefix, ngx_error_log);
     if (log == NULL) {
         return 1;
     }
@@ -393,9 +394,9 @@
 
     if (ngx_show_help) {
         ngx_write_stderr(
-            "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
-                         "[-p prefix] [-g directives]" NGX_LINEFEED
-                         NGX_LINEFEED
+            "Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]" NGX_LINEFEED
+            "             [-e filename] [-c filename] [-g directives]"
+                          NGX_LINEFEED NGX_LINEFEED
             "Options:" NGX_LINEFEED
             "  -?,-h         : this help" NGX_LINEFEED
             "  -v            : show version and exit" NGX_LINEFEED
@@ -414,6 +415,12 @@
 #else
             "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
 #endif
+            "  -e filename   : set error log file (default: "
+#ifdef NGX_ERROR_LOG_STDERR
+                               "stderr)" NGX_LINEFEED
+#else
+                               NGX_ERROR_LOG_PATH ")" NGX_LINEFEED
+#endif
             "  -c filename   : set configuration file (default: " NGX_CONF_PATH
                                ")" NGX_LINEFEED
             "  -g directives : set global directives out of configuration "
@@ -800,6 +807,24 @@
                 ngx_log_stderr(0, "option \"-p\" requires directory name");
                 return NGX_ERROR;
 
+            case 'e':
+                if (*p) {
+                    ngx_error_log = p;
+
+                } else if (argv[++i]) {
+                    ngx_error_log = (u_char *) argv[i];
+
+                } else {
+                    ngx_log_stderr(0, "option \"-e\" requires file name");
+                    return NGX_ERROR;
+                }
+
+                if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
+                    ngx_error_log = (u_char *) "";
+                }
+
+                goto next;
+
             case 'c':
                 if (*p) {
                     ngx_conf_file = p;
@@ -992,6 +1017,14 @@
         }
     }
 
+    if (ngx_error_log) {
+        cycle->error_log.len = ngx_strlen(ngx_error_log);
+        cycle->error_log.data = ngx_error_log;
+
+    } else {
+        ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
+    }
+
     if (ngx_conf_params) {
         cycle->conf_param.len = ngx_strlen(ngx_conf_params);
         cycle->conf_param.data = ngx_conf_params;
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index d7479fa..6978c3e 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -96,6 +96,15 @@
         return NULL;
     }
 
+    cycle->error_log.len = old_cycle->error_log.len;
+    cycle->error_log.data = ngx_pnalloc(pool, old_cycle->error_log.len + 1);
+    if (cycle->error_log.data == NULL) {
+        ngx_destroy_pool(pool);
+        return NULL;
+    }
+    ngx_cpystrn(cycle->error_log.data, old_cycle->error_log.data,
+                old_cycle->error_log.len + 1);
+
     cycle->conf_file.len = old_cycle->conf_file.len;
     cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
     if (cycle->conf_file.data == NULL) {
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index 0f7d9bc..0c47f25 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -80,6 +80,7 @@
     ngx_str_t                 conf_param;
     ngx_str_t                 conf_prefix;
     ngx_str_t                 prefix;
+    ngx_str_t                 error_log;
     ngx_str_t                 lock_file;
     ngx_str_t                 hostname;
 };
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index 8e9408d..0c09426 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -315,7 +315,7 @@
 
 
 ngx_log_t *
-ngx_log_init(u_char *prefix)
+ngx_log_init(u_char *prefix, u_char *error_log)
 {
     u_char  *p, *name;
     size_t   nlen, plen;
@@ -323,13 +323,11 @@
     ngx_log.file = &ngx_log_file;
     ngx_log.log_level = NGX_LOG_NOTICE;
 
-    name = (u_char *) NGX_ERROR_LOG_PATH;
+    if (error_log == NULL) {
+        error_log = (u_char *) NGX_ERROR_LOG_PATH;
+    }
 
-    /*
-     * we use ngx_strlen() here since BCC warns about
-     * condition is always false and unreachable code
-     */
-
+    name = error_log;
     nlen = ngx_strlen(name);
 
     if (nlen == 0) {
@@ -369,7 +367,7 @@
                 *p++ = '/';
             }
 
-            ngx_cpystrn(p, (u_char *) NGX_ERROR_LOG_PATH, nlen + 1);
+            ngx_cpystrn(p, error_log, nlen + 1);
 
             p = name;
         }
@@ -403,8 +401,7 @@
 ngx_int_t
 ngx_log_open_default(ngx_cycle_t *cycle)
 {
-    ngx_log_t         *log;
-    static ngx_str_t   error_log = ngx_string(NGX_ERROR_LOG_PATH);
+    ngx_log_t  *log;
 
     if (ngx_log_get_file_log(&cycle->new_log) != NULL) {
         return NGX_OK;
@@ -425,7 +422,7 @@
 
     log->log_level = NGX_LOG_ERR;
 
-    log->file = ngx_conf_open_file(cycle, &error_log);
+    log->file = ngx_conf_open_file(cycle, &cycle->error_log);
     if (log->file == NULL) {
         return NGX_ERROR;
     }
diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h
index afb73bf..ab64a5a 100644
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -228,7 +228,7 @@
 
 /*********************************/
 
-ngx_log_t *ngx_log_init(u_char *prefix);
+ngx_log_t *ngx_log_init(u_char *prefix, u_char *error_log);
 void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
 void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
 u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);