nginx-0.1.14-RELEASE import

    *) Feature: the autoconfiguration directives:
       --http-client-body-temp-path=PATH, --http-proxy-temp-path=PATH, and
       --http-fastcgi-temp-path=PATH

    *) Change: the directory name for the temporary files with the client
       request body is specified by directive client_body_temp_path, by
       default it is <prefix>/client_body_temp.

    *) Feature: the ngx_http_fastcgi_module and the directives:
       fastcgi_pass, fastcgi_root, fastcgi_index, fastcgi_params,
       fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout,
       fastcgi_send_lowat, fastcgi_header_buffer_size, fastcgi_buffers,
       fastcgi_busy_buffers_size, fastcgi_temp_path,
       fastcgi_max_temp_file_size, fastcgi_temp_file_write_size,
       fastcgi_next_upstream, and fastcgi_x_powered_by.

    *) Bugfix: the "[alert] zero size buf" error; the bug had appeared in
       0.1.3.

    *) Change: the URI must be specified after the host name in the
       proxy_pass directive.

    *) Change: the %3F symbol in the URI was considered as the argument
       string start.

    *) Feature: the unix domain sockets support in the
       ngx_http_proxy_module.

    *) Feature: the ssl_engine and ssl_ciphers directives.
       Thanks to Sergey Skvortsov for SSL-accelerator.
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 26406b3..68da2ba 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -451,12 +451,15 @@
     if (!(ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)))) {
         return NULL;
     }
-    /* set by pcalloc()
+
+    /*
+     * set by pcalloc()
      *
-     * ccf->pid = NULL;
-     * ccf->newpid = NULL;
-     * ccf->priority = 0;
+     *     ccf->pid = NULL;
+     *     ccf->newpid = NULL;
+     *     ccf->priority = 0;
      */
+
     ccf->daemon = NGX_CONF_UNSET;
     ccf->master = NGX_CONF_UNSET;
     ccf->worker_processes = NGX_CONF_UNSET;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 3286519..4b98cda 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.13"
+#define NGINX_VER          "nginx/0.1.14"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index 768400d..fbfd394 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -69,7 +69,7 @@
 } ngx_bufs_t;
 
 
-typedef int  (*ngx_output_chain_filter_pt)(void *ctx, ngx_chain_t *out);
+typedef ngx_int_t (*ngx_output_chain_filter_pt)(void *ctx, ngx_chain_t *in);
 
 typedef struct {
     ngx_buf_t                   *buf;
@@ -141,7 +141,7 @@
 
 
 ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in);
-ngx_int_t ngx_chain_writer(void *data, ngx_chain_t *in);
+ngx_int_t ngx_chain_writer(void *ctx, ngx_chain_t *in);
 
 ngx_int_t ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain,
                              ngx_chain_t *in);
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 0e94056..8dcdd54 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -239,8 +239,8 @@
     }
 
 #define ngx_conf_merge_str_value(conf, prev, default)                        \
-    if (conf.len == 0) {                                                     \
-        if (prev.len) {                                                      \
+    if (conf.data == NULL) {                                                 \
+        if (prev.data) {                                                      \
             conf.len = prev.len;                                             \
             conf.data = prev.data;                                           \
         } else {                                                             \
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index cc9640c..64be1ec 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -18,7 +18,7 @@
 {
     size_t               len;
     ngx_listening_t     *ls;
-    struct sockaddr_in  *addr_in;
+    struct sockaddr_in  *sin;
 
     if (!(ls = ngx_array_push(&cf->cycle->listening))) {
         return NULL;
@@ -26,13 +26,13 @@
 
     ngx_memzero(ls, sizeof(ngx_listening_t));
 
-    if (!(addr_in = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+    if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
         return NULL;
     }
 
-    addr_in->sin_family = AF_INET;
-    addr_in->sin_addr.s_addr = addr;
-    addr_in->sin_port = htons(port);
+    sin->sin_family = AF_INET;
+    sin->sin_addr.s_addr = addr;
+    sin->sin_port = htons(port);
 
 
     ls->addr_text.data = ngx_palloc(cf->pool,
@@ -50,8 +50,7 @@
     ls->fd = (ngx_socket_t) -1;
     ls->family = AF_INET;
     ls->type = SOCK_STREAM;
-    ls->protocol = IPPROTO_IP;
-    ls->sockaddr = (struct sockaddr *) addr_in;
+    ls->sockaddr = (struct sockaddr *) sin;
     ls->socklen = sizeof(struct sockaddr_in);
     ls->addr = offsetof(struct sockaddr_in, sin_addr);
     ls->addr_text_max_len = INET_ADDRSTRLEN;
@@ -65,7 +64,7 @@
     size_t               len;
     ngx_uint_t           i;
     ngx_listening_t     *ls;
-    struct sockaddr_in  *addr_in;
+    struct sockaddr_in  *sin;
 
     ls = cycle->listening.elts;
     for (i = 0; i < cycle->listening.nelts; i++) {
@@ -86,9 +85,9 @@
             continue;
         }
 
-        addr_in = (struct sockaddr_in *) ls[i].sockaddr;
+        sin = (struct sockaddr_in *) ls[i].sockaddr;
 
-        if (addr_in->sin_family != AF_INET) {
+        if (sin->sin_family != AF_INET) {
             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
                           "the inherited socket #%d has "
                           "unsupported family", ls[i].fd);
@@ -105,7 +104,7 @@
             return NGX_ERROR;
         }
 
-        ls[i].family = addr_in->sin_family;
+        ls[i].family = sin->sin_family;
         len = ngx_sock_ntop(ls[i].family, ls[i].sockaddr,
                             ls[i].addr_text.data, INET_ADDRSTRLEN);
         if (len == 0) {
@@ -113,7 +112,7 @@
         }
 
         ls[i].addr_text.len = ngx_sprintf(ls[i].addr_text.data + len, ":%d",
-                                        ntohs(addr_in->sin_port))
+                                          ntohs(sin->sin_port))
                               - ls[i].addr_text.data;
     }
 
@@ -163,7 +162,7 @@
                 continue;
             }
 
-            s = ngx_socket(ls[i].family, ls[i].type, ls[i].protocol);
+            s = ngx_socket(ls[i].family, ls[i].type, 0);
 
             if (s == -1) {
                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
@@ -313,7 +312,7 @@
 {
     ngx_socket_t  fd;
 
-    if (c->pool == NULL) {
+    if (c->fd == -1) {
         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
         return;
     }
@@ -388,8 +387,6 @@
     c->fd = (ngx_socket_t) -1;
     c->data = NULL;
 
-    ngx_destroy_pool(c->pool);
-
     if (ngx_close_socket(fd) == -1) {
 
         /* we use ngx_cycle->log because c->log was in c->pool */
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 40f19a8..20589a5 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -23,7 +23,6 @@
 
     int               family;
     int               type;
-    int               protocol;
 
     void            (*handler)(ngx_connection_t *c); /* handler of accepted
                                                         connection */
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 79fb009..db43a44 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -18,6 +18,7 @@
 typedef struct ngx_command_s     ngx_command_t;
 typedef struct ngx_file_s        ngx_file_t;
 typedef struct ngx_event_s       ngx_event_t;
+typedef struct ngx_peers_s       ngx_peers_t;
 typedef struct ngx_connection_s  ngx_connection_t;
 
 typedef void (*ngx_event_handler_pt)(ngx_event_t *ev);
@@ -60,6 +61,9 @@
 #include <ngx_rbtree.h>
 #include <ngx_times.h>
 #include <ngx_inet.h>
+#if (NGX_HAVE_UNIX_DOMAIN)
+#include <ngx_unix_domain.h>
+#endif
 #include <ngx_cycle.h>
 #include <ngx_process_cycle.h>
 #include <ngx_conf_file.h>
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 9592a81..ad9049e 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -9,7 +9,7 @@
 #include <ngx_event.h>
 
 
-static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *s1, struct sockaddr *s2);
+static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
 static void ngx_clean_old_cycles(ngx_event_t *ev);
 
 
@@ -531,18 +531,18 @@
 }
 
 
-static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *s1, struct sockaddr *s2)
+static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2)
 {
     struct sockaddr_in  *sin1, *sin2;
 
     /* AF_INET only */
 
-    if (s1->sa_family != AF_INET || s2->sa_family != AF_INET) {
+    if (sa1->sa_family != AF_INET || sa2->sa_family != AF_INET) {
         return NGX_DECLINED;
     }
 
-    sin1 = (struct sockaddr_in *) s1;
-    sin2 = (struct sockaddr_in *) s2;
+    sin1 = (struct sockaddr_in *) sa1;
+    sin2 = (struct sockaddr_in *) sa2;
 
     if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
         return NGX_DECLINED;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 08d9aba..37983fe 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -193,7 +193,7 @@
     ssize_t      level;
     ngx_uint_t   i, n;
     ngx_str_t   *value;
-    ngx_path_t  *path, **pp, **slot;
+    ngx_path_t  *path, **slot;
 
     slot = (ngx_path_t **) (p + cmd->offset);
 
@@ -209,7 +209,7 @@
 
     path->name = value[1];
     path->len = 0;
-    path->gc_handler = (ngx_gc_handler_pt) cmd->post;
+    path->cleaner = (ngx_gc_handler_pt) cmd->post;
     path->conf_file = cf->conf_file->file.name.data;
     path->line = cf->conf_file->line;
 
@@ -227,42 +227,65 @@
         path->level[i++] = 0;
     }
 
+    *slot = path;
 
-    pp = cf->cycle->pathes.elts;
+    if (ngx_add_path(cf, slot) == NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
+{
+    ngx_uint_t   i, n;
+    ngx_path_t  *path, **p;
+
+    path = *slot;
+
+    p = cf->cycle->pathes.elts;
     for (i = 0; i < cf->cycle->pathes.nelts; i++) {
-        if (pp[i]->name.len == path->name.len
-            && ngx_strcmp(pp[i]->name.data, path->name.data) == 0)
+        if (p[i]->name.len == path->name.len
+            && ngx_strcmp(p[i]->name.data, path->name.data) == 0)
         {
             for (n = 0; n < 3; n++) {
-                if (pp[i]->level[n] != path->level[n]) {
+                if (p[i]->level[n] != path->level[n]) {
+                    if (path->conf_file == NULL) {
+                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                      "the path name \"%V\" in %s:%ui has "
+                                      "the same name as default path but "
+                                      "the different levels, you need to "
+                                      "define default path in http section",
+                                      &p[i]->name, p[i]->conf_file, p[i]->line);
+                        return NGX_ERROR;
+                    }
+
                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                   "the same \"%V\" path name in %s:%ui "
-                                   "has the different levels than",
-                                   &pp[i]->name, pp[i]->conf_file, pp[i]->line);
-                    return NGX_CONF_ERROR;
+                                      "the same path name \"%V\" in %s:%ui "
+                                      "has the different levels than",
+                                      &p[i]->name, p[i]->conf_file, p[i]->line);
+                    return NGX_ERROR;
                 }
 
-                if (pp[i]->level[n] == 0) {
+                if (p[i]->level[n] == 0) {
                     break;
                 }
             }
 
-            *slot = pp[i];
+            *slot = p[i];
 
-            return NGX_CONF_OK;
+            return NGX_OK;
         }
     }
 
-    *slot = path;
-
-
-    if (!(pp = ngx_array_push(&cf->cycle->pathes))) {
-        return NGX_CONF_ERROR;
+    if (!(p = ngx_array_push(&cf->cycle->pathes))) {
+        return NGX_ERROR;
     }
 
-    *pp = path;
+    *p = path;
 
-    return NGX_CONF_OK;
+    return NGX_OK;
 }
 
 
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index 94fd8c7..bc64ed8 100644
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -35,7 +35,7 @@
     ngx_str_t           name;
     ngx_uint_t          len;
     ngx_uint_t          level[3];
-    ngx_gc_handler_pt   gc_handler;
+    ngx_gc_handler_pt   cleaner;
 
     u_char             *conf_file;
     ngx_uint_t          line;
@@ -58,6 +58,7 @@
                                ngx_pool_t *pool, int persistent);
 void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path);
 ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
+ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
 ngx_int_t ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user);
 
 void ngx_init_temp_number();
@@ -66,19 +67,34 @@
 char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
-#define ngx_conf_merge_path_value(conf, prev, path, l1, l2, l3, pool)        \
-    if (conf == NULL) {                                                      \
-        if (prev == NULL) {                                                  \
-            ngx_test_null(conf, ngx_palloc(pool, sizeof(ngx_path_t)), NULL); \
-            conf->name.len = sizeof(path) - 1;                               \
-            conf->name.data = (u_char *) path;                               \
-            conf->level[0] = l1;                                             \
-            conf->level[1] = l2;                                             \
-            conf->level[2] = l3;                                             \
-            conf->len = l1 + l2 + l3 + (l1 ? 1:0) + (l2 ? 1:0) + (l3 ? 1:0); \
-        } else {                                                             \
-            conf = prev;                                                     \
-        }                                                                    \
+#define ngx_conf_merge_path_value(curr, prev, path, l1, l2, l3, clean, cf)    \
+    if (curr == NULL) {                                                       \
+        if (prev == NULL) {                                                   \
+            if (!(curr = ngx_palloc(cf->pool, sizeof(ngx_path_t)))) {         \
+                return NGX_CONF_ERROR;                                        \
+            }                                                                 \
+                                                                              \
+            curr->name.len = sizeof(path) - 1;                                \
+            curr->name.data = (u_char *) path;                                \
+                                                                              \
+            if (ngx_conf_full_name(cf->cycle, &curr->name) == NGX_ERROR) {    \
+                return NGX_CONF_ERROR;                                        \
+            }                                                                 \
+                                                                              \
+            curr->level[0] = l1;                                              \
+            curr->level[1] = l2;                                              \
+            curr->level[2] = l3;                                              \
+            curr->len = l1 + l2 + l3 + (l1 ? 1:0) + (l2 ? 1:0) + (l3 ? 1:0);  \
+            curr->cleaner = clean;                                            \
+            curr->conf_file = NULL;                                           \
+                                                                              \
+            if (ngx_add_path(cf, &curr) == NGX_ERROR) {                       \
+                return NGX_CONF_ERROR;                                        \
+            }                                                                 \
+                                                                              \
+        } else {                                                              \
+            curr = prev;                                                      \
+        }                                                                     \
     }
 
 
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 22a5334..56d2e98 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -4,9 +4,10 @@
  */
 
 
-
 #include <ngx_config.h>
 #include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_event_connect.h>
 
 
 /*
@@ -16,7 +17,7 @@
  * and they are faster by 1.5-2.5 times, so it is worth to keep them.
  *
  * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
- * than using FreeBSD libc's snrpintf().
+ * than using FreeBSD libc's snprintf().
  */
 
 
@@ -64,13 +65,13 @@
 
 /* AF_INET only */
 
-size_t ngx_sock_ntop(int family, struct sockaddr *addr, u_char *text,
+size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text,
                      size_t len)
 {
     u_char              *p;
     size_t               n;
     ngx_uint_t           i;
-    struct sockaddr_in  *addr_in;
+    struct sockaddr_in  *sin;
 
     if (len == 0) {
         return 0;
@@ -80,8 +81,8 @@
         return 0;
     }
 
-    addr_in = (struct sockaddr_in *) addr;
-    p = (u_char *) &addr_in->sin_addr;
+    sin = (struct sockaddr_in *) sa;
+    p = (u_char *) &sin->sin_addr;
 
     if (len > INET_ADDRSTRLEN) {
         len = INET_ADDRSTRLEN;
@@ -216,56 +217,259 @@
 }
 
 
-#if 0
-
-ngx_int_t ngx_inet_addr_port(ngx_conf_t *cf, ngx_command_t *cmd,
-                             ngx_str_t *addr_port)
+ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
 {
-    u_char          *host;
-    ngx_int_t        port;
-    ngx_uint_t       p;
-    struct hostent  *h;
+    char                *err;
+    u_char              *host;
+    in_addr_t            in_addr;
+    ngx_uint_t           i, len;
+    ngx_peers_t         *peers;
+    struct hostent      *h;
+    struct sockaddr_in  *sin;
 
-    for (p = 0; p < addr_port->len; p++) {
-        if (addr_port->data[p] == ':') {
+    err = ngx_inet_parse_host_port(u);
+
+    if (err) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "%s in upstream \"%V\"", err, &u->name);
+        return NULL;
+    }
+
+    if (u->default_port) {
+        if (u->default_port_value == 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "no port in upstream \"%V\"", &u->name);
+            return NULL;
+        }
+
+        u->port = u->default_port_value;
+
+        if (!(u->port_text.data = ngx_palloc(cf->pool, sizeof("65536") - 1))) {
+            return NULL;
+        }
+
+        u->port_text.len = ngx_sprintf(u->port_text.data, "%d",
+                                       u->default_port_value)
+                           - u->port_text.data;
+
+    } else if (u->port) {
+        if (u->port == u->default_port_value) {
+            u->default_port = 1;
+        }
+
+    } else {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "no port in upstream \"%V\"", &u->name);
+        return NULL;
+    }
+
+    if (u->host.len == 0) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "no host in upstream \"%V\"", &u->name);
+        return NULL;
+    }
+
+    u->port = htons(u->port);
+
+    if (!(host = ngx_palloc(cf->pool, u->host.len + 1))) {
+        return NULL;
+    }
+
+    ngx_cpystrn(host, u->host.data, u->host.len + 1);
+
+    /* AF_INET only */
+
+    in_addr = inet_addr((char *) host);
+
+    if (in_addr == INADDR_NONE) {
+        h = gethostbyname((char *) host);
+
+        if (h == NULL || h->h_addr_list[0] == NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "host %s is not found in upstream \"%V\"",
+                               host, &u->name);
+            return NULL;
+        }
+
+        for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
+
+        /* MP: ngx_shared_palloc() */
+
+        peers = ngx_pcalloc(cf->pool,
+                            sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
+
+        if (peers == NULL) {
+            return NULL;
+        }
+
+        peers->number = i;
+        peers->weight = 1;
+
+        for (i = 0; h->h_addr_list[i] != NULL; i++) {
+
+            if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+                return NULL;
+            }
+
+            sin->sin_family = AF_INET;
+            sin->sin_port = u->port;
+            sin->sin_addr.s_addr = *(in_addr_t *)(h->h_addr_list[i]);
+
+            peers->peer[i].sockaddr = (struct sockaddr *) sin;
+            peers->peer[i].socklen = sizeof(struct sockaddr_in);
+
+            len = INET_ADDRSTRLEN - 1 + 1 + u->port_text.len;
+    
+            if (!(peers->peer[i].name.data = ngx_palloc(cf->pool, len))) {
+                return NULL;
+            }
+
+            len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin,
+                                peers->peer[i].name.data, len);
+
+            peers->peer[i].name.data[len++] = ':';
+
+            ngx_memcpy(peers->peer[i].name.data + len,
+                       u->port_text.data, u->port_text.len);
+
+            peers->peer[i].name.len = len + u->port_text.len;
+
+            peers->peer[i].uri_separator = "";
+
+            peers->peer[i].weight = 1;
+            peers->peer[i].max_fails = 1;
+            peers->peer[i].fail_timeout = 60;
+        }
+
+    } else {
+
+        /* MP: ngx_shared_palloc() */
+
+        if (!(peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)))) {
+            return NULL;
+        }
+
+        if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+            return NULL;
+        }
+
+        peers->number = 1;
+
+        sin->sin_family = AF_INET;
+        sin->sin_port = u->port;
+        sin->sin_addr.s_addr = in_addr;
+
+        peers->peer[0].sockaddr = (struct sockaddr *) sin;
+        peers->peer[0].socklen = sizeof(struct sockaddr_in);
+
+        len = u->host.len + 1 + u->port_text.len;
+
+        peers->peer[0].name.len = len;
+
+        if (!(peers->peer[0].name.data = ngx_palloc(cf->pool, len))) {
+            return NULL;
+        }
+
+        len = u->host.len;
+
+        ngx_memcpy(peers->peer[0].name.data, u->host.data, len);
+
+        peers->peer[0].name.data[len++] = ':';
+
+        ngx_memcpy(peers->peer[0].name.data + len,
+                   u->port_text.data, u->port_text.len);
+
+        peers->peer[0].uri_separator = "";
+    }
+
+    return peers;
+}
+
+
+char *ngx_inet_parse_host_port(ngx_inet_upstream_t *u)
+{
+    size_t      i;
+    ngx_int_t   port;
+    ngx_str_t  *url;
+
+    url = &u->url;
+
+    if (u->port_only) {
+        i = 0;
+
+    } else {
+        if (url->data[0] == ':' || url->data[0] == '/') {
+            return "invalid host";
+        }
+
+        i = 1;
+    }
+
+    u->host.data = url->data;
+    u->host_header = *url;
+
+    for (/* void */; i < url->len; i++) {
+
+        if (url->data[i] == ':') {
+            u->port_text.data = &url->data[i] + 1;
+            u->host.len = i;
+
+            if (!u->uri_part) {
+                u->port_text.len = &url->data[url->len] - u->port_text.data;
+                break;
+            }
+        }
+
+        if (url->data[i] == '/') {
+            u->uri.data = &url->data[i];
+            u->uri.len = url->len - i;
+            u->host_header.len = i;
+
+            if (u->host.len == 0) {
+                u->host.len = i;
+            }
+
+            if (u->port_text.data == NULL) {
+                u->default_port = 1;
+                return NULL;
+            }
+
+            u->port_text.len = &url->data[i] - u->port_text.data;
+
+            if (u->port_text.len == 0) {
+                return "invalid port";
+            }
+
             break;
         }
     }
 
-    in_addr->host.len = p;
-    if (!(in_addr->host.data = ngx_palloc(pool, p + 1))) {
-        return NGX_ERROR;
+    if (u->port_text.data == NULL) {
+        port = ngx_atoi(url->data, url->len);
+
+        if (port == NGX_ERROR) {
+            u->default_port = 1;
+            u->host.len = url->len;
+
+            return NULL;
+        }
+
+        u->port_text = *url;
+        u->wildcard = 1;
+
+    } else {
+        if (u->port_text.len == 0) {
+            return "no URI";
+        }
+
+        port = ngx_atoi(u->port_text.data, u->port_text.len);
+
+        if (port == NGX_ERROR || port < 1 || port > 65536) {
+            return "invalid port";
+        }
     }
 
-    ngx_cpystrn(in_addr->host.data, addr_port->data, p + 1);
+    u->port = (in_port_t) port;
 
-    if (p == addr_port->len) {
-        p = 0;
-    }
-
-    port = ngx_atoi(&addr[p], args[1].len - p);
-    if (port == NGX_ERROR && p == 0) {
-
-        /* default port */
-        iap->port = 0;
-
-    } else if ((port == NGX_ERROR && p != 0) /* "listen host:NONNUMBER" */
-               || (port < 1 || port > 65536)) { /* "listen 99999" */
-
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "invalid port \"%s\" in \"%s\" directive, "
-                           "it must be a number between 1 and 65535",
-                           &addr[p], cmd->name.data);
-
-        return NGX_CONF_ERROR;
-
-    } else if (p == 0) {
-        ls->addr = INADDR_ANY;
-        ls->port = (in_port_t) port;
-        return NGX_CONF_OK;
-    }
-
-    return NGX_OK;
+    return NULL;
 }
-
-#endif
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
index d0e1f8d..a01fc8a 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -8,17 +8,44 @@
 #define _NGX_INET_H_INCLUDED_
 
 
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
 typedef struct {
     in_addr_t  addr;
     in_addr_t  mask;
 } ngx_inet_cidr_t;
 
 
-size_t ngx_sock_ntop(int family, struct sockaddr *addr, u_char *text,
+typedef struct {
+    ngx_str_t     name;           /* "schema:host:port/uri" */
+    ngx_str_t     url;            /* "host:port/uri" */
+    ngx_str_t     host;
+    ngx_str_t     uri;
+    ngx_str_t     host_header;    /* "host:port" */
+    ngx_str_t     port_text;      /* "port" */
+
+    in_port_t     port;
+
+    in_port_t     default_port_value;
+
+    unsigned      default_port:1;
+    unsigned      wildcard:1;
+
+    unsigned      uri_part:1;
+    unsigned      port_only:1;
+} ngx_inet_upstream_t;
+
+
+size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text,
                      size_t len);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
 
 ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
 
+ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u);
+char *ngx_inet_parse_host_port(ngx_inet_upstream_t *u);
+
 
 #endif /* _NGX_INET_H_INCLUDED_ */
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index b925e48..2b8da22 100644
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -80,7 +80,7 @@
             if (bsize == 0 && !ngx_buf_special(ctx->in->buf)) {
 
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
-                              "zero size buf");
+                              "zero size buf in output");
 
                 ngx_debug_point();
 
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c
index 35b4892..9b0c74e 100644
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -54,11 +54,11 @@
     if (re == NULL) {
        if ((size_t) erroff == pattern->len) {
            ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\"",
+                        "pcre_compile() failed: %s in \"%s\"%Z",
                         errstr, pattern->data);
         } else {
            ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\" at \"%s\"",
+                        "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
                         errstr, pattern->data, pattern->data + erroff);
         }
     }
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index dd6d06a..37a75aa 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -86,7 +86,11 @@
 
 u_char *ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
 {
-    u_char         *p, zero, *last, temp[NGX_INT64_LEN];
+    u_char         *p, zero, *last, temp[NGX_INT64_LEN + 1];
+                                    /*
+                                     * really we need temp[NGX_INT64_LEN] only,
+                                     * but icc shows the warning
+                                     */
     int             d;
     size_t          len;
     uint32_t        ui32;
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index d0b87e0..abef82d 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -64,7 +64,7 @@
 
 /* msvc and icc compile memcpy() to the inline "rep movs" */
 #define ngx_memcpy(dst, src, n)   memcpy(dst, src, n)
-#define ngx_cpymem(dst, src, n)   ((u_char *) memcpy(dst, src, n)) + n
+#define ngx_cpymem(dst, src, n)   ((u_char *) memcpy(dst, src, n)) + (n)
 
 
 /* msvc and icc compile memcmp() to the inline loop */
diff --git a/src/core/ngx_unix_domain.c b/src/core/ngx_unix_domain.c
new file mode 100644
index 0000000..436777f
--- /dev/null
+++ b/src/core/ngx_unix_domain.c
@@ -0,0 +1,84 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_event_connect.h>
+
+
+/* Solaris has predefined "#define sun 1" */
+#undef sun
+
+
+ngx_peers_t *ngx_unix_upstream_parse(ngx_conf_t *cf,
+                                     ngx_unix_domain_upstream_t *u)
+{
+    size_t               len;
+    ngx_uint_t           i;
+    ngx_peers_t         *peers;
+    struct sockaddr_un  *sun;
+
+    len = u->url.len - 5;
+
+    if (u->uri_part) {
+        for (i = 5; i < u->url.len; i++) {
+            if (u->url.data[i] == ':') {
+                len = i - 5;
+                u->uri.len = u->url.len - 5 - len - 1;
+                u->uri.data = u->url.data + 5 + len + 1;
+
+                break;
+            }
+        }
+
+        if (u->uri.len == 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "the unix domain upstream \"%V\" has no URI",
+                               &u->name);
+            return NULL;
+        }
+    }
+
+    if (len == 0) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the unix domain socket \"%V\" has no path",
+                           &u->name);
+        return NULL;
+    }
+
+    if (len + 1 > sizeof(sun->sun_path)) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the unix domain socket path \"%V\" is too long",
+                           &u->name);
+        return NULL;
+    }
+
+    /* MP: ngx_shared_palloc() */
+
+    if (!(peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)))) {
+        return NULL;
+    }
+
+    if (!(sun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un)))) {
+        return NULL;
+    }
+
+    peers->number = 1;
+
+    sun->sun_family = AF_UNIX;
+    ngx_cpystrn((u_char *) sun->sun_path, u->url.data + 5, len + 1);
+
+    peers->peer[0].sockaddr = (struct sockaddr *) sun;
+    peers->peer[0].socklen = sizeof(struct sockaddr_un);
+
+    peers->peer[0].name.len = 5 + len;
+    peers->peer[0].name.data = u->url.data;
+
+    peers->peer[0].uri_separator = ":";
+
+    return peers;
+}
diff --git a/src/core/ngx_unix_domain.h b/src/core/ngx_unix_domain.h
new file mode 100644
index 0000000..2c1de83
--- /dev/null
+++ b/src/core/ngx_unix_domain.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_UNIX_DOMAIN_H_INCLUDED_
+#define _NGX_UNIX_DOMAIN_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct {
+    ngx_str_t     name;           /* "schema:unix:path:/uri" */
+    ngx_str_t     url;            /* "unix:path:/uri" */
+    ngx_str_t     uri;
+
+    ngx_uint_t    uri_part;       /* unsigned  uri_part:1; */
+} ngx_unix_domain_upstream_t;
+
+
+ngx_peers_t *ngx_unix_upstream_parse(ngx_conf_t *cf,
+                                     ngx_unix_domain_upstream_t *u);
+
+
+#endif /* _NGX_UNIX_DOMAIN_H_INCLUDED_ */
+