Index: ChangeLog =================================================================== Index: .cvsignore =================================================================== Index: src/.cvsignore =================================================================== Index: src/configfile-glue.c =================================================================== --- src/configfile-glue.c (.../tags/lighttpd-1.4.23) +++ src/configfile-glue.c (.../branches/lighttpd-1.4.x) @@ -103,7 +103,6 @@ if (e != ds->value->ptr && !*e && l >=0 && l <= 65535) { *((unsigned short *)(cv[i].destination)) = l; break; - } } @@ -112,10 +111,40 @@ return -1; } default: - log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a integer, range 0 ... 65535"); + log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a short integer, range 0 ... 65535"); return -1; } break; + case T_CONFIG_INT: + switch(du->type) { + case TYPE_INTEGER: { + data_integer *di = (data_integer *)du; + + *((unsigned int *)(cv[i].destination)) = di->value; + break; + } + case TYPE_STRING: { + data_string *ds = (data_string *)du; + + if (ds->value->ptr && *ds->value->ptr) { + char *e; + long l = strtol(ds->value->ptr, &e, 10); + if (e != ds->value->ptr && !*e && l >= 0) { + *((unsigned int *)(cv[i].destination)) = l; + break; + } + } + + + log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value); + + return -1; + } + default: + log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected an integer, range 0 ... 4294967295"); + return -1; + } + break; case T_CONFIG_BOOLEAN: if (du->type == TYPE_STRING) { data_string *ds = (data_string *)du; Index: src/mod_cgi.c =================================================================== --- src/mod_cgi.c (.../tags/lighttpd-1.4.23) +++ src/mod_cgi.c (.../branches/lighttpd-1.4.x) @@ -56,6 +56,7 @@ typedef struct { array *cgi; + unsigned short execute_x_only; } plugin_config; typedef struct { @@ -151,6 +152,7 @@ config_values_t cv[] = { { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "cgi.execute-x-only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET} }; @@ -165,8 +167,10 @@ assert(s); s->cgi = array_init(); + s->execute_x_only = 0; cv[0].destination = s->cgi; + cv[1].destination = &(s->execute_x_only); p->config_storage[i] = s; @@ -580,12 +584,9 @@ #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid); #endif - pid = 0; - return HANDLER_GO_ON; } else { log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid); - pid = 0; return HANDLER_GO_ON; } } @@ -1005,7 +1006,7 @@ args[i++] = cgi_handler->ptr; } args[i++] = con->physical.path->ptr; - args[i++] = NULL; + args[i ] = NULL; /* search for the last / */ if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) { @@ -1018,8 +1019,6 @@ *c = '/'; } - openDevNull(STDERR_FILENO); - /* we don't need the client socket */ for (i = 3; i < 256; i++) { if (i != srv->errorlog_fd) close(i); @@ -1198,6 +1197,8 @@ if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) { PATCH(cgi); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.execute-x-only"))) { + PATCH(execute_x_only); } } } @@ -1220,6 +1221,7 @@ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) return HANDLER_GO_ON; if (!S_ISREG(sce->st.st_mode)) return HANDLER_GO_ON; + if (p->conf.execute_x_only == 1 && (sce->st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) return HANDLER_GO_ON; s_len = fn->used - 1; Index: src/network_write.c =================================================================== --- src/network_write.c (.../tags/lighttpd-1.4.23) +++ src/network_write.c (.../branches/lighttpd-1.4.x) @@ -46,15 +46,27 @@ toSend = c->mem->used - 1 - c->offset; #ifdef __WIN32 if ((r = send(fd, offset, toSend, 0)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); + /* no error handling for windows... */ + log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd); return -1; } #else if ((r = write(fd, offset, toSend)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); + switch (errno) { + case EAGAIN: + case EINTR: + r = 0; + break; + case EPIPE: + case ECONNRESET: + return -2; + default: + log_error_write(srv, __FILE__, __LINE__, "ssd", + "write failed:", strerror(errno), fd); - return -1; + return -1; + } } #endif @@ -98,7 +110,7 @@ return -1; } -#if defined USE_MMAP +#ifdef USE_MMAP if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno)); @@ -109,13 +121,26 @@ close(ifd); if ((r = write(fd, p + offset, toSend)) <= 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno)); - munmap(p, sce->st.st_size); - return -1; + switch (errno) { + case EAGAIN: + case EINTR: + r = 0; + break; + case EPIPE: + case ECONNRESET: + munmap(p, sce->st.st_size); + return -2; + default: + log_error_write(srv, __FILE__, __LINE__, "ssd", + "write failed:", strerror(errno), fd); + munmap(p, sce->st.st_size); + + return -1; + } } munmap(p, sce->st.st_size); -#else +#else /* USE_MMAP */ buffer_prepare_copy(srv->tmp_buf, toSend); lseek(ifd, offset, SEEK_SET); @@ -127,12 +152,33 @@ } close(ifd); - if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno)); +#ifdef __WIN32 + if ((r = send(fd, srv->tmp_buf->ptr, toSend, 0)) < 0) { + /* no error handling for windows... */ + log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd); return -1; } -#endif +#else /* __WIN32 */ + if ((r = write(fd, srv->tmp_buf->ptr, toSend)) < 0) { + switch (errno) { + case EAGAIN: + case EINTR: + r = 0; + break; + case EPIPE: + case ECONNRESET: + return -2; + default: + log_error_write(srv, __FILE__, __LINE__, "ssd", + "write failed:", strerror(errno), fd); + + return -1; + } + } +#endif /* __WIN32 */ +#endif /* USE_MMAP */ + c->offset += r; cq->bytes_out += r; Index: src/mod_secure_download.c =================================================================== --- src/mod_secure_download.c (.../tags/lighttpd-1.4.23) +++ src/mod_secure_download.c (.../branches/lighttpd-1.4.x) @@ -37,7 +37,7 @@ buffer *secret; buffer *uri_prefix; - unsigned short timeout; + unsigned int timeout; } plugin_config; typedef struct { @@ -99,7 +99,7 @@ { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ - { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ + { "secdownload.timeout", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -245,8 +245,8 @@ } /* timed-out */ - if ( (srv->cur_ts > ts && srv->cur_ts - ts > p->conf.timeout) || - (srv->cur_ts < ts && ts - srv->cur_ts > p->conf.timeout) ) { + if ( (srv->cur_ts > ts && (unsigned int) (srv->cur_ts - ts) > p->conf.timeout) || + (srv->cur_ts < ts && (unsigned int) (ts - srv->cur_ts) > p->conf.timeout) ) { /* "Gone" as the url will never be valid again instead of "408 - Timeout" where the request may be repeated */ con->http_status = 410; Index: src/base.h =================================================================== --- src/base.h (.../tags/lighttpd-1.4.23) +++ src/base.h (.../branches/lighttpd-1.4.x) @@ -84,6 +84,7 @@ typedef enum { T_CONFIG_UNSET, T_CONFIG_STRING, T_CONFIG_SHORT, + T_CONFIG_INT, T_CONFIG_BOOLEAN, T_CONFIG_ARRAY, T_CONFIG_LOCAL, @@ -281,7 +282,7 @@ unsigned short etag_use_mtime; unsigned short etag_use_size; unsigned short force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */ - unsigned short max_request_size; + unsigned int max_request_size; unsigned short kbytes_per_second; /* connection kb/s limit */ @@ -472,6 +473,7 @@ buffer *errorlog_file; unsigned short errorlog_use_syslog; + buffer *breakagelog_file; unsigned short dont_daemonize; buffer *changeroot; @@ -490,7 +492,7 @@ unsigned short max_worker; unsigned short max_fds; unsigned short max_conns; - unsigned short max_request_size; + unsigned int max_request_size; unsigned short log_request_header_on_error; unsigned short log_state_handling; @@ -538,7 +540,7 @@ /* the errorlog */ int errorlog_fd; - enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG, ERRORLOG_PIPE } errorlog_mode; + enum { ERRORLOG_FILE, ERRORLOG_FD, ERRORLOG_SYSLOG, ERRORLOG_PIPE } errorlog_mode; buffer *errorlog_buf; fdevents *ev, *ev_ins; Index: src/mod_rewrite.c =================================================================== --- src/mod_rewrite.c (.../tags/lighttpd-1.4.23) +++ src/mod_rewrite.c (.../branches/lighttpd-1.4.x) @@ -176,7 +176,7 @@ data_unset *du; if (NULL != (du = array_get_element(ca, option))) { - data_array *da = (data_array *)du; + data_array *da; size_t j; if (du->type != TYPE_ARRAY) { @@ -373,7 +373,7 @@ } } else { const char **list; - size_t start, end; + size_t start; size_t k; /* it matched */ @@ -383,17 +383,15 @@ buffer_reset(con->request.uri); - start = 0; end = pattern_len; + start = 0; for (k = 0; k < pattern_len; k++) { if (pattern[k] == '$' || pattern[k] == '%') { /* got one */ size_t num = pattern[k + 1] - '0'; - end = k; + buffer_append_string_len(con->request.uri, pattern + start, k - start); - buffer_append_string_len(con->request.uri, pattern + start, end - start); - if (!isdigit((unsigned char)pattern[k + 1])) { /* enable escape: "%%" => "%", "%a" => "%a", "$$" => "$" */ buffer_append_string_len(con->request.uri, pattern+k, pattern[k] == pattern[k+1] ? 1 : 2); Index: src/connections.c =================================================================== --- src/connections.c (.../tags/lighttpd-1.4.23) +++ src/connections.c (.../branches/lighttpd-1.4.x) @@ -782,13 +782,13 @@ CLEAN(request.pathinfo); CLEAN(request.request); - CLEAN(request.orig_uri); + /* CLEAN(request.orig_uri); */ CLEAN(uri.scheme); - CLEAN(uri.authority); - CLEAN(uri.path); + /* CLEAN(uri.authority); */ + /* CLEAN(uri.path); */ CLEAN(uri.path_raw); - CLEAN(uri.query); + /* CLEAN(uri.query); */ CLEAN(physical.doc_root); CLEAN(physical.path); @@ -1401,6 +1401,11 @@ "state for fd", con->fd, connection_get_state(con->state)); } + buffer_reset(con->uri.authority); + buffer_reset(con->uri.path); + buffer_reset(con->uri.query); + buffer_reset(con->request.orig_uri); + if (http_request_parse(srv, con)) { /* we have to read some data from the POST request */ @@ -1725,7 +1730,7 @@ case HANDLER_FINISHED: break; default: - log_error_write(srv, __FILE__, __LINE__, ""); + log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r); break; } break; Index: src/network.c =================================================================== --- src/network.c (.../tags/lighttpd-1.4.23) +++ src/network.c (.../branches/lighttpd-1.4.x) @@ -90,6 +90,7 @@ srv_socket = calloc(1, sizeof(*srv_socket)); srv_socket->fd = -1; + srv_socket->fde_ndx = -1; srv_socket->srv_token = buffer_init(); buffer_copy_string_buffer(srv_socket->srv_token, host_token); @@ -103,7 +104,7 @@ if (NULL == (sp = strrchr(b->ptr, ':'))) { log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b); - return -1; + goto error_free_socket; } host = b->ptr; @@ -126,7 +127,7 @@ } else if (port == 0 || port > 65535) { log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port); - return -1; + goto error_free_socket; } if (*host == '\0') host = NULL; @@ -138,12 +139,12 @@ if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); - return -1; + goto error_free_socket; } #else log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: Unix Domain sockets are not supported."); - return -1; + goto error_free_socket; #endif } @@ -153,7 +154,7 @@ if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); - return -1; + goto error_free_socket; } srv_socket->use_ipv6 = 1; } @@ -163,17 +164,22 @@ srv_socket->addr.plain.sa_family = AF_INET; if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); - return -1; + goto error_free_socket; } } +#ifdef FD_CLOEXEC + /* set FD_CLOEXEC now, fdevent_fcntl_set is called later; needed for pipe-logger forks */ + fcntl(srv_socket->fd, F_SETFD, FD_CLOEXEC); +#endif + /* */ srv->cur_fds = srv_socket->fd; val = 1; if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); - return -1; + goto error_free_socket; } switch(srv_socket->addr.plain.sa_family) { @@ -198,7 +204,7 @@ "sssss", "getaddrinfo failed: ", gai_strerror(r), "'", host, "'"); - return -1; + goto error_free_socket; } memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen); @@ -220,17 +226,17 @@ log_error_write(srv, __FILE__, __LINE__, "sds", "gethostbyname failed: ", h_errno, host); - return -1; + goto error_free_socket; } if (he->h_addrtype != AF_INET) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype); - return -1; + goto error_free_socket; } if (he->h_length != sizeof(struct in_addr)) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length); - return -1; + goto error_free_socket; } memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length); @@ -260,7 +266,7 @@ host); - return -1; + goto error_free_socket; } /* connect failed */ @@ -275,14 +281,12 @@ "testing socket failed:", host, strerror(errno)); - return -1; + goto error_free_socket; } break; default: - addr_len = 0; - - return -1; + goto error_free_socket; } if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { @@ -298,12 +302,12 @@ host, port, strerror(errno)); break; } - return -1; + goto error_free_socket; } if (-1 == listen(srv_socket->fd, 128 * 8)) { log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno)); - return -1; + goto error_free_socket; } if (s->is_ssl) { @@ -316,14 +320,14 @@ if (0 == RAND_status()) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "not enough entropy in the pool"); - return -1; + goto error_free_socket; } } if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); - return -1; + goto error_free_socket; } if (!s->ssl_use_sslv2) { @@ -331,7 +335,7 @@ if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); - return -1; + goto error_free_socket; } } @@ -340,33 +344,33 @@ if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); - return -1; + goto error_free_socket; } } if (buffer_is_empty(s->ssl_pemfile)) { log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); - return -1; + goto error_free_socket; } if (!buffer_is_empty(s->ssl_ca_file)) { if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); - return -1; + goto error_free_socket; } } if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); - return -1; + goto error_free_socket; } if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); - return -1; + goto error_free_socket; } if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { @@ -374,7 +378,7 @@ "Private key does not match the certificate public key, reason:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); - return -1; + goto error_free_socket; } SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1); SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); @@ -390,7 +394,7 @@ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "ssl requested but openssl support is not compiled in"); - return -1; + goto error_free_socket; #endif #ifdef TCP_DEFER_ACCEPT } else if (s->defer_accept) { @@ -414,7 +418,6 @@ } srv_socket->is_ssl = s->is_ssl; - srv_socket->fde_ndx = -1; if (srv->srv_sockets.size == 0) { srv->srv_sockets.size = 4; @@ -430,6 +433,21 @@ buffer_free(b); return 0; + +error_free_socket: + if (srv_socket->fd != -1) { + /* check if server fd are already registered */ + if (srv_socket->fde_ndx != -1) { + fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); + fdevent_unregister(srv->ev, srv_socket->fd); + } + + close(srv_socket->fd); + } + buffer_free(srv_socket->srv_token); + free(srv_socket); + + return -1; } int network_close(server *srv) { @@ -567,12 +585,8 @@ /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; - if (dc->cond != CONFIG_COND_EQ) { - log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"]."); + if (dc->cond != CONFIG_COND_EQ) continue; - return -1; - } - /* check if we already know this socket, * if yes, don't init it */ for (j = 0; j < srv->srv_sockets.used; j++) { Index: src/configfile.c =================================================================== --- src/configfile.c (.../tags/lighttpd-1.4.23) +++ src/configfile.c (.../branches/lighttpd-1.4.x) @@ -42,12 +42,12 @@ { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */ { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */ - { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ + { "server.max-request-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ { "server.max-worker", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 13 */ { "server.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */ - { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 15 */ + { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 15 */ { "debug.log-condition-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 16 */ - { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */ + { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },/* 17 */ { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */ { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */ @@ -91,12 +91,13 @@ { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 46 */ { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 47 */ { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 48 */ - { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */ - { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */ - { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */ + { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */ + { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */ + { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */ { "server.reject-expect-100-with-417", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 52 */ { "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */ - { "server.defer-accept", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 54 */ + { "server.defer-accept", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 54 */ + { "server.breakagelog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 55 */ { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -139,6 +140,8 @@ cv[43].destination = &(srv->srvconf.max_conns); cv[12].destination = &(srv->srvconf.max_request_size); cv[52].destination = &(srv->srvconf.reject_expect_100_with_417); + cv[55].destination = srv->srvconf.breakagelog_file; + srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); assert(srv->config_storage); @@ -290,6 +293,7 @@ PATCH(log_condition_handling); PATCH(log_file_not_found); PATCH(log_ssl_noise); + PATCH(log_timeouts); PATCH(range_requests); PATCH(force_lowercase_filenames); @@ -1135,15 +1139,15 @@ * - select works everywhere * - linux-* are experimental */ +#ifdef USE_LINUX_EPOLL + { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, +#endif #ifdef USE_POLL { FDEVENT_HANDLER_POLL, "poll" }, #endif #ifdef USE_SELECT { FDEVENT_HANDLER_SELECT, "select" }, #endif -#ifdef USE_LINUX_EPOLL - { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, -#endif #ifdef USE_LINUX_SIGIO { FDEVENT_HANDLER_LINUX_RTSIG, "linux-rtsig" }, #endif Index: src/mod_evhost.c =================================================================== --- src/mod_evhost.c (.../tags/lighttpd-1.4.23) +++ src/mod_evhost.c (.../branches/lighttpd-1.4.x) @@ -213,7 +213,7 @@ if (colon != ptr) { ds = data_string_init(); buffer_copy_string_len(ds->key,CONST_STR_LEN("%")); - buffer_append_long(ds->key, i++); + buffer_append_long(ds->key, i /* ++ */); buffer_copy_string_len(ds->value,ptr,colon-ptr); array_insert_unique(host,(data_unset *)ds); @@ -294,10 +294,10 @@ char *colon = strchr(con->uri.authority->ptr, ':'); if(colon == NULL) { - buffer_append_string_buffer(p->tmp_buf, con->uri.authority); // adds fqdn + buffer_append_string_buffer(p->tmp_buf, con->uri.authority); /* adds fqdn */ } else { /* strip the port out of the authority-part of the URI scheme */ - buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); // adds fqdn + buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); /* adds fqdn */ } } else if (NULL != (ds = (data_string *)array_get_element(parsed_host,p->conf.path_pieces[i]->ptr))) { if (ds->value->used) { Index: src/splaytree.c =================================================================== --- src/splaytree.c (.../tags/lighttpd-1.4.23) +++ src/splaytree.c (.../branches/lighttpd-1.4.x) @@ -61,12 +61,11 @@ * size fields are maintained */ splay_tree * splaytree_splay (splay_tree *t, int i) { splay_tree N, *l, *r, *y; - int comp, root_size, l_size, r_size; + int comp, l_size, r_size; if (t == NULL) return t; N.left = N.right = NULL; l = r = &N; - root_size = node_size(t); l_size = r_size = 0; for (;;) { Index: src/lemon.c =================================================================== --- src/lemon.c (.../tags/lighttpd-1.4.23) +++ src/lemon.c (.../branches/lighttpd-1.4.x) @@ -39,6 +39,12 @@ # endif #endif +#if __GNUC__ > 2 +#define NORETURN __attribute__ ((__noreturn__)) +#else +#define NORETURN +#endif + /* #define PRIVATE static */ #define PRIVATE static @@ -51,7 +57,7 @@ char *msort(); extern void *malloc(); -extern void memory_error(); +extern void memory_error() NORETURN; /******** From the file "action.h" *************************************/ struct action *Action_new(); @@ -59,7 +65,7 @@ void Action_add(); /********* From the file "assert.h" ************************************/ -void myassert(); +void myassert() NORETURN; #ifndef NDEBUG # define assert(X) if(!(X))myassert(__FILE__,__LINE__) #else @@ -1333,7 +1339,7 @@ /* Report an out-of-memory condition and abort. This function ** is used mostly by the "MemoryCheck" macro in struct.h */ -void memory_error(){ +void memory_error() { fprintf(stderr,"Out of memory. Aborting...\n"); exit(1); } @@ -1608,7 +1614,6 @@ FILE *err; { int spcnt, i; - spcnt = 0; if( argv[0] ) fprintf(err,"%s",argv[0]); spcnt = strlen(argv[0]) + 1; for(i=1; ierrorcnt++; return; } @@ -2343,6 +2349,7 @@ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); free(filebuf); + fclose(fp); gp->errorcnt++; return; } @@ -2913,7 +2920,7 @@ }else if( sp->destructor ){ cp = sp->destructor; fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename); - }else if( lemp->vardest ){ + }else{ cp = lemp->vardest; if( cp==0 ) return; fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename); @@ -3042,7 +3049,7 @@ int *plineno; /* Pointer to the line number */ int mhflag; /* True if generating makeheaders output */ { - int lineno = *plineno; /* The line number of the output */ + int lineno; /* The line number of the output */ char **types; /* A hash table of datatypes */ int arraysize; /* Size of the "types" array */ int maxdtlength; /* Maximum length of any ".datatype" field. */ Index: src/mod_scgi.c =================================================================== --- src/mod_scgi.c (.../tags/lighttpd-1.4.23) +++ src/mod_scgi.c (.../branches/lighttpd-1.4.x) @@ -331,8 +331,21 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc); +static void reset_signals(void) { +#ifdef SIGTTOU + signal(SIGTTOU, SIG_DFL); +#endif +#ifdef SIGTTIN + signal(SIGTTIN, SIG_DFL); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); +#endif + signal(SIGHUP, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + signal(SIGUSR1, SIG_DFL); +} - static handler_ctx * handler_ctx_init() { handler_ctx * hctx; @@ -772,10 +785,8 @@ env.used = 0; if (scgi_fd != 0) { - close(0); dup2(scgi_fd, 0); close(scgi_fd); - scgi_fd = 0; } /* we don't need the client socket */ @@ -783,8 +794,6 @@ close(fd); } - openDevNull(STDERR_FILENO); - /* build clean environment */ if (host->bin_env_copy->used) { for (i = 0; i < host->bin_env_copy->used; i++) { @@ -828,6 +837,8 @@ buffer_copy_string_len(b, CONST_STR_LEN("exec ")); buffer_append_string_buffer(b, host->bin_path); + reset_signals(); + /* exec the cgi */ execle("/bin/sh", "sh", "-c", b->ptr, (char *)NULL, env.ptr); @@ -2163,8 +2174,11 @@ int ret; /* sanity check */ - if (!host || - ((!host->host->used || !host->port) && !host->unixsocket->used)) { + if (!host) { + log_error_write(srv, __FILE__, __LINE__, "s", "fatal error: host = NULL"); + return HANDLER_ERROR; + } + if (((!host->host->used || !host->port) && !host->unixsocket->used)) { log_error_write(srv, __FILE__, __LINE__, "sxddd", "write-req: error", host, @@ -2299,8 +2313,8 @@ chunkqueue_remove_finished_chunks(hctx->wb); - if (-1 == ret) { - if (errno == ENOTCONN) { + if (ret < 0) { + if (errno == ENOTCONN || ret == -2) { /* the connection got dropped after accept() * * this is most of the time a PHP which dies @@ -2325,24 +2339,17 @@ */ log_error_write(srv, __FILE__, __LINE__, "ssosd", - "[REPORT ME] connection was dropped after accept(). reconnect() denied:", + "connection was dropped after accept(). reconnect() denied:", "write-offset:", hctx->wb->bytes_out, "reconnect attempts:", hctx->reconnects); return HANDLER_ERROR; - } - - if ((errno != EAGAIN) && - (errno != EINTR)) { - + } else { + /* -1 == ret => error on our side */ log_error_write(srv, __FILE__, __LINE__, "ssd", - "write failed:", strerror(errno), errno); + "write failed:", strerror(errno), errno); return HANDLER_ERROR; - } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - - return HANDLER_WAIT_FOR_EVENT; } } @@ -2469,12 +2476,10 @@ } static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) { - plugin_data *p; connection *con; if (NULL == hctx) return HANDLER_GO_ON; - p = hctx->plugin_data; con = hctx->remote_conn; log_error_write(srv, __FILE__, __LINE__, "ssdsd", @@ -2724,27 +2729,29 @@ /* check if extension matches */ for (k = 0; k < p->conf.exts->used; k++) { size_t ct_len; + scgi_extension *ext = p->conf.exts->exts[k]; - extension = p->conf.exts->exts[k]; + if (ext->key->used == 0) continue; - if (extension->key->used == 0) continue; + ct_len = ext->key->used - 1; - ct_len = extension->key->used - 1; - if (s_len < ct_len) continue; /* check extension in the form "/scgi_pattern" */ - if (*(extension->key->ptr) == '/') { - if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) + if (*(ext->key->ptr) == '/') { + if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) { + extension = ext; break; - } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) { + } + } else if (0 == strncmp(fn->ptr + s_len - ct_len, ext->key->ptr, ct_len)) { /* check extension in the form ".fcg" */ + extension = ext; break; } } /* extension doesn't match */ - if (k == p->conf.exts->used) { + if (NULL == extension) { return HANDLER_GO_ON; } Index: src/mod_mysql_vhost.c =================================================================== --- src/mod_mysql_vhost.c (.../tags/lighttpd-1.4.23) +++ src/mod_mysql_vhost.c (.../branches/lighttpd-1.4.x) @@ -259,8 +259,14 @@ #define FOO(x) (s->x->used ? s->x->ptr : NULL) +#if MYSQL_VERSION_ID >= 40100 + /* CLIENT_MULTI_STATEMENTS first appeared in 4.1 */ if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), + FOO(mydb), s->port, FOO(mysock), CLIENT_MULTI_STATEMENTS)) { +#else + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), FOO(mydb), s->port, FOO(mysock), 0)) { +#endif log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql)); return HANDLER_ERROR; @@ -369,6 +375,9 @@ if (!row || cols < 1) { /* no such virtual host */ mysql_free_result(result); +#if MYSQL_VERSION_ID >= 40100 + while (mysql_next_result(p->conf.mysql) == 0); +#endif return HANDLER_GO_ON; } @@ -402,6 +411,9 @@ c->fcgi_offset = c->fcgi_arg->used = 0; } mysql_free_result(result); +#if MYSQL_VERSION_ID >= 40100 + while (mysql_next_result(p->conf.mysql) == 0); +#endif /* fix virtual server and docroot */ GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name); @@ -416,6 +428,9 @@ return HANDLER_GO_ON; ERR500: if (result) mysql_free_result(result); +#if MYSQL_VERSION_ID >= 40100 + while (mysql_next_result(p->conf.mysql) == 0); +#endif con->http_status = 500; /* Internal Error */ con->mode = DIRECT; return HANDLER_FINISHED; @@ -424,15 +439,15 @@ /* this function is called at dlopen() time and inits the callbacks */ int mod_mysql_vhost_plugin_init(plugin *p); int mod_mysql_vhost_plugin_init(plugin *p) { - p->version = LIGHTTPD_VERSION_ID; - p->name = buffer_init_string("mysql_vhost"); + p->version = LIGHTTPD_VERSION_ID; + p->name = buffer_init_string("mysql_vhost"); - p->init = mod_mysql_vhost_init; - p->cleanup = mod_mysql_vhost_cleanup; - p->handle_request_done = mod_mysql_vhost_handle_connection_close; + p->init = mod_mysql_vhost_init; + p->cleanup = mod_mysql_vhost_cleanup; + p->connection_reset = mod_mysql_vhost_handle_connection_close; - p->set_defaults = mod_mysql_vhost_set_defaults; - p->handle_docroot = mod_mysql_vhost_handle_docroot; + p->set_defaults = mod_mysql_vhost_set_defaults; + p->handle_docroot = mod_mysql_vhost_handle_docroot; return 0; } @@ -441,7 +456,7 @@ int mod_mysql_vhost_plugin_init(plugin *p); int mod_mysql_vhost_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; - p->name = buffer_init_string("mysql_vhost"); + p->name = buffer_init_string("mysql_vhost"); return 0; } Index: src/request.c =================================================================== --- src/request.c (.../tags/lighttpd-1.4.23) +++ src/request.c (.../branches/lighttpd-1.4.x) @@ -111,7 +111,7 @@ /* check the first character at right of the dot */ if (is_ip == 0) { - if (!light_isalpha(host->ptr[i+1])) { + if (!light_isalnum(host->ptr[i+1])) { return -1; } } else if (!light_isdigit(host->ptr[i+1])) { @@ -133,7 +133,7 @@ } } else if (i == 0) { /* the first character of the hostname */ - if (!light_isalpha(c)) { + if (!light_isalnum(c)) { return -1; } label_len++; @@ -540,8 +540,8 @@ con->response.keep_alive = 0; con->keep_alive = 0; - log_error_write(srv, __FILE__, __LINE__, "s", "no uri specified -> 400"); if (srv->srvconf.log_request_header_on_error) { + log_error_write(srv, __FILE__, __LINE__, "s", "no uri specified -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); Index: src/network_backends.h =================================================================== --- src/network_backends.h (.../tags/lighttpd-1.4.23) +++ src/network_backends.h (.../branches/lighttpd-1.4.x) @@ -45,6 +45,11 @@ #include "base.h" +/* return values: + * >= 0 : chunks completed + * -1 : error (on our side) + * -2 : remote close + */ int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq); int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq); Index: src/mod_rrdtool.c =================================================================== --- src/mod_rrdtool.c (.../tags/lighttpd-1.4.23) +++ src/mod_rrdtool.c (.../branches/lighttpd-1.4.x) @@ -139,10 +139,8 @@ args[i++] = p->conf.path_rrdtool_bin->ptr; args[i++] = dash; - args[i++] = NULL; + args[i ] = NULL; - openDevNull(STDERR_FILENO); - /* we don't need the client socket */ for (i = 3; i < 256; i++) { close(i); @@ -268,7 +266,7 @@ "RRA:MIN:0.5:24:775 " "RRA:MIN:0.5:288:797\n")); - if (-1 == (r = safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) { + if (-1 == (safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) { log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-write: failed", strerror(errno)); Index: src/stat_cache.c =================================================================== --- src/stat_cache.c (.../tags/lighttpd-1.4.23) +++ src/stat_cache.c (.../branches/lighttpd-1.4.x) @@ -503,12 +503,10 @@ } if (NULL == sce) { - int osize = 0; +#ifdef DEBUG_STAT_CACHE + int osize = splaytree_size(sc->files); +#endif - if (sc->files) { - osize = sc->files->size; - } - sce = stat_cache_entry_init(); buffer_copy_string_buffer(sce->name, name); Index: src/response.h =================================================================== --- src/response.h (.../tags/lighttpd-1.4.23) +++ src/response.h (.../branches/lighttpd-1.4.x) @@ -10,6 +10,7 @@ int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen); int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen); +int response_header_append(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen); handler_t http_response_prepare(server *srv, connection *con); int http_response_redirect_to_directory(server *srv, connection *con); Index: src/mod_proxy.c =================================================================== --- src/mod_proxy.c (.../tags/lighttpd-1.4.23) +++ src/mod_proxy.c (.../branches/lighttpd-1.4.x) @@ -756,12 +756,15 @@ switch(hctx->state) { case PROXY_STATE_INIT: +#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) if (strstr(host->host->ptr,":")) { if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno)); return HANDLER_ERROR; } - } else { + } else +#endif + { if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno)); return HANDLER_ERROR; @@ -842,17 +845,14 @@ chunkqueue_remove_finished_chunks(hctx->wb); - if (-1 == ret) { - if (errno != EAGAIN && - errno != EINTR) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); + if (-1 == ret) { /* error on our side */ + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - return HANDLER_ERROR; - } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; + } else if (-2 == ret) { /* remote close */ + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno); - return HANDLER_WAIT_FOR_EVENT; - } + return HANDLER_WAIT_FOR_EVENT; } if (hctx->wb->bytes_out == hctx->wb->bytes_in) { @@ -1107,19 +1107,20 @@ /* check if extension matches */ for (k = 0; k < p->conf.extensions->used; k++) { + data_array *ext = NULL; size_t ct_len; - extension = (data_array *)p->conf.extensions->data[k]; + ext = (data_array *)p->conf.extensions->data[k]; - if (extension->key->used == 0) continue; + if (ext->key->used == 0) continue; - ct_len = extension->key->used - 1; + ct_len = ext->key->used - 1; if (s_len < ct_len) continue; /* check extension in the form "/proxy_pattern" */ - if (*(extension->key->ptr) == '/') { - if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { + if (*(ext->key->ptr) == '/') { + if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) { if (s_len > ct_len + 1) { char *pi_offset; @@ -1127,15 +1128,17 @@ path_info_offset = pi_offset - fn->ptr; } } + extension = ext; break; } - } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) { + } else if (0 == strncmp(fn->ptr + s_len - ct_len, ext->key->ptr, ct_len)) { /* check extension in the form ".fcg" */ + extension = ext; break; } } - if (k == p->conf.extensions->used) { + if (NULL == extension) { return HANDLER_GO_ON; } Index: src/Makefile.am =================================================================== --- src/Makefile.am (.../tags/lighttpd-1.4.23) +++ src/Makefile.am (.../branches/lighttpd-1.4.x) @@ -13,14 +13,14 @@ versionstamp: @test -f versionstamp.h || touch versionstamp.h; \ REVISION=""; \ - if test -x "`which svnversion`"; then \ - REVISION="$$(LANG=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)"; \ + if test -d "$(top_srcdir)/.svn" -a -x "`which svnversion`"; then \ + REVISION="$$(LANG= LC_ALL=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)"; \ if test "$$REVISION" = "exported"; then \ REVISION=""; \ fi; \ fi; \ if test -z "$$REVISION" -a -x "`which git`"; then \ - REVISION="$$(cd "$(top_srcdir)"; LANG=C git describe --always 2>/dev/null || echo)"; \ + REVISION="$$(cd "$(top_srcdir)"; LANG= LC_ALL=C git describe --always 2>/dev/null || echo)"; \ fi; \ if test -n "$$REVISION"; then \ echo "#define REPO_VERSION \"-devel-$$REVISION\"" > versionstamp.h.tmp; \ Index: src/mod_expire.c =================================================================== --- src/mod_expire.c (.../tags/lighttpd-1.4.23) +++ src/mod_expire.c (.../branches/lighttpd-1.4.x) @@ -342,7 +342,7 @@ buffer_copy_string_len(p->expire_tstmp, CONST_STR_LEN("max-age=")); buffer_append_long(p->expire_tstmp, expires - srv->cur_ts); /* as expires >= srv->cur_ts the difference is >= 0 */ - response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp)); + response_header_append(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp)); return HANDLER_GO_ON; } Index: src/http_auth.c =================================================================== --- src/http_auth.c (.../tags/lighttpd-1.4.23) +++ src/http_auth.c (.../branches/lighttpd-1.4.x) @@ -918,15 +918,15 @@ char a1[256]; char a2[256]; - char *username; - char *realm; - char *nonce; - char *uri; - char *algorithm; - char *qop; - char *cnonce; - char *nc; - char *respons; + char *username = NULL; + char *realm = NULL; + char *nonce = NULL; + char *uri = NULL; + char *algorithm = NULL; + char *qop = NULL; + char *cnonce = NULL; + char *nc = NULL; + char *respons = NULL; char *e, *c; const char *m = NULL; @@ -967,15 +967,9 @@ dkv[6].ptr = &cnonce; dkv[7].ptr = &nc; dkv[8].ptr = &respons; - dkv[9].ptr = NULL; UNUSED(req); - for (i = 0; dkv[i].key; i++) { - *(dkv[i].ptr) = NULL; - } - - if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST && p->conf.auth_backend != AUTH_BACKEND_PLAIN) { log_error_write(srv, __FILE__, __LINE__, "s", Index: src/mod_redirect.c =================================================================== --- src/mod_redirect.c (.../tags/lighttpd-1.4.23) +++ src/mod_redirect.c (.../branches/lighttpd-1.4.x) @@ -203,7 +203,7 @@ } } else { const char **list; - size_t start, end; + size_t start; size_t k; /* it matched */ @@ -213,17 +213,15 @@ buffer_reset(p->location); - start = 0; end = pattern_len; + start = 0; for (k = 0; k < pattern_len; k++) { if (pattern[k] == '$' || pattern[k] == '%') { /* got one */ size_t num = pattern[k + 1] - '0'; - end = k; + buffer_append_string_len(p->location, pattern + start, k - start); - buffer_append_string_len(p->location, pattern + start, end - start); - if (!isdigit((unsigned char)pattern[k + 1])) { /* enable escape: "%%" => "%", "%a" => "%a", "$$" => "$" */ buffer_append_string_len(p->location, pattern+k, pattern[k] == pattern[k+1] ? 1 : 2); Index: src/mod_webdav.c =================================================================== --- src/mod_webdav.c (.../tags/lighttpd-1.4.23) +++ src/mod_webdav.c (.../branches/lighttpd-1.4.x) @@ -1096,6 +1096,7 @@ } #endif +#ifdef USE_LOCKS static int webdav_lockdiscovery(server *srv, connection *con, buffer *locktoken, const char *lockscope, const char *locktype, int depth) { @@ -1150,6 +1151,8 @@ return 0; } +#endif + /** * check if resource is having the right locks to access to resource * Index: src/configparser.y =================================================================== --- src/configparser.y (.../tags/lighttpd-1.4.23) +++ src/configparser.y (.../branches/lighttpd-1.4.x) @@ -72,7 +72,7 @@ op1->free(op1); return (data_unset *)ds; } else { - fprintf(stderr, "data type mismatch, cannot be merge\n"); + fprintf(stderr, "data type mismatch, cannot merge\n"); return NULL; } } @@ -193,7 +193,6 @@ du = configparser_merge_data(du, B); if (NULL == du) { ctx->ok = 0; - du->free(du); } else { buffer_copy_string_buffer(du->key, A); @@ -470,7 +469,7 @@ case CONFIG_COND_MATCH: { #ifdef HAVE_PCRE_H const char *errptr; - int erroff; + int erroff, captures; if (NULL == (dc->regex = pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { @@ -487,6 +486,14 @@ fprintf(stderr, "studying regex failed: %s -> %s\n", rvalue->ptr, errptr); ctx->ok = 0; + } else if (0 != (pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, &captures))) { + fprintf(stderr, "getting capture count for regex failed: %s\n", + rvalue->ptr); + ctx->ok = 0; + } else if (captures > 9) { + fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n", + rvalue->ptr); + ctx->ok = 0; } else { dc->string = buffer_init_buffer(rvalue); } Index: src/mod_status.c =================================================================== --- src/mod_status.c (.../tags/lighttpd-1.4.23) +++ src/mod_status.c (.../branches/lighttpd-1.4.x) @@ -438,7 +438,7 @@ buffer_append_string_len(b, CONST_STR_LEN( "
\n
legend\n"
-		". = connect, C = close, E = hard error\n"
+		". = connect, C = close, E = hard error, k = keep-alive\n"
 		"r = read, R = read-POST, W = write, h = handle-request\n"
 		"q = request-start,  Q = request-end\n"
 		"s = response-start, S = response-end\n"));
@@ -449,8 +449,14 @@
 
 	for (j = 0; j < srv->conns->used; j++) {
 		connection *c = srv->conns->ptr[j];
-		const char *state = connection_get_short_state(c->state);
+		const char *state;
 
+		if (CON_STATE_READ == c->state && c->request.orig_uri->used > 0) {
+			state = "k";
+		} else {
+			state = connection_get_short_state(c->state);
+		}
+
 		buffer_append_string_len(b, state, 1);
 
 		if (((j + 1) % 50) == 0) {
@@ -497,7 +503,11 @@
 
 		buffer_append_string_len(b, CONST_STR_LEN(""));
 
-		buffer_append_string(b, connection_get_state(c->state));
+		if (CON_STATE_READ == c->state && c->request.orig_uri->used > 0) {
+			buffer_append_string_len(b, CONST_STR_LEN("keep-alive"));
+		} else {
+			buffer_append_string(b, connection_get_state(c->state));
+		}
 
 		buffer_append_string_len(b, CONST_STR_LEN(""));
 
@@ -611,10 +621,10 @@
 }
 
 static handler_t mod_status_handle_server_statistics(server *srv, connection *con, void *p_d) {
-	plugin_data *p = p_d;
-	buffer *b = p->module_list;
+	buffer *b;
 	size_t i;
 	array *st = srv->status;
+	UNUSED(p_d);
 
 	if (0 == st->used) {
 		/* we have nothing to send */
Index: src/mod_ssi.c
===================================================================
--- src/mod_ssi.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_ssi.c	(.../branches/lighttpd-1.4.x)
@@ -362,7 +362,8 @@
 	switch(ssicmd) {
 	case SSI_ECHO: {
 		/* echo */
-		int var = 0, enc = 0;
+		int var = 0;
+		/* int enc = 0; */
 		const char *var_val = NULL;
 		stat_cache_entry *sce = NULL;
 
@@ -381,6 +382,7 @@
 			{ NULL, SSI_ECHO_UNSET }
 		};
 
+/*
 		struct {
 			const char *var;
 			enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
@@ -391,6 +393,7 @@
 
 			{ NULL, SSI_ENC_UNSET }
 		};
+*/
 
 		for (i = 2; i < n; i += 2) {
 			if (0 == strcmp(l[i], "var")) {
@@ -405,6 +408,7 @@
 					}
 				}
 			} else if (0 == strcmp(l[i], "encoding")) {
+/*
 				int j;
 
 				for (j = 0; encvars[j].var; j++) {
@@ -413,6 +417,7 @@
 						break;
 					}
 				}
+*/
 			} else {
 				log_error_write(srv, __FILE__, __LINE__, "sss",
 						"ssi: unknow attribute for ",
Index: src/mod_auth.c
===================================================================
--- src/mod_auth.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_auth.c	(.../branches/lighttpd-1.4.x)
@@ -468,7 +468,7 @@
 
 			if (method == NULL) {
 				log_error_write(srv, __FILE__, __LINE__, "ss",
-						"the require field is missing in:",
+						"the method field is missing in:",
 						"auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
 				return HANDLER_ERROR;
 			} else {
@@ -483,7 +483,7 @@
 
 			if (realm == NULL) {
 				log_error_write(srv, __FILE__, __LINE__, "ss",
-						"the require field is missing in:",
+						"the realm field is missing in:",
 						"auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
 				return HANDLER_ERROR;
 			}
Index: src/mod_cml_lua.c
===================================================================
--- src/mod_cml_lua.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_cml_lua.c	(.../branches/lighttpd-1.4.x)
@@ -2,6 +2,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "mod_cml.h"
 #include "mod_cml_funcs.h"
Index: src/http-header-glue.c
===================================================================
--- src/http-header-glue.c	(.../tags/lighttpd-1.4.23)
+++ src/http-header-glue.c	(.../branches/lighttpd-1.4.x)
@@ -104,6 +104,21 @@
 	return response_header_insert(srv, con, key, keylen, value, vallen);
 }
 
+int response_header_append(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
+	data_string *ds;
+
+	UNUSED(srv);
+
+	/* if there already is a key by this name append the value */
+	if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
+		buffer_append_string_len(ds->value, CONST_STR_LEN(", "));
+		buffer_append_string_len(ds->value, value, vallen);
+		return 0;
+	}
+
+	return response_header_insert(srv, con, key, keylen, value, vallen);
+}
+
 int http_response_redirect_to_directory(server *srv, connection *con) {
 	buffer *o;
 
@@ -259,7 +274,7 @@
 					}
 
 					if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
-						con->http_status = 304;
+						if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
 						return HANDLER_FINISHED;
 					} else {
 						char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
@@ -281,15 +296,16 @@
 						strncpy(buf, con->request.http_if_modified_since, used_len);
 						buf[used_len] = '\0';
 
-						tm.tm_isdst = 0;
 						if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
 							con->http_status = 412;
 							con->mode = DIRECT;
 							return HANDLER_FINISHED;
 						}
+						tm.tm_isdst = 0;
 						t_header = mktime(&tm);
 
 						strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
+						tm.tm_isdst = 0;
 						t_file = mktime(&tm);
 
 						if (t_file > t_header) return HANDLER_GO_ON;
@@ -318,7 +334,7 @@
 		}
 
 		if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
-			con->http_status = 304;
+			if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
 			return HANDLER_FINISHED;
 		} else {
 			char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
@@ -331,18 +347,17 @@
 			strncpy(buf, con->request.http_if_modified_since, used_len);
 			buf[used_len] = '\0';
 
-			tm.tm_isdst = 0;
 			if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
 				/**
 				 * parsing failed, let's get out of here 
 				 */
-				log_error_write(srv, __FILE__, __LINE__, "ss",
-						"strptime() failed on", buf);
 				return HANDLER_GO_ON;
 			}
+			tm.tm_isdst = 0;
 			t_header = mktime(&tm);
 
 			strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
+			tm.tm_isdst = 0;
 			t_file = mktime(&tm);
 
 			if (t_file > t_header) return HANDLER_GO_ON;
Index: src/mod_setenv.c
===================================================================
--- src/mod_setenv.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_setenv.c	(.../branches/lighttpd-1.4.x)
@@ -215,7 +215,7 @@
 	return HANDLER_GO_ON;
 }
 
-REQUESTDONE_FUNC(mod_setenv_reset) {
+CONNECTION_FUNC(mod_setenv_reset) {
 	plugin_data *p = p_d;
 
 	UNUSED(srv);
@@ -240,7 +240,7 @@
 	p->set_defaults  = mod_setenv_set_defaults;
 	p->cleanup     = mod_setenv_free;
 
-	p->handle_request_done  = mod_setenv_reset;
+	p->connection_reset  = mod_setenv_reset;
 
 	p->data        = NULL;
 
Index: src/mod_fastcgi.c
===================================================================
--- src/mod_fastcgi.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_fastcgi.c	(.../branches/lighttpd-1.4.x)
@@ -122,24 +122,11 @@
 	 *
 	 */
 
-	unsigned short min_procs;
 	unsigned short max_procs;
 	size_t num_procs;    /* how many procs are started */
 	size_t active_procs; /* how many of them are really running */
 
-	unsigned short max_load_per_proc;
-
 	/*
-	 * kick the process from the list if it was not
-	 * used for idle_timeout until min_procs is
-	 * reached. this helps to get the processlist
-	 * small again we had a small peak load.
-	 *
-	 */
-
-	unsigned short idle_timeout;
-
-	/*
 	 * time after a disabled remote connection is tried to be re-enabled
 	 *
 	 *
@@ -384,6 +371,21 @@
 /* ok, we need a prototype */
 static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents);
 
+static void reset_signals(void) {
+#ifdef SIGTTOU
+	signal(SIGTTOU, SIG_DFL);
+#endif
+#ifdef SIGTTIN
+	signal(SIGTTIN, SIG_DFL);
+#endif
+#ifdef SIGTSTP
+	signal(SIGTSTP, SIG_DFL);
+#endif
+	signal(SIGHUP, SIG_DFL);
+	signal(SIGPIPE, SIG_DFL);
+	signal(SIGUSR1, SIG_DFL);
+}
+
 static void fastcgi_status_copy_procname(buffer *b, fcgi_extension_host *host, fcgi_proc *proc) {
 	buffer_copy_string_len(b, CONST_STR_LEN("fastcgi.backend."));
 	buffer_append_string_buffer(b, host->id);
@@ -993,8 +995,6 @@
 				close(fcgi_fd);
 			}
 
-			openDevNull(STDERR_FILENO);
-
 			/* we don't need the client socket */
 			for (i = 3; i < 256; i++) {
 				close(i);
@@ -1054,6 +1054,7 @@
 				*c = '/';
 			}
 
+			reset_signals();
 
 			/* exec the cgi */
 			execve(arg.ptr[0], arg.ptr, env.ptr);
@@ -1235,20 +1236,17 @@
 
 						{ "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 5 */
 						{ "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 6 */
-						{ "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
-						{ "max-procs",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 8 */
-						{ "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
-						{ "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
-						{ "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
+						{ "max-procs",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 */
+						{ "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 8 */
 
-						{ "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 12 */
-						{ "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 13 */
+						{ "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
+						{ "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 10 */
 
-						{ "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
-						{ "allow-x-send-file",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 15 */
-						{ "strip-request-uri",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 16 */
-						{ "kill-signal",        NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },      /* 17 */
-						{ "fix-root-scriptname",   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 18 */
+						{ "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 11 */
+						{ "allow-x-send-file",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },     /* 12 */
+						{ "strip-request-uri",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 13 */
+						{ "kill-signal",        NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 14 */
+						{ "fix-root-scriptname",   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 15 */
 
 						{ NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
 					};
@@ -1267,12 +1265,9 @@
 					buffer_copy_string_buffer(host->id, da_host->key);
 
 					host->check_local  = 1;
-					host->min_procs    = 4;
 					host->max_procs    = 4;
-					host->max_load_per_proc = 1;
-					host->idle_timeout = 60;
 					host->mode = FCGI_RESPONDER;
-					host->disable_time = 60;
+					host->disable_time = 1;
 					host->break_scriptfilename_for_php = 0;
 					host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
 					host->kill_signal = SIGTERM;
@@ -1286,19 +1281,16 @@
 
 					fcv[5].destination = &(host->check_local);
 					fcv[6].destination = &(host->port);
-					fcv[7].destination = &(host->min_procs);
-					fcv[8].destination = &(host->max_procs);
-					fcv[9].destination = &(host->max_load_per_proc);
-					fcv[10].destination = &(host->idle_timeout);
-					fcv[11].destination = &(host->disable_time);
+					fcv[7].destination = &(host->max_procs);
+					fcv[8].destination = &(host->disable_time);
 
-					fcv[12].destination = host->bin_env;
-					fcv[13].destination = host->bin_env_copy;
-					fcv[14].destination = &(host->break_scriptfilename_for_php);
-					fcv[15].destination = &(host->allow_xsendfile);
-					fcv[16].destination = host->strip_request_uri;
-					fcv[17].destination = &(host->kill_signal);
-					fcv[18].destination = &(host->fix_root_path_name);
+					fcv[9].destination = host->bin_env;
+					fcv[10].destination = host->bin_env_copy;
+					fcv[11].destination = &(host->break_scriptfilename_for_php);
+					fcv[12].destination = &(host->allow_xsendfile);
+					fcv[13].destination = host->strip_request_uri;
+					fcv[14].destination = &(host->kill_signal);
+					fcv[15].destination = &(host->fix_root_path_name);
 
 					if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
 						return HANDLER_ERROR;
@@ -1355,23 +1347,16 @@
 						/* a local socket + self spawning */
 						size_t pno;
 
-						/* HACK:  just to make sure the adaptive spawing is disabled */
-						host->min_procs = host->max_procs;
-
-						if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
-						if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
-
 						if (s->debug) {
-							log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
+							log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsd",
 									"--- fastcgi spawning local",
 									"\n\tproc:", host->bin_path,
 									"\n\tport:", host->port,
 									"\n\tsocket", host->unixsocket,
-									"\n\tmin-procs:", host->min_procs,
 									"\n\tmax-procs:", host->max_procs);
 						}
 
-						for (pno = 0; pno < host->min_procs; pno++) {
+						for (pno = 0; pno < host->max_procs; pno++) {
 							fcgi_proc *proc;
 
 							proc = fastcgi_process_init();
@@ -1391,7 +1376,7 @@
 										"--- fastcgi spawning",
 										"\n\tport:", host->port,
 										"\n\tsocket", host->unixsocket,
-										"\n\tcurrent:", pno, "/", host->min_procs);
+										"\n\tcurrent:", pno, "/", host->max_procs);
 							}
 
 							if (fcgi_spawn_connection(srv, p, host, proc)) {
@@ -1426,7 +1411,6 @@
 
 						host->first = proc;
 
-						host->min_procs = 1;
 						host->max_procs = 1;
 					}
 
@@ -2739,7 +2723,7 @@
 					log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
 							"--- fastcgi spawning",
 							"\n\tsocket", proc->connection_name,
-							"\n\tcurrent:", 1, "/", host->min_procs);
+							"\n\tcurrent:", 1, "/", host->max_procs);
 				}
 
 				if (fcgi_spawn_connection(srv, p, host, proc)) {
@@ -2778,8 +2762,11 @@
 	 *     - tcp socket (do not check host->host->uses, as it may be not set which means INADDR_LOOPBACK)
 	 *     - unix socket
 	 */
-	if (!host ||
-	    (!host->port && !host->unixsocket->used)) {
+	if (!host) {
+		log_error_write(srv, __FILE__, __LINE__, "s", "fatal error: host = NULL");
+		return HANDLER_ERROR;
+	}
+	if ((!host->port && !host->unixsocket->used)) {
 		log_error_write(srv, __FILE__, __LINE__, "sxddd",
 				"write-req: error",
 				host,
@@ -2787,7 +2774,7 @@
 				host->port,
 				host->unixsocket->used);
 
-		hctx->proc->disabled_until = srv->cur_ts + 10;
+		hctx->proc->disabled_until = srv->cur_ts + hctx->host->disable_time;
 		hctx->proc->state = PROC_STATE_DIED;
 
 		return HANDLER_ERROR;
@@ -2803,7 +2790,7 @@
 			log_error_write(srv, __FILE__, __LINE__, "ss",
 					"getsockopt failed:", strerror(errno));
 
-			hctx->proc->disabled_until = srv->cur_ts + 10;
+			hctx->proc->disabled_until = srv->cur_ts + hctx->host->disable_time;
 			hctx->proc->state = PROC_STATE_DIED;
 
 			return HANDLER_ERROR;
@@ -2817,7 +2804,7 @@
 						"socket:", hctx->proc->connection_name);
 			}
 
-			hctx->proc->disabled_until = srv->cur_ts + 5;
+			hctx->proc->disabled_until = srv->cur_ts + hctx->host->disable_time;
 
 			if (hctx->proc->is_local) {
 				hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
@@ -2910,13 +2897,13 @@
 			/* cool down the backend, it is overloaded
 			 * -> EAGAIN */
 
-			log_error_write(srv, __FILE__, __LINE__, "ssdsd",
-				"backend is overloaded; we'll disable it for 2 seconds and send the request to another backend instead:",
+			log_error_write(srv, __FILE__, __LINE__, "sdssdsd",
+				"backend is overloaded; we'll disable it for", hctx->host->disable_time, "seconds and send the request to another backend instead:",
 				"reconnects:", hctx->reconnects,
 				"load:", host->load);
 
 
-			hctx->proc->disabled_until = srv->cur_ts + 2;
+			hctx->proc->disabled_until = srv->cur_ts + hctx->host->disable_time;
 			hctx->proc->state = PROC_STATE_OVERLOADED;
 
 			fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
@@ -2930,18 +2917,18 @@
 			 * - ECONNREFUSED for tcp-ip sockets
 			 * - ENOENT for unix-domain-sockets
 			 *
-			 * for check if the host is back in 5 seconds
+			 * for check if the host is back in hctx->host->disable_time seconds
 			 *  */
 
-			hctx->proc->disabled_until = srv->cur_ts + 5;
+			hctx->proc->disabled_until = srv->cur_ts + hctx->host->disable_time;
 			if (hctx->proc->is_local) {
 				hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
 			} else {
 				hctx->proc->state = PROC_STATE_DIED;
 			}
 
-			log_error_write(srv, __FILE__, __LINE__, "ssdsd",
-				"backend died; we'll disable it for 5 seconds and send the request to another backend instead:",
+			log_error_write(srv, __FILE__, __LINE__, "sdssdsd",
+				"backend died; we'll disable it for", hctx->host->disable_time, "seconds and send the request to another backend instead:",
 				"reconnects:", hctx->reconnects,
 				"load:", host->load);
 
@@ -3032,11 +3019,6 @@
 						"reconnect attempts:", hctx->reconnects);
 
 				return HANDLER_ERROR;
-			case EAGAIN:
-			case EINTR:
-				fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
-
-				return HANDLER_WAIT_FOR_EVENT;
 			default:
 				log_error_write(srv, __FILE__, __LINE__, "ssd",
 						"write failed:", strerror(errno), errno);
@@ -3266,7 +3248,7 @@
 						log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
 								"--- fastcgi spawning",
 								"\n\tsocket", proc->connection_name,
-								"\n\tcurrent:", 1, "/", host->min_procs);
+								"\n\tcurrent:", 1, "/", host->max_procs);
 					}
 
 					if (fcgi_spawn_connection(srv, p, host, proc)) {
@@ -3288,18 +3270,18 @@
 				    hctx->reconnects < 5) {
 					fcgi_reconnect(srv, hctx);
 
-					log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+					log_error_write(srv, __FILE__, __LINE__, "ssbsBSBs",
 						"response not received, request not sent",
 						"on socket:", proc->connection_name,
-						"for", con->uri.path, ", reconnecting");
+						"for", con->uri.path, "?", con->uri.query, ", reconnecting");
 
 					return HANDLER_WAIT_FOR_FD;
 				}
 
-				log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
+				log_error_write(srv, __FILE__, __LINE__, "sosbsBSBs",
 						"response not received, request sent:", hctx->wb->bytes_out,
 						"on socket:", proc->connection_name,
-						"for", con->uri.path, ", closing connection");
+						"for", con->uri.path, "?", con->uri.query, ", closing connection");
 
 				fcgi_connection_close(srv, hctx);
 
@@ -3311,10 +3293,10 @@
 				/* response might have been already started, kill the connection */
 				fcgi_connection_close(srv, hctx);
 
-				log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+				log_error_write(srv, __FILE__, __LINE__, "ssbsBSBs",
 						"response already sent out, but backend returned error",
 						"on socket:", proc->connection_name,
-						"for", con->uri.path, ", terminating connection");
+						"for", con->uri.path, "?", con->uri.query, ", terminating connection");
 
 				connection_set_state(srv, con, CON_STATE_ERROR);
 			}
@@ -3364,9 +3346,9 @@
 			 * even if the FCGI_FIN packet is not received yet
 			 */
 		} else {
-			log_error_write(srv, __FILE__, __LINE__, "sbsbsd",
+			log_error_write(srv, __FILE__, __LINE__, "sBSbsbsd",
 					"error: unexpected close of fastcgi connection for",
-					con->uri.path,
+					con->uri.path, "?", con->uri.query,
 					"(no fastcgi process on socket:", proc->connection_name, "?)",
 					hctx->state);
 
@@ -3489,25 +3471,27 @@
 		/* check if extension matches */
 		for (k = 0; k < p->conf.exts->used; k++) {
 			size_t ct_len; /* length of the config entry */
+			fcgi_extension *ext = p->conf.exts->exts[k];
 
-			extension = p->conf.exts->exts[k];
+			if (ext->key->used == 0) continue;
 
-			if (extension->key->used == 0) continue;
+			ct_len = ext->key->used - 1;
 
-			ct_len = extension->key->used - 1;
-
 			/* check _url_ in the form "/fcgi_pattern" */
-			if (extension->key->ptr[0] == '/') {
+			if (ext->key->ptr[0] == '/') {
 				if ((ct_len <= con->uri.path->used -1) &&
-				    (strncmp(con->uri.path->ptr, extension->key->ptr, ct_len) == 0))
+				    (strncmp(con->uri.path->ptr, ext->key->ptr, ct_len) == 0)) {
+					extension = ext;
 					break;
-			} else if ((ct_len <= s_len) && (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len))) {
+				}
+			} else if ((ct_len <= s_len) && (0 == strncmp(fn->ptr + s_len - ct_len, ext->key->ptr, ct_len))) {
 				/* check extension in the form ".fcg" */
+				extension = ext;
 				break;
 			}
 		}
 		/* extension doesn't match */
-		if (k == p->conf.exts->used) {
+		if (NULL == extension) {
 			return HANDLER_GO_ON;
 		}
 	}
@@ -3535,8 +3519,8 @@
 		if (!extension->note_is_sent) {
 			extension->note_is_sent = 1;
 
-			log_error_write(srv, __FILE__, __LINE__, "sbsbs",
-					"all handlers for ", con->uri.path,
+			log_error_write(srv, __FILE__, __LINE__, "sBSbsbs",
+					"all handlers for", con->uri.path, "?", con->uri.query,
 					"on", extension->key,
 					"are down.");
 		}
@@ -3727,107 +3711,12 @@
 			for (n = 0; n < ex->used; n++) {
 
 				fcgi_proc *proc;
-				unsigned long sum_load = 0;
 				fcgi_extension_host *host;
 
 				host = ex->hosts[n];
 
 				fcgi_restart_dead_procs(srv, p, host);
 
-				for (proc = host->first; proc; proc = proc->next) {
-					sum_load += proc->load;
-				}
-
-				if (host->num_procs &&
-				    host->num_procs < host->max_procs &&
-				    (sum_load / host->num_procs) > host->max_load_per_proc) {
-					/* overload, spawn new child */
-					if (p->conf.debug) {
-						log_error_write(srv, __FILE__, __LINE__, "s",
-								"overload detected, spawning a new child");
-					}
-
-					for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
-
-					if (proc) {
-						if (proc == host->unused_procs) host->unused_procs = proc->next;
-
-						if (proc->next) proc->next->prev = NULL;
-
-						host->max_id++;
-					} else {
-						proc = fastcgi_process_init();
-						proc->id = host->max_id++;
-					}
-
-					host->num_procs++;
-
-					if (buffer_is_empty(host->unixsocket)) {
-						proc->port = host->port + proc->id;
-					} else {
-						buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
-						buffer_append_string_len(proc->unixsocket, CONST_STR_LEN("-"));
-						buffer_append_long(proc->unixsocket, proc->id);
-					}
-
-					if (fcgi_spawn_connection(srv, p, host, proc)) {
-						log_error_write(srv, __FILE__, __LINE__, "s",
-								"ERROR: spawning fcgi failed.");
-						return HANDLER_ERROR;
-					}
-
-					proc->prev = NULL;
-					proc->next = host->first;
-					if (host->first) {
-						host->first->prev = proc;
-					}
-					host->first = proc;
-				}
-
-				for (proc = host->first; proc; proc = proc->next) {
-					if (proc->load != 0) break;
-					if (host->num_procs <= host->min_procs) break;
-					if (proc->pid == 0) continue;
-
-					if (srv->cur_ts - proc->last_used > host->idle_timeout) {
-						/* a proc is idling for a long time now,
-						 * terminate it */
-
-						if (p->conf.debug) {
-							log_error_write(srv, __FILE__, __LINE__, "ssbsd",
-									"idle-timeout reached; terminating child:",
-									"socket:", proc->connection_name,
-									"pid", proc->pid);
-						}
-
-
-						if (proc->next) proc->next->prev = proc->prev;
-						if (proc->prev) proc->prev->next = proc->next;
-
-						if (proc->prev == NULL) host->first = proc->next;
-
-						proc->prev = NULL;
-						proc->next = host->unused_procs;
-
-						if (host->unused_procs) host->unused_procs->prev = proc;
-						host->unused_procs = proc;
-
-						kill(proc->pid, SIGTERM);
-
-						proc->state = PROC_STATE_KILLED;
-
-						log_error_write(srv, __FILE__, __LINE__, "ssbsd",
-									"killed:",
-									"socket:", proc->connection_name,
-									"pid", proc->pid);
-
-						host->num_procs--;
-
-						/* proc is now in unused, let the next second handle the next process */
-						break;
-					}
-				}
-
 				for (proc = host->unused_procs; proc; proc = proc->next) {
 					int status;
 
Index: src/fdevent_poll.c
===================================================================
--- src/fdevent_poll.c	(.../tags/lighttpd-1.4.23)
+++ src/fdevent_poll.c	(.../branches/lighttpd-1.4.x)
@@ -132,7 +132,7 @@
 	if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
 	if (poll_r & POLLPRI) r |= FDEVENT_PRI;
 
-	return ev->pollfds[ndx].revents;
+	return r;
 }
 
 static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) {
Index: src/fdevent_select.c
===================================================================
--- src/fdevent_select.c	(.../tags/lighttpd-1.4.23)
+++ src/fdevent_select.c	(.../branches/lighttpd-1.4.x)
@@ -38,7 +38,7 @@
 	UNUSED(fde_ndx);
 
 	/* we should be protected by max-fds, but you never know */
-	assert(fd < FD_SETSIZE);
+	assert(fd < ((int)FD_SETSIZE));
 
 	if (events & FDEVENT_IN) {
 		FD_SET(fd, &(ev->select_set_read));
Index: src/CMakeLists.txt
===================================================================
Index: src/server.c
===================================================================
--- src/server.c	(.../tags/lighttpd-1.4.23)
+++ src/server.c	(.../branches/lighttpd-1.4.x)
@@ -187,6 +187,7 @@
 	CLEAN(cond_check_buf);
 
 	CLEAN(srvconf.errorlog_file);
+	CLEAN(srvconf.breakagelog_file);
 	CLEAN(srvconf.groupname);
 	CLEAN(srvconf.username);
 	CLEAN(srvconf.changeroot);
@@ -242,8 +243,8 @@
 	srv->srvconf.reject_expect_100_with_417 = 1;
 
 	/* use syslog */
-	srv->errorlog_fd = -1;
-	srv->errorlog_mode = ERRORLOG_STDERR;
+	srv->errorlog_fd = STDERR_FILENO;
+	srv->errorlog_mode = ERRORLOG_FD;
 
 	srv->split_vals = array_init();
 
@@ -271,6 +272,7 @@
 	CLEAN(cond_check_buf);
 
 	CLEAN(srvconf.errorlog_file);
+	CLEAN(srvconf.breakagelog_file);
 	CLEAN(srvconf.groupname);
 	CLEAN(srvconf.username);
 	CLEAN(srvconf.changeroot);
@@ -717,7 +719,7 @@
 		}
 
 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
-			srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
+			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
 		} else {
 			srv->max_fds = rlim.rlim_cur;
 		}
@@ -730,7 +732,7 @@
 #endif
 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
 			/* don't raise the limit above FD_SET_SIZE */
-			if (srv->max_fds > FD_SETSIZE - 200) {
+			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
 				log_error_write(srv, __FILE__, __LINE__, "sd",
 						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
 						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
@@ -780,7 +782,7 @@
 		 * Change group before chroot, when we have access
 		 * to /etc/group
 		 * */
-		if (srv->srvconf.groupname->used) {
+		if (NULL != grp) {
 			setgid(grp->gr_gid);
 			setgroups(0, NULL);
 			if (srv->srvconf.username->used) {
@@ -804,7 +806,7 @@
 #endif
 #ifdef HAVE_PWD_H
 		/* drop root privs */
-		if (srv->srvconf.username->used) {
+		if (NULL != pwd) {
 			setuid(pwd->pw_uid);
 		}
 #endif
@@ -843,7 +845,7 @@
 		}
 
 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
-			srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
+			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
 		} else {
 			srv->max_fds = rlim.rlim_cur;
 		}
@@ -857,7 +859,7 @@
 #endif
 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
 			/* don't raise the limit above FD_SET_SIZE */
-			if (srv->max_fds > FD_SETSIZE - 200) {
+			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
 				log_error_write(srv, __FILE__, __LINE__, "sd",
 						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
 						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
Index: src/mod_dirlisting.c
===================================================================
--- src/mod_dirlisting.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_dirlisting.c	(.../branches/lighttpd-1.4.x)
@@ -198,7 +198,7 @@
 	data_unset *du;
 
 	if (NULL != (du = array_get_element(ca, option))) {
-		data_array *da = (data_array *)du;
+		data_array *da;
 		size_t j;
 
 		if (du->type != TYPE_ARRAY) {
Index: src/mod_magnet.c
===================================================================
--- src/mod_magnet.c	(.../tags/lighttpd-1.4.23)
+++ src/mod_magnet.c	(.../branches/lighttpd-1.4.x)
@@ -283,17 +283,11 @@
 }
 
 static int magnet_reqhdr_get(lua_State *L) {
-	server *srv;
 	connection *con;
 	data_string *ds;
 
 	const char *key = luaL_checkstring(L, 2);
 
-	lua_pushstring(L, "lighty.srv");
-	lua_gettable(L, LUA_REGISTRYINDEX);
-	srv = lua_touserdata(L, -1);
-	lua_pop(L, 1);
-
 	lua_pushstring(L, "lighty.con");
 	lua_gettable(L, LUA_REGISTRYINDEX);
 	con = lua_touserdata(L, -1);
Index: src/log.c
===================================================================
--- src/log.c	(.../tags/lighttpd-1.4.23)
+++ src/log.c	(.../branches/lighttpd-1.4.x)
@@ -62,7 +62,6 @@
 		/* create write pipe and spawn process */
 
 		int to_log_fds[2];
-		pid_t pid;
 
 		if (pipe(to_log_fds)) {
 			log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
@@ -70,7 +69,7 @@
 		}
 
 		/* fork, execve */
-		switch (pid = fork()) {
+		switch (fork()) {
 		case 0:
 			/* child */
 			close(STDIN_FILENO);
@@ -150,14 +149,14 @@
  */
 
 int log_error_open(server *srv) {
-	int close_stderr = 1;
-
 #ifdef HAVE_SYSLOG_H
 	/* perhaps someone wants to use syslog() */
 	openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
 #endif
-	srv->errorlog_mode = ERRORLOG_STDERR;
 
+	srv->errorlog_mode = ERRORLOG_FD;
+	srv->errorlog_fd = STDERR_FILENO;
+
 	if (srv->srvconf.errorlog_use_syslog) {
 		srv->errorlog_mode = ERRORLOG_SYSLOG;
 	} else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
@@ -171,20 +170,36 @@
 
 	log_error_write(srv, __FILE__, __LINE__, "s", "server started");
 
-#ifdef HAVE_VALGRIND_VALGRIND_H
-	/* don't close stderr for debugging purposes if run in valgrind */
-	if (RUNNING_ON_VALGRIND) close_stderr = 0;
-#endif
-
-	if (srv->errorlog_mode == ERRORLOG_STDERR && srv->srvconf.dont_daemonize) {
+	if (srv->errorlog_mode == ERRORLOG_FD && !srv->srvconf.dont_daemonize) {
 		/* We can only log to stderr in dont-daemonize mode;
 		 * if we do daemonize and no errorlog file is specified, we log into /dev/null
 		 */
-		close_stderr = 0;
+		srv->errorlog_fd = -1;
 	}
 
-	/* move stderr to /dev/null */
-	if (close_stderr) openDevNull(STDERR_FILENO);
+	if (!buffer_is_empty(srv->srvconf.breakagelog_file)) {
+		int breakage_fd;
+		const char *logfile = srv->srvconf.breakagelog_file->ptr;
+
+		if (srv->errorlog_mode == ERRORLOG_FD) {
+			srv->errorlog_fd = dup(STDERR_FILENO);
+#ifdef FD_CLOEXEC
+			fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
+#endif
+		}
+
+		if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) {
+			return -1;
+		}
+
+		if (STDERR_FILENO != breakage_fd) {
+			dup2(breakage_fd, STDERR_FILENO);
+			close(breakage_fd);
+		}
+	} else if (!srv->srvconf.dont_daemonize) {
+		/* move stderr to /dev/null */
+		openDevNull(STDERR_FILENO);
+	}
 	return 0;
 }
 
@@ -235,15 +250,19 @@
 	switch(srv->errorlog_mode) {
 	case ERRORLOG_PIPE:
 	case ERRORLOG_FILE:
-		close(srv->errorlog_fd);
+	case ERRORLOG_FD:
+		if (-1 != srv->errorlog_fd) {
+			/* don't close STDERR */
+			if (STDERR_FILENO != srv->errorlog_fd)
+				close(srv->errorlog_fd);
+			srv->errorlog_fd = -1;
+		}
 		break;
 	case ERRORLOG_SYSLOG:
 #ifdef HAVE_SYSLOG_H
 		closelog();
 #endif
 		break;
-	case ERRORLOG_STDERR:
-		break;
 	}
 
 	return 0;
@@ -255,7 +274,8 @@
 	switch(srv->errorlog_mode) {
 	case ERRORLOG_PIPE:
 	case ERRORLOG_FILE:
-	case ERRORLOG_STDERR:
+	case ERRORLOG_FD:
+		if (-1 == srv->errorlog_fd) return 0;
 		/* cache the generated timestamp */
 		if (srv->cur_ts != srv->last_generated_debug_ts) {
 			buffer_prepare_copy(srv->ts_debug_str, 255);
@@ -349,13 +369,10 @@
 	switch(srv->errorlog_mode) {
 	case ERRORLOG_PIPE:
 	case ERRORLOG_FILE:
+	case ERRORLOG_FD:
 		buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
 		write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
 		break;
-	case ERRORLOG_STDERR:
-		buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
-		write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
-		break;
 	case ERRORLOG_SYSLOG:
 		syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
 		break;
Index: src/proc_open.c
===================================================================
--- src/proc_open.c	(.../tags/lighttpd-1.4.23)
+++ src/proc_open.c	(.../branches/lighttpd-1.4.x)
@@ -309,6 +309,14 @@
 
 	if (err) {
 		proc_read_fd_to_buffer(proc.err.fd, err);
+	} else {
+		buffer *tmp = buffer_init();
+		proc_read_fd_to_buffer(proc.err.fd, tmp);
+		if (tmp->used > 0 &&  write(2, (void*)tmp->ptr, tmp->used) < 0) {
+			perror("error writing pipe");
+			return -1;
+		}
+		buffer_free(tmp);
 	}
 	pipe_close(&proc.err);
 
Index: tests/.cvsignore
===================================================================
Index: tests/bug-12.conf
===================================================================
--- tests/bug-12.conf	(.../tags/lighttpd-1.4.23)
+++ tests/bug-12.conf	(.../branches/lighttpd-1.4.x)
@@ -8,6 +8,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/fastcgi-10.conf
===================================================================
--- tests/fastcgi-10.conf	(.../tags/lighttpd-1.4.23)
+++ tests/fastcgi-10.conf	(.../branches/lighttpd-1.4.x)
@@ -6,6 +6,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/bug-06.conf
===================================================================
--- tests/bug-06.conf	(.../tags/lighttpd-1.4.23)
+++ tests/bug-06.conf	(.../branches/lighttpd-1.4.x)
@@ -8,6 +8,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/mod-extforward.conf
===================================================================
Index: tests/var-include.conf
===================================================================
--- tests/var-include.conf	(.../tags/lighttpd-1.4.23)
+++ tests/var-include.conf	(.../branches/lighttpd-1.4.x)
@@ -10,6 +10,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/404-handler.conf
===================================================================
--- tests/404-handler.conf	(.../tags/lighttpd-1.4.23)
+++ tests/404-handler.conf	(.../branches/lighttpd-1.4.x)
@@ -10,6 +10,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/lowercase.conf
===================================================================
--- tests/lowercase.conf	(.../tags/lighttpd-1.4.23)
+++ tests/lowercase.conf	(.../branches/lighttpd-1.4.x)
@@ -6,6 +6,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 
 server.force-lowercase-filenames = "enable"
 
Index: tests/condition.conf
===================================================================
--- tests/condition.conf	(.../tags/lighttpd-1.4.23)
+++ tests/condition.conf	(.../branches/lighttpd-1.4.x)
@@ -10,6 +10,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/fastcgi-13.conf
===================================================================
--- tests/fastcgi-13.conf	(.../tags/lighttpd-1.4.23)
+++ tests/fastcgi-13.conf	(.../branches/lighttpd-1.4.x)
@@ -10,6 +10,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/mod-compress.conf
===================================================================
--- tests/mod-compress.conf	(.../tags/lighttpd-1.4.23)
+++ tests/mod-compress.conf	(.../branches/lighttpd-1.4.x)
@@ -11,6 +11,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 
 server.modules = (
Index: tests/lighttpd.conf
===================================================================
--- tests/lighttpd.conf	(.../tags/lighttpd-1.4.23)
+++ tests/lighttpd.conf	(.../branches/lighttpd-1.4.x)
@@ -13,6 +13,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/fastcgi-responder.conf
===================================================================
--- tests/fastcgi-responder.conf	(.../tags/lighttpd-1.4.23)
+++ tests/fastcgi-responder.conf	(.../branches/lighttpd-1.4.x)
@@ -15,6 +15,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/fastcgi-auth.conf
===================================================================
--- tests/fastcgi-auth.conf	(.../tags/lighttpd-1.4.23)
+++ tests/fastcgi-auth.conf	(.../branches/lighttpd-1.4.x)
@@ -12,6 +12,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Apache 1.3.29"
 
Index: tests/proxy.conf
===================================================================
--- tests/proxy.conf	(.../tags/lighttpd-1.4.23)
+++ tests/proxy.conf	(.../branches/lighttpd-1.4.x)
@@ -6,6 +6,7 @@
 ## bind to localhost (default: all interfaces)
 server.bind                = "localhost"
 server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.breakagelog         = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.breakage.log"
 server.name                = "www.example.org"
 server.tag                 = "Proxy"
 
Index: tests/LightyTest.pm
===================================================================
--- tests/LightyTest.pm	(.../tags/lighttpd-1.4.23)
+++ tests/LightyTest.pm	(.../branches/lighttpd-1.4.x)
@@ -87,14 +87,21 @@
 	my $self = shift;
 	my $port = shift;
 	my $child = shift;
+	my $timeout = 5*10; # 5 secs, select waits 0.1 s
 
 	while (0 == $self->listening_on($port)) {
 		select(undef, undef, undef, 0.1);
+		$timeout--;
 
 		# the process is gone, we failed
 		if (0 != waitpid($child, WNOHANG)) {
 			return -1;
 		}
+		if (0 >= $timeout) {
+			diag("Timeout while trying to connect; killing child");
+			kill('TERM', $child);
+			return -1;
+		}
 	}
 
 	return 0;
Index: configure.ac
===================================================================
Index: doc/.cvsignore
===================================================================
Index: doc/fastcgi.txt
===================================================================
--- doc/fastcgi.txt	(.../tags/lighttpd-1.4.23)
+++ doc/fastcgi.txt	(.../branches/lighttpd-1.4.x)
@@ -95,23 +95,22 @@
       (
         ( "host" =>  ,
           "port" =>  ,
-	  "socket" => ,       # either socket
-	                              # or host+port
-	  "bin-path" => ,     # OPTIONAL
-	  "bin-environment" => , # OPTIONAL
-	  "bin-copy-environment" => , # OPTIONAL
+          "socket" => ,       # either socket
+                                      # or host+port
+          "bin-path" => ,     # OPTIONAL
+          "bin-environment" => , # OPTIONAL
+          "bin-copy-environment" => , # OPTIONAL
           "mode" => ,         # OPTIONAL
           "docroot" =>  ,     # OPTIONAL if "mode"
-	                              # is not "authorizer"
+                                      # is not "authorizer"
           "check-local" => ,  # OPTIONAL
-	  "min-procs" => ,   # OPTIONAL
-	  "max-procs" => ,   # OPTIONAL
-	  "max-load-per-proc" => , # OPTIONAL
-	  "idle-timeout" => , # OPTIONAL
-	  "broken-scriptfilename" => , # OPTIONAL
+          "max-procs" => ,   # OPTIONAL
+          "broken-scriptfilename" => , # OPTIONAL
           "disable-time" => , # optional
-          "allow-x-send-file" =>  # optional
-	),
+          "allow-x-send-file" => , # optional
+          "kill-signal" => , # OPTIONAL
+          "fix-root-scriptname" => ,
+                                      # OPTIONAL
         ( "host" => ...
         )
       )
@@ -127,42 +126,38 @@
   :"socket":    path to the unix-domain socket
   :"mode":      is the FastCGI protocol mode.
                 Default is "responder", also "authorizer"
-		mode is implemented.
+                mode is implemented.
   :"docroot":   is optional and is the docroot on the remote
                 host for default "responder" mode. For
-		"authorizer" mode it is MANDATORY and it points
-		to docroot for authorized requests. For security
-		reasons it is recommended to keep this docroot
+                "authorizer" mode it is MANDATORY and it points
+                to docroot for authorized requests. For security
+                reasons it is recommended to keep this docroot
                 outside of server.document-root tree.
   :"check-local": is optional and may be "enable" (default) or
                 "disable". If enabled the server first check
-		for a file in local server.document-root tree
-		and return 404 (Not Found) if no such file.
+                for a file in local server.document-root tree
+                and return 404 (Not Found) if no such file.
                 If disabled, the server forward request to
-		FastCGI interface without this check.
+                FastCGI interface without this check.
   :"broken-scriptfilename": breaks SCRIPT_FILENAME in a wat that
                 PHP can extract PATH_INFO from it (default: disabled)
   :"disable-time": time to wait before a disabled backend is checked
                 again
   :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
                 are allowed
+  :"fix-root-scriptname": fix broken path-info split for "/" extension ("prefix")
 
   If bin-path is set:
 
-  :"min-procs": sets the minium processes to start
   :"max-procs": the upper limit of the processess to start
-  :"max-load-per-proc": maximum number of waiting processes on
-                average per process before a new process is
-                spawned
-  :"idle-timeout": number of seconds before a unused process
-                gets terminated
   :"bin-environment": put an entry into the environment of
                 the started process
   :"bin-copy-environement": clean up the environment and copy
                 only the specified entries into the fresh
                 environment of the spawn process
+  :"kill-signal": signal to terminate the FastCGI process with,
+                defauls to SIGTERM
 
-
 Examples
 --------
 
@@ -171,11 +166,11 @@
     fastcgi.server = ( ".php" =>
       (( "host" => "127.0.0.1",
          "port" => 1026,
-	 "bin-path" => "/usr/local/bin/php"
+         "bin-path" => "/usr/local/bin/php"
       )),
       ".php4" =>
       (( "host" => "127.0.0.1",
-	 "port" => 1026
+         "port" => 1026
       ))
     )
 
@@ -183,10 +178,10 @@
 
     fastcgi.server = ( "/remote_scripts/" =>
       (( "host" => "192.168.0.3",
-	 "port" => 9000,
+         "port" => 9000,
          "check-local" => "disable",
          "docroot" => "/" # remote server may use
-	                  # it's own docroot
+                          # it's own docroot
       ))
     )
 
@@ -206,7 +201,7 @@
 
     fastcgi.server = ( "/remote_scripts/" =>
       (( "host" => "10.0.0.2",
-	 "port" => 9000,
+         "port" => 9000,
          "docroot" => "/path_to_private_docs",
          "mode" => "authorizer"
       ))
@@ -318,10 +313,10 @@
      $ PHP_FCGI_CHILDREN=384 ./lighttpd -f ./lighttpd.conf
 
      fastcgi.server = ( ".php" =>
-  	(( "socket" => "/tmp/php.socket",
+        (( "socket" => "/tmp/php.socket",
            "bin-path" => "/usr/local/bin/php",
            "min-procs" => 1,
-	   "max-procs" => 1,
+           "max-procs" => 1,
            "max-load-per-proc" => 4,
            "idle-timeout" => 20
         ))
@@ -408,7 +403,7 @@
            "PHP_FCGI_CHILDREN" => "16",
            "PHP_FCGI_MAX_REQUESTS" => "10000" ),
         "bin-copy-environment" => (
-	   "PATH", "SHELL", "USER" )
+           "PATH", "SHELL", "USER" )
      ))
    )
 
Index: SConstruct
===================================================================
Index: Makefile.am
===================================================================
--- Makefile.am	(.../tags/lighttpd-1.4.23)
+++ Makefile.am	(.../branches/lighttpd-1.4.x)
@@ -2,4 +2,6 @@
 
 EXTRA_DIST=autogen.sh SConstruct
 
+ACLOCAL_AMFLAGS = -I m4
+
 distcleancheck_listfiles = find -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
Index: autogen.sh
===================================================================
--- autogen.sh	(.../tags/lighttpd-1.4.23)
+++ autogen.sh	(.../branches/lighttpd-1.4.x)
@@ -1,27 +1,92 @@
 #!/bin/sh
 # Run this to generate all the initial makefiles, etc.
 
-LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
 LIBTOOLIZE_FLAGS="--copy --force"
-ACLOCAL=${ACLOCAL:-aclocal}
-AUTOHEADER=${AUTOHEADER:-autoheader}
-AUTOMAKE=${AUTOMAKE:-automake}
-AUTOMAKE_FLAGS="--add-missing --copy"
-AUTOCONF=${AUTOCONF:-autoconf}
+AUTOMAKE_FLAGS="--add-missing --copy --foreign"
 
 ARGV0=$0
+ARGS="$@"
 
-set -e
 
-
 run() {
-	echo "$ARGV0: running \`$@'"
-	$@
+	echo "$ARGV0: running \`$@' $ARGS"
+	$@ $ARGS
 }
 
+## jump out if one of the programs returns 'false'
+set -e
+
+## on macosx glibtoolize, others have libtool
+if test x$LIBTOOLIZE = x; then
+  if test \! "x`which glibtoolize 2> /dev/null | grep -v '^no'`" = x; then
+    LIBTOOLIZE=glibtoolize
+  elif test \! "x`which libtoolize-1.5 2> /dev/null | grep -v '^no'`" = x; then
+    LIBTOOLIZE=libtoolize-1.5
+  elif test \! "x`which libtoolize 2> /dev/null | grep -v '^no'`" = x; then
+    LIBTOOLIZE=libtoolize
+  else 
+    echo "libtoolize 1.5.x wasn't found, exiting"; exit 0
+  fi
+fi
+
+## suse has aclocal and aclocal-1.9
+if test x$ACLOCAL = x; then
+  if test \! "x`which aclocal-1.9 2> /dev/null | grep -v '^no'`" = x; then
+    ACLOCAL=aclocal-1.9
+  elif test \! "x`which aclocal19 2> /dev/null | grep -v '^no'`" = x; then
+    ACLOCAL=aclocal19
+  elif test \! "x`which aclocal 2> /dev/null | grep -v '^no'`" = x; then
+    ACLOCAL=aclocal
+  else 
+    echo "automake 1.9.x (aclocal) wasn't found, exiting"; exit 0
+  fi
+fi
+
+if test x$AUTOMAKE = x; then
+  if test \! "x`which automake-1.9 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOMAKE=automake-1.9
+  elif test \! "x`which automake19 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOMAKE=automake19
+  elif test \! "x`which automake 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOMAKE=automake
+  else 
+    echo "automake 1.9.x wasn't found, exiting"; exit 0
+  fi
+fi
+
+
+## macosx has autoconf-2.59 and autoconf-2.60
+if test x$AUTOCONF = x; then
+  if test \! "x`which autoconf-2.59 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOCONF=autoconf-2.59
+  elif test \! "x`which autoconf259 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOCONF=autoconf259
+  elif test \! "x`which autoconf 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOCONF=autoconf
+  else 
+    echo "autoconf 2.59+ wasn't found, exiting"; exit 0
+  fi
+fi
+
+if test x$AUTOHEADER = x; then
+  if test \! "x`which autoheader-2.59 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOHEADER=autoheader-2.59
+  elif test \! "x`which autoheader259 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOHEADER=autoheader259
+  elif test \! "x`which autoheader 2> /dev/null | grep -v '^no'`" = x; then
+    AUTOHEADER=autoheader
+  else 
+    echo "autoconf 2.59+ (autoheader) wasn't found, exiting"; exit 0
+  fi
+fi
+
+mkdir -p m4
 run $LIBTOOLIZE $LIBTOOLIZE_FLAGS
-run $ACLOCAL $ACLOCAL_FLAGS
+run $ACLOCAL $ACLOCAL_FLAGS -I m4
 run $AUTOHEADER
 run $AUTOMAKE $AUTOMAKE_FLAGS
 run $AUTOCONF
-echo "Now type './configure ...' and 'make' to compile."
+
+if test "$ARGS" = "" ; then
+  echo "Now type './configure ...' and 'make' to compile."
+fi
Index: NEWS
===================================================================
--- NEWS	(.../tags/lighttpd-1.4.23)
+++ NEWS	(.../branches/lighttpd-1.4.x)
@@ -3,7 +3,42 @@
 NEWS
 ====
 
-- 1.4.23 -
+- 1.4.24 -
+  * Add T_CONFIG_INT for bigger integers from the config (needed for #1966)
+  * Use unsigned int (and T_CONFIG_INT) for max_request_size
+  * Use unsigned int for secdownload.timeout (fixes #1966)
+  * Keep url/host values from connection to display information while keep-alive in mod_status (fixes #1202)
+  * Add server.breakagelog, a "special" stderr (fixes #1863)
+  * Fix config evaluation for debug.log-timeouts option (#1529)
+  * Add "cgi.execute-x-only" to mod_cgi, requires +x for cgi scripts (fixes #2013)
+  * Fix FD_SETSIZE comparision warnings
+  * Add "lua-5.1" to searched pkg-config names for lua
+  * Fix unused function webdav_lockdiscovery in mod_webdav
+  * cmake: Fix crypt lib check
+  * cmake: Add -export-dynamic to link flags, fixes build on FreeBSD
+  * Set FD_CLOEXEC for bound sockets before pipe-logger forks (fixes #2026)
+  * Reset ignored signals to SIG_DFL before exec() in fastcgi/scgi (fixes #2029)
+  * Show "no uri specified -> 400" error only when "debug.log-request-header-on-error" is enabled (fixes #2030)
+  * Fix hanging connection in mod_scgi (fixes #2024)
+  * Allow digits in hostnames in more places (fixes #1148)
+  * Use connection_reset instead of handle_request_done for cleanup callbacks
+  * Change mod_expire to append Cache-Control instead of overwriting it (fixes #1997)
+  * Allow all comparisons for $SERVER["socket"] - only bind for "=="
+  * Remove strptime failed message (fixes #2031)
+  * Fix issues found with clang analyzer
+  * Try to fix server.tag issue with localized svnversion
+  * Fix handling network-write return values (#2024)
+  * Use disable-time in fastcgi for all disables after errors, default is 1sec (fixes #2040)
+  * Remove adaptive spawning code from fastcgi (was disabled for a long time)
+  * Allow mod_mysql_vhost to use stored procedures (fixes #2011, thx Ben Brown)
+  * Fix ipv6 in mod_proxy (fixes #2043)
+  * Print errors from include_shell to stderr
+  * Set tm.tm_isdst = 0 before mktime() (fixes #2047)
+  * Use linux-epoll by default if available (fixes #2021, thx Olaf van der Spek)
+  * Print an error if you use too many captures in a regex pattern (fixes #2059)
+  * Combine Cache-Control header value in mod_expire to existing HTTP header if header already added by other modules (fixes #2068)
+
+- 1.4.23 - 2009-06-19
   * Added some extra warning options in cmake and fix the resulting warnings (unused/static functions)
   * New lighttpd man page (moved it to section 8) (fixes #1875)
   * Create rrd file for empty rrdfile in mod_rrdtool (#1788)
Index: CMakeLists.txt
===================================================================