summaryrefslogtreecommitdiffstats
path: root/usr.sbin/httpd/src
diff options
context:
space:
mode:
authorbeck <beck@openbsd.org>1998-10-11 19:44:59 +0000
committerbeck <beck@openbsd.org>1998-10-11 19:44:59 +0000
commit0ad52bed66a21e2d9cde06cdbb2fa8563982553b (patch)
tree436beee31e9b2153b6be177e3461de7701b82945 /usr.sbin/httpd/src
parenttypo: Thuner != Thunder; spotted by theo. (diff)
downloadwireguard-openbsd-0ad52bed66a21e2d9cde06cdbb2fa8563982553b.tar.xz
wireguard-openbsd-0ad52bed66a21e2d9cde06cdbb2fa8563982553b.zip
Apache 1.3.3 merge + proxy_segv fix
Diffstat (limited to 'usr.sbin/httpd/src')
-rw-r--r--usr.sbin/httpd/src/CHANGES120
-rw-r--r--usr.sbin/httpd/src/Configure20
-rw-r--r--usr.sbin/httpd/src/README.EBCDIC60
-rw-r--r--usr.sbin/httpd/src/helpers/GuessOS15
-rw-r--r--usr.sbin/httpd/src/include/ap_config.h6
-rw-r--r--usr.sbin/httpd/src/include/ap_mmn.h3
-rw-r--r--usr.sbin/httpd/src/include/httpd.h25
-rw-r--r--usr.sbin/httpd/src/main/alloc.c62
-rw-r--r--usr.sbin/httpd/src/main/buff.c15
-rw-r--r--usr.sbin/httpd/src/main/http_config.c60
-rw-r--r--usr.sbin/httpd/src/main/http_core.c17
-rw-r--r--usr.sbin/httpd/src/main/http_log.c201
-rw-r--r--usr.sbin/httpd/src/main/http_main.c330
-rw-r--r--usr.sbin/httpd/src/main/http_protocol.c409
-rw-r--r--usr.sbin/httpd/src/main/http_request.c48
-rw-r--r--usr.sbin/httpd/src/main/util.c5
-rw-r--r--usr.sbin/httpd/src/main/util_script.c5
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_util.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth_db.c4
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c4
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_autoindex.c148
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_cgi.c1
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_digest.c4
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_include.c1
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_log_config.c7
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_speling.c23
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_status.c8
-rw-r--r--usr.sbin/httpd/src/os/bs2000/bs2login.c3
-rw-r--r--usr.sbin/httpd/src/os/bs2000/ebcdic.c3
-rw-r--r--usr.sbin/httpd/src/os/win32/registry.c2
-rw-r--r--usr.sbin/httpd/src/os/win32/util_win32.c40
-rw-r--r--usr.sbin/httpd/src/support/dbmmanage4
33 files changed, 1140 insertions, 517 deletions
diff --git a/usr.sbin/httpd/src/CHANGES b/usr.sbin/httpd/src/CHANGES
index 03bfe02f369..2d9899db077 100644
--- a/usr.sbin/httpd/src/CHANGES
+++ b/usr.sbin/httpd/src/CHANGES
@@ -1,3 +1,121 @@
+Changes with Apache 1.3.3
+
+ *) Added a complete implementation of the Expect header field as
+ specified in rev-05 of HTTP/1.1. Disabled the 100 Continue
+ response when we already know the final status, which is mighty
+ useful for PUT responses that result in 302 or 401. [Roy Fielding]
+
+ *) Remove extra trailing whitespace from the getline results as part
+ of the protocol processing, which is extra nice because it works
+ between continuation lines, is almost no cost in the normal case
+ of no extra whitespace, and saves memory. [Roy Fielding]
+
+ *) Added new HTTP status codes and default response bodies from the
+ revised HTTP/1.1 (307, 416, 417), WebDAV (102, 207, 422, 423), and
+ HTTP Extension Framework (510) specifications. Did not add the
+ WebDAV 424 and 425 codes because they are bogus. We don't use any
+ of these codes yet, but they are now available to 3rd-party modules.
+ [Roy Fielding]
+
+ *) Fix a possible race condition between timed-out requests and the
+ ap_bhalfduplex select that might result in an infinite loop on
+ platforms that do not validate the descriptor. [Roy Fielding]
+
+ *) WIN32: Add "-k shutdown" and "-k restart" options to signal a
+ running Apache server [Paul Sutton]
+
+ *) Fix mod_autoindex bug where directories got a size of "0k" instead
+ of "-". [Martin Plechsmid <plechsmi@karlin.mff.cuni.cz>, Marc Slemko]
+ PR#3130
+
+ *) PORT: DRS 6000 machine. [Paul Debleecker <pdebleecker@jetair.be>]
+
+ *) Add the server signature text (from the core ServerSignature directive)
+ to the list of envariables available to scripts, SSI, and the like.
+ [Ken Coar]
+
+ *) PORT: Fix sys/resource.h handling for SCO 3.x platform.
+ [M. Laak <maert@proinv.ee>] PR#3108
+
+ *) Fallback from sysconf-based to plain HZ-based `ticks per second'
+ calculation in mod_status for all systems which don't have POSIX
+ sysconf() (like UTS 2.1) and not only for the NEXT platform.
+ [Dave Dykstra <dwd@bell-labs.com>] PR#3055
+
+ *) Fix `require ...' directive parsing in mod_auth, mod_auth_dbm and
+ mod_auth_db by using ap_getword_white() (which uses ap_isspace())
+ instead of ap_getword(..., ' ') (which parses only according to spaces
+ but not tabs). [James Morris <jmorris@intercode.com.au>,
+ Ralf S. Engelschall] PR#3105
+
+ *) Fix the SERVER_NAME variable under sub-request situations (where
+ `UseCanonicalName off' is used) like CGI's called from SSI pages or
+ RewriteCond variables by adopting r->hostname to sub-requests.
+ [James Grinter <jrg@blodwen.demon.co.uk>] PR#3111
+
+ *) Fix stderr redirection under syslog-based error logging situation.
+ [Youichirou Koga <y-koga@jp.FreeBSD.org>] PR#3095
+
+ *) Document `ErrorLog syslog:facility' variant of error logging.
+ [Youichirou Koga <y-koga@jp.FreeBSD.org>] PR#3096
+
+ *) Fix http://localhost/ hints in top-level INSTALL document.
+ [Rob Jenson <robjen@spotch.com>, Ralf S. Engelschall] PR#3088
+
+ *) Quote paths in default configuration files. [Wilfredo Sanchez]
+
+ *) PORT: Remove extra HAVE_SYS_RESOURCE_H define for RHAPSODY since
+ it is now taken care of properly by the header file tests.
+ [Wilfredo Sanchez <wsanchez@apple.com>]
+
+ *) Fix problem with scripts and filehandle inheritance on Win32.
+ [Ken Parzygnat <kparz@raleigh.ibm.com>] PR#2884, 2910
+
+ *) Win32 name canonicalisation could end up using the server's
+ working directory to fill in some blanks. [Ken Parzygnat
+ <kparz@raleigh.ibm.com>] PR#3001
+
+ *) Correct invalid assumption by ap_sub_req_lookup_file() that all
+ absolute paths begin with "/" -- because they don't on Win32.
+ [Ken Parzygnat <kparz@raleigh.ibm.com>] PR#2976, 3074
+
+ *) Add [REDIRECT_]VARIANTS environment variable to mod_speling
+ so that ErrorDocument 300 processors can reformat the list
+ if desired. [Ken Coar] PR#2859
+
+ *) Add +/- incremental prefixes to IndexOptions keywords, and
+ enable merging of multiple IndexOptions directives. [Ken Coar]
+
+ *) PORT: Allow GuessOS to recognize Unixware 7.0.1 [Steve Cameron
+ <steve.cameron@compaq.com>]
+
+ *) Reconstructed the loop through multiple htaccess file names so
+ that missing files are not confused with unreadable files.
+ [Roy Fielding]
+
+ *) The ap_pfopen and ap_pfdopen routines were failing to protect the
+ errno on an error, which leads to one error being mistaken for
+ another when reading non-existent .htaccess files.
+ [Jim Jagielski]
+
+ *) OS/2: The new header tests get things right, need to update
+ ap_config.h. [Brian Havard]
+
+ *) The Perl %ENV hash will now be setup by default when using the
+ mod_include `perl' command [Doug MacEachern]
+
+ *) PORT: Add Pyramid DC/OSx support to configuration mechanism.
+ [Earle Ake <akee@wpdiss1.wpafb.af.mil>]
+
+ *) PORT: Fix sys/resource.h handling for Amdahl's UTS 2.1
+ [Dave Dykstra <dwd@bell-labs.com>] PR#3054
+
+ *) Correct comment in mod_log_config.c about its internals.
+ [Elf Sternberg <elf@halcyon.com>]
+
+ *) Avoid possible line overflow in Configure: Use an awkfile to
+ handle the creation of modules.c [Jim Jagielski]
+
Changes with Apache 1.3.2
*) Fix bug in ap_remove_module(), which caused problems for dso's
@@ -2129,7 +2247,7 @@ Changes with Apache 1.3b4
[robinton@amtrash.comlink.de (Soeren Ziehe), Martin Kraemer]
*) PORT: Apache now compiles & runs on an EBCDIC mainframe
- (the Siemens Nixdorf BS2000-OSD family) in the POSIX subsystem
+ (the Siemens BS2000/OSD family) in the POSIX subsystem
[Martin Kraemer]
*) PORT: Fix problem killing children when terminating. Allow ^C
diff --git a/usr.sbin/httpd/src/Configure b/usr.sbin/httpd/src/Configure
index a8822c7dcfe..e961d076187 100644
--- a/usr.sbin/httpd/src/Configure
+++ b/usr.sbin/httpd/src/Configure
@@ -618,6 +618,12 @@ case "$PLAT" in
DEF_WANTHSREGEX=yes
LIBS="$LIBS -lsocket -lnsl -lc"
;;
+ pyramid-pyramid-svr4)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4 -DNO_LONG_DOUBLE"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
DS/90\ 7000-*-sysv4*)
OS='UXP/DS'
CFLAGS="$CFLAGS -DUXPDS"
@@ -708,6 +714,12 @@ case "$PLAT" in
DEF_WANTHSREGEX=yes
LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
;;
+ drs6000*)
+ OS='DRS6000'
+ CFLAGS="$CFLAGS -DSVR4"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
+ ;;
*) # default: Catch systems we don't know about
OS='Unknown and unsupported OS'
echo Sorry, but we cannot grok \"$PLAT\"
@@ -1499,7 +1511,7 @@ if [ "x$using_shlib" = "x1" ] ; then
# select the special subtarget for shared core generation
SUBTARGET=target_shared
# determine additional suffixes for libhttpd.so
- V=1 R=3 P=2
+ V=1 R=3 P=3
if [ ".$SHLIB_SUFFIX_DEPTH" = .0 ]; then
SHLIB_SUFFIX_LIST=""
fi
@@ -1540,7 +1552,7 @@ fi
####################################################################
## Now create modules.c
##
-cat $tmpfile | sed 's/_module//' | awk >modules.c '
+$CAT > $awkfile <<'EOFM'
BEGIN {
modules[n++] = "core"
pmodules[pn++] = "core"
@@ -1588,7 +1600,9 @@ cat $tmpfile | sed 's/_module//' | awk >modules.c '
print " NULL"
print "};"
print ""
- }'
+ }
+EOFM
+$CAT $tmpfile | sed 's/_module//' | awk -f $awkfile > modules.c
####################################################################
## figure out which module dir require use to autocreate a Makefile.
diff --git a/usr.sbin/httpd/src/README.EBCDIC b/usr.sbin/httpd/src/README.EBCDIC
index 749ddc66765..e3361adadf3 100644
--- a/usr.sbin/httpd/src/README.EBCDIC
+++ b/usr.sbin/httpd/src/README.EBCDIC
@@ -2,8 +2,8 @@
This version of Apache comes with a first-cut (working, but not
fully tested) port to a mainframe machine which uses the EBCDIC
-character set as its native codeset (It is the SIEMENS NIXDORF
-family of mainframes running the BS2000 operating system. This
+character set as its native codeset (It is the SIEMENS family
+of mainframes running the BS2000 operating system. This
mainframe OS nowadays features a SVR4-like POSIX subsystem).
The port was started initially to
@@ -22,7 +22,7 @@ decisions of the port to this machine.
#ifdef CHARSET_EBCDIC Code which is needed for any EBCDIC
based machine
#ifdef _OSD_POSIX Code which is needed for the BS2000
- SIEMENS NIXDORF mainframe platform only.
+ SIEMENS mainframe platform only.
* The possibility to translate between ASCII and EBCDIC at the
socket level (on BS2000 POSIX, there is a socket option which
@@ -88,56 +88,6 @@ decisions of the port to this machine.
An example for the latter case is the wwwcount program which we ported
as well.
-What works:
-- In the following list,
- + means: works, tested
- - means: doesn't work for some reason
- ? means: compiled-in, but untested
-
- http_core.c +
- mod_access.c +
- mod_actions.c ?
- mod_alias.c +
- mod_asis.c ?
- mod_auth.c +
- mod_auth_anon.c +
- mod_auth_db.c ? with own libdb.a
- mod_auth_dbm.c ? with own libdb.a
- mod_autoindex.c +
- mod_cern_meta.c ?
- mod_cgi.c +
- mod_digest.c - / MD5 not ported yet
- mod_dir.c +
- mod_env.c +
- mod_example.c - / not tried yet
- mod_expires.c +
- mod_headers.c +
- mod_imap.c +
- mod_include.c +
- mod_info.c +
- mod_log_agent.c +
- mod_log_config.c +
- mod_log_referer.c +
- mod_mime.c +
- mod_mime_magic.c - / not tried yet
- mod_negotiation.c +
- mod_proxy.c +
- mod_rewrite.c ? / untested
- mod_setenvif.c +
- mod_so.c - / no shared libs
- mod_speling.c +
- mod_status.c +
- mod_unique_id.c +
- mod_userdir.c +
- mod_usertrack.c ? / untested
-
-Additional (third-party) modules: See:
- mod_jserv.c - / JAVA still being ported http://java.apache.org/
- mod_php.c - / not ported yet http://www.php.net/
- mod_put.c ? / untested http://hpwww.ec-lyon.fr/~vincent/apache/mod_put.html
- mod_session.c ? / untested ftp://hachiman.vidya.com/pub/apache/mod_session.tar.gz
-
-
Notes:
To use the mod_auth_db functionality, you will need a working libdb.a.
On the system where I did the port none was available, so I ported the
@@ -145,4 +95,6 @@ standard db-1.85.14 with little problems. Note however that you will need
a working perl5 as well if you want to use Apache's dbmmanage script to
maintain db user databases.
- Martin Kraemer, 31-Mar-1998
+See also the ebcdic.html document which is part of the apache documentation.
+
+ Martin Kraemer, 1-Oct-1998
diff --git a/usr.sbin/httpd/src/helpers/GuessOS b/usr.sbin/httpd/src/helpers/GuessOS
index 5901305312d..096df4fd965 100644
--- a/usr.sbin/httpd/src/helpers/GuessOS
+++ b/usr.sbin/httpd/src/helpers/GuessOS
@@ -53,9 +53,11 @@ if [ "x$XREL" != "x" ]; then
echo "whatever-whatever-unixware1"; exit 0
;;
5)
- if [ "x$VERSION" = "x7" ]; then
- echo "${MACHINE}-whatever-unixware7"; exit 0
- fi
+ case "$VERSION" in
+ 7*)
+ echo "${MACHINE}-whatever-unixware7"; exit 0
+ ;;
+ esac
;;
esac
fi
@@ -246,6 +248,13 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
echo "whatever-unisys-sysv4"; exit 0;
;;
+ *:*:dcosx:NILE*)
+ echo "pyramid-pyramid-svr4"; exit 0;
+ ;;
+
+ *:*:*:"DRS 6000")
+ echo "drs6000-whatever-whatever"; exit 0;
+ ;;
esac
#
diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h
index e12639e81ab..60e35665ab6 100644
--- a/usr.sbin/httpd/src/include/ap_config.h
+++ b/usr.sbin/httpd/src/include/ap_config.h
@@ -372,7 +372,6 @@ typedef int pid_t;
#define USE_MMAP_SCOREBOARD
#define MAP_TMPFILE
#define HAVE_RESOURCE
-#define HAVE_SYS_RESOURCE_H /* apaci should catch this but doesn't */
#define HAVE_SNPRINTF
#define JMP_BUF jmp_buf
#define USE_LONGJMP
@@ -466,6 +465,7 @@ typedef int rlim_t;
#define NO_WRITEV
#include <sys/time.h>
#define HAVE_SYSLOG 1
+#undef HAVE_SYS_RESOURCE_H
#elif defined(SCO5)
@@ -615,6 +615,7 @@ extern char *crypt();
#define WEXITSTATUS(status) (int)((status).w_retcode)
#define WTERMSIG(status) (int)((status).w_termsig)
#define strftime(buf,bufsize,fmt,tm) ascftime(buf,fmt,tm)
+#undef HAVE_SYS_RESOURCE_H /* exists but does not provide *rlimit funcs */
#include <sys/types.h>
#include <sys/time.h>
@@ -645,6 +646,7 @@ extern char *crypt();
typedef quad_t rlim_t;
#endif
#define USE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
#define HAVE_SYSLOG 1
#define SYS_SIGLIST sys_siglist
@@ -706,8 +708,6 @@ typedef int rlim_t;
#define NEED_STRNCASECMP
#define NO_SETSID
#define NO_TIMES
-/* ap_config_auto.h gets this wrong, force sys/select.h to be included */
-#define HAVE_SYS_SELECT_H
#define CASE_BLIND_FILESYSTEM
/* Add some drive name support */
#define chdir _chdir2
diff --git a/usr.sbin/httpd/src/include/ap_mmn.h b/usr.sbin/httpd/src/include/ap_mmn.h
index 718dcd21136..5ad482c319d 100644
--- a/usr.sbin/httpd/src/include/ap_mmn.h
+++ b/usr.sbin/httpd/src/include/ap_mmn.h
@@ -159,6 +159,9 @@
* 4. compat.h -> ap_compat.h
* 5. apctype.h -> ap_ctype.h
* 19980806 (1.3.2-dev) - add ap_log_rerror()
+ * - add ap_scan_script_header_err_core()
+ * - add ap_uuencode()
+ * - add ap_custom_response()
* 19980811 (1.3.2-dev) - added limit_req_line, limit_req_fieldsize, and
* limit_req_fields to server_rec.
* added limit_req_body to core_dir_config and
diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h
index 0323072bf0a..d93a896a2db 100644
--- a/usr.sbin/httpd/src/include/httpd.h
+++ b/usr.sbin/httpd/src/include/httpd.h
@@ -410,7 +410,7 @@ extern "C" {
* Example: "Apache/1.1.0 MrWidget/0.1-alpha"
*/
-#define SERVER_BASEVERSION "Apache/1.3.2" /* SEE COMMENTS ABOVE */
+#define SERVER_BASEVERSION "Apache/1.3.3" /* SEE COMMENTS ABOVE */
#define SERVER_VERSION SERVER_BASEVERSION
enum server_token_type {
SrvTk_MIN, /* eg: Apache/1.3.0 */
@@ -427,7 +427,7 @@ API_EXPORT(const char *) ap_get_server_built(void);
* For a final release, 'betaseq' should be set to '99'.
* For example, Apache 1.4.2 should be '1040299'
*/
-#define APACHE_RELEASE 1030299
+#define APACHE_RELEASE 1030399
#define SERVER_PROTOCOL "HTTP/1.1"
#ifndef SERVER_SUPPORT
@@ -443,10 +443,15 @@ API_EXPORT(const char *) ap_get_server_built(void);
/* ----------------------- HTTP Status Codes ------------------------- */
-#define RESPONSE_CODES 38
+/* The size of the static array in http_protocol.c for storing
+ * all of the potential response status-lines (a sparse table).
+ * A future version should dynamically generate the table at startup.
+ */
+#define RESPONSE_CODES 54
#define HTTP_CONTINUE 100
#define HTTP_SWITCHING_PROTOCOLS 101
+#define HTTP_PROCESSING 102
#define HTTP_OK 200
#define HTTP_CREATED 201
#define HTTP_ACCEPTED 202
@@ -454,12 +459,14 @@ API_EXPORT(const char *) ap_get_server_built(void);
#define HTTP_NO_CONTENT 204
#define HTTP_RESET_CONTENT 205
#define HTTP_PARTIAL_CONTENT 206
+#define HTTP_MULTI_STATUS 207
#define HTTP_MULTIPLE_CHOICES 300
#define HTTP_MOVED_PERMANENTLY 301
#define HTTP_MOVED_TEMPORARILY 302
#define HTTP_SEE_OTHER 303
#define HTTP_NOT_MODIFIED 304
#define HTTP_USE_PROXY 305
+#define HTTP_TEMPORARY_REDIRECT 307
#define HTTP_BAD_REQUEST 400
#define HTTP_UNAUTHORIZED 401
#define HTTP_PAYMENT_REQUIRED 402
@@ -476,6 +483,10 @@ API_EXPORT(const char *) ap_get_server_built(void);
#define HTTP_REQUEST_ENTITY_TOO_LARGE 413
#define HTTP_REQUEST_URI_TOO_LARGE 414
#define HTTP_UNSUPPORTED_MEDIA_TYPE 415
+#define HTTP_RANGE_NOT_SATISFIABLE 416
+#define HTTP_EXPECTATION_FAILED 417
+#define HTTP_UNPROCESSABLE_ENTITY 422
+#define HTTP_LOCKED 423
#define HTTP_INTERNAL_SERVER_ERROR 500
#define HTTP_NOT_IMPLEMENTED 501
#define HTTP_BAD_GATEWAY 502
@@ -483,6 +494,7 @@ API_EXPORT(const char *) ap_get_server_built(void);
#define HTTP_GATEWAY_TIME_OUT 504
#define HTTP_VERSION_NOT_SUPPORTED 505
#define HTTP_VARIANT_ALSO_VARIES 506
+#define HTTP_NOT_EXTENDED 510
#define DOCUMENT_FOLLOWS HTTP_OK
#define PARTIAL_CONTENT HTTP_PARTIAL_CONTENT
@@ -740,6 +752,13 @@ struct request_rec {
* that way, a sub request's list can (temporarily) point to a parent's list
*/
const struct htaccess_result *htaccess;
+
+/* Things placed at the end of the record to avoid breaking binary
+ * compatibility. It would be nice to remember to reorder the entire
+ * record to improve 64bit alignment the next time we need to break
+ * binary compatibility for some other reason.
+ */
+ unsigned expecting_100; /* is client waiting for a 100 response? */
};
diff --git a/usr.sbin/httpd/src/main/alloc.c b/usr.sbin/httpd/src/main/alloc.c
index 67b4c224b67..e85a85aa3d2 100644
--- a/usr.sbin/httpd/src/main/alloc.c
+++ b/usr.sbin/httpd/src/main/alloc.c
@@ -1744,6 +1744,7 @@ API_EXPORT(FILE *) ap_pfopen(pool *a, const char *name, const char *mode)
FILE *fd = NULL;
int baseFlag, desc;
int modeFlags = 0;
+ int saved_errno;
#ifdef WIN32
modeFlags = _S_IREAD | _S_IWRITE;
@@ -1766,22 +1767,26 @@ API_EXPORT(FILE *) ap_pfopen(pool *a, const char *name, const char *mode)
else {
fd = fopen(name, mode);
}
-
+ saved_errno = errno;
if (fd != NULL)
ap_note_cleanups_for_file(a, fd);
ap_unblock_alarms();
+ errno = saved_errno;
return fd;
}
API_EXPORT(FILE *) ap_pfdopen(pool *a, int fd, const char *mode)
{
FILE *f;
+ int saved_errno;
ap_block_alarms();
f = ap_fdopen(fd, mode);
+ saved_errno = errno;
if (f != NULL)
ap_note_cleanups_for_file(a, f);
ap_unblock_alarms();
+ errno = saved_errno;
return f;
}
@@ -2217,6 +2222,10 @@ API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), voi
HANDLE hPipeInputWrite = NULL;
HANDLE hPipeErrorRead = NULL;
HANDLE hPipeErrorWrite = NULL;
+ HANDLE hPipeInputWriteDup = NULL;
+ HANDLE hPipeOutputReadDup = NULL;
+ HANDLE hPipeErrorReadDup = NULL;
+ HANDLE hCurrentProcess;
int pid = 0;
child_info info;
@@ -2255,6 +2264,57 @@ API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), voi
}
return 0;
}
+ /*
+ * When the pipe handles are created, the security descriptor
+ * indicates that the handle can be inherited. However, we do not
+ * want the server side handles to the pipe to be inherited by the
+ * child CGI process. If the child CGI does inherit the server
+ * side handles, then the child may be left around if the server
+ * closes its handles (e.g. if the http connection is aborted),
+ * because the child will have a valid copy of handles to both
+ * sides of the pipes, and no I/O error will occur. Microsoft
+ * recommends using DuplicateHandle to turn off the inherit bit
+ * under NT and Win95.
+ */
+ hCurrentProcess = GetCurrentProcess();
+ if ((pipe_in && !DuplicateHandle(hCurrentProcess, hPipeInputWrite,
+ hCurrentProcess,
+ &hPipeInputWriteDup, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ || (pipe_out && !DuplicateHandle(hCurrentProcess, hPipeOutputRead,
+ hCurrentProcess, &hPipeOutputReadDup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ || (pipe_err && !DuplicateHandle(hCurrentProcess, hPipeErrorRead,
+ hCurrentProcess, &hPipeErrorReadDup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))) {
+ if (pipe_in) {
+ CloseHandle(hPipeInputRead);
+ CloseHandle(hPipeInputWrite);
+ }
+ if (pipe_out) {
+ CloseHandle(hPipeOutputRead);
+ CloseHandle(hPipeOutputWrite);
+ }
+ if (pipe_err) {
+ CloseHandle(hPipeErrorRead);
+ CloseHandle(hPipeErrorWrite);
+ }
+ return 0;
+ }
+ else {
+ if (pipe_in) {
+ CloseHandle(hPipeInputWrite);
+ hPipeInputWrite = hPipeInputWriteDup;
+ }
+ if (pipe_out) {
+ CloseHandle(hPipeOutputRead);
+ hPipeOutputRead = hPipeOutputReadDup;
+ }
+ if (pipe_err) {
+ CloseHandle(hPipeErrorRead);
+ hPipeErrorRead = hPipeErrorReadDup;
+ }
+ }
/* The script writes stdout to this pipe handle */
info.hPipeOutputWrite = hPipeOutputWrite;
diff --git a/usr.sbin/httpd/src/main/buff.c b/usr.sbin/httpd/src/main/buff.c
index 0501b1a7377..a8cb2515160 100644
--- a/usr.sbin/httpd/src/main/buff.c
+++ b/usr.sbin/httpd/src/main/buff.c
@@ -562,14 +562,22 @@ static int saferead(BUFF *fb, char *buf, int nbyte)
#endif
-/* note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE */
+/* Test the descriptor and flush the output buffer if it looks like
+ * we will block on the next read.
+ *
+ * Note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE
+ */
API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
{
int rv;
fd_set fds;
struct timeval tv;
- if (fb->incnt > 0 || fb->outcnt == 0) {
+ /* We don't need to do anything if the connection has been closed
+ * or there is something readable in the incoming buffer
+ * or there is nothing flushable in the output buffer.
+ */
+ if (fb == NULL || fb->fd_in < 0 || fb->incnt > 0 || fb->outcnt == 0) {
return;
}
/* test for a block */
@@ -579,7 +587,8 @@ API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
- } while (rv < 0 && errno == EINTR);
+ } while (rv < 0 && errno == EINTR && !(fb->flags & B_EOUT));
+
/* treat any error as if it would block as well */
if (rv != 1) {
ap_bflush(fb);
diff --git a/usr.sbin/httpd/src/main/http_config.c b/usr.sbin/httpd/src/main/http_config.c
index 307e9044d1e..50f865712b1 100644
--- a/usr.sbin/httpd/src/main/http_config.c
+++ b/usr.sbin/httpd/src/main/http_config.c
@@ -1206,7 +1206,7 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,
char *filename = NULL;
const struct htaccess_result *cache;
struct htaccess_result *new;
- void *dc;
+ void *dc = NULL;
/* firstly, search cache */
for (cache = r->htaccess; cache != NULL; cache = cache->next)
@@ -1224,41 +1224,39 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,
parms.path = ap_pstrdup(r->pool, d);
/* loop through the access names and find the first one */
- while (!f && access_name[0]) {
- char *w = ap_getword_conf(r->pool, &access_name);
- filename = ap_make_full_path(r->pool, d, w);
- f = ap_pcfg_openfile(r->pool, filename);
- }
- if (f) {
- dc = ap_create_per_dir_config(r->pool);
- parms.config_file = f;
+ while (access_name[0]) {
+ filename = ap_make_full_path(r->pool, d,
+ ap_getword_conf(r->pool, &access_name));
- errmsg = ap_srm_command_loop(&parms, dc);
+ if ((f = ap_pcfg_openfile(r->pool, filename)) != NULL) {
- ap_cfg_closefile(f);
+ dc = ap_create_per_dir_config(r->pool);
- if (errmsg) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, r, "%s: %s",
- filename, errmsg);
- ap_table_setn(r->notes, "error-notes", errmsg);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
+ parms.config_file = f;
- *result = dc;
- }
- else {
- if (errno == ENOENT || errno == ENOTDIR)
- dc = NULL;
- else {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
- "%s pcfg_openfile: unable to check htaccess file, ensure it is readable",
- filename);
- ap_table_setn(r->notes, "error-notes",
- "Server unable to read htaccess file, denying "
- "access to be safe");
- return HTTP_FORBIDDEN;
- }
+ errmsg = ap_srm_command_loop(&parms, dc);
+
+ ap_cfg_closefile(f);
+
+ if (errmsg) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, r,
+ "%s: %s", filename, errmsg);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ *result = dc;
+ break;
+ }
+ else if (errno != ENOENT && errno != ENOTDIR) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
+ "%s pcfg_openfile: unable to check htaccess file, "
+ "ensure it is readable",
+ filename);
+ ap_table_setn(r->notes, "error-notes",
+ "Server unable to read htaccess file, denying "
+ "access to be safe");
+ return HTTP_FORBIDDEN;
+ }
}
/* cache it */
diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c
index de5a7e04aab..320f907e6f1 100644
--- a/usr.sbin/httpd/src/main/http_core.c
+++ b/usr.sbin/httpd/src/main/http_core.c
@@ -2670,8 +2670,20 @@ static int core_translate(request_rec *r)
(r->uri + r->server->pathlen), NULL);
}
else {
- r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri,
- NULL);
+ /*
+ * Make sure that we do not mess up the translation by adding two
+ * /'s in a row. This happens under windows when the document
+ * root ends with a /
+ */
+ if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] == '/')
+ && (*(r->uri) == '/')) {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri+1,
+ NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri,
+ NULL);
+ }
}
return OK;
@@ -2743,7 +2755,6 @@ static int default_handler(request_rec *r)
emsg = ap_pstrcat(r->pool, emsg, r->filename, r->path_info, NULL);
}
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, emsg);
- ap_table_setn(r->notes, "error-notes", emsg);
return HTTP_NOT_FOUND;
}
if (r->method_number != M_GET) {
diff --git a/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c
index 094bbfc5746..3c380862563 100644
--- a/usr.sbin/httpd/src/main/http_log.c
+++ b/usr.sbin/httpd/src/main/http_log.c
@@ -154,7 +154,7 @@ static const TRANS priorities[] = {
{NULL, -1},
};
-static int error_log_child (void *cmd, child_info *pinfo)
+static int error_log_child(void *cmd, child_info *pinfo)
{
/* Child process code for 'ErrorLog "|..."';
* may want a common framework for this, since I expect it will
@@ -165,23 +165,23 @@ static int error_log_child (void *cmd, child_info *pinfo)
ap_cleanup_for_exec();
#ifdef SIGHUP
/* No concept of a child process on Win32 */
- signal (SIGHUP, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
#endif /* ndef SIGHUP */
#if defined(WIN32)
- child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
return(child_pid);
#elif defined(OS2)
/* For OS/2 we need to use a '/' */
- execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
#else
- execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
+ execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
#endif
- exit (1);
+ exit(1);
/* NOT REACHED */
return(child_pid);
}
-static void open_error_log (server_rec *s, pool *p)
+static void open_error_log(server_rec *s, pool *p)
{
char *fname;
@@ -190,9 +190,9 @@ static void open_error_log (server_rec *s, pool *p)
if (!ap_spawn_child(p, error_log_child, (void *)(s->error_fname+1),
kill_after_timeout, &dummy, NULL, NULL)) {
- perror ("ap_spawn_child");
- fprintf (stderr, "Couldn't fork child for ErrorLog process\n");
- exit (1);
+ perror("ap_spawn_child");
+ fprintf(stderr, "Couldn't fork child for ErrorLog process\n");
+ exit(1);
}
s->error_log = dummy;
@@ -219,8 +219,8 @@ static void open_error_log (server_rec *s, pool *p)
}
#endif
else {
- fname = ap_server_root_relative (p, s->error_fname);
- if(!(s->error_log = ap_pfopen(p, fname, "a"))) {
+ fname = ap_server_root_relative(p, s->error_fname);
+ if (!(s->error_log = ap_pfopen(p, fname, "a"))) {
perror("fopen");
fprintf(stderr,"httpd: could not open error log file %s.\n", fname);
exit(1);
@@ -228,18 +228,18 @@ static void open_error_log (server_rec *s, pool *p)
}
}
-void ap_open_logs (server_rec *s_main, pool *p)
+void ap_open_logs(server_rec *s_main, pool *p)
{
server_rec *virt, *q;
int replace_stderr;
- open_error_log (s_main, p);
+ open_error_log(s_main, p);
replace_stderr = 1;
if (s_main->error_log) {
/* replace stderr with this new log */
fflush(stderr);
- if (dup2(fileno(s_main->error_log), 2) == -1) {
+ if (dup2(fileno(s_main->error_log), STDERR_FILENO) == -1) {
ap_log_error(APLOG_MARK, APLOG_CRIT, s_main,
"unable to replace stderr with error_log");
} else {
@@ -262,20 +262,23 @@ void ap_open_logs (server_rec *s_main, pool *p)
if (q->error_fname != NULL &&
strcmp(q->error_fname, virt->error_fname) == 0)
break;
- if (q == virt) open_error_log (virt, p);
- else virt->error_log = q->error_log;
+ if (q == virt)
+ open_error_log(virt, p);
+ else
+ virt->error_log = q->error_log;
}
else
virt->error_log = s_main->error_log;
}
}
-API_EXPORT(void) ap_error_log2stderr (server_rec *s) {
- if(fileno(s->error_log) != STDERR_FILENO)
- dup2(fileno(s->error_log),STDERR_FILENO);
+API_EXPORT(void) ap_error_log2stderr(server_rec *s) {
+ if ( s->error_log != NULL
+ && fileno(s->error_log) != STDERR_FILENO)
+ dup2(fileno(s->error_log), STDERR_FILENO);
}
-static void log_error_core (const char *file, int line, int level,
+static void log_error_core(const char *file, int line, int level,
const server_rec *s, const request_rec *r,
const char *fmt, va_list args)
{
@@ -423,7 +426,7 @@ static void log_error_core (const char *file, int line, int level,
#endif
}
-API_EXPORT(void) ap_log_error (const char *file, int line, int level,
+API_EXPORT(void) ap_log_error(const char *file, int line, int level,
const server_rec *s, const char *fmt, ...)
{
va_list args;
@@ -440,27 +443,35 @@ API_EXPORT(void) ap_log_rerror(const char *file, int line, int level,
va_start(args, fmt);
log_error_core(file, line, level, r->server, r, fmt, args);
- if (ap_table_get(r->notes, "error-notes") == NULL) {
- char errstr[MAX_STRING_LEN];
-
- ap_vsnprintf(errstr, sizeof(errstr), fmt, args);
- ap_table_set(r->notes, "error-notes", errstr);
+ /*
+ * IF the error level is 'warning' or more severe,
+ * AND there isn't already error text associated with this request,
+ * THEN make the message text available to ErrorDocument and
+ * other error processors. This can be disabled by stuffing
+ * something, even an empty string, into the "error-notes" cell
+ * before calling this routine.
+ */
+ if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
+ && (ap_table_get(r->notes, "error-notes") == NULL)) {
+ ap_table_setn(r->notes, "error-notes",
+ ap_pvsprintf(r->pool, fmt, args));
}
va_end(args);
}
-void ap_log_pid (pool *p, char *fname)
+void ap_log_pid(pool *p, char *fname)
{
FILE *pid_file;
struct stat finfo;
static pid_t saved_pid = -1;
pid_t mypid;
- if (!fname) return;
+ if (!fname)
+ return;
- fname = ap_server_root_relative (p, fname);
+ fname = ap_server_root_relative(p, fname);
mypid = getpid();
- if (mypid != saved_pid && stat(fname,&finfo) == 0) {
+ if (mypid != saved_pid && stat(fname, &finfo) == 0) {
/* USR1 and HUP call this on each restart.
* Only warn on first time through for this pid.
*
@@ -475,28 +486,28 @@ void ap_log_pid (pool *p, char *fname)
);
}
- if(!(pid_file = fopen(fname,"w"))) {
+ if(!(pid_file = fopen(fname, "w"))) {
perror("fopen");
- fprintf(stderr,"httpd: could not log pid to file %s\n", fname);
+ fprintf(stderr, "httpd: could not log pid to file %s\n", fname);
exit(1);
}
- fprintf(pid_file,"%ld\n",(long)mypid);
+ fprintf(pid_file, "%ld\n", (long)mypid);
fclose(pid_file);
saved_pid = mypid;
}
-API_EXPORT(void) ap_log_error_old (const char *err, server_rec *s)
+API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s)
{
ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err);
}
-API_EXPORT(void) ap_log_unixerr (const char *routine, const char *file,
+API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
const char *msg, server_rec *s)
{
ap_log_error(file, 0, APLOG_ERR, s, "%s", msg);
}
-API_EXPORT(void) ap_log_printf (const server_rec *s, const char *fmt, ...)
+API_EXPORT(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
{
va_list args;
@@ -505,7 +516,7 @@ API_EXPORT(void) ap_log_printf (const server_rec *s, const char *fmt, ...)
va_end(args);
}
-API_EXPORT(void) ap_log_reason (const char *reason, const char *file, request_rec *r)
+API_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r)
{
ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
"access to %s failed for %s, reason: %s",
@@ -514,7 +525,7 @@ API_EXPORT(void) ap_log_reason (const char *reason, const char *file, request_re
reason);
}
-API_EXPORT(void) ap_log_assert (const char *szExp, const char *szFile, int nLine)
+API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
{
fprintf(stderr, "[%s] file %s, line %d, assertion \"%s\" failed\n",
ap_get_time(), szFile, nLine, szExp);
@@ -530,9 +541,9 @@ API_EXPORT(void) ap_log_assert (const char *szExp, const char *szFile, int nLine
#ifndef NO_RELIABLE_PIPED_LOGS
/* forward declaration */
-static void piped_log_maintenance (int reason, void *data, ap_wait_t status);
+static void piped_log_maintenance(int reason, void *data, ap_wait_t status);
-static int piped_log_spawn (piped_log *pl)
+static int piped_log_spawn(piped_log *pl)
{
int pid;
@@ -545,32 +556,32 @@ static int piped_log_spawn (piped_log *pl)
* XXX: close all the relevant stuff, but hey, it could be broken. */
RAISE_SIGSTOP(PIPED_LOG_SPAWN);
/* we're now in the child */
- close (STDIN_FILENO);
- dup2 (pl->fds[0], STDIN_FILENO);
-
- ap_cleanup_for_exec ();
- signal (SIGCHLD, SIG_DFL); /* for HPUX */
- signal (SIGHUP, SIG_IGN);
- execl (SHELL_PATH, SHELL_PATH, "-c", pl->program, NULL);
- fprintf (stderr,
+ close(STDIN_FILENO);
+ dup2(pl->fds[0], STDIN_FILENO);
+
+ ap_cleanup_for_exec();
+ signal(SIGCHLD, SIG_DFL); /* for HPUX */
+ signal(SIGHUP, SIG_IGN);
+ execl(SHELL_PATH, SHELL_PATH, "-c", pl->program, NULL);
+ fprintf(stderr,
"piped_log_spawn: unable to exec %s -c '%s': %s\n",
SHELL_PATH, pl->program, strerror (errno));
- exit (1);
+ exit(1);
}
if (pid == -1) {
- fprintf (stderr,
+ fprintf(stderr,
"piped_log_spawn: unable to fork(): %s\n", strerror (errno));
- ap_unblock_alarms ();
+ ap_unblock_alarms();
return -1;
}
ap_unblock_alarms();
pl->pid = pid;
- ap_register_other_child (pid, piped_log_maintenance, pl, pl->fds[1]);
+ ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]);
return 0;
}
-static void piped_log_maintenance (int reason, void *data, ap_wait_t status)
+static void piped_log_maintenance(int reason, void *data, ap_wait_t status)
{
piped_log *pl = data;
@@ -578,30 +589,30 @@ static void piped_log_maintenance (int reason, void *data, ap_wait_t status)
case OC_REASON_DEATH:
case OC_REASON_LOST:
pl->pid = -1;
- ap_unregister_other_child (pl);
+ ap_unregister_other_child(pl);
if (pl->program == NULL) {
/* during a restart */
break;
}
- if (piped_log_spawn (pl) == -1) {
+ if (piped_log_spawn(pl) == -1) {
/* what can we do? This could be the error log we're having
* problems opening up... */
- fprintf (stderr,
+ fprintf(stderr,
"piped_log_maintenance: unable to respawn '%s': %s\n",
- pl->program, strerror (errno));
+ pl->program, strerror(errno));
}
break;
case OC_REASON_UNWRITABLE:
if (pl->pid != -1) {
- kill (pl->pid, SIGTERM);
+ kill(pl->pid, SIGTERM);
}
break;
case OC_REASON_RESTART:
pl->program = NULL;
if (pl->pid != -1) {
- kill (pl->pid, SIGTERM);
+ kill(pl->pid, SIGTERM);
}
break;
@@ -611,67 +622,67 @@ static void piped_log_maintenance (int reason, void *data, ap_wait_t status)
}
-static void piped_log_cleanup (void *data)
+static void piped_log_cleanup(void *data)
{
piped_log *pl = data;
if (pl->pid != -1) {
- kill (pl->pid, SIGTERM);
+ kill(pl->pid, SIGTERM);
}
- ap_unregister_other_child (pl);
- close (pl->fds[0]);
- close (pl->fds[1]);
+ ap_unregister_other_child(pl);
+ close(pl->fds[0]);
+ close(pl->fds[1]);
}
-static void piped_log_cleanup_for_exec (void *data)
+static void piped_log_cleanup_for_exec(void *data)
{
piped_log *pl = data;
- close (pl->fds[0]);
- close (pl->fds[1]);
+ close(pl->fds[0]);
+ close(pl->fds[1]);
}
-API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program)
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
{
piped_log *pl;
- pl = ap_palloc (p, sizeof (*pl));
+ pl = ap_palloc(p, sizeof (*pl));
pl->p = p;
- pl->program = ap_pstrdup (p, program);
+ pl->program = ap_pstrdup(p, program);
pl->pid = -1;
ap_block_alarms ();
- if (pipe (pl->fds) == -1) {
+ if (pipe(pl->fds) == -1) {
int save_errno = errno;
ap_unblock_alarms();
errno = save_errno;
return NULL;
}
- ap_register_cleanup (p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
- if (piped_log_spawn (pl) == -1) {
+ ap_register_cleanup(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
+ if (piped_log_spawn(pl) == -1) {
int save_errno = errno;
- ap_kill_cleanup (p, pl, piped_log_cleanup);
- close (pl->fds[0]);
- close (pl->fds[1]);
- ap_unblock_alarms ();
+ ap_kill_cleanup(p, pl, piped_log_cleanup);
+ close(pl->fds[0]);
+ close(pl->fds[1]);
+ ap_unblock_alarms();
errno = save_errno;
return NULL;
}
- ap_unblock_alarms ();
+ ap_unblock_alarms();
return pl;
}
-API_EXPORT(void) ap_close_piped_log (piped_log *pl)
+API_EXPORT(void) ap_close_piped_log(piped_log *pl)
{
- ap_block_alarms ();
- piped_log_cleanup (pl);
- ap_kill_cleanup (pl->p, pl, piped_log_cleanup);
- ap_unblock_alarms ();
+ ap_block_alarms();
+ piped_log_cleanup(pl);
+ ap_kill_cleanup(pl->p, pl, piped_log_cleanup);
+ ap_unblock_alarms();
}
#else
-static int piped_log_child (void *cmd, child_info *pinfo)
+static int piped_log_child(void *cmd, child_info *pinfo)
{
/* Child process code for 'TransferLog "|..."';
* may want a common framework for this, since I expect it will
@@ -681,10 +692,10 @@ static int piped_log_child (void *cmd, child_info *pinfo)
ap_cleanup_for_exec();
#ifdef SIGHUP
- signal (SIGHUP, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
#endif
#if defined(WIN32)
- child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
return(child_pid);
#elif defined(OS2)
/* For OS/2 we need to use a '/' */
@@ -692,24 +703,24 @@ static int piped_log_child (void *cmd, child_info *pinfo)
#else
execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
#endif
- perror ("exec");
- fprintf (stderr, "Exec of shell for logging failed!!!\n");
+ perror("exec");
+ fprintf(stderr, "Exec of shell for logging failed!!!\n");
return(child_pid);
}
-API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program)
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
{
piped_log *pl;
FILE *dummy;
if (!ap_spawn_child(p, piped_log_child, (void *)program,
kill_after_timeout, &dummy, NULL, NULL)) {
- perror ("ap_spawn_child");
- fprintf (stderr, "Couldn't fork child for piped log process\n");
+ perror("ap_spawn_child");
+ fprintf(stderr, "Couldn't fork child for piped log process\n");
exit (1);
}
- pl = ap_palloc (p, sizeof (*pl));
+ pl = ap_palloc(p, sizeof (*pl));
pl->p = p;
pl->write_f = dummy;
@@ -717,8 +728,8 @@ API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program)
}
-API_EXPORT(void) ap_close_piped_log (piped_log *pl)
+API_EXPORT(void) ap_close_piped_log(piped_log *pl)
{
- ap_pfclose (pl->p, pl->write_f);
+ ap_pfclose(pl->p, pl->write_f);
}
#endif
diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c
index 2b6833f1542..defbca0b5bf 100644
--- a/usr.sbin/httpd/src/main/http_main.c
+++ b/usr.sbin/httpd/src/main/http_main.c
@@ -999,6 +999,10 @@ static void usage(char *bin)
fprintf(stderr, " -l : list compiled-in modules\n");
fprintf(stderr, " -S : show parsed settings (currently only vhost settings)\n");
fprintf(stderr, " -t : run syntax test for configuration files only\n");
+#ifdef WIN32
+ fprintf(stderr, " -k shutdown : tell running Apache to shutdown\n");
+ fprintf(stderr, " -k restart : tell running Apache to do a graceful restart\n");
+#endif
exit(1);
}
@@ -2542,17 +2546,41 @@ static int volatile generation;
#ifdef WIN32
/*
- * signal_parent() tells the parent process to wake up and do something.
- * Once woken it will look at shutdown_pending and restart_pending to decide
- * what to do. If neither variable is set, it will do a shutdown. This function
- * if called by start_shutdown() or start_restart() in the parent's process
- * space, so that the variables get set. However it can also be called
- * by child processes to force the parent to exit in an emergency.
+ * Signalling Apache on NT.
+ *
+ * Under Unix, Apache can be told to shutdown or restart by sending various
+ * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so
+ * we use "events" instead. The parent apache process goes into a loop
+ * where it waits forever for a set of events. Two of those events are
+ * called
+ *
+ * apPID_shutdown
+ * apPID_restart
+ *
+ * (where PID is the PID of the apache parent process). When one of these
+ * is signalled, the Apache parent performs the appropriate action. The events
+ * can become signalled through internal Apache methods (e.g. if the child
+ * finds a fatal error and needs to kill its parent), via the service
+ * control manager (the control thread will signal the shutdown event when
+ * requested to stop the Apache service), from the -k Apache command line,
+ * or from any external program which finds the Apache PID from the
+ * httpd.pid file.
+ *
+ * The signal_parent() function, below, is used to signal one of these events.
+ * It can be called by any child or parent process, since it does not
+ * rely on global variables.
+ *
+ * On entry, type gives the event to signal. 0 means shutdown, 1 means
+ * graceful restart.
*/
-static void signal_parent(void)
+static void signal_parent(int type)
{
HANDLE e;
+ char *signal_name;
+ extern char signal_shutdown_name[];
+ extern char signal_restart_name[];
+
/* after updating the shutdown_pending or restart flags, we need
* to wake up the parent process so it can see the changes. The
* parent will normally be waiting for either a child process
@@ -2564,21 +2592,28 @@ static void signal_parent(void)
return;
}
- APD1("*** SIGNAL_PARENT SET ***");
+ switch(type) {
+ case 0: signal_name = signal_shutdown_name; break;
+ case 1: signal_name = signal_restart_name; break;
+ default: return;
+ }
- e = OpenEvent(EVENT_ALL_ACCESS, FALSE, "apache-signal");
+ APD2("signal_parent signalling event \"%s\"", signal_name);
+
+ e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name);
if (!e) {
- /* Um, problem, can't signal the main loop, which means we can't
+ /* Um, problem, can't signal the parent, which means we can't
* signal ourselves to die. Ignore for now...
*/
ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
- "OpenEvent on apache-signal event");
+ "OpenEvent on %s event", signal_name);
return;
}
if (SetEvent(e) == 0) {
/* Same problem as above */
ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
- "SetEvent on apache-signal event");
+ "SetEvent on %s event", signal_name);
+ CloseHandle(e);
return;
}
CloseHandle(e);
@@ -2586,24 +2621,19 @@ static void signal_parent(void)
#endif
/*
- * start_shutdown() and start_restart(), below, are a first stab at
+ * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
* functions to initiate shutdown or restart without relying on signals.
* Previously this was initiated in sig_term() and restart() signal handlers,
* but we want to be able to start a shutdown/restart from other sources --
* e.g. on Win32, from the service manager. Now the service manager can
- * call start_shutdown() or start_restart() as appropiate.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
+ * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
+ * these functions can also be called by the child processes, since global
+ * variables are no longer used to pass on the required action to the parent.
*/
void ap_start_shutdown(void)
{
+#ifndef WIN32
if (shutdown_pending == 1) {
/* Um, is this _probably_ not an error, if the user has
* tried to do a shutdown twice quickly, so we won't
@@ -2612,24 +2642,23 @@ void ap_start_shutdown(void)
return;
}
shutdown_pending = 1;
-
-#ifdef WIN32
- signal_parent(); /* get the parent process to wake up */
+#else
+ signal_parent(0); /* get the parent process to wake up */
#endif
}
/* do a graceful restart if graceful == 1 */
void ap_start_restart(int graceful)
{
+#ifndef WIN32
if (restart_pending == 1) {
/* Probably not an error - don't bother reporting it */
return;
}
restart_pending = 1;
is_graceful = graceful;
-
-#ifdef WIN32
- signal_parent(); /* get the parent process to wake up */
+#else
+ signal_parent(1); /* get the parent process to wake up */
#endif /* WIN32 */
}
@@ -4633,11 +4662,13 @@ int REALMAIN(int argc, char *argv[])
*
* Signalling between the parent and working process uses a Win32
* event. Each child has a unique name for the event, which is
- * passed to it with the -c argument when the child is spawned. The
+ * passed to it with the -Z argument when the child is spawned. The
* parent sets (signals) this event to tell the child to die.
* At present all children do a graceful die - they finish all
* current jobs _and_ empty the listen queue before they exit.
- * A non-graceful die would need a second event.
+ * A non-graceful die would need a second event. The -Z argument in
+ * the child is also used to create the shutdown and restart events,
+ * since the prefix (apPID) contains the parent process PID.
*
* The code below starts with functions at the lowest level -
* worker threads, and works up to the top level - the main()
@@ -5001,17 +5032,37 @@ extern void main_control_server(void *); /* in hellop.c */
event *exit_event;
mutex *start_mutex;
+#define MAX_SIGNAL_NAME 30 /* Long enough for apPID_shutdown, where PID is an int */
+char signal_name_prefix[MAX_SIGNAL_NAME];
+char signal_restart_name[MAX_SIGNAL_NAME];
+char signal_shutdown_name[MAX_SIGNAL_NAME];
+
#define MAX_SELECT_ERRORS 100
+/*
+ * Initialise the signal names, in the global variables signal_name_prefix,
+ * signal_restart_name and signal_shutdown_name.
+ */
+
+void setup_signal_names(char *prefix)
+{
+ ap_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix);
+ ap_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name),
+ "%s_shutdown", signal_name_prefix);
+ ap_snprintf(signal_restart_name, sizeof(signal_restart_name),
+ "%s_restart", signal_name_prefix);
+
+ APD2("signal prefix %s", signal_name_prefix);
+}
+
+/*
+ * worker_main() is main loop for the child process. The loop in
+ * this function becomes the controlling thread for the actually working
+ * threads (which run in a loop in child_sub_main()).
+ */
+
void worker_main(void)
{
- /*
- * I am writing this stuff specifically for NT.
- * have pulled out a lot of the restart and
- * graceful restart stuff, because that is only
- * useful on Unix (not sure it even makes sense
- * in a multi-threaded env.
- */
int nthreads;
fd_set main_fds;
int srv;
@@ -5059,7 +5110,13 @@ void worker_main(void)
reinit_scoreboard(pconf);
- //ap_acquire_mutex(start_mutex);
+ /*
+ * Wait until we have permission to start accepting connections.
+ * start_mutex is used to ensure that only one child ever
+ * goes into the listen/accept loop at once. Also wait on exit_event,
+ * in case we (this child) is told to die before we get a chance to
+ * serve any requests.
+ */
hObjects[0] = (HANDLE)start_mutex;
hObjects[1] = (HANDLE)exit_event;
rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
@@ -5085,7 +5142,7 @@ void worker_main(void)
ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
"No sockets were created for listening");
- signal_parent(); /* tell parent to die */
+ signal_parent(0); /* tell parent to die */
ap_destroy_pool(pchild);
cleanup_scoreboard();
@@ -5114,15 +5171,11 @@ void worker_main(void)
/* spawn off the threads */
child_handles = (thread *) alloca(nthreads * sizeof(int));
- {
- int i;
-
- for (i = 0; i < nthreads; i++) {
- child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
- }
- if (nthreads > max_daemons_limit) {
- max_daemons_limit = nthreads;
- }
+ for (i = 0; i < nthreads; i++) {
+ child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
+ }
+ if (nthreads > max_daemons_limit) {
+ max_daemons_limit = nthreads;
}
while (1) {
@@ -5288,22 +5341,21 @@ void worker_main(void)
clean_parent_exit(0);
} /* standalone_main */
-/* Spawn a child Apache process. The child process has the command
- * line arguments from argc and argv[], plus a -Z argument giving the
- * name of an event. The child should open and poll or wait on this
- * event. When it is signalled, the child should die. prefix is a
- * prefix string for the event name.
+/*
+ * Spawn a child Apache process. The child process has the command line arguments from
+ * argc and argv[], plus a -Z argument giving the name of an event. The child should
+ * open and poll or wait on this event. When it is signalled, the child should die.
+ * prefix is a prefix string for the event name.
*
- * The child_num argument on entry contains a serial number for this
- * child (used to create a unique event name). On exit, this number
- * will have been incremented by one, ready for the next call.
+ * The child_num argument on entry contains a serial number for this child (used to create
+ * a unique event name). On exit, this number will have been incremented by one, ready
+ * for the next call.
*
* On exit, the value pointed to be *ev will contain the event created
* to signal the new child process.
*
- * The return value is the handle to the child process if successful,
- * else -1. If -1 is returned the error will already have been logged
- * by ap_log_error().
+ * The return value is the handle to the child process if successful, else -1. If -1 is
+ * returned the error will already have been logged by ap_log_error().
*/
int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, char *prefix)
@@ -5311,8 +5363,15 @@ int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, ch
char buf[40], mod[200];
int i, rv;
char **pass_argv = (char **) alloca(sizeof(char *) * (argc + 3));
-
- ap_snprintf(buf, sizeof(buf), "%s_%d", prefix, ++(*child_num));
+
+ /* We need an event to tell the child process to kill itself when
+ * the parent is doing a shutdown/restart. This will be named
+ * apPID_CN where PID is the parent Apache process PID and
+ * N is a unique child serial number. prefix contains
+ * the "apPID" part. The child will get the name of this
+ * event as its -Z command line argument.
+ */
+ ap_snprintf(buf, sizeof(buf), "%s_C%d", prefix, ++(*child_num));
_flushall();
*ev = CreateEvent(NULL, TRUE, FALSE, buf);
if (!*ev) {
@@ -5409,10 +5468,11 @@ int master_main(int argc, char **argv)
int *child;
int child_num = 0;
int rv, cld;
- char buf[100];
+ char signal_prefix_string[100];
int i;
time_t tmstart;
- HANDLE signal_event; /* used to signal shutdown/restart to parent */
+ HANDLE signal_shutdown_event; /* used to signal shutdown to parent */
+ HANDLE signal_restart_event; /* used to signal a restart to parent */
HANDLE process_handles[MAX_PROCESSES];
HANDLE process_kill_events[MAX_PROCESSES];
int current_live_processes = 0; /* number of child process we know about */
@@ -5425,22 +5485,34 @@ int master_main(int argc, char **argv)
is_graceful = 0;
++generation;
- signal_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, "apache-signal");
- if (!signal_event) {
+ ap_snprintf(signal_prefix_string, sizeof(signal_prefix_string),
+ "ap%d", getpid());
+ setup_signal_names(signal_prefix_string);
+
+ signal_shutdown_event = CreateEvent(NULL, TRUE, FALSE, signal_shutdown_name);
+ if (!signal_shutdown_event) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
+ "Cannot create shutdown event %s", signal_shutdown_name);
+ exit(1);
+ }
+ APD2("master_main: created event %s", signal_shutdown_name);
+ signal_restart_event = CreateEvent(NULL, TRUE, FALSE, signal_restart_name);
+ if (!signal_restart_event) {
+ CloseHandle(signal_shutdown_event);
ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
- "Cannot open apache-signal event");
+ "Cannot create restart event %s", signal_restart_name);
exit(1);
}
+ APD2("master_main: created event %s", signal_restart_name);
- sprintf(buf, "Apache%d", getpid());
- start_mutex = ap_create_mutex(buf);
+ start_mutex = ap_create_mutex(signal_prefix_string);
ev = (event **) alloca(sizeof(event *) * nchild);
child = (int *) alloca(sizeof(int) * (nchild+1));
while (processes_to_create--) {
service_set_status(SERVICE_START_PENDING);
if (create_process(process_handles, process_kill_events,
- &current_live_processes, &child_num, buf, argc, argv) < 0) {
+ &current_live_processes, &child_num, signal_prefix_string, argc, argv) < 0) {
goto die_now;
}
}
@@ -5461,8 +5533,6 @@ int master_main(int argc, char **argv)
ap_set_version();
ap_init_modules(pconf, server_conf);
version_locked++;
- if (!is_graceful)
- reinit_scoreboard(pconf);
restart_pending = shutdown_pending = 0;
@@ -5478,15 +5548,17 @@ int master_main(int argc, char **argv)
ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
"master_main: no child processes alive! creating one");
if (create_process(process_handles, process_kill_events,
- &current_live_processes, &child_num, buf, argc, argv) < 0) {
+ &current_live_processes, &child_num, signal_prefix_string,
+ argc, argv) < 0) {
goto die_now;
}
if (processes_to_create) {
processes_to_create--;
}
}
- process_handles[current_live_processes] = signal_event;
- rv = WaitForMultipleObjects(current_live_processes+1, (HANDLE *)process_handles,
+ process_handles[current_live_processes] = signal_shutdown_event;
+ process_handles[current_live_processes+1] = signal_restart_event;
+ rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,
FALSE, INFINITE);
if (rv == WAIT_FAILED) {
/* Something serious is wrong */
@@ -5495,13 +5567,35 @@ int master_main(int argc, char **argv)
shutdown_pending = 1;
break;
}
- ap_assert(rv != WAIT_TIMEOUT);
+ if (rv == WAIT_TIMEOUT) {
+ /* Hey, this cannot happen */
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
+ shutdown_pending = 1;
+ }
+
cld = rv - WAIT_OBJECT_0;
APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
if (cld == current_live_processes) {
- /* stop_event is signalled, we should exit now */
- if (ResetEvent(signal_event) == 0)
- APD1("main process: *** ERROR: ResetEvent(stop_event) failed ***");
+ /* shutdown event signalled, we should exit now */
+ if (ResetEvent(signal_shutdown_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "ResetEvent(signal_shutdown_event)");
+ /* Continue -- since we are doing a shutdown anyway */
+ }
+ shutdown_pending = 1;
+ APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
+ shutdown_pending, restart_pending);
+ break;
+ }
+ if (cld == current_live_processes+1) {
+ /* restart event signalled, we should exit now */
+ if (ResetEvent(signal_restart_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "ResetEvent(signal_restart_event)");
+ /* Continue -- hopefully the restart will fix the problem */
+ }
+ restart_pending = 1;
APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
shutdown_pending, restart_pending);
break;
@@ -5510,7 +5604,8 @@ int master_main(int argc, char **argv)
cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
APD2("main_process: child in slot %d died", rv);
if (processes_to_create) {
- create_process(process_handles, process_kill_events, &current_live_processes, &child_num, buf, argc, argv);
+ create_process(process_handles, process_kill_events, &current_live_processes,
+ &child_num, signal_prefix_string, argc, argv);
processes_to_create--;
}
}
@@ -5527,7 +5622,6 @@ int master_main(int argc, char **argv)
ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
"SetEvent for child process in slot #%d", i);
}
-
break;
}
if (restart_pending) {
@@ -5539,7 +5633,8 @@ int master_main(int argc, char **argv)
for (i = 0; i < nchild; ++i) {
if (current_live_processes >= MAX_PROCESSES)
break;
- create_process(process_handles, process_kill_events, &current_live_processes, &child_num, buf, argc, argv);
+ create_process(process_handles, process_kill_events, &current_live_processes,
+ &child_num, signal_prefix_string, argc, argv);
processes_to_create--;
}
for (i = 0; i < children_to_kill; i++) {
@@ -5559,7 +5654,8 @@ int master_main(int argc, char **argv)
APD2("*** main process shutdown, processes=%d ***", current_live_processes);
die_now:
- CloseHandle(signal_event);
+ CloseHandle(signal_restart_event);
+ CloseHandle(signal_shutdown_event);
tmstart = time(NULL);
while (current_live_processes && ((tmstart+60) > time(NULL))) {
@@ -5579,7 +5675,6 @@ die_now:
"forcing termination of child #%d (handle %d)", i, process_handles[i]);
TerminateProcess((HANDLE) process_handles[i], 1);
}
- service_set_status(SERVICE_STOPPED);
/* cleanup pid file on normal shutdown */
{
@@ -5597,9 +5692,61 @@ die_now:
}
ap_destroy_mutex(start_mutex);
+
+ service_set_status(SERVICE_STOPPED);
return (0);
}
+/*
+ * Send signal to a running Apache. On entry signal should contain
+ * either "shutdown" or "restart"
+ */
+
+void send_signal(pool *p, char *signal)
+{
+ char prefix[20];
+ FILE *fp;
+ int nread;
+ char *fname;
+ int end;
+
+ fname = ap_server_root_relative (p, ap_pid_fname);
+
+ fp = fopen(fname, "r");
+ if (!fp) {
+ printf("Cannot read apache PID file %s\n", fname);
+ return;
+ }
+ prefix[0] = 'a';
+ prefix[1] = 'p';
+
+ nread = fread(prefix+2, 1, sizeof(prefix)-3, fp);
+ if (nread == 0) {
+ fclose(fp);
+ printf("PID file %s was empty\n", fname);
+ return;
+ }
+ fclose(fp);
+
+ /* Terminate the prefix string */
+ end = 2 + nread - 1;
+ while (end > 0 && (prefix[end] == '\r' || prefix[end] == '\n'))
+ end--;
+ prefix[end + 1] = '\0';
+
+ setup_signal_names(prefix);
+
+ if (!strcasecmp(signal, "shutdown"))
+ ap_start_shutdown();
+ else if (!strcasecmp(signal, "restart"))
+ ap_start_restart(1);
+ else
+ printf("Unknown signal name \"%s\". Use either shutdown or restart.\n",
+ signal);
+
+ return;
+}
+
#ifdef WIN32
__declspec(dllexport)
int apache_main(int argc, char *argv[])
@@ -5613,6 +5760,7 @@ int REALMAIN(int argc, char *argv[])
int run_as_service = 1;
int install = 0;
int configtestonly = 0;
+ char *signal_to_send = NULL;
common_init();
@@ -5637,7 +5785,7 @@ int REALMAIN(int argc, char *argv[])
ap_setup_prelinked_modules();
- while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVhlZ:iusSt")) != -1) {
+ while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVhlZ:iusStk:")) != -1) {
char **new;
switch (c) {
case 'c':
@@ -5659,7 +5807,9 @@ int REALMAIN(int argc, char *argv[])
cp = strchr(optarg, '_');
ap_assert(cp);
*cp = 0;
- start_mutex = ap_open_mutex(optarg);
+ setup_signal_names(optarg);
+ start_mutex = ap_open_mutex(signal_name_prefix);
+ ap_assert(start_mutex);
child = 1;
break;
case 'i':
@@ -5674,6 +5824,9 @@ int REALMAIN(int argc, char *argv[])
case 'S':
ap_dump_settings = 1;
break;
+ case 'k':
+ signal_to_send = optarg;
+ break;
#endif /* WIN32 */
case 'd':
ap_cpystrn(ap_server_root, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_root));
@@ -5718,7 +5871,12 @@ int REALMAIN(int argc, char *argv[])
exit(0);
}
- if (!child) {
+ if (signal_to_send) {
+ send_signal(pconf, signal_to_send);
+ exit(0);
+ }
+
+ if (!child && !ap_dump_settings && !install) {
ap_log_pid(pconf, ap_pid_fname);
}
ap_set_version();
diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c
index 98f58517ea8..e28df5c4636 100644
--- a/usr.sbin/httpd/src/main/http_protocol.c
+++ b/usr.sbin/httpd/src/main/http_protocol.c
@@ -551,6 +551,17 @@ static int getline(char *s, int n, BUFF *in, int fold)
total += retval; /* and how long s has become */
if (*pos == '\n') { /* Did we get a full line of input? */
+ /*
+ * Trim any extra trailing spaces or tabs except for the first
+ * space or tab at the beginning of a blank string. This makes
+ * it much easier to check field values for exact matches, and
+ * saves memory as well. Terminate string at end of line.
+ */
+ while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
+ --pos; /* trim extra trailing spaces or tabs */
+ --total; /* but not one at the beginning of line */
+ ++n;
+ }
*pos = '\0';
--total;
++n;
@@ -767,8 +778,6 @@ static void get_mime_headers(request_rec *r)
while (*value == ' ' || *value == '\t')
++value; /* Skip to start of value */
- /* XXX: should strip trailing whitespace as well */
-
ap_table_addn(tmp_headers, copy, value);
}
@@ -778,8 +787,9 @@ static void get_mime_headers(request_rec *r)
request_rec *ap_read_request(conn_rec *conn)
{
request_rec *r;
- int access_status;
pool *p;
+ const char *expect;
+ int access_status;
p = ap_make_sub_pool(conn->pool);
r = ap_pcalloc(p, sizeof(request_rec));
@@ -846,6 +856,23 @@ request_rec *ap_read_request(conn_rec *conn)
}
else {
ap_kill_timeout(r);
+
+ if (r->header_only) {
+ /*
+ * Client asked for headers only with HTTP/0.9, which doesn't send
+ * headers! Have to dink things just to make sure the error message
+ * comes through...
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client sent invalid HTTP/0.9 request: HEAD %s",
+ r->uri);
+ r->header_only = 0;
+ r->status = HTTP_BAD_REQUEST;
+ ap_send_error_response(r, 0);
+ ap_bflush(r->connection->client);
+ ap_log_transaction(r);
+ return r;
+ }
}
r->status = HTTP_OK; /* Until further notice. */
@@ -860,6 +887,49 @@ request_rec *ap_read_request(conn_rec *conn)
conn->keptalive = 0; /* We now have a request to play with */
+ if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
+ ((r->proto_num == HTTP_VERSION(1,1)) &&
+ !ap_table_get(r->headers_in, "Host"))) {
+ /*
+ * Client sent us an HTTP/1.1 or later request without telling us the
+ * hostname, either with a full URL or a Host: header. We therefore
+ * need to (as per the 1.1 spec) send an error. As a special case,
+ * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
+ * a Host: header, and the server MUST respond with 400 if it doesn't.
+ */
+ r->status = HTTP_BAD_REQUEST;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client sent HTTP/1.1 request without hostname "
+ "(see RFC2068 section 9, and 14.23): %s", r->uri);
+ ap_send_error_response(r, 0);
+ ap_bflush(r->connection->client);
+ ap_log_transaction(r);
+ return r;
+ }
+ if (((expect = ap_table_get(r->headers_in, "Expect")) != NULL) &&
+ (expect[0] != '\0')) {
+ /*
+ * The Expect header field was added to HTTP/1.1 after RFC 2068
+ * as a means to signal when a 100 response is desired and,
+ * unfortunately, to signal a poor man's mandatory extension that
+ * the server must understand or return 417 Expectation Failed.
+ */
+ if (strcasecmp(expect, "100-continue") == 0) {
+ r->expecting_100 = 1;
+ }
+ else {
+ r->status = HTTP_EXPECTATION_FAILED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "client sent an unrecognized expectation value of "
+ "Expect: %s", expect);
+ ap_send_error_response(r, 0);
+ ap_bflush(r->connection->client);
+ (void) ap_discard_request_body(r);
+ ap_log_transaction(r);
+ return r;
+ }
+ }
+
if ((access_status = ap_run_post_read_request(r))) {
ap_die(access_status, r);
ap_log_transaction(r);
@@ -895,6 +965,7 @@ void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
rnew->err_headers_out = ap_make_table(rnew->pool, 5);
rnew->notes = ap_make_table(rnew->pool, 5);
+ rnew->expecting_100 = r->expecting_100;
rnew->read_length = r->read_length;
rnew->read_body = REQUEST_NO_BODY;
@@ -988,7 +1059,8 @@ API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
static char *status_lines[] = {
"100 Continue",
"101 Switching Protocols",
-#define LEVEL_200 2
+ "102 Processing",
+#define LEVEL_200 3
"200 OK",
"201 Created",
"202 Accepted",
@@ -996,14 +1068,17 @@ static char *status_lines[] = {
"204 No Content",
"205 Reset Content",
"206 Partial Content",
-#define LEVEL_300 9
+ "207 Multi-Status",
+#define LEVEL_300 11
"300 Multiple Choices",
"301 Moved Permanently",
- "302 Moved Temporarily",
+ "302 Found",
"303 See Other",
"304 Not Modified",
"305 Use Proxy",
-#define LEVEL_400 15
+ "306 unused",
+ "307 Temporary Redirect",
+#define LEVEL_400 19
"400 Bad Request",
"401 Authorization Required",
"402 Payment Required",
@@ -1020,14 +1095,26 @@ static char *status_lines[] = {
"413 Request Entity Too Large",
"414 Request-URI Too Large",
"415 Unsupported Media Type",
-#define LEVEL_500 31
+ "416 Requested Range Not Satisfiable",
+ "417 Expectation Failed",
+ "418 unused",
+ "419 unused",
+ "420 unused",
+ "421 unused",
+ "422 Unprocessable Entity",
+ "423 Locked",
+#define LEVEL_500 43
"500 Internal Server Error",
"501 Method Not Implemented",
"502 Bad Gateway",
"503 Service Temporarily Unavailable",
"504 Gateway Time-out",
"505 HTTP Version Not Supported",
- "506 Variant Also Varies"
+ "506 Variant Also Negotiates"
+ "507 unused",
+ "508 unused",
+ "509 unused",
+ "510 Not Extended",
};
/* The index is found by its offset from the x00 code of each level.
@@ -1441,7 +1528,7 @@ API_EXPORT(int) ap_should_client_block(request_rec *r)
if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
return 0;
- if (r->proto_num >= HTTP_VERSION(1,1)) {
+ if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
/* sending 100 Continue interim response */
ap_bvputs(r->connection->client,
SERVER_PROTOCOL, " ", status_lines[0], "\015\012\015\012",
@@ -1653,6 +1740,11 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r)
if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
return rv;
+ /* If we are discarding the request body, then we must already know
+ * the final status code, therefore disable the sending of 100 continue.
+ */
+ r->expecting_100 = 0;
+
if (ap_should_client_block(r)) {
char dumpbuf[HUGE_STRING_LEN];
@@ -2127,132 +2219,177 @@ void ap_send_error_response(request_rec *r, int recursive_error)
"</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
NULL);
- if ((error_notes = ap_table_get(r->notes, "error-notes"))) {
- ap_bputs(error_notes, fd);
- }
- else
- switch (status) {
- case REDIRECT:
- case MOVED:
- ap_bvputs(fd, "The document has moved <A HREF=\"",
- ap_escape_html(r->pool, location), "\">here</A>.<P>\n", NULL);
- break;
- case HTTP_SEE_OTHER:
- ap_bvputs(fd, "The answer to your request is located <A HREF=\"",
- ap_escape_html(r->pool, location), "\">here</A>.<P>\n", NULL);
- break;
- case HTTP_USE_PROXY:
- ap_bvputs(fd, "This resource is only accessible through the proxy\n",
- ap_escape_html(r->pool, location), "<BR>\nYou will need to ",
- "configure your client to use that proxy.<P>\n", NULL);
- break;
- case HTTP_PROXY_AUTHENTICATION_REQUIRED:
- case AUTH_REQUIRED:
- ap_bputs("This server could not verify that you\n", fd);
- ap_bputs("are authorized to access the document you\n", fd);
- ap_bputs("requested. Either you supplied the wrong\n", fd);
- ap_bputs("credentials (e.g., bad password), or your\n", fd);
- ap_bputs("browser doesn't understand how to supply\n", fd);
- ap_bputs("the credentials required.<P>\n", fd);
- break;
- case BAD_REQUEST:
- ap_bputs("Your browser sent a request that\n", fd);
- ap_bputs("this server could not understand.<P>\n", fd);
- break;
- case HTTP_FORBIDDEN:
- ap_bvputs(fd, "You don't have permission to access ",
- ap_escape_html(r->pool, r->uri), "\non this server.<P>\n",
- NULL);
- break;
- case NOT_FOUND:
- ap_bvputs(fd, "The requested URL ", ap_escape_html(r->pool, r->uri),
- " was not found on this server.<P>\n", NULL);
- break;
- case METHOD_NOT_ALLOWED:
- ap_bvputs(fd, "The requested method ", r->method, " is not allowed "
- "for the URL ", ap_escape_html(r->pool, r->uri),
- ".<P>\n", NULL);
- break;
- case NOT_ACCEPTABLE:
- ap_bvputs(fd,
- "An appropriate representation of the requested resource ",
- ap_escape_html(r->pool, r->uri),
- " could not be found on this server.<P>\n", NULL);
- /* fall through */
- case MULTIPLE_CHOICES:
- {
- const char *list;
- if ((list = ap_table_get(r->notes, "variant-list")))
- ap_bputs(list, fd);
- }
- break;
- case LENGTH_REQUIRED:
- ap_bvputs(fd, "A request of the requested method ", r->method,
- " requires a valid Content-length.<P>\n", NULL);
- break;
- case PRECONDITION_FAILED:
- ap_bvputs(fd, "The precondition on the request for the URL ",
- ap_escape_html(r->pool, r->uri), " evaluated to false.<P>\n",
- NULL);
- break;
- case NOT_IMPLEMENTED:
- ap_bvputs(fd, ap_escape_html(r->pool, r->method), " to ",
- ap_escape_html(r->pool, r->uri), " not supported.<P>\n", NULL);
- break;
- case BAD_GATEWAY:
- ap_bputs("The proxy server received an invalid\015\012", fd);
- ap_bputs("response from an upstream server.<P>\015\012", fd);
- break;
- case VARIANT_ALSO_VARIES:
- ap_bvputs(fd, "A variant for the requested entity ",
- ap_escape_html(r->pool, r->uri), " is itself a ",
- "transparently negotiable resource.<P>\n", NULL);
- break;
- case HTTP_REQUEST_TIME_OUT:
- ap_bputs("I'm tired of waiting for your request.\n", fd);
- break;
- case HTTP_GONE:
- ap_bvputs(fd, "The requested resource<BR>",
- ap_escape_html(r->pool, r->uri),
- "<BR>\nis no longer available on this server ",
- "and there is no forwarding address.\n",
- "Please remove all references to this resource.\n", NULL);
- break;
- case HTTP_REQUEST_ENTITY_TOO_LARGE:
- ap_bvputs(fd, "The requested resource<BR>",
- ap_escape_html(r->pool, r->uri), "<BR>\n",
- "does not allow request data with ", r->method,
- " requests, or the amount of data provided in\n",
- "the request exceeds the capacity limit.\n", NULL);
- break;
- case HTTP_REQUEST_URI_TOO_LARGE:
- ap_bputs("The requested URL's length exceeds the capacity\n", fd);
- ap_bputs("limit for this server.\n", fd);
- break;
- case HTTP_UNSUPPORTED_MEDIA_TYPE:
- ap_bputs("The supplied request data is not in a format\n", fd);
- ap_bputs("acceptable for processing by this resource.\n", fd);
- break;
- case HTTP_SERVICE_UNAVAILABLE:
- ap_bputs("The server is temporarily unable to service your\n", fd);
- ap_bputs("request due to maintenance downtime or capacity\n", fd);
- ap_bputs("problems. Please try again later.\n", fd);
- break;
- case HTTP_GATEWAY_TIME_OUT:
- ap_bputs("The proxy server did not receive a timely response\n", fd);
- ap_bputs("from the upstream server.<P>\n", fd);
- break;
- default: /* HTTP_INTERNAL_SERVER_ERROR */
- ap_bputs("The server encountered an internal error or\n", fd);
- ap_bputs("misconfiguration and was unable to complete\n", fd);
- ap_bputs("your request.<P>\n", fd);
- ap_bputs("Please contact the server administrator,\n ", fd);
- ap_bputs(ap_escape_html(r->pool, r->server->server_admin), fd);
- ap_bputs(" and inform them of the time the error occurred,\n", fd);
- ap_bputs("and anything you might have done that may have\n", fd);
- ap_bputs("caused the error.<P>\n", fd);
- break;
- }
+ switch (status) {
+ case HTTP_MOVED_PERMANENTLY:
+ case HTTP_MOVED_TEMPORARILY:
+ case HTTP_TEMPORARY_REDIRECT:
+ ap_bvputs(fd, "The document has moved <A HREF=\"",
+ ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
+ NULL);
+ break;
+ case HTTP_SEE_OTHER:
+ ap_bvputs(fd, "The answer to your request is located <A HREF=\"",
+ ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
+ NULL);
+ break;
+ case HTTP_USE_PROXY:
+ ap_bvputs(fd, "This resource is only accessible "
+ "through the proxy\n",
+ ap_escape_html(r->pool, location),
+ "<BR>\nYou will need to ",
+ "configure your client to use that proxy.<P>\n", NULL);
+ break;
+ case HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ case AUTH_REQUIRED:
+ ap_bputs("This server could not verify that you\n", fd);
+ ap_bputs("are authorized to access the document you\n", fd);
+ ap_bputs("requested. Either you supplied the wrong\n", fd);
+ ap_bputs("credentials (e.g., bad password), or your\n", fd);
+ ap_bputs("browser doesn't understand how to supply\n", fd);
+ ap_bputs("the credentials required.<P>\n", fd);
+ break;
+ case BAD_REQUEST:
+ ap_bputs("Your browser sent a request that\n", fd);
+ ap_bputs("this server could not understand.<P>\n", fd);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case HTTP_FORBIDDEN:
+ ap_bvputs(fd, "You don't have permission to access ",
+ ap_escape_html(r->pool, r->uri),
+ "\non this server.<P>\n", NULL);
+ break;
+ case NOT_FOUND:
+ ap_bvputs(fd, "The requested URL ",
+ ap_escape_html(r->pool, r->uri),
+ " was not found on this server.<P>\n", NULL);
+ break;
+ case METHOD_NOT_ALLOWED:
+ ap_bvputs(fd, "The requested method ", r->method,
+ " is not allowed "
+ "for the URL ", ap_escape_html(r->pool, r->uri),
+ ".<P>\n", NULL);
+ break;
+ case NOT_ACCEPTABLE:
+ ap_bvputs(fd,
+ "An appropriate representation of the "
+ "requested resource ",
+ ap_escape_html(r->pool, r->uri),
+ " could not be found on this server.<P>\n", NULL);
+ /* fall through */
+ case MULTIPLE_CHOICES:
+ {
+ const char *list;
+ if ((list = ap_table_get(r->notes, "variant-list")))
+ ap_bputs(list, fd);
+ }
+ break;
+ case LENGTH_REQUIRED:
+ ap_bvputs(fd, "A request of the requested method ", r->method,
+ " requires a valid Content-length.<P>\n", NULL);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case PRECONDITION_FAILED:
+ ap_bvputs(fd, "The precondition on the request for the URL ",
+ ap_escape_html(r->pool, r->uri),
+ " evaluated to false.<P>\n", NULL);
+ break;
+ case NOT_IMPLEMENTED:
+ ap_bvputs(fd, ap_escape_html(r->pool, r->method), " to ",
+ ap_escape_html(r->pool, r->uri),
+ " not supported.<P>\n", NULL);
+ break;
+ case BAD_GATEWAY:
+ ap_bputs("The proxy server received an invalid\015\012", fd);
+ ap_bputs("response from an upstream server.<P>\015\012", fd);
+ break;
+ case VARIANT_ALSO_VARIES:
+ ap_bvputs(fd, "A variant for the requested entity ",
+ ap_escape_html(r->pool, r->uri), " is itself a ",
+ "transparently negotiable resource.<P>\n", NULL);
+ break;
+ case HTTP_REQUEST_TIME_OUT:
+ ap_bputs("I'm tired of waiting for your request.\n", fd);
+ break;
+ case HTTP_GONE:
+ ap_bvputs(fd, "The requested resource<BR>",
+ ap_escape_html(r->pool, r->uri),
+ "<BR>\nis no longer available on this server ",
+ "and there is no forwarding address.\n",
+ "Please remove all references to this resource.\n",
+ NULL);
+ break;
+ case HTTP_REQUEST_ENTITY_TOO_LARGE:
+ ap_bvputs(fd, "The requested resource<BR>",
+ ap_escape_html(r->pool, r->uri), "<BR>\n",
+ "does not allow request data with ", r->method,
+ " requests, or the amount of data provided in\n",
+ "the request exceeds the capacity limit.\n", NULL);
+ break;
+ case HTTP_REQUEST_URI_TOO_LARGE:
+ ap_bputs("The requested URL's length exceeds the capacity\n"
+ "limit for this server.<P>\n", fd);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case HTTP_UNSUPPORTED_MEDIA_TYPE:
+ ap_bputs("The supplied request data is not in a format\n"
+ "acceptable for processing by this resource.\n", fd);
+ break;
+ case HTTP_RANGE_NOT_SATISFIABLE:
+ ap_bputs("None of the range-specifier values in the Range\n"
+ "request-header field overlap the current extent\n"
+ "of the selected resource.\n", fd);
+ break;
+ case HTTP_EXPECTATION_FAILED:
+ ap_bvputs(fd, "The expectation given in the Expect request-header"
+ "\nfield could not be met by this server.<P>\n"
+ "The client sent<PRE>\n Expect: ",
+ ap_table_get(r->headers_in, "Expect"), "\n</PRE>\n"
+ "but we only allow the 100-continue expectation.\n",
+ NULL);
+ break;
+ case HTTP_UNPROCESSABLE_ENTITY:
+ ap_bputs("The server understands the media type of the\n"
+ "request entity, but was unable to process the\n"
+ "contained instructions.\n", fd);
+ break;
+ case HTTP_LOCKED:
+ ap_bputs("The requested resource is currently locked.\n"
+ "The lock must be released or proper identification\n"
+ "given before the method can be applied.\n", fd);
+ break;
+ case HTTP_SERVICE_UNAVAILABLE:
+ ap_bputs("The server is temporarily unable to service your\n"
+ "request due to maintenance downtime or capacity\n"
+ "problems. Please try again later.\n", fd);
+ break;
+ case HTTP_GATEWAY_TIME_OUT:
+ ap_bputs("The proxy server did not receive a timely response\n"
+ "from the upstream server.\n", fd);
+ break;
+ case HTTP_NOT_EXTENDED:
+ ap_bputs("A mandatory extension policy in the request is not\n"
+ "accepted by the server for this resource.\n", fd);
+ break;
+ default: /* HTTP_INTERNAL_SERVER_ERROR */
+ ap_bvputs(fd, "The server encountered an internal error or\n"
+ "misconfiguration and was unable to complete\n"
+ "your request.<P>\n"
+ "Please contact the server administrator,\n ",
+ ap_escape_html(r->pool, r->server->server_admin),
+ " and inform them of the time the error occurred,\n"
+ "and anything you might have done that may have\n"
+ "caused the error.<P>\n", NULL);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ }
+ break;
+ }
if (recursive_error) {
ap_bvputs(fd, "<P>Additionally, a ",
diff --git a/usr.sbin/httpd/src/main/http_request.c b/usr.sbin/httpd/src/main/http_request.c
index 62918edc2ea..918dc9226bf 100644
--- a/usr.sbin/httpd/src/main/http_request.c
+++ b/usr.sbin/httpd/src/main/http_request.c
@@ -188,8 +188,10 @@ static int get_path_info(request_rec *r)
}
#ifdef WIN32
- /* If the path is x:/, then convert it to x:/., coz that's what stat needs to work properly */
- if(strlen(path) == 3 && path[1] == ':') {
+ /* If the path is x:/, then convert it to x:/., coz that's what stat
+ * needs to work properly
+ */
+ if (strlen(path) == 3 && path[1] == ':') {
strcpy(buf,path);
buf[3]='.';
buf[4]='\0';
@@ -674,6 +676,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
char *udir;
rnew = make_sub_request(r);
+ rnew->hostname = r->hostname;
rnew->request_time = r->request_time;
rnew->connection = r->connection;
rnew->server = r->server;
@@ -751,6 +754,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
char *fdir;
rnew = make_sub_request(r);
+ rnew->hostname = r->hostname;
rnew->request_time = r->request_time;
rnew->connection = r->connection;
rnew->server = r->server;
@@ -826,7 +830,14 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
* file may not have a uri associated with it -djg
*/
rnew->uri = "INTERNALLY GENERATED file-relative req";
+#ifdef WIN32
+ rnew->filename = ((new_file[0] == '/'
+ || (ap_isalpha(new_file[0])
+ && new_file[1] == ':'
+ && new_file[2] == '/')) ?
+#else
rnew->filename = ((new_file[0] == '/') ?
+#endif
ap_pstrdup(rnew->pool, new_file) :
ap_make_full_path(rnew->pool, fdir, new_file));
rnew->per_dir_config = r->server->lookup_defaults;
@@ -1013,39 +1024,6 @@ static void process_request_internal(request_rec *r)
{
int access_status;
- /*
- * Kluge to be reading the assbackwards field outside of protocol.c, but
- * we've got to check for this sort of nonsense somewhere...
- */
-
- if (r->assbackwards && r->header_only) {
- /*
- * Client asked for headers only with HTTP/0.9, which doesn't send
- * headers! Have to dink things even to make sure the error message
- * comes through...
- */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "client sent illegal HTTP/0.9 request: %s", r->uri);
- r->header_only = 0;
- ap_die(BAD_REQUEST, r);
- return;
- }
-
- if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
- ((r->proto_num == HTTP_VERSION(1,1)) && !ap_table_get(r->headers_in, "Host"))) {
- /*
- * Client sent us a HTTP/1.1 or later request without telling us the
- * hostname, either with a full URL or a Host: header. We therefore
- * need to (as per the 1.1 spec) send an error. As a special case,
- * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
- * a Host: header, and the server MUST respond with 400 if it doesn't.
- */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "client sent HTTP/1.1 request without hostname (see RFC2068 section 9, and 14.23): %s", r->uri);
- ap_die(BAD_REQUEST, r);
- return;
- }
-
/* Ignore embedded %2F's in path for proxy requests */
if (!r->proxyreq && r->parsed_uri.path) {
access_status = ap_unescape_url(r->parsed_uri.path);
diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c
index 6ea60371380..eee03233261 100644
--- a/usr.sbin/httpd/src/main/util.c
+++ b/usr.sbin/httpd/src/main/util.c
@@ -738,6 +738,7 @@ API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name)
poolfile_t *new_pfile;
FILE *file;
struct stat stbuf;
+ int saved_errno;
if (name == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL,
@@ -747,9 +748,11 @@ API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name)
file = ap_pfopen(p, name, "r");
#ifdef DEBUG
+ saved_errno = errno;
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL,
"Opening config file %s (%s)",
name, (file == NULL) ? strerror(errno) : "successful");
+ errno = saved_errno;
#endif
if (file == NULL)
return NULL;
@@ -761,10 +764,12 @@ API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name)
#else
strcmp(name, "/dev/null") != 0) {
#endif
+ saved_errno = errno;
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL,
"Access to file %s denied by server: not a regular file",
name);
ap_pfclose(p, file);
+ errno = saved_errno;
return NULL;
}
diff --git a/usr.sbin/httpd/src/main/util_script.c b/usr.sbin/httpd/src/main/util_script.c
index 270d377867f..9ee38bf8edd 100644
--- a/usr.sbin/httpd/src/main/util_script.c
+++ b/usr.sbin/httpd/src/main/util_script.c
@@ -262,6 +262,7 @@ API_EXPORT(void) ap_add_common_vars(request_rec *r)
#endif
ap_table_addn(e, "PATH", env_path);
+ ap_table_setn(e, "SERVER_SIGNATURE", ap_psignature("", r));
ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
ap_table_addn(e, "SERVER_NAME", ap_get_server_name(r));
ap_table_addn(e, "SERVER_PORT",
@@ -458,8 +459,6 @@ API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
ap_kill_timeout(r);
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"Premature end of script headers: %s", r->filename);
- ap_table_setn(r->notes, "error-notes",
- "Premature end of script headers");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -543,8 +542,6 @@ API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
ap_kill_timeout(r);
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"%s: %s", malformed, r->filename);
- ap_table_setn(r->notes, "error-notes",
- ap_pstrdup(r->pool, malformed));
return HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_util.c b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
index c917d7645fc..a2dfd0e8ed7 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_util.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
@@ -581,7 +581,7 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c)
ap_reset_timeout(r);
if (w <= 0) {
- if (c != NULL) {
+ if (c != NULL && c->fp != NULL) {
/* when a send failure occurs, we need to decide
* whether to continue loading and caching the
* document, or to abort the whole thing
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth.c b/usr.sbin/httpd/src/modules/standard/mod_auth.c
index c4ca529cf63..605ef9cfa65 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth.c
@@ -264,7 +264,7 @@ static int check_user_access(request_rec *r)
method_restricted = 1;
t = reqs[x].requirement;
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
if (!strcmp(w, "valid-user"))
return OK;
if (!strcmp(w, "user")) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
index 26a994b7367..a4b5da96ce5 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
@@ -281,7 +281,7 @@ static int db_check_auth(request_rec *r)
continue;
t = reqs[x].requirement;
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
if (!strcmp(w, "group") && sec->auth_dbgrpfile) {
const char *orig_groups, *groups;
@@ -298,7 +298,7 @@ static int db_check_auth(request_rec *r)
}
orig_groups = groups;
while (t[0]) {
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
groups = orig_groups;
while (groups[0]) {
v = ap_getword(r->pool, &groups, ',');
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
index b280513f232..d4a72b23977 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
@@ -266,7 +266,7 @@ static int dbm_check_auth(request_rec *r)
continue;
t = reqs[x].requirement;
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
if (!strcmp(w, "group") && sec->auth_dbmgrpfile) {
const char *orig_groups, *groups;
@@ -283,7 +283,7 @@ static int dbm_check_auth(request_rec *r)
}
orig_groups = groups;
while (t[0]) {
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
groups = orig_groups;
while (groups[0]) {
v = ap_getword(r->pool, &groups, ',');
diff --git a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
index 691b78d09b2..18f35cecce3 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
@@ -93,6 +93,7 @@ module MODULE_VAR_EXPORT autoindex_module;
#define SUPPRESS_DESC 32
#define SUPPRESS_PREAMBLE 64
#define SUPPRESS_COLSORT 128
+#define NO_OPTIONS 256
#define K_PAD 1
#define K_NOPAD 0
@@ -130,6 +131,8 @@ typedef struct autoindex_config_struct {
char *default_icon;
int opts;
+ int incremented_opts;
+ int decremented_opts;
int name_width;
int name_adjust;
int icon_width;
@@ -293,7 +296,11 @@ static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg)
cfg = (autoindex_config_rec *) d;
curopts = cfg->opts;
- newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & !FANCY_INDEXING));
+ if (curopts & NO_OPTIONS) {
+ return "FancyIndexing directive conflicts with existing "
+ "IndexOptions None";
+ }
+ newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & ~FANCY_INDEXING));
cfg->opts = newopts;
return NULL;
}
@@ -301,51 +308,97 @@ static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg)
static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
{
char *w;
- int opts = 0;
+ int opts;
+ int opts_add;
+ int opts_remove;
+ char action;
autoindex_config_rec *d_cfg = (autoindex_config_rec *) d;
+ opts = d_cfg->opts;
+ opts_add = d_cfg->incremented_opts;
+ opts_remove = d_cfg->decremented_opts;
while (optstr[0]) {
+ int option = 0;
+
w = ap_getword_conf(cmd->pool, &optstr);
+ if ((*w == '+') || (*w == '-')) {
+ action = *(w++);
+ }
+ else {
+ action = '\0';
+ }
if (!strcasecmp(w, "FancyIndexing")) {
- opts |= FANCY_INDEXING;
+ option = FANCY_INDEXING;
}
else if (!strcasecmp(w, "IconsAreLinks")) {
- opts |= ICONS_ARE_LINKS;
+ option = ICONS_ARE_LINKS;
}
else if (!strcasecmp(w, "ScanHTMLTitles")) {
- opts |= SCAN_HTML_TITLES;
+ option = SCAN_HTML_TITLES;
}
else if (!strcasecmp(w, "SuppressLastModified")) {
- opts |= SUPPRESS_LAST_MOD;
+ option = SUPPRESS_LAST_MOD;
}
else if (!strcasecmp(w, "SuppressSize")) {
- opts |= SUPPRESS_SIZE;
+ option = SUPPRESS_SIZE;
}
else if (!strcasecmp(w, "SuppressDescription")) {
- opts |= SUPPRESS_DESC;
+ option = SUPPRESS_DESC;
}
else if (!strcasecmp(w, "SuppressHTMLPreamble")) {
- opts |= SUPPRESS_PREAMBLE;
+ option = SUPPRESS_PREAMBLE;
}
else if (!strcasecmp(w, "SuppressColumnSorting")) {
- opts |= SUPPRESS_COLSORT;
+ option = SUPPRESS_COLSORT;
}
else if (!strcasecmp(w, "None")) {
- opts = 0;
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with 'None' keyword";
+ }
+ opts = NO_OPTIONS;
+ opts_add = 0;
+ opts_remove = 0;
}
else if (!strcasecmp(w, "IconWidth")) {
- d_cfg->icon_width = DEFAULT_ICON_WIDTH;
+ if (action != '-') {
+ d_cfg->icon_width = DEFAULT_ICON_WIDTH;
+ }
+ else {
+ d_cfg->icon_width = 0;
+ }
}
else if (!strncasecmp(w, "IconWidth=", 10)) {
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with IconWidth=n";
+ }
d_cfg->icon_width = atoi(&w[10]);
}
else if (!strcasecmp(w, "IconHeight")) {
- d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
+ if (action != '-') {
+ d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
+ }
+ else {
+ d_cfg->icon_height = 0;
+ }
}
else if (!strncasecmp(w, "IconHeight=", 11)) {
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with IconHeight=n";
+ }
d_cfg->icon_height = atoi(&w[11]);
}
+ else if (!strcasecmp(w, "NameWidth")) {
+ if (action != '-') {
+ return "NameWidth with no value may only appear as "
+ "'-NameWidth'";
+ }
+ d_cfg->name_width = DEFAULT_NAME_WIDTH;
+ d_cfg->name_adjust = 0;
+ }
else if (!strncasecmp(w, "NameWidth=", 10)) {
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with NameWidth=n";
+ }
if (w[10] == '*') {
d_cfg->name_adjust = 1;
}
@@ -361,7 +414,25 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
else {
return "Invalid directory indexing option";
}
+ if (action == '\0') {
+ opts |= option;
+ opts_add = 0;
+ opts_remove = 0;
+ }
+ else if (action == '+') {
+ opts_add |= option;
+ opts_remove &= ~option;
+ }
+ else {
+ opts_remove |= option;
+ opts_add &= ~option;
+ }
+ }
+ if ((opts & NO_OPTIONS) && (opts & ~NO_OPTIONS)) {
+ return "Cannot combine other IndexOptions keywords with 'None'";
}
+ d_cfg->incremented_opts = opts_add;
+ d_cfg->decremented_opts = opts_remove;
d_cfg->opts = opts;
return NULL;
}
@@ -414,6 +485,8 @@ static void *create_autoindex_config(pool *p, char *dummy)
new->hdr_list = ap_make_array(p, 4, sizeof(struct item));
new->rdme_list = ap_make_array(p, 4, sizeof(struct item));
new->opts = 0;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
return (void *) new;
}
@@ -436,7 +509,48 @@ static void *merge_autoindex_configs(pool *p, void *basev, void *addv)
new->desc_list = ap_append_arrays(p, add->desc_list, base->desc_list);
new->icon_list = ap_append_arrays(p, add->icon_list, base->icon_list);
new->rdme_list = ap_append_arrays(p, add->rdme_list, base->rdme_list);
- new->opts = add->opts;
+ if (add->opts & NO_OPTIONS) {
+ /*
+ * If the current directory says 'no options' then we also
+ * clear any incremental mods from being inheritable further down.
+ */
+ new->opts = NO_OPTIONS;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
+ }
+ else {
+ /*
+ * If there were any non-incremental options selected for
+ * this directory, they dominate and we don't inherit *anything.*
+ * Contrariwise, we *do* inherit if the only settings here are
+ * incremental ones.
+ */
+ if (add->opts == 0) {
+ new->incremented_opts = (base->incremented_opts
+ | add->incremented_opts)
+ & ~add->decremented_opts;
+ new->decremented_opts = (base->decremented_opts
+ | add->decremented_opts);
+ /*
+ * We may have incremental settings, so make sure we don't
+ * inadvertently inherit an IndexOptions None from above.
+ */
+ new->opts = (base->opts & ~NO_OPTIONS);
+ }
+ else {
+ /*
+ * There are local non-incremental settings, which clear
+ * all inheritance from above. They *are* the new base settings.
+ */
+ new->opts = add->opts;;
+ }
+ /*
+ * We're guaranteed that there'll be no overlap between
+ * the add-options and the remove-options.
+ */
+ new->opts |= new->incremented_opts;
+ new->opts &= ~new->decremented_opts;
+ }
new->name_width = add->name_width;
new->name_adjust = add->name_adjust;
@@ -455,7 +569,7 @@ struct ent {
char *icon;
char *alt;
char *desc;
- size_t size;
+ off_t size;
time_t lm;
struct ent *next;
int ascending;
@@ -745,7 +859,7 @@ static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
p = (struct ent *) ap_pcalloc(r->pool, sizeof(struct ent));
p->name = ap_pstrdup(r->pool, name);
- p->size = 0;
+ p->size = -1;
p->icon = NULL;
p->alt = NULL;
p->desc = NULL;
@@ -765,7 +879,7 @@ static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
if (!(p->alt = find_alt(d, rr, 1))) {
p->alt = "DIR";
}
- p->size = 0;
+ p->size = -1;
p->name = ap_pstrcat(r->pool, name, "/", NULL);
}
else {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_cgi.c b/usr.sbin/httpd/src/modules/standard/mod_cgi.c
index fd5906c4ec2..70f7956228f 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_cgi.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_cgi.c
@@ -433,7 +433,6 @@ static int cgi_handler(request_rec *r)
&script_out, &script_in, &script_err)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"couldn't spawn child process: %s", r->filename);
- ap_table_setn(r->notes, "error-notes", "Couldn't spawn child process");
return HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_digest.c b/usr.sbin/httpd/src/modules/standard/mod_digest.c
index 08e52f4ecfe..f44e7e3edea 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_digest.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_digest.c
@@ -159,7 +159,7 @@ static int get_digest_rec(request_rec *r, digest_header_rec * response)
return AUTH_REQUIRED;
}
- if (strcasecmp(scheme=ap_getword(r->pool, &auth_line, ' '), "Digest")) {
+ if (strcasecmp(scheme = ap_getword_white(r->pool, &auth_line), "Digest")) {
/* Client tried to authenticate using wrong auth scheme */
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
"client used wrong authentication scheme: %s for %s",
@@ -345,7 +345,7 @@ static int digest_check_auth(request_rec *r)
method_restricted = 1;
t = reqs[x].requirement;
- w = ap_getword(r->pool, &t, ' ');
+ w = ap_getword_white(r->pool, &t);
if (!strcmp(w, "valid-user"))
return OK;
else if (!strcmp(w, "user")) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_include.c b/usr.sbin/httpd/src/modules/standard/mod_include.c
index 612759ed6e9..3acc0c6f696 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_include.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_include.c
@@ -946,6 +946,7 @@ static int handle_perl(FILE *in, request_rec *r, const char *error)
}
}
perl_stdout2client(r);
+ perl_setup_env(r);
perl_call_handler(sub, r, av);
return OK;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_log_config.c b/usr.sbin/httpd/src/modules/standard/mod_log_config.c
index 1fa8f498589..da6d2bcb458 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_log_config.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_log_config.c
@@ -202,10 +202,9 @@ static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
* multi_log_state is our per-(virtual)-server configuration. We store
* an array of the logs we are going to use, each of type config_log_state.
* If a default log format is given by LogFormat, store in default_format
- * (backward compat. with mod_log_config). We also store a pointer to
- * the logs specified for the main server for virtual servers, so that
- * if this vhost has now logs defined, we can use the main server's
- * logs instead.
+ * (backward compat. with mod_log_config). We also store for each virtual
+ * server a pointer to the logs specified for the main server, so that if this
+ * vhost has no logs defined, we can use the main server's logs instead.
*
* So, for the main server, config_logs contains a list of the log files
* and server_config_logs in empty. For a vhost, server_config_logs
diff --git a/usr.sbin/httpd/src/modules/standard/mod_speling.c b/usr.sbin/httpd/src/modules/standard/mod_speling.c
index 53f8c1da34d..7d1b976d639 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_speling.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_speling.c
@@ -453,18 +453,21 @@ static int check_speling(request_rec *r)
t = "";
for (i = 0; i < candidates->nelts; ++i) {
+ char *vuri;
+ const char *reason;
+ reason = sp_reason_str[(int) (variant[i].quality)];
/* The format isn't very neat... */
- t = ap_pstrcat(p, t, "<li><a href=\"", url,
- variant[i].name, r->path_info,
- r->parsed_uri.query ? "?" : "",
- r->parsed_uri.query ? r->parsed_uri.query : "",
- "\">", variant[i].name, r->path_info,
- r->parsed_uri.query ? "?" : "",
- r->parsed_uri.query ? r->parsed_uri.query : "",
- "</a> (",
- sp_reason_str[(int) (variant[i].quality)],
- ")\n", NULL);
+ vuri = ap_pstrcat(p, url, variant[i].name, r->path_info,
+ (r->parsed_uri.query != NULL) ? "?" : "",
+ (r->parsed_uri.query != NULL)
+ ? r->parsed_uri.query : "",
+ NULL);
+ ap_table_mergen(r->subprocess_env, "VARIANTS",
+ ap_pstrcat(p, "\"", vuri, "\";\"",
+ reason, "\"", NULL));
+ t = ap_pstrcat(p, t, "<li><a href=\"", vuri,
+ "\">", vuri, "</a> (", reason, ")\n", NULL);
/*
* when we have printed the "close matches" and there are
diff --git a/usr.sbin/httpd/src/modules/standard/mod_status.c b/usr.sbin/httpd/src/modules/standard/mod_status.c
index 2c24df1ff51..31e9aa41abb 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_status.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_status.c
@@ -240,10 +240,12 @@ static int status_handler(request_rec *r)
unsigned long bcount = 0;
unsigned long kbcount = 0;
long req_time;
-#if defined(NEXT)
- float tick = HZ;
-#elif !defined(NO_TIMES)
+#ifndef NO_TIMES
+#ifdef _SC_CLK_TCK
float tick = sysconf(_SC_CLK_TCK);
+#else
+ float tick = HZ;
+#endif
#endif
int short_report = 0;
int no_table_report = 0;
diff --git a/usr.sbin/httpd/src/os/bs2000/bs2login.c b/usr.sbin/httpd/src/os/bs2000/bs2login.c
index 361c59d92f7..afba7fd928b 100644
--- a/usr.sbin/httpd/src/os/bs2000/bs2login.c
+++ b/usr.sbin/httpd/src/os/bs2000/bs2login.c
@@ -67,9 +67,6 @@ static const char *bs2000_account = NULL;
/* It stores the account name for later use */
const char *os_set_account(pool *p, const char *account)
{
- if (bs2000_account != NULL && strcasecmp(bs2000_account, account) != 0)
- return "BS2000Account: can be defined only once.";
-
bs2000_account = ap_pstrdup(p, account);
return NULL;
}
diff --git a/usr.sbin/httpd/src/os/bs2000/ebcdic.c b/usr.sbin/httpd/src/os/bs2000/ebcdic.c
index d8c650c0ebc..4a268488de8 100644
--- a/usr.sbin/httpd/src/os/bs2000/ebcdic.c
+++ b/usr.sbin/httpd/src/os/bs2000/ebcdic.c
@@ -62,8 +62,7 @@
/*
Initial Port for Apache-1.3 by <Martin.Kraemer@Mch.SNI.De>
-"BS2000 OSD" is a POSIX on a main frame.
-It is made by Siemens Nixdorf AG, Germany.
+"BS2000 OSD" is a POSIX on a main frame. It is made by Siemens AG, Germany.
Within the POSIX subsystem, the same character set was chosen as in
"native BS2000", namely EBCDIC.
diff --git a/usr.sbin/httpd/src/os/win32/registry.c b/usr.sbin/httpd/src/os/win32/registry.c
index 64aa72982a6..665f8ee67e7 100644
--- a/usr.sbin/httpd/src/os/win32/registry.c
+++ b/usr.sbin/httpd/src/os/win32/registry.c
@@ -28,7 +28,7 @@
#define VENDOR "Apache Group"
#define SOFTWARE "Apache"
-#define VERSION "1.3.2"
+#define VERSION "1.3.3"
#define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION
diff --git a/usr.sbin/httpd/src/os/win32/util_win32.c b/usr.sbin/httpd/src/os/win32/util_win32.c
index 47d8f7af9b5..3aac08767ce 100644
--- a/usr.sbin/httpd/src/os/win32/util_win32.c
+++ b/usr.sbin/httpd/src/os/win32/util_win32.c
@@ -23,7 +23,18 @@ static BOOL sub_canonical_filename(char *szCanon, unsigned nCanon,
for (nSlashes = 0; s > szFile && s[-1] == '\\'; ++nSlashes, --s)
;
- n = GetFullPathName(szFile, sizeof buf, buf, &szFilePart);
+ if (strlen(szFile)==2 && szFile[1]==':') {
+ /*
+ * If the file name is x:, do not call GetFullPathName
+ * because it will use the current path of the executable
+ */
+ strcpy(buf,szFile);
+ n = strlen(buf);
+ szFilePart = buf + n;
+ }
+ else {
+ n = GetFullPathName(szFile, sizeof buf, buf, &szFilePart);
+ }
ap_assert(n);
ap_assert(n < sizeof buf);
@@ -36,6 +47,8 @@ static BOOL sub_canonical_filename(char *szCanon, unsigned nCanon,
* is no '\' in szInFile, it must just be a file name, so it should be
* valid to use the name from GetFullPathName. Be sure to adjust the
* 's' variable so the rest of the code functions normally.
+ * Note it is possible to get here when szFile == 'x:', but that is OK
+ * because we will bail out of this routine early.
*/
if (!s) {
szFile = buf;
@@ -180,9 +193,21 @@ API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile)
buf[0] = ap_tolower(buf[0]);
- ap_assert(strlen(buf)+nSlashes < sizeof buf);
- while (nSlashes--) {
- strcat(buf, "/");
+ if (nSlashes) {
+ /*
+ * If there were additional trailing slashes, add them back on.
+ * Be sure not to add more than were originally there though,
+ * by checking to see if sub_canonical_filename added one;
+ * this could happen in cases where the file name is 'd:/'
+ */
+ ap_assert(strlen(buf)+nSlashes < sizeof buf);
+
+ if (nSlashes && buf[strlen(buf)-1] == '/')
+ nSlashes--;
+
+ while (nSlashes--) {
+ strcat(buf, "/");
+ }
}
return ap_pstrdup(pPool, buf);
@@ -233,8 +258,13 @@ API_EXPORT(int) os_stat(const char *szPath, struct stat *pStat)
return stat(buf, pStat);
}
+ /*
+ * Below removes the trailing /, however, do not remove
+ * it in the case of 'x:/' or stat will fail
+ */
n = strlen(szPath);
- if (szPath[n - 1] == '\\' || szPath[n - 1] == '/') {
+ if ((szPath[n - 1] == '\\' || szPath[n - 1] == '/') &&
+ !(n == 3 && szPath[1] == ':')) {
char buf[_MAX_PATH];
ap_assert(n < _MAX_PATH);
diff --git a/usr.sbin/httpd/src/support/dbmmanage b/usr.sbin/httpd/src/support/dbmmanage
index 824cda540d6..042c686497e 100644
--- a/usr.sbin/httpd/src/support/dbmmanage
+++ b/usr.sbin/httpd/src/support/dbmmanage
@@ -89,9 +89,9 @@ my $Is_Win32 = $^O eq "MSWin32";
my %DB = ();
my @range = ();
my($mode, $flags) = $command =~
- /^(?:view|check)$/ ? (undef, O_RDONLY) : (0644, O_RDWR|O_CREAT);
+ /^(?:view|check)$/ ? (0644, O_RDONLY) : (0644, O_RDWR|O_CREAT);
-tie %DB, "AnyDBM_File", $file, $flags, $mode;
+tie %DB, "AnyDBM_File", $file, $flags, $mode || die "Can't tie $file: $!";
dbmc->$command();
untie %DB;