You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by dg...@hyperreal.org on 1998/01/30 10:14:35 UTC

cvs commit: apache-1.2/support logresolve.c suexec.c

dgaudet     98/01/30 01:14:32

  Modified:    .        ABOUT_APACHE CHANGES KEYS README
               conf     httpd.conf-dist
               htdocs   index.html
               htdocs/manual custom-error.html footer.html header.html
                        new_features_1_2.html process-model.html
                        suexec.html vhosts-in-depth.html virtual-host.html
               htdocs/manual/misc FAQ.html compat_notes.html
                        fin_wait_2.html footer.html header.html index.html
                        known_bugs.html nopgp.html perf-bsd44.html
                        perf.html security_tips.html vif-info.html
               htdocs/manual/mod core.html directives.html footer.html
                        header.html mod_auth_anon.html mod_auth_msql.html
                        mod_browser.html mod_cern_meta.html mod_env.html
                        mod_headers.html mod_include.html mod_mime.html
                        mod_proxy.html mod_rewrite.html mod_status.html
                        mod_userdir.html
               src      CHANGES Configuration.tmpl Configure INSTALL
                        Makefile.tmpl PORTING alloc.c buff.c buff.h conf.h
                        http_bprintf.c http_conf_globals.h http_config.c
                        http_config.h http_core.c http_main.c
                        http_protocol.c http_protocol.h http_request.c
                        httpd.h mod_auth_anon.c mod_browser.c
                        mod_cern_meta.c mod_cgi.c mod_digest.c mod_dir.c
                        mod_imap.c mod_include.c mod_info.c
                        mod_negotiation.c mod_rewrite.c mod_rewrite.h
                        mod_status.c mod_userdir.c mod_usertrack.c
                        scoreboard.h util.c util_script.c
               src/helpers GuessOS
               src/modules/proxy mod_proxy.h proxy_cache.c proxy_ftp.c
                        proxy_http.c proxy_util.c
               support  logresolve.c suexec.c
  Added:       .        STATUS
  Removed:     htdocs/manual/mod mod_autoindex.html
               src      mod_autoindex.c
  Log:
  part of the surgery, this merges APACHE_1_2_X onto the main branch
  
  Revision  Changes    Path
  1.2       +4 -4      apache-1.2/ABOUT_APACHE
  
  Index: ABOUT_APACHE
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/ABOUT_APACHE,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ABOUT_APACHE	1997/06/03 23:23:13	1.1
  +++ ABOUT_APACHE	1998/01/30 09:12:39	1.2
  @@ -67,16 +67,17 @@
   
   ============================================================================
   
  -Current Apache Group, 1 June 1997
  +Current Apache Group in alphabetical order as of 1 August 1997:
   
      Brian Behlendorf       Organic Online, California 
      Ken Coar               Process Software Corporation, New England, USA 
      Mark J. Cox            UKWeb, UK 
  +   Ralf S. Engelschall    Munich, Germany.
      Roy T. Fielding        UC Irvine, California 
      Dean Gaudet            Steam Tunnel Operations, California 
      Rob Hartill            Internet Movie DB, UK 
      Jim Jagielski          jaguNET ISP, Maryland 
  -   Alexei Kosut           Nueva High School, California 
  +   Alexei Kosut           Stanford University, California 
      Ben Laurie             Freelance Consultant, UK 
      Chuck Murcko           The Topsail Group, Pennsylvania 
      Aram W. Mirzadeh       Qosina Corporation, New York 
  @@ -99,8 +100,7 @@
      Paul Richards (convinced the group to use remote CVS after 1.0),
      Kevin Hughes (creator of all those nifty icons),
      Henry Spencer (author of the regex library), Garey Smiley (OS/2 port),
  -   Ralf S. Engelschall (mod_rewrite), Howard Fear (mod_include),
  -   Florent Guillaume (language negotiation).
  +   Howard Fear (mod_include), Florent Guillaume (language negotiation)
   
   Many 3rd-party modules, frequently used and recommended, are also
   freely-available and linked from the related projects page:
  
  
  
  1.10      +0 -1      apache-1.2/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/CHANGES,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- CHANGES	1997/04/24 23:51:34	1.9
  +++ CHANGES	1998/01/30 09:12:40	1.10
  @@ -117,7 +117,6 @@
          Apache 1.2. Some of the changes visible to users:
          
                 - Improved FTP proxy supporting PASV mode
  -              - NoProxy directive for excluding sites to proxy
                 - CONNECT mode ports are configurable from a list
                 - NoCache * directive for disabling proxy caching
                 - Numerous bug fixes
  
  
  
  1.10      +16 -0     apache-1.2/KEYS
  
  Index: KEYS
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/KEYS,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- KEYS	1997/06/05 17:02:12	1.9
  +++ KEYS	1998/01/30 09:12:41	1.10
  @@ -169,3 +169,19 @@
   =vUdL
   -----END PGP PUBLIC KEY BLOCK-----
   
  +Type Bits/KeyID    Date       User ID
  +pub  1024/26BB437D 1997/04/28 Ralf S. Engelschall <rs...@engelschall.com>
  +
  +-----BEGIN PGP PUBLIC KEY BLOCK-----
  +Version: 2.6.3ia
  +
  +mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
  +syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
  ++oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
  +tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
  +EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
  +p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
  +cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
  +hiXZ
  +=K7lL
  +-----END PGP PUBLIC KEY BLOCK-----
  
  
  
  1.9       +4 -4      apache-1.2/README
  
  Index: README
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/README,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- README	1996/12/01 05:38:15	1.8
  +++ README	1998/01/30 09:12:43	1.9
  @@ -62,12 +62,12 @@
   
   Details of the latest version are in the apache project page (above).
   
  -Licencing
  +Licensing
   ---------
   
   Please see the file called LICENSE.
   
  -Acknowledgements
  +Acknowledgments
   ----------------
   
   We wish to acknowledge the following copyrighted works that make up
  @@ -78,8 +78,8 @@
   Urbana-Champaign.
   
   This software contains code derived from the RSA Data Security Inc. MD5
  -Message-Diest Algorithm, including various modifications by Spyglass Inc.,
  -Caregie Mellon University, and Bell Communications Research, Inc. 
  +Message-Digest Algorithm, including various modifications by Spyglass Inc.,
  +Carnegie Mellon University, and Bell Communications Research, Inc. 
   (Bellcore).
   
   This package contains software written and copyrighted by Henry Spencer. 
  
  
  
  1.2       +48 -0     apache-1.2/STATUS
  
  
  
  
  1.14      +4 -1      apache-1.2/conf/httpd.conf-dist
  
  Index: httpd.conf-dist
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/conf/httpd.conf-dist,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- httpd.conf-dist	1997/05/04 20:18:04	1.13
  +++ httpd.conf-dist	1998/01/30 09:12:49	1.14
  @@ -20,6 +20,9 @@
   
   # HostnameLookups: Log the names of clients or just their IP numbers
   #   e.g.   www.apache.org (on) or 204.62.129.132 (off)
  +# You should probably turn this off unless you are going to actually
  +# use the information in your logs, or with a CGI.  Leaving this on
  +# can slow down access to your site.
   HostnameLookups on
   
   # If you wish httpd to run as a different user or group, you must run
  @@ -173,7 +176,7 @@
   # alias flag, or through kernel patches like VIF.
   
   # Any httpd.conf or srm.conf directive may go into a VirtualHost command.
  -# See alto the BindAddress entry.
  +# See also the BindAddress entry.
    
   #<VirtualHost host.some_domain.com>
   #ServerAdmin webmaster@host.some_domain.com
  
  
  
  1.6       +47 -23    apache-1.2/htdocs/index.html
  
  Index: index.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/index.html,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- index.html	1997/05/01 05:26:31	1.5
  +++ index.html	1998/01/30 09:12:51	1.6
  @@ -1,23 +1,47 @@
  -<HTML><HEAD>
  -<TITLE>Test Page for Apache</TITLE>
  -</HEAD><BODY>
  -
  -<H1>It Worked!</H1>
  -
  -If you can see this, then your 
  -<A HREF="http://www.apache.org/">Apache</A> installation was 
  -successful.  You may now add content to this directory and 
  -replace this page.
  -
  -<P>
  -The Apache <A HREF="manual/index.html">documentation has been
  -included with this distribution.</A>
  -
  -<P>
  -You are free to use the image below on an Apache-powered web
  -server.  Thanks for using Apache!
  -
  -<P>
  -<img src="apache_pb.gif" alt="">
  -
  -</BODY></HTML>
  +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
  +<HTML>
  + <HEAD>
  +  <TITLE>Test Page for Apache Installation</TITLE>
  + </HEAD>
  +<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
  + <BODY
  +  BGCOLOR="#FFFFFF"
  +  TEXT="#000000"
  +  LINK="#0000FF"
  +  VLINK="#000080"
  +  ALINK="#FF0000"
  + >
  +  <H1 ALIGN="CENTER">It Worked!</H1>
  +  <P>
  +  If you can see this, it means that the installation of the
  +  <A
  +   HREF="http://www.apache.org/"
  +  >Apache</A>
  +  software on this system was successful.  You may now add content to
  +  this directory and replace this page.
  +  </P>
  +  <HR WIDTH="50%" SIZE="8">
  +  <BLOCKQUOTE>
  +   If you are seeing this instead of the content you expected, please
  +   <STRONG>contact the administrator of the site involved.</STRONG>  If
  +   you send mail about this to the authors of the Apache software, who almost
  +   certainly have nothing to do with this site, your message will be
  +   <STRONG><BIG>ignored</BIG></STRONG>.
  +  </BLOCKQUOTE>
  +  <HR WIDTH="50%" SIZE="8">
  +  <P>
  +  The Apache
  +  <A
  +   HREF="manual/index.html"
  +  >documentation</A>
  +  has been included with this distribution.
  +  </P>
  +  <P>
  +  You are free to use the image below on an Apache-powered web
  +  server.  Thanks for using Apache!
  +  </P>
  +  <P ALIGN="CENTER">
  +  <IMG SRC="apache_pb.gif" ALT="">
  +  </P>
  + </BODY>
  +</HTML>
  
  
  
  1.9       +2 -2      apache-1.2/htdocs/manual/custom-error.html
  
  Index: custom-error.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/custom-error.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- custom-error.html	1997/06/04 11:07:47	1.8
  +++ custom-error.html	1998/01/30 09:12:53	1.9
  @@ -29,9 +29,9 @@
         response, then this response can be replaced with either some
         friendlier text or by a redirection to another URL (local or
         external).
  -	
  +        
         <P>
  -	
  +        
   <DT>Old behavior
   
     <DD>NCSA httpd 1.3 would return some boring old error/problem message 
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/footer.html
  
  Index: footer.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/footer.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- footer.html	1996/11/21 10:47:09	1.2
  +++ footer.html	1998/01/30 09:12:54	1.3
  @@ -1,3 +1,6 @@
   <HR>
  +<H3 ALIGN="CENTER">
  + Apache HTTP Server Version 1.2
  +</H3>
   
   <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A>
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/header.html
  
  Index: header.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/header.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- header.html	1997/06/04 02:55:15	1.2
  +++ header.html	1998/01/30 09:12:55	1.3
  @@ -1,3 +1,6 @@
   <DIV ALIGN="CENTER">
    <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]">
  + <H3>
  +  Apache HTTP Server Version 1.2
  + </H3>
   </DIV>
  
  
  
  1.30      +6 -6      apache-1.2/htdocs/manual/new_features_1_2.html
  
  Index: new_features_1_2.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/new_features_1_2.html,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- new_features_1_2.html	1997/06/04 11:07:51	1.29
  +++ new_features_1_2.html	1998/01/30 09:12:57	1.30
  @@ -193,12 +193,12 @@
   <li><b><a href="mod/mod_proxy.html">Optional proxy module</a></b><br>
   An improved FTP, HTTP, and CONNECT mode SSL proxy is included with
   Apache 1.2. Some of the changes visible to users:
  -	<dl><dl>
  -	<dt>- Improved FTP proxy supporting PASV mode
  -	<dt>- ProxyBlock directive for excluding sites to proxy
  -	<dt>- NoCache * directive for disabling proxy caching
  -	<dt>- Numerous bug fixes
  -	</dl></dl>
  +        <dl><dl>
  +        <dt>- Improved FTP proxy supporting PASV mode
  +        <dt>- ProxyBlock directive for excluding sites to proxy
  +        <dt>- NoCache * directive for disabling proxy caching
  +        <dt>- Numerous bug fixes
  +        </dl></dl>
   
   </ul>
   
  
  
  
  1.9       +3 -3      apache-1.2/htdocs/manual/process-model.html
  
  Index: process-model.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/process-model.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- process-model.html	1997/06/04 11:07:51	1.8
  +++ process-model.html	1998/01/30 09:12:58	1.9
  @@ -39,9 +39,9 @@
   The defaults for each variable are:
   
   <PRE>
  -MinSpareServers		5
  -MaxSpareServers		10
  -StartServers		5
  +MinSpareServers         5
  +MaxSpareServers         10
  +StartServers            5
   </PRE>
   
   There is an absolute maximum number of simultaneous children defined
  
  
  
  1.12      +157 -156  apache-1.2/htdocs/manual/suexec.html
  
  Index: suexec.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/suexec.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- suexec.html	1997/06/05 20:07:19	1.11
  +++ suexec.html	1998/01/30 09:12:59	1.12
  @@ -17,14 +17,15 @@
   
   <P ALIGN="LEFT">
   <OL>
  -	<LH><BIG><STRONG>CONTENTS</STRONG></BIG></LH>
  -	<LI><A HREF="#what">What is suEXEC?</A></LI>
  -	<LI><A HREF="#before">Before we begin.</A></LI>
  -	<LI><A HREF="#model">suEXEC Security Model.</A></LI>
  -	<LI><A HREF="#install">Configuring & Installing suEXEC</A></LI>
  -	<LI><A HREF="#enable">Enabling & Disabling suEXEC</A></LI>
  -	<LI><A HREF="#debug">Debugging suEXEC</A></LI>
  -	<LI><A HREF="#jabberwock">Beware the Jabberwock: Warnings & Examples</A></LI>
  +        <LH><BIG><STRONG>CONTENTS</STRONG></BIG></LH>
  +        <LI><A HREF="#what">What is suEXEC?</A></LI>
  +        <LI><A HREF="#before">Before we begin.</A></LI>
  +        <LI><A HREF="#model">suEXEC Security Model.</A></LI>
  +        <LI><A HREF="#install">Configuring &amp; Installing suEXEC</A></LI>
  +        <LI><A HREF="#enable">Enabling &amp; Disabling suEXEC</A></LI>
  +        <LI><A HREF="#debug">Debugging suEXEC</A></LI>
  +        <LI><A HREF="#jabberwock">Beware the Jabberwock: Warnings &amp;
  +         Examples</A></LI> 
   </OL>
   </P>
   
  @@ -119,124 +120,124 @@
   The wrapper then employs the following process to determine success or
   failure -- if any one of these conditions fail, the program logs the failure
   and exits with an error, otherwise it will continue:
  -	<OL>
  -	<LI><STRONG>Was the wrapper called with the proper number of arguments?</STRONG>
  -	<BLOCKQUOTE>
  -	The wrapper will only execute if it is given the proper number of arguments.
  -	The proper argument format is known to the Apache web server.  If the wrapper
  -	is not receiving the proper number of arguments, it is either being hacked, or
  -	there is something wrong with the suEXEC portion of your Apache binary.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the user executing this wrapper a valid user of this system?</STRONG>
  -	<BLOCKQUOTE>
  -	This is to ensure that the user executing the wrapper is truly a user of the system.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is this valid user allowed to run the wrapper?</STRONG>
  -	<BLOCKQUOTE>
  -	Is this user the user allowed to run this wrapper?  Only one user (the Apache
  -	user) is allowed to execute this program.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Does the target program have an unsafe hierarchical reference?</STRONG>
  -	<BLOCKQUOTE>
  -	Does the target program contain a leading '/' or have a '..' backreference?  These
  -	are not allowed; the target program must reside within the Apache webspace.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target user name valid?</STRONG>
  -	<BLOCKQUOTE>
  -	Does the target user exist?
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target group name valid?</STRONG>
  -	<BLOCKQUOTE>
  -	Does the target group exist?
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target user <EM>NOT</EM> superuser?</STRONG>
  -	<BLOCKQUOTE>
  -	Presently, suEXEC does not allow 'root' to execute CGI/SSI programs.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target userid <EM>ABOVE</EM> the minimum ID number?</STRONG>
  -	<BLOCKQUOTE>
  -	The minimum user ID number is specified during configuration.  This allows you
  -	to set the lowest possible userid that will be allowed to execute CGI/SSI programs.
  -	This is useful to block out "system" accounts.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target group <EM>NOT</EM> the superuser group?</STRONG>
  -	<BLOCKQUOTE>
  -	Presently, suEXEC does not allow the 'root' group to execute CGI/SSI programs.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target groupid <EM>ABOVE</EM> the minimum ID number?</STRONG>
  -	<BLOCKQUOTE>
  -	The minimum group ID number is specified during configuration.  This allows you
  -	to set the lowest possible groupid that will be allowed to execute CGI/SSI programs.
  -	This is useful to block out "system" groups.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Can the wrapper successfully become the target user and group?</STRONG>
  -	<BLOCKQUOTE>
  -	Here is where the program becomes the target user and group via setuid and setgid
  -	calls.  The group access list is also initialized with all of the groups of which
  -	the user is a member.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Does the directory in which the program resides exist?</STRONG>
  -	<BLOCKQUOTE>
  -	If it doesn't exist, it can't very well contain files.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the directory within the Apache webspace?</STRONG>
  -	<BLOCKQUOTE>
  -	If the request is for a regular portion of the server, is the requested directory
  -	within the server's document root?  If the request is for a UserDir, is the requested
  -	directory within the user's document root?
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the directory <EM>NOT</EM> writable by anyone else?</STRONG>
  -	<BLOCKQUOTE>
  -	We don't want to open up the directory to others; only the owner user may be able
  -	to alter this directories contents.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Does the target program exist?</STRONG>
  -	<BLOCKQUOTE>
  -	If it doesn't exists, it can't very well be executed.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target program <EM>NOT</EM> writable by anyone else?</STRONG>
  -	<BLOCKQUOTE>
  -	We don't want to give anyone other than the owner the ability to change the program.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target program <EM>NOT</EM> setuid or setgid?</STRONG>
  -	<BLOCKQUOTE>
  -	We do not want to execute programs that will then change our UID/GID again.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Is the target user/group the same as the program's user/group?</STRONG>
  -	<BLOCKQUOTE>
  -	Is the user the owner of the file?
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Can we successfully clean the process environment to ensure safe operations?</STRONG>
  -	<BLOCKQUOTE>
  -	suEXEC cleans the process' environment by establishing a safe execution PATH (defined
  -	during configuration), as well as only passing through those variables whose names
  -	are listed in the safe environment list (also created during configuration).
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI><STRONG>Can we successfully become the target program and execute?</STRONG>
  -	<BLOCKQUOTE>
  -	Here is where suEXEC ends and the target program begins.
  -	</BLOCKQUOTE>
  -	</LI>
  -	</OL>
  +        <OL>
  +        <LI><STRONG>Was the wrapper called with the proper number of arguments?</STRONG>
  +        <BLOCKQUOTE>
  +        The wrapper will only execute if it is given the proper number of arguments.
  +        The proper argument format is known to the Apache web server.  If the wrapper
  +        is not receiving the proper number of arguments, it is either being hacked, or
  +        there is something wrong with the suEXEC portion of your Apache binary.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the user executing this wrapper a valid user of this system?</STRONG>
  +        <BLOCKQUOTE>
  +        This is to ensure that the user executing the wrapper is truly a user of the system.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is this valid user allowed to run the wrapper?</STRONG>
  +        <BLOCKQUOTE>
  +        Is this user the user allowed to run this wrapper?  Only one user (the Apache
  +        user) is allowed to execute this program.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Does the target program have an unsafe hierarchical reference?</STRONG>
  +        <BLOCKQUOTE>
  +        Does the target program contain a leading '/' or have a '..' backreference?  These
  +        are not allowed; the target program must reside within the Apache webspace.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target user name valid?</STRONG>
  +        <BLOCKQUOTE>
  +        Does the target user exist?
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target group name valid?</STRONG>
  +        <BLOCKQUOTE>
  +        Does the target group exist?
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target user <EM>NOT</EM> superuser?</STRONG>
  +        <BLOCKQUOTE>
  +        Presently, suEXEC does not allow 'root' to execute CGI/SSI programs.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target userid <EM>ABOVE</EM> the minimum ID number?</STRONG>
  +        <BLOCKQUOTE>
  +        The minimum user ID number is specified during configuration.  This allows you
  +        to set the lowest possible userid that will be allowed to execute CGI/SSI programs.
  +        This is useful to block out "system" accounts.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target group <EM>NOT</EM> the superuser group?</STRONG>
  +        <BLOCKQUOTE>
  +        Presently, suEXEC does not allow the 'root' group to execute CGI/SSI programs.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target groupid <EM>ABOVE</EM> the minimum ID number?</STRONG>
  +        <BLOCKQUOTE>
  +        The minimum group ID number is specified during configuration.  This allows you
  +        to set the lowest possible groupid that will be allowed to execute CGI/SSI programs.
  +        This is useful to block out "system" groups.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Can the wrapper successfully become the target user and group?</STRONG>
  +        <BLOCKQUOTE>
  +        Here is where the program becomes the target user and group via setuid and setgid
  +        calls.  The group access list is also initialized with all of the groups of which
  +        the user is a member.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Does the directory in which the program resides exist?</STRONG>
  +        <BLOCKQUOTE>
  +        If it doesn't exist, it can't very well contain files.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the directory within the Apache webspace?</STRONG>
  +        <BLOCKQUOTE>
  +        If the request is for a regular portion of the server, is the requested directory
  +        within the server's document root?  If the request is for a UserDir, is the requested
  +        directory within the user's document root?
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the directory <EM>NOT</EM> writable by anyone else?</STRONG>
  +        <BLOCKQUOTE>
  +        We don't want to open up the directory to others; only the owner user may be able
  +        to alter this directories contents.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Does the target program exist?</STRONG>
  +        <BLOCKQUOTE>
  +        If it doesn't exists, it can't very well be executed.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target program <EM>NOT</EM> writable by anyone else?</STRONG>
  +        <BLOCKQUOTE>
  +        We don't want to give anyone other than the owner the ability to change the program.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target program <EM>NOT</EM> setuid or setgid?</STRONG>
  +        <BLOCKQUOTE>
  +        We do not want to execute programs that will then change our UID/GID again.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Is the target user/group the same as the program's user/group?</STRONG>
  +        <BLOCKQUOTE>
  +        Is the user the owner of the file?
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Can we successfully clean the process environment to ensure safe operations?</STRONG>
  +        <BLOCKQUOTE>
  +        suEXEC cleans the process' environment by establishing a safe execution PATH (defined
  +        during configuration), as well as only passing through those variables whose names
  +        are listed in the safe environment list (also created during configuration).
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI><STRONG>Can we successfully become the target program and execute?</STRONG>
  +        <BLOCKQUOTE>
  +        Here is where suEXEC ends and the target program begins.
  +        </BLOCKQUOTE>
  +        </LI>
  +        </OL>
   </P>
   
   <P ALIGN="LEFT">
  @@ -257,7 +258,7 @@
   <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG>
   </P>
   
  -<H3><A NAME="install">Configuring & Installing suEXEC</A></H3>
  +<H3><A NAME="install">Configuring &amp; Installing suEXEC</A></H3>
   <P ALIGN="LEFT">
   Here's where we begin the fun.  The configuration and installation of suEXEC is
   a four step process: edit the suEXEC header file, compile suEXEC, place the
  @@ -396,7 +397,7 @@
   <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG>
   </P>
   
  -<H3><A NAME="enable">Enabling & Disabling suEXEC</A></H3>
  +<H3><A NAME="enable">Enabling &amp; Disabling suEXEC</A></H3>
   <P ALIGN="LEFT">
   After properly installing the <STRONG>suexec</STRONG> wrapper
   executable, you must kill and restart the Apache server.  A simple
  @@ -454,7 +455,7 @@
   <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG>
   </P>
   
  -<H3><A NAME="jabberwock">Beware the Jabberwock: Warnings & Examples</A></H3>
  +<H3><A NAME="jabberwock">Beware the Jabberwock: Warnings &amp; Examples</A></H3>
   <P ALIGN="LEFT">
   <STRONG>NOTE!</STRONG>  This section may not be complete.  For the latest
   revision of this section of the documentation, see the Apache Group's
  @@ -467,33 +468,33 @@
   limitations on server setup.  Please review these before submitting any
   "bugs" regarding suEXEC.
   <UL>
  -	<LH><STRONG>suEXEC Points Of Interest</STRONG></LH>
  -	<LI>Hierarchy limitations
  -	<BLOCKQUOTE>
  -	For security and efficiency reasons, all suexec requests must
  -	remain within either a top-level document root for virtual
  -	host requests, or one top-level personal document root for
  -	userdir requests.  For example, if you have four VirtualHosts
  -	configured, you would need to structure all of your VHosts'
  -	document roots off of one main Apache document hierarchy to
  -	take advantage of suEXEC for VirtualHosts. (Example forthcoming.)
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI>suEXEC's PATH environment variable
  -	<BLOCKQUOTE>
  -	This can be a dangerous thing to change.  Make certain every
  -	path you include in this define is a <STRONG>trusted</STRONG>
  -	directory.  You don't want to open people up to having someone
  -	from across the world running a trojan horse on them.
  -	</BLOCKQUOTE>
  -	</LI>
  -	<LI>Altering the suEXEC code
  -	<BLOCKQUOTE>
  -	Again, this can cause <STRONG>Big Trouble</STRONG> if you try
  -	this without knowing what you are doing.  Stay away from it
  -	if at all possible.
  -	</BLOCKQUOTE>
  -	</LI>
  +        <LH><STRONG>suEXEC Points Of Interest</STRONG></LH>
  +        <LI>Hierarchy limitations
  +        <BLOCKQUOTE>
  +        For security and efficiency reasons, all suexec requests must
  +        remain within either a top-level document root for virtual
  +        host requests, or one top-level personal document root for
  +        userdir requests.  For example, if you have four VirtualHosts
  +        configured, you would need to structure all of your VHosts'
  +        document roots off of one main Apache document hierarchy to
  +        take advantage of suEXEC for VirtualHosts. (Example forthcoming.)
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI>suEXEC's PATH environment variable
  +        <BLOCKQUOTE>
  +        This can be a dangerous thing to change.  Make certain every
  +        path you include in this define is a <STRONG>trusted</STRONG>
  +        directory.  You don't want to open people up to having someone
  +        from across the world running a trojan horse on them.
  +        </BLOCKQUOTE>
  +        </LI>
  +        <LI>Altering the suEXEC code
  +        <BLOCKQUOTE>
  +        Again, this can cause <STRONG>Big Trouble</STRONG> if you try
  +        this without knowing what you are doing.  Stay away from it
  +        if at all possible.
  +        </BLOCKQUOTE>
  +        </LI>
   </UL>
   
   <P ALIGN="CENTER">
  
  
  
  1.10      +8 -4      apache-1.2/htdocs/manual/vhosts-in-depth.html
  
  Index: vhosts-in-depth.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/vhosts-in-depth.html,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- vhosts-in-depth.html	1997/06/04 11:07:52	1.9
  +++ vhosts-in-depth.html	1998/01/30 09:13:01	1.10
  @@ -357,23 +357,27 @@
   <li>Place all main_server definitions before any VirtualHost definitions.
   (This is to aid the readability of the configuration -- the post-config
   merging process makes it non-obvious that definitions mixed in around
  -virtualhosts might affect all virtualhosts.)</p>
  +virtualhosts might affect all virtualhosts.)
  +<p>
   
   <li>Arrange your VirtualHosts such
   that all name-based virtual hosts come first, followed by IP-based
  -virtual hosts, followed by any <SAMP>_default_</SAMP> virtual host</p>
  +virtual hosts, followed by any <SAMP>_default_</SAMP> virtual host
  +<p>
   
   <li>Avoid <code>ServerPaths</code> which are prefixes of other
   <code>ServerPaths</code>.  If you cannot avoid this then you have to
   ensure that the longer (more specific) prefix vhost appears earlier in
   the configuration file than the shorter (less specific) prefix
   (<EM>i.e.</EM>, &quot;ServerPath /abc&quot; should appear after
  -&quot;ServerPath /abcdef&quot;). </p>
  +&quot;ServerPath /abcdef&quot;).
  +<p>
   
   <li>Do not use <i>port-based</i> vhosts in the same server as
   name-based vhosts.  A loose definition for port-based is a vhost which
   is determined by the port on the server (<em>i.e.</em> one server with
  -ports 8000, 8080, and 80 all of which have different configurations).</p>
  +ports 8000, 8080, and 80 all of which have different configurations).
  +<p>
   
   </ul>
   
  
  
  
  1.13      +2 -2      apache-1.2/htdocs/manual/virtual-host.html
  
  Index: virtual-host.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/virtual-host.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- virtual-host.html	1997/06/04 11:07:52	1.12
  +++ virtual-host.html	1998/01/30 09:13:02	1.13
  @@ -186,9 +186,9 @@
   "rlimit" to some large number, like 512.  
   <LI>Edit http_main.c to add calls to setrlimit() from main(), along the lines of
   <PRE>
  -	struct rlimit rlp;
  +        struct rlimit rlp;
   
  -	rlp.rlim_cur = rlp.rlim_max = 512;
  +        rlp.rlim_cur = rlp.rlim_max = 512;
           if (setrlimit(RLIMIT_NPROC, &rlp)) {
               fprintf(stderr, "setrlimit(RLIMIT_NPROC) failed.\n");
               exit(1);
  
  
  
  1.64      +800 -139  apache-1.2/htdocs/manual/misc/FAQ.html
  
  Index: FAQ.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/FAQ.html,v
  retrieving revision 1.63
  retrieving revision 1.64
  diff -u -r1.63 -r1.64
  --- FAQ.html	1997/06/04 11:42:55	1.63
  +++ FAQ.html	1998/01/30 09:13:06	1.64
  @@ -15,7 +15,7 @@
     <!--#include virtual="header.html" -->
     <H1 ALIGN="CENTER">Apache Server Frequently Asked Questions</H1>
     <P>
  -  $Revision: 1.63 $ ($Date: 1997/06/04 11:42:55 $)
  +  $Revision: 1.64 $ ($Date: 1998/01/30 09:13:06 $)
     </P>
     <P>
     The latest version of this FAQ is always available from the main
  @@ -35,6 +35,11 @@
   <!--    apache.org or apacheweek.com).                              -->
   <!--  - When adding items, make sure they're put in the right place -->
   <!--    - verify that the numbering matches up.                     -->
  +<!--  - *Don't* use <PRE></PRE> blocks - they don't appear          -->
  +<!--    correctly in a reliable way when this is converted to text  -->
  +<!--    with Lynx.  Use <DL><DD><CODE>xxx<BR>xx</CODE></DD></DL>    -->
  +<!--    blocks inside a <P></P> instead.  This is necessary to get  -->
  +<!--    the horizontal and vertical indenting right.                -->
   <!--  - Don't forget to include an HR tag after the last /P tag     -->
   <!--    but before the /LI in an item.                              -->
     <P>
  @@ -51,8 +56,8 @@
   <!-- - mod_auth & passwd lines "user:pw:.*" - ++1st colon onward is -->
   <!--   treated as pw, not just ++1st to --2nd.                      -->
   <!-- - SSL:                                                         -->
  -<!--   Can I use Apache-SSL for free in Canada?                     -->
  -<!--   Why can't I use Apache-SSL in the U.S.?                      -->
  +<!--   - Can I use Apache-SSL for free in Canada?                   -->
  +<!--   - Why can't I use Apache-SSL in the U.S.?                    -->
   <!-- - How can I found out how many visitors my site gets?          -->
   <!-- - How do I add a counter?                                      -->
   <!-- - How do I configure Apache as a proxy?                        -->
  @@ -61,17 +66,19 @@
   <!--   HTTP/1.1 browsers?                                           -->
   <!-- - Is there an Apache for W95/WNT?                              -->
   <!-- - Why does Apache die when a vhost can't be DNS-resolved?      -->
  -<!-- - How do I setup an access restriction so that people from     -->
  -<!--   this domain don't have to authenticate, and all others can   -->
  -<!--   do so via a username and password?                           -->
   <!-- - Why do I get "send lost connection" messages in my error     -->
   <!--   log?                                                         -->
   <!--   - specifically consider .pdf files which seem to cause this  -->
   <!--     a lot when accessed via the plugin ... and also mention    -->
   <!--     how range-requests can cause bytes served < file size      -->
  -<!-- - Why does http://host/~user not work but http://host/~user/   -->
  -<!--   works properly?                                              -->
  +<!-- - Why do directory indexes appear as garbage?  (A: -lucb)      -->
   <!-- - How do I add a footer to all pages offered by my server?     -->
  +<!-- - Fix midi question; a bigger problem than midi vs. x-midi is  -->
  +<!--   the simple fact that older versions of Apache (and new ones  -->
  +<!--   that have been upgraded without upgrading the mime.types     -->
  +<!--   file) don't have the type listed at all.                     -->
  +<!-- - Why is my .htaccess ignored?                                 -->
  +<!-- - RewriteRule /~fraggle/* /cgi-bin/fraggle.pl does not work    -->
   <UL>
    <LI><STRONG>Background</STRONG>
     <OL START=1>
  @@ -80,7 +87,7 @@
      <LI><A HREF="#why">Why was Apache created?</A>
      </LI>
      <LI><A HREF="#relate">How does The Apache Group's work relate to
  -    other servers?</A> 
  +    other servers?</A>
      </LI>
      <LI><A HREF="#name">Why the name &quot;Apache&quot;?</A>
      </LI>
  @@ -111,7 +118,7 @@
      </LI>
      <LI><A HREF="#premature-script-headers">What does it mean when my
           CGIs fail with &quot;<SAMP>Premature end of script
  -        headers</SAMP>&quot;?</A> 
  +        headers</SAMP>&quot;?</A>
      </LI>
      <LI><A HREF="#ssi-part-i">How do I enable SSI (parsed HTML)?</A>
      </LI>
  @@ -126,6 +133,8 @@
      <LI><A HREF="#fdlim">Why can't I run more than &lt;<EM>n</EM>&gt;
       virtual hosts?</A>
      </LI>
  +   <LI><A HREF="#freebsd-setsize">Can I increase FD_SETSIZE on FreeBSD?</A>
  +   </LI>
      <LI><A HREF="#limitGET">Why do I keep getting &quot;access denied&quot; for
       form POST requests?</A>
      </LI>
  @@ -140,7 +149,7 @@
      </LI>
      <LI><A HREF="#cookies1">Why does Apache send a cookie on every response?</A>
      </LI>
  -   <LI><A HREF="#cookies2">Why don't my cookies work, I even compiled in 
  +   <LI><A HREF="#cookies2">Why don't my cookies work, I even compiled in
       <SAMP>mod_cookies</SAMP>?</A>
      </LI>
      <LI><A HREF="#jdk1-and-http1.1">Why do my Java app[let]s give me plain text
  @@ -155,11 +164,14 @@
      <LI><A HREF="#nodelay">Why am I getting &quot;<SAMP>httpd: could not
       set socket option TCP_NODELAY</SAMP>&quot; in my error log?</A>
      </LI>
  +   <LI><A HREF="#peerreset">Why am I getting &quot;<SAMP>connection
  +    reset by peer</SAMP>&quot; in my error log?</A>
  +   </LI>
      <LI><A HREF="#nph-scripts">How can I get my script's output without
       Apache buffering it?</A>
      </LI>
      <LI><A HREF="#linuxiovec">Why do I get complaints about redefinition
  -    of `struct iovec' when compiling under Linux?</A>
  +    of &quot;<CODE>struct iovec</CODE>&quot; when compiling under Linux?</A>
      </LI>
      <LI><A HREF="#wheres-the-dump">The errorlog says Apache dumped core,
       but where's the dump file?</A>
  @@ -181,6 +193,65 @@
      <LI><A HREF="#addlog">How do I add browsers and referrers to my
       logs?</A>
      </LI>
  +   <LI><A HREF="#bind8.1">Why do I get an error about an undefined
  +    reference to &quot;<SAMP>__inet_ntoa</SAMP>&quot; or other
  +    <SAMP>__inet_*</SAMP> symbols?</A>
  +   </LI>
  +   <LI><A HREF="#set-servername">Why does accessing directories only work
  +    when I include the trailing "/"
  +    (<EM>e.g.</EM>,&nbsp;<SAMP>http://foo.domain.com/~user/</SAMP>) but
  +    not when I omit it
  +    (<EM>e.g.</EM>,&nbsp;<SAMP>http://foo.domain.com/~user</SAMP>)?</A>
  +   </LI>
  +   <LI><A HREF="#user-authentication">How do I set up Apache to require
  +    a username and password to access certain documents?</A>
  +   </LI>
  +   <LI><A HREF="#remote-user-var">Why is the environment variable
  +   <SAMP>REMOTE_USER</SAMP> not set?</A>
  +   </LI>
  +   <LI><A HREF="#remote-auth-only">How do I set up Apache to allow access
  +    to certain documents only if a site is either a local site
  +    <EM>or</EM> the user supplies a password and username?</A>
  +   </LI>
  +   <LI><A HREF="#no-info-directives">Why doesn't mod_info list any
  +    directives?</A>
  +   <LI><A HREF="#linux-shmget">When I run it under Linux I get "shmget:
  +    function not found", what should I do?</A>
  +   </LI>
  +   <LI><A HREF="#authauthoritative">Why does my authentication give
  +    me a server error?</A>
  +   <LI><A HREF="#auth-on-same-machine">Do I have to keep the (mSQL)
  +    authentication information on the same machine?</A>
  +   </LI>
  +   <LI><A HREF="#msql-slow">Why is my mSQL authentication terribly slow?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-more-config">Where can I find mod_rewrite rulesets
  +    which already solve particular URL-related problems?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-article">Where can I find any published information about
  +    URL-manipulations and mod_rewrite?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-complexity">Why is mod_rewrite so difficult to learn
  +    and seems so complicated?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-dontwork">What can I do if my RewriteRules don't work
  +    as expected?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-prefixdocroot">Why don't some of my URLs get
  +    prefixed with DocumentRoot when using mod_rewrite?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-nocase">How can I make all my URLs case-insensitive
  +    with mod_rewrite?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-virthost">Why are RewriteRules in my VirtualHost
  +    parts ignored?</A>
  +   </LI>
  +   <LI><A HREF="#rewrite-envwhitespace">How can I use strings with whitespaces
  +    in RewriteRule's ENV flag?</A>
  +   </LI>
  +   <LI><A HREF="#cgi-spec">Where can I find the &quot;CGI
  +    specification&quot;?</A>
  +   </LI>
     </OL>
    </LI>
   </UL>
  @@ -188,8 +259,6 @@
   <HR>
   
     <H2>The Answers</H2>
  -  <P>
  -  </P>
     <H3>
      Background
     </H3>
  @@ -220,10 +289,10 @@
     <P>
     To address the concerns of a group of WWW providers and part-time httpd
     programmers that httpd didn't behave as they wanted it to behave.
  -  Apache is an entirely volunteer effort, completely funded by its 
  +  Apache is an entirely volunteer effort, completely funded by its
     members, not by commercial sales.
  -  <HR>
     </P>
  +  <HR>
    </LI>
    <LI><A NAME="relate">
         <STRONG>How does The Apache Group's work relate to other
  @@ -254,7 +323,7 @@
     For an independent assessment, see
     <A
      HREF="http://webcompare.iworld.com/compare/chart.html"
  -  >Web Compare</A>'s 
  +  >Web Compare</A>'s
     comparison chart.
     </P>
     <P>
  @@ -273,7 +342,7 @@
         <STRONG>How thoroughly tested is Apache?</STRONG>
        </A>
     <P>
  -  Apache is run on over 400,000 Internet servers (as of April 1997). It has
  +  Apache is run on over 500,000 Internet servers (as of July 1997). It has
     been tested thoroughly by both developers and users. The Apache Group
     maintains rigorous standards before releasing new versions of their
     server, and our server runs without a hitch on over one third of all
  @@ -380,10 +449,10 @@
       <P>
       Apache tries to be helpful when it encounters a problem.  In many
       cases, it will provide some details by writing one or messages to
  -    the server error log.  Sometimes this is enough for you to diagnose 
  +    the server error log.  Sometimes this is enough for you to diagnose
       &amp; fix the problem yourself (such as file permissions or the like).
  -    The default location of the error log is 
  -    <CODE>/usr/local/etc/httpd/logs/error_log</CODE>, but see the 
  +    The default location of the error log is
  +    <SAMP>/usr/local/etc/httpd/logs/error_log</SAMP>, but see the
       <A
        HREF="../mod/core.html#errorlog"
       ><SAMP>ErrorLog</SAMP></A>
  @@ -446,16 +515,12 @@
       dump, please include a backtrace (if possible).  As an example,
       </P>
       <P>
  -    <CODE>
  -     <DL>
  -      <DD># cd <EM>ServerRoot</EM>
  -      </DD>
  -      <DD># dbx httpd core
  -      </DD>
  -      <DD>(dbx) where
  -      </DD>
  -     </DL>
  -    </CODE>
  +    <DL>
  +     <DD><CODE># cd <EM>ServerRoot</EM><BR>
  +      # dbx httpd core<BR>
  +      (dbx) where</CODE>
  +     </DD>
  +    </DL>
       </P>
       <P>
       (Substitute the appropriate locations for your
  @@ -477,7 +542,7 @@
     NCSA httpd 1.4 and NCSA httpd 1.5.
     </P>
     <P>
  -  NCSA httpd appears to be moving toward adding experimental features 
  +  NCSA httpd appears to be moving toward adding experimental features
     which are not generally required at the moment. Some of the experiments
     will succeed while others will inevitably be dropped. The Apache
     philosophy is to add what's needed as and when it is needed.
  @@ -515,6 +580,7 @@
     ><SAMP>AddHandler</SAMP></A>
     directive.
     </P>
  +  <P>
     <OL>
      <LI>In an appropriate section of your server configuration files, add
       a line such as
  @@ -524,9 +590,11 @@
        </DD>
       </DL>
       </P>
  +    <P>
       The server will then recognize that all files in that location (and
       its logical descendants) that end in &quot;<SAMP>.cgi</SAMP>&quot;
       are script files, not documents.
  +    </P>
      </LI>
      <LI>Make sure that the directory location is covered by an
       <A
  @@ -535,39 +603,96 @@
       declaration that includes the <SAMP>ExecCGI</SAMP> option.
      </LI>
     </OL>
  +  </P>
  +  <P>
  +  In some situations it can be not conform to your local policy to actually
  +  allow all files named &quot;<SAMP>*.cgi</SAMP>&quot; to be executable.
  +  Perhaps all you want is to enable a particular file in a normal directory to
  +  be executable. This can be alternatively accomplished 
  +  via 
  +  <A
  +   HREF="../mod/mod_rewrite.html"
  +  ><SAMP>mod_rewrite</SAMP></A> 
  +  and the following steps:
  +  </P>
  +  <P>
  +  <OL>
  +   <LI>Locally add to the corresponding <SAMP>.htaccess</SAMP> file a ruleset
  +       similar to this one:
  +    <P>
  +    <DL>
  +     <DD><CODE>RewriteEngine on
  +      <BR>
  +      RewriteBase   /~foo/bar/
  +      <BR>
  +      RewriteRule   ^quux\.cgi$  -  [T=application/x-httpd-cgi]</CODE>
  +     </DD>
  +    </DL>
  +    </P>
  +   </LI>
  +   <LI>Make sure that the directory location is covered by an
  +    <A
  +     HREF="../mod/core.html#options"
  +    ><SAMP>Options</SAMP></A>
  +        declaration that includes the <SAMP>ExecCGI</SAMP> and
  +        <SAMP>FollowSymLinks</SAMP> option.
  +   </LI>
  +  </OL>
  +  </P>
     <HR>
    </LI>
    <LI><A NAME="premature-script-headers">
         <STRONG>What does it mean when my CGIs fail with
         &quot;<SAMP>Premature end of script headers</SAMP>&quot;?</STRONG>
  -     </A> 
  +     </A>
     <P>
     It means just what it says: the server was expecting a complete set of
     HTTP headers (one or more followed by a blank line), and didn't get
  -  them.  The most common cause of this (aside from people not
  -  outputting the required headers at all) a result of an interaction
  -  with perl's output buffering.  To make perl flush its buffers 
  -  after each output statement, insert the following statements before your
  -  first <CODE>print</CODE> or <CODE>write</CODE> statement:
  +  them.
     </P>
     <P>
  -  <CODE>
  -   <DL>
  -    <DD>$cfh = select (STDOUT);
  -    </DD>
  -    <DD>$| = 1;
  -    </DD>
  -    <DD>select ($cfh);
  -    </DD>
  -   </DL>
  -  </CODE>
  +  The most common cause of this problem is the script dying before
  +  sending the complete set of headers, or possibly any at all, to the
  +  server.  To see if this is the case, try running the script standalone
  +  from an interactive session, rather than as a script under the server.
  +  If you get error messages, this is almost certainly the cause of the
  +  &quot;premature end of script headers&quot; message.
  +  </P>
  +  <P>
  +  The second most common cause of this (aside from people not
  +  outputting the required headers at all) is a result of an interaction
  +  with Perl's output buffering.  To make Perl flush its buffers
  +  after each output statement, insert the following statements around
  +  the <CODE>print</CODE> or <CODE>write</CODE> statements that send your
  +  HTTP headers:
  +  </P>
  +  <P>
  +  <DL>
  +   <DD><CODE>{<BR>
  +    &nbsp;local ($oldbar) = $|;<BR>
  +    &nbsp;$cfh = select (STDOUT);<BR>
  +    &nbsp;$| = 1;<BR>
  +    &nbsp;#<BR>
  +    &nbsp;# print your HTTP headers here<BR>
  +    &nbsp;#<BR>
  +    &nbsp;$| = $oldbar;<BR>
  +    &nbsp;select ($cfh);<BR>
  +    }</CODE>
  +   </DD>
  +  </DL>
     </P>
     <P>
  -  This is generally only necessary when you are calling external 
  -  programs from your script that send output to stdout.  
  +  This is generally only necessary when you are calling external
  +  programs from your script that send output to stdout, or if there will
  +  be a long delay between the time the headers are sent and the actual
  +  content starts being emitted.  To maximize performance, you should
  +  turn buffer-flushing back <EM>off</EM> (with <CODE>$| = 0</CODE> or the
  +  equivalent) after the statements that send the headers, as displayed
  +  above.
  +  </P>
     <P>
     If your script isn't written in Perl, do the equivalent thing for
  -  whatever language you <EM>are</EM> using (<EM>e.g.</EM>, for C, call 
  +  whatever language you <EM>are</EM> using (<EM>e.g.</EM>, for C, call
     <CODE>fflush()</CODE> after writing the headers).
     </P>
     <HR>
  @@ -579,7 +704,7 @@
     SSI (an acronym for Server-Side Include) directives allow static HTML
     documents to be enhanced at run-time (<EM>e.g.</EM>, when delivered to
     a client by Apache).  The format of SSI directives is covered
  -  in the <A HREF="../mod/mod_include.html">mod_include manual</A>; 
  +  in the <A HREF="../mod/mod_include.html">mod_include manual</A>;
     suffice it to say that Apache supports not only SSI but
     xSSI (eXtended SSI) directives.
     </P>
  @@ -587,7 +712,13 @@
     Processing a document at run-time is called <EM>parsing</EM> it; hence
     the term &quot;parsed HTML&quot; sometimes used for documents that
     contain SSI instructions.  Parsing tends to be <EM>extremely</EM>
  -  resource-consumptive, and is not enabled by default.
  +  resource-consumptive, and is not enabled by default.  It can also
  +  interfere with the cachability of your documents, which can put a
  +  further load on your server.  (see the
  +  <A
  +   HREF="#ssi-part-ii"
  +  >next question</A>
  +  for more information about this.)
     </P>
     <P>
     To enable SSI processing, you need to
  @@ -695,8 +826,12 @@
         <STRONG>Does or will Apache act as a Proxy server?</STRONG>
        </A>
     <P>
  -  Apache version 1.1 and above comes with a proxy module. If compiled
  -  in, this will make Apache act as a caching-proxy server.  
  +  Apache version 1.1 and above comes with a
  +  <A
  +   HREF="../mod/mod_proxy.html"
  +  >proxy module</A>.
  +  If compiled
  +  in, this will make Apache act as a caching-proxy server.
     </P>
     <HR>
    </LI>
  @@ -706,7 +841,7 @@
     <P>
     &quot;Multiviews&quot; is the general name given to the Apache
     server's ability to provide language-specific document variants in
  -  response to a request.  This is documented quite thoroughly in the 
  +  response to a request.  This is documented quite thoroughly in the
     <A
      HREF="../content-negotiation.html"
      REL="Help"
  @@ -725,23 +860,23 @@
         virtual hosts?</STRONG>
        </A>
     <P>
  -  You are probably running into resource limitations in your 
  -  operating system.  The most common limitation is the 
  -  <EM>per</EM>-process limit on <STRONG>file descriptors</STRONG>, 
  -  which is almost always the cause of problems seen when adding 
  -  virtual hosts.  Apache often does not give an intuitive error 
  -  message because it is normally some library routine (such as 
  -  <CODE>gethostbyname()</CODE>) which needs file descriptors and 
  -  doesn't complain intelligibly when it can't get them.  
  +  You are probably running into resource limitations in your
  +  operating system.  The most common limitation is the
  +  <EM>per</EM>-process limit on <STRONG>file descriptors</STRONG>,
  +  which is almost always the cause of problems seen when adding
  +  virtual hosts.  Apache often does not give an intuitive error
  +  message because it is normally some library routine (such as
  +  <CODE>gethostbyname()</CODE>) which needs file descriptors and
  +  doesn't complain intelligibly when it can't get them.
     </P>
     <P>
     Each log file requires a file descriptor, which means that if you are
     using separate access and error logs for each virtual host, each
  -  virtual host needs two file descriptors.  Each 
  +  virtual host needs two file descriptors.  Each
     <A
      HREF="../mod/core.html#listen"
     ><SAMP>Listen</SAMP></A>
  -  directive also needs a file descriptor.  
  +  directive also needs a file descriptor.
     </P>
     <P>
     Typical values for &lt;<EM>n</EM>&gt; that we've seen are in
  @@ -760,16 +895,17 @@
          <A
           HREF="../mod/core.html#listen"
          ><SAMP>Listen</SAMP></A>
  -       directives.  If there are no other servers running on the machine 
  -       and all of them are running on the same port, you normally don't 
  -       need any Listen directives at all.
  +       directives.  If there are no other servers running on the machine
  +       on the same port then you normally don't
  +       need any Listen directives at all.  By default Apache listens to
  +       all addresses on port 80.
      </LI>
  -   <LI>Reduce the number of log files.  You can use 
  +   <LI>Reduce the number of log files.  You can use
          <A
           HREF="../mod/mod_log_config.html"
          ><SAMP>mod_log_config</SAMP></A>
          to log all requests to a single log file while including the name
  -       of the virtual host in the log file.  You can then write a 
  +       of the virtual host in the log file.  You can then write a
          script to split the logfile into separate files later if
          necessary.
      </LI>
  @@ -780,22 +916,73 @@
          <A
           HREF="perf.html"
          >performance hints</A>
  -       page.
  +       page.  There is a specific note for
  +       <A HREF="#freebsd-setsize">FreeBSD</A> below.
      </LI>
      <LI>&quot;Don't do that&quot; - try to run with fewer virtual hosts
      </LI>
      <LI>Spread your operation across multiple server processes (using
  -       <A
  -        HREF="../mod/core.html#listen"
  -       ><SAMP>Listen</SAMP></A>
  -       for example, but see the first point) and/or ports.
  +    <A
  +     HREF="../mod/core.html#listen"
  +    ><SAMP>Listen</SAMP></A>
  +    for example, but see the first point) and/or ports.
      </LI>
     </OL>
     <P>
     Since this is an operating-system limitation, there's not much else
     available in the way of solutions.
     </P>
  +  <P>
  +  As of 1.2.1 we have made attempts to work around various limitations
  +  involving running with many descriptors.
  +  <A HREF="descriptors.html">More information is available.</A>
  +  </P>
  +  <HR>
  + </LI>
  +
  + <LI><A NAME="freebsd-setsize">
  +      <STRONG>Can I increase <SAMP>FD_SETSIZE</SAMP> on FreeBSD?</STRONG>
  +     </A>
  +  <P>
  +  On versions of FreeBSD before 3.0, the <SAMP>FD_SETSIZE</SAMP> define 
  +  defaults to 256.  This means that you will have trouble usefully using
  +  more than 256 file descriptors in Apache.  This can be increased, but
  +  doing so can be tricky.
  +
  +  If you are using a version prior to 2.2, you need to recompile your
  +  kernel with a larger FD_SETSIZE.  This can be done by adding a 
  +  line such as:
  +  </P>
  +  <DL>
  +   <DD><CODE>options FD_SETSIZE <EM>nnn</EM></CODE>
  +   </DD>
  +  </DL>
  +  <P>
  +  To your kernel config file.  Starting at version 2.2, this is no
  +  longer necessary.
  +  </P>
  +  <P>
  +  If you are using a version of 2.1-stable from after 1997/03/10 or
  +  2.2 or 3.0-current from before 1997/06/28, there is a limit in
  +  the resolver library that prevents it from using more file descriptors
  +  than what FD_SETSIZE is set to when libc is compiled.  To increase
  +  this, you have to recompile libc with a higher FD_SETSIZE.
  +  </P>
  +  <P>
  +  In FreeBSD 3.0, the default FD_SETSIZE has been increased to
  +  1024 and the above limitation in the resolver library
  +  has been removed.
  +  </P>
  +  <P>
  +  After you deal with the appropriate changes above, you can increase 
  +  the setting of <SAMP>FD_SETSIZE</SAMP> at Apache compilation time 
  +  by adding &quot;<SAMP>-DFD_SETSIZE=<EM>nnn</EM></SAMP>&quot; to the
  +  <SAMP>EXTRA_CFLAGS</SAMP> line in your <SAMP>Configuration</SAMP>
  +  file.
  +  </P>
     <HR>
  + </LI>
  +
    <LI><A NAME="limitGET">
         <STRONG>Why do I keep getting &quot;access denied&quot; for form POST
         requests?</STRONG>
  @@ -807,17 +994,13 @@
     would affect the location where the POST-handling script resides:
     </P>
     <P>
  -  <CODE>
  -   <DL>
  -    <DD>&lt;Limit GET&gt;
  -    </DD>
  -    <DD>&nbsp;&nbsp;&nbsp;&nbsp;:
  -    </DD>
  -   </DL>
  -  </CODE>
  +  <DL>
  +   <DD><CODE>&lt;Limit GET&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;:</CODE>
  +   </DD>
  +  </DL>
     </P>
     <P>
  -  Change that to <SAMP>&lt;Limit GET POST&gt;</SAMP> and the problem
  +  Change that to <CODE>&lt;Limit GET POST&gt;</CODE> and the problem
     will probably go away.
     </P>
     <HR>
  @@ -854,7 +1037,7 @@
      </LI>
      <LI>Web authentication passwords (at least for Basic authentication)
       generally fly across the wire, and through intermediate proxy
  -    systems, in what amounts to plaintext.  &quot;O'er the net we
  +    systems, in what amounts to plain text.  &quot;O'er the net we
       go/Caching all the way;/O what fun it is to surf/Giving my password
       away!&quot;
      </LI>
  @@ -875,12 +1058,14 @@
     warranty, though, and you'll lose all accumulated UNIX guru points.
     </P>
     <HR>
  + </LI>
    <LI><A NAME="errordoc401">
         <STRONG>Why doesn't my <CODE>ErrorDocument 401</CODE> work?</STRONG>
        </A>
     <P>
  -  You need to use it with a URL in the form "/foo/bar" and not one
  -  with a method and hostname such as "http://host/foo/bar".  See the
  +  You need to use it with a URL in the form
  +  &quot;<SAMP>/foo/bar</SAMP>&quot; and not one with a method and
  +  hostname such as &quot;<SAMP>http://host/foo/bar</SAMP>&quot;.  See the
     <A
      HREF="../mod/core.html#errordocument"
     ><SAMP>ErrorDocument</SAMP></A>
  @@ -908,7 +1093,7 @@
        </A>
     <P>
     Apache does <EM>not</EM> send automatically send a cookie on every
  -  response, unless you have re-compiled it with the 
  +  response, unless you have re-compiled it with the
     <A
      HREF="../mod/mod_cookies.html"
     ><SAMP>mod_cookies</SAMP></A>
  @@ -917,11 +1102,11 @@
     This module may help track users, and uses cookies to do this. If
     you are not using the data generated by <SAMP>mod_cookies</SAMP>, do
     not compile it into Apache. Note that in 1.2 this module was renamed
  -  to the more correct name 
  +  to the more correct name
     <A
      HREF="../mod/mod_usertrack.html"
     ><SAMP>mod_usertrack</SAMP></A>,
  -  and cookies 
  +  and cookies
     have to be specifically enabled with the
     <A
       HREF="../mod/mod_usertrack.html#cookietracking"
  @@ -986,7 +1171,9 @@
     </P>
     <P>
     <DL>
  -   <DD><CODE>BrowserMatch Java/1.0 force-response-1.0</CODE>
  +   <DD><CODE>BrowserMatch Java1.0 force-response-1.0
  +    <BR>
  +    BrowserMatch JDK/1.0 force-response-1.0</CODE>
      </DD>
     </DL>
     </P>
  @@ -1014,7 +1201,7 @@
     ><CITE>Publishing Pages with PUT</CITE></A>.
     </P>
     <HR>
  -  </LI>
  + </LI>
    <LI><A NAME="fastcgi">
         <STRONG>Why isn't FastCGI included with Apache any more?</STRONG>
        </A>
  @@ -1036,7 +1223,7 @@
    <LI><A NAME="nodelay">
         <STRONG>Why am I getting &quot;<SAMP>httpd: could not set socket
         option TCP_NODELAY</SAMP>&quot; in my error log?</STRONG>
  -     </A> 
  +     </A>
     <P>
     This message almost always indicates that the client disconnected
     before Apache reached the point of calling <CODE>setsockopt()</CODE>
  @@ -1045,6 +1232,20 @@
     </P>
     <HR>
    </LI>
  + <LI><A NAME="peerreset">
  +      <STRONG>Why am I getting &quot;<SAMP>connection reset by
  +      peer</SAMP>&quot; in my error log?</STRONG>
  +     </A>
  +  <P>
  +  This is a normal message and nothing about which to be alarmed.  It simply
  +  means that the client canceled the connection before it had been
  +  completely set up - such as by the end-user pressing the &quot;Stop&quot;
  +  button.  People's patience being what it is, sites with response-time
  +  problems or slow network links may experiences this more than
  +  high-capacity ones or those with large pipes to the network.
  +  </P>
  +  <HR>
  + </LI>
    <LI><A NAME="nph-scripts">
         <STRONG>How can I get my script's output without Apache buffering
         it?</STRONG>
  @@ -1079,25 +1280,25 @@
     <P>
     As an example how you might handle the former (in a Perl script):
     </P>
  -  <CODE>
  -   <DL>
  -    <DD>if ($0 =~ m:/*nph-:) {
  -        <BR>
  -        &nbsp;&nbsp;&nbsp;&nbsp;
  -        $HTTP_headers&nbsp;=&nbsp;
  -        &quot;HTTP/1.1&nbsp;200&nbsp;OK\015\012&quot;;
  -        <BR>
  -        &nbsp;&nbsp;&nbsp;&nbsp;
  -        $HTTP_headers&nbsp;.=&nbsp;
  -        &quot;Connection:&nbsp;close\015\012&quot;;
  -        <BR>
  -        &nbsp;&nbsp;&nbsp;&nbsp;
  -        printf&nbsp;($HTTP_headers);
  -        <BR>
  -        };
  -    </DD>
  -   </DL>
  -  </CODE>
  +  <P>
  +  <DL>
  +   <DD><CODE>if ($0 =~ m:^(.*/)*nph-[^/]*$:) {
  +    <BR>
  +    &nbsp;&nbsp;&nbsp;&nbsp;
  +    $HTTP_headers&nbsp;=&nbsp;
  +    &quot;HTTP/1.1&nbsp;200&nbsp;OK\015\012&quot;;
  +    <BR>
  +    &nbsp;&nbsp;&nbsp;&nbsp;
  +    $HTTP_headers&nbsp;.=&nbsp;
  +    &quot;Connection:&nbsp;close\015\012&quot;;
  +    <BR>
  +    &nbsp;&nbsp;&nbsp;&nbsp;
  +    print&nbsp;$HTTP_headers;
  +    <BR>
  +    }</CODE>
  +   </DD>
  +  </DL>
  +  </P>
     <P>
     and then follow with your normal non-<SAMP>nph</SAMP> headers.
     </P>
  @@ -1105,16 +1306,18 @@
    </LI>
    <LI><A NAME="linuxiovec">
         <STRONG>Why do I get complaints about redefinition
  -      of `struct iovec' when compiling under Linux?</STRONG>
  +      of &quot;<CODE>struct iovec</CODE>&quot; when
  +      compiling under Linux?</STRONG>
        </A>
     <P>
     This is a conflict between your C library includes and your kernel
     includes.  You need to make sure that the versions of both are matched
     properly.  There are two workarounds, either one will solve the problem:
     </P>
  +  <P>
     <UL>
      <LI>Remove the definition of <CODE>struct iovec</CODE> from your C
  -    library includes.  It is located in <CODE>/usr/include/sys/uio.h</CODE>.  
  +    library includes.  It is located in <CODE>/usr/include/sys/uio.h</CODE>.
       <STRONG>Or,</STRONG>
      </LI>
      <LI>Add  <CODE>-DNO_WRITEV</CODE> to the <CODE>EXTRA_CFLAGS</CODE>
  @@ -1122,6 +1325,7 @@
       This hurts performance and should only be used as a last resort.
      </LI>
     </UL>
  +  </P>
     <HR>
    </LI>
    <LI><A NAME="wheres-the-dump">
  @@ -1129,12 +1333,12 @@
         file?</STRONG>
        </A>
     <P>
  -  In Apache version 1.2 (beginning with 1.2b8), the error log message
  +  In Apache version 1.2, the error log message
     about dumped core includes the directory where the dump file should be
     located.  However, many Unixes do not allow a process that has
  -  called <CODE>setuid()</CODE> to dump core for security reasons; 
  -  the typical Apache setup has the server started as root to bind to 
  -  port 80, after which it changes UIDs to a non-privileged user to 
  +  called <CODE>setuid()</CODE> to dump core for security reasons;
  +  the typical Apache setup has the server started as root to bind to
  +  port 80, after which it changes UIDs to a non-privileged user to
     serve requests.
     </P>
     <P>
  @@ -1183,10 +1387,12 @@
       this by adding the <SAMP>-DMAXIMUM_DNS</SAMP> clause to the
       <SAMP>EXTRA_CFLAGS</SAMP> definition in your
       <SAMP>Configuration</SAMP> file.  For example:
  +    <P>
       <DL>
        <DD><CODE>EXTRA_CFLAGS=-DMAXIMUM_DNS</CODE>
        </DD>
       </DL>
  +    </P>
       <P>
       This will cause Apache to be very paranoid about making sure a
       particular host address is <EM>really</EM> assigned to the name it
  @@ -1207,8 +1413,8 @@
     encryption technology.  If Apache included SSL in the base package,
     its distribution would involve all sorts of legal and bureaucratic
     issues, and it would no longer be freely available.  Also, some of
  -  the technology required to talk to current clients using SSL is 
  -  patented by <A HREF="http://www.rsa.com/">RSA Data Security</A>, 
  +  the technology required to talk to current clients using SSL is
  +  patented by <A HREF="http://www.rsa.com/">RSA Data Security</A>,
     who restricts its use without a license.
     </P>
     <P>
  @@ -1227,9 +1433,9 @@
     ><CITE>Apache and Secure Transactions</CITE></A>.
     </P>
     <HR>
  -  </LI>
  -  <LI><A NAME="HPUX-core">
  -       <STRONG>Why do I get core dumps under HPUX using HP's ANSI 
  + </LI>
  + <LI><A NAME="HPUX-core">
  +       <STRONG>Why do I get core dumps under HPUX using HP's ANSI
                  C compiler?</STRONG>
         </A>
     <P>
  @@ -1259,10 +1465,12 @@
      <LI>Instruct Apache to send a different <SAMP>Content-type</SAMP>
       header for these files by adding the following line to your server's
       configuration files:
  +    <P>
       <DL>
        <DD><CODE>AddType audio/x-midi .mid .midi .kar</CODE>
        </DD>
       </DL>
  +    </P>
       <P>
       Note that this may break browsers that <EM>do</EM> recognize the
       <SAMP>audio/midi</SAMP> MIME type unless they're prepared to also
  @@ -1275,7 +1483,7 @@
    <LI><A NAME="cantbuild">
          <STRONG>Why won't Apache compile with my system's
          <SAMP>cc</SAMP>?</STRONG>
  -      </A>
  +     </A>
     <P>
     If the server won't compile on your system, it is probably due to one
     of the following causes:
  @@ -1304,7 +1512,7 @@
       the operating system.
      </LI>
      <LI><STRONG>Your operating system or compiler may be out of
  -    revision.</STRONG> 
  +    revision.</STRONG>
       <BR>
       Software vendors (including those that develop operating systems)
       issue new releases for a reason; sometimes to add functionality, but
  @@ -1368,29 +1576,482 @@
     </P>
     <HR>
    </LI>
  - <LI><A NAME="jdk1.x">
  -      <STRONG>Why do Java applets and applications not work
  -      with documents on my Apache server?</A></STRONG>
  + <LI><A NAME="bind8.1">
  +      <STRONG>Why do I get an error about an undefined reference to
  +      &quot;<SAMP>__inet_ntoa</SAMP>&quot; or other
  +      <SAMP>__inet_*</SAMP> symbols?</STRONG>
  +     </A>
  +  <P>
  +  If you have installed <A HREF="http://www.isc.org/bind.html">BIND-8</A>
  +  then this is normally due to a conflict between your include files
  +  and your libraries.  BIND-8 installs its include files and libraries
  +  <CODE>/usr/local/include/</CODE> and <CODE>/usr/local/lib/</CODE>, while
  +  the resolver that comes with your system is probably installed in
  +  <CODE>/usr/include/</CODE> and <CODE>/usr/lib/</CODE>.  If
  +  your system uses the header files in <CODE>/usr/local/include/</CODE>
  +  before those in <CODE>/usr/include/</CODE> but you do not use the new
  +  resolver library, then the two versions will conflict.
  +  </P>
  +  <P>
  +  To resolve this, you can either make sure you use the include files
  +  and libraries that came with your system or make sure to use the
  +  new include files and libraries.  Adding <CODE>-lbind</CODE> to the
  +  <CODE>EXTRA_LDFLAGS</CODE> line in your <SAMP>Configuration</SAMP>
  +  file, then re-running <SAMP>Configure</SAMP>, should resolve the
  +  problem.  (Apache versions 1.2.* and earlier use
  +  <CODE>EXTRA_LFLAGS</CODE> instead.)
  +  </P>
  +  <P>
  +  <STRONG>Note:</STRONG>As of BIND 8.1.1, the bind libraries and files are
  +  installed under <SAMP>/usr/local/bind</SAMP> by default, so you
  +  should not run into this problem.  Should you want to use the bind
  +  resolvers you'll have to add the following to the respective lines:
  +  </P>
  +  <P>
  +  <DL>
  +   <DD><CODE>EXTRA_CFLAGS=-I/usr/local/bind/include
  +    <BR>
  +    EXTRA_LDFLAGS=-L/usr/local/bind/lib
  +    <BR>
  +    EXTRA_LIBS=-lbind</CODE>
  +   </DD>
  +  </DL>
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="set-servername">
  +      <STRONG>Why does accessing directories only work when I include
  +      the trailing "/"
  +      (<EM>e.g.</EM>,&nbsp;<SAMP>http://foo.domain.com/~user/</SAMP>)
  +      but not when I omit it
  +      (<EM>e.g.</EM>,&nbsp;<SAMP>http://foo.domain.com/~user</SAMP>)?</STRONG>
        </A>
     <P>
  -  The Java Development Kit (JDK) libraries versions 1.0.2 and 1.1 do not
  -  correctly interpret the &quot;<SAMP>HTTP/1.1</SAMP>&quot; response
  -  header that Apache 1.2 sends.  Instead, if they don't see an exact
  -  match for &quot;<SAMP>HTTP/1.0</SAMP>&quot;, they assume the headers
  -  are part of the document content.
  +  When you access a directory without a trailing "/", Apache needs
  +  to send what is called a redirect to the client to tell it to
  +  add the trailing slash.  If it did not do so, relative URLs would
  +  not work properly.  When it sends the redirect, it needs to know
  +  the name of the server so that it can include it in the redirect.
  +  There are two ways for Apache to find this out; either it can guess,
  +  or you can tell it.  If your DNS is configured correctly, it can
  +  normally guess without any problems.  If it is not, however, then
  +  you need to tell it.
     </P>
     <P>
  -  This is a known problem, and it has been reported to Sun's JavaSoft
  -  unit.  In the meantime, Apache 1.2 servers can work around this by
  -  adding the following lines to their configuration files:
  +  Add a <A HREF="../mod/core.html#servername">ServerName</A> directive
  +  to the config file to tell it what the domain name of the server is.
     </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="user-authentication">
  +      <STRONG>How do I set up Apache to require a username and
  +      password to access certain documents?</STRONG>
  +     </A>
  +  <P>
  +  There are several ways to do this; some of the more popular
  +  ones are to use the <A HREF="../mod/mod_auth.html">mod_auth</A>,
  +  <A HREF="../mod/mod_auth_db.html">mod_auth_db</A>, or
  +  <A HREF="../mod/mod_auth_dbm.html">mod_auth_dbm</A> modules.
  +  </P>
  +  <P>
  +  For an explanation on how to implement these restrictions, see
  +  <A
  +   HREF="http://www.apacheweek.com/"
  +  ><CITE>Apache Week</CITE></A>'s
  +  articles on
  +  <A
  +   HREF="http://www.apacheweek.com/features/userauth"
  +  ><CITE>Using User Authentication</CITE></A>
  +  or
  +  <A
  +   HREF="http://www.apacheweek.com/features/dbmauth"
  +  ><CITE>DBM User Authentication</CITE></A>.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="remote-user-var">
  +         <STRONG>Why is the environment variable 
  +         <SAMP>REMOTE_USER</SAMP> not set?</STRONG>
  +         </A>
  +  <P>
  +  This variable is set and thus available in SSI or CGI scripts <STRONG>if and
  +  only if</STRONG> the requested document was protected by access
  +  authentication.  For an explanation on how to implement these restrictions,
  +  see
  +  <A
  +   HREF="http://www.apacheweek.com/"
  +  ><CITE>Apache Week</CITE></A>'s
  +  articles on
  +  <A
  +   HREF="http://www.apacheweek.com/features/userauth"
  +  ><CITE>Using User Authentication</CITE></A>
  +  or
  +  <A
  +   HREF="http://www.apacheweek.com/features/dbmauth"
  +  ><CITE>DBM User Authentication</CITE></A>.
  +  </P>
  +  <P>
  +  Hint: When using a CGI script to receive the data of a HTML <SAMP>FORM</SAMP>
  +  notice that protecting the document containing the <SAMP>FORM</SAMP> is not
  +  sufficient to provide <SAMP>REMOTE_USER</SAMP> to the CGI script.  You have
  +  to protect the CGI script, too. Or alternatively only the CGI script (then
  +  authentication happens only after filling out the form).
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="remote-auth-only">
  +      <STRONG>How do I set up Apache to allow access to certain
  +      documents only if a site is either a local site <EM>or</EM>
  +      the user supplies a password and username?</STRONG>
  +     </A>
  +  <P>
  +  Use the <A HREF="../mod/core.html#satisfy">Satisfy</A> directive,
  +  in particular the <CODE>Satisfy Any</CODE> directive, to require
  +  that only one of the access restrictions be met.  For example,
  +  adding the following configuration to a <SAMP>.htaccess</SAMP>
  +  or server configuration file would restrict access to people who
  +  either are accessing the site from a host under domain.com or
  +  who can supply a valid username and password:
  +  </P>
  +  <P>
     <DL>
  -   <DD>BrowserMatch&nbsp;Java1.0&nbsp;force-response-1.0</CODE>
  +   <DD><CODE>deny from all
  +    <BR>
  +    allow from .domain.com
  +    <BR>
  +    AuthType Basic
  +    <BR>
  +    AuthUserFile /usr/local/etc/httpd/conf/htpasswd.users
  +    <BR>
  +    AuthName special directory
  +    <BR>
  +    require valid-user
  +    <BR>
  +    satisfy any</CODE>
      </DD>
     </DL>
  +  </P>
  +  <P>
  +  See the <A HREF="#user-authentication">user authentication</A>
  +  question and the <A HREF="../mod/mod_access.html">mod_access</A>
  +  module for details on how the above directives work.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="no-info-directives">
  +      <STRONG>Why doesn't mod_info list any directives?</STRONG>
  +     </A>
  +  <P>
  +  The
  +  <A
  +   HREF="../mod/mod_info.html"
  +  ><SAMP>mod_info</SAMP></A>
  +  module allows you to use a Web browser to see how your server is
  +  configured.  Among the information it displays is the list modules and
  +  their configuration directives.  The &quot;current&quot; values for
  +  the directives are not necessarily those of the running server; they
  +  are extracted from the configuration files themselves at the time of
  +  the request.  If the files have been changed since the server was last
  +  reloaded, the display will will not match the values actively in use.
  +  If the files and the path to the files are not readable by the user as
  +  which the server is running (see the
  +  <A
  +   HREF="../mod/core.html#user"
  +  ><SAMP>User</SAMP></A>
  +  directive), then <SAMP>mod_info</SAMP> cannot read them in order to
  +  list their values.  An entry <EM>will</EM> be made in the error log in
  +  this event, however.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="linux-shmget">
  +      <STRONG>When I run it under Linux I get "shmget:
  +      function not found", what should I do?</STRONG>
  +     </A>
  +  <P>
  +  Your kernel has been built without SysV IPC support.  You will have to
  +  rebuild the kernel with that support enabled (it's under the
  +  &quot;General Setup&quot; submenu).  Documentation for
  +  kernel building is beyond the scope of this FAQ; you should consult
  +  the
  +  <A HREF="http://www.linuxhq.com/HOWTO/Kernel-HOWTO.html"
  +  >Kernel HOWTO</A>,
  +  or the documentation provided with your distribution, or a
  +  <A HREF="http://www.linuxhq.com/HOWTO/META-FAQ.html"
  +  >Linux newsgroup/mailing list</A>.
  +  As a last-resort workaround, you can
  +  comment out the <CODE>#define HAVE_SHMGET</CODE> definition in the
  +  <SAMP>LINUX</SAMP> section of
  +  <SAMP>src/conf.h</SAMP> and rebuild the server.  This will produce
  +  a server which is slower and less reliable.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="authauthoritative">
  +      <STRONG>Why does my authentication give me a server error?</STRONG>
  +     </A>
  +  <P>
  +  Under normal circumstances, the Apache access control modules will
  +  pass unrecognized user IDs on to the next access control module in
  +  line.  Only if the user ID is recognized and the password is validated
  +  (or not) will it give the usual success or &quot;authentication
  +  failed&quot; messages.
  +  </P>
  +  <P>
  +  However, if the last access module in line 'declines' the validation
  +  request (because it has never heard of the user ID or because it is not
  +  configured), the <SAMP>http_request</SAMP> handler will give one of
  +  the following, confusing, errors:
  +  </P>
  +  <UL>
  +   <LI><SAMP>check access</SAMP>
  +   </LI>
  +   <LI><SAMP>check user.  No user file?</SAMP>
  +   </LI>
  +   <LI><SAMP>check access.  No groups file?</SAMP>
  +   </LI>
  +  </UL>
  +  <P>
  +  This does <EM>not</EM> mean that you have to add an
  +  '<SAMP>AuthUserFile&nbsp;/dev/null</SAMP>' line as some magazines suggest!
  +  </P>
  +  <P>
  +  The solution is to ensure that at least the last module is authoritative
  +  and <STRONG>CONFIGURED</STRONG>. By default, <SAMP>mod_auth</SAMP> is
  +  authoritative and will give an OK/Denied, but only if it is configured
  +  with the proper <SAMP>AuthUserFile</SAMP>.  Likewise, if a valid group
  +  is required.  (Remember that the modules are processed in the reverse
  +  order from that in which they appear in your compile-time
  +  <SAMP>Configuration</SAMP> file.)
  +  </P>
  +  <P>
  +  A typical situation for this error is when you are using the
  +  <SAMP>mod_auth_dbm</SAMP>, <SAMP>mod_auth_msql</SAMP>,
  +  <SAMP>mod_auth_mysql</SAMP>, <SAMP>mod_auth_anon</SAMP> or
  +  <SAMP>mod_auth_cookie</SAMP> modules on their own.  These are by
  +  default <STRONG>not</STRONG> authoritative, and this will pass the
  +  buck on to the (non-existent) next authentication module when the
  +  user ID is not in their respective database.  Just add the appropriate
  +  '<SAMP><EM>XXX</EM>Authoritative yes</SAMP>' line to the configuration.
  +  </P>
  +  <P>
  +  In general it is a good idea (though not terribly efficient) to have the
  +  file-based <SAMP>mod_auth</SAMP> a module of last resort. This allows
  +  you to access the web server with a few special passwords even if the
  +  databases are down or corrupted.  This does cost a
  +  file open/seek/close for each request in a protected area.
  +  </P>
     <HR>
  -  <!-- Don't forget to add HR tags at the end of each list item.. -->
    </LI>
  + <LI><A NAME="auth-on-same-machine">
  +      <STRONG>Do I have to keep the (mSQL) authentication information
  +      on the same machine?</STRONG>
  +     </A>
  +  <P>
  +  Some organizations feel very strongly about keeping the authentication
  +  information on a different machine than the webserver. With the
  +  <SAMP>mod_auth_msql</SAMP>, <SAMP>mod_auth_mysql</SAMP>, and other SQL
  +  modules connecting to (R)DBMses this is quite possible. Just configure
  +  an explicit host to contact.
  +  </P>
  +  <P>
  +  Be aware that with mSQL and Oracle, opening and closing these database
  +  connections is very expensive and time consuming. You might want to
  +  look at the code in the <SAMP>auth_*</SAMP> modules and play with the
  +  compile time flags to alleviate this somewhat, if your RDBMS licences
  +  allow for it.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="msql-slow">
  +      <STRONG>Why is my mSQL authentication terribly slow?</STRONG>
  +     </A>
  +  <P>
  +  You have probably configured the Host by specifying a FQHN,
  +  and thus the libmsql will use a full blown tcp/ip socket to talk to
  +  the database, rather than a fast internal device.  The
  +  <SAMP>libmsql</SAMP>, the mSQL FAQ, and the <SAMP>mod_auth_msql</SAMP>
  +  documentation warn you about this.  If you have to use different
  +  hosts, check out the <SAMP>mod_auth_msql</SAMP> code for
  +  some compile time flags which might - or might not - suit you.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-more-config">
  +          <STRONG>Where can I find mod_rewrite rulesets which already solve
  +          particular URL-related problems?</STRONG>
  +     </A>
  +  <P>
  +  There is a collection of 
  +  <A
  +      HREF="http://www.engelschall.com/sw/mod_rewrite/docs/mod_rewrite/solutions.html#Solutions"
  +  >Practical Solutions for URL-Manipulation</A>
  +  where you can
  +  find all typical solutions the author of 
  +  <A
  +   HREF="../mod/mod_rewrite.html"
  +  ><SAMP>mod_rewrite</SAMP></A> 
  +  currently knows of. If you have more
  +  interesting rulesets which solve particular problems not currently covered in
  +  this document, send it to 
  +  <A
  +      HREF="mailto:rse@apache.org"
  +  >Ralf S. Engelschall</A>
  +  for inclusion. The
  +  other webmasters will thank you for avoiding the reinvention of the wheel.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-article">
  +          <STRONG>Where can I find any published information about URL-manipulations and
  +          mod_rewrite?</STRONG>
  +     </A>
  +  <P>
  +  There is an article from 
  +  <A
  +      HREF="mailto:rse@apache.org"
  +  >Ralf S. Engelschall</A>
  +  about URL-manipulations based on
  +  <A
  +   HREF="../mod/mod_rewrite.html"
  +  ><SAMP>mod_rewrite</SAMP></A> 
  +  in the &quot;iX Multiuser Multitasking Magazin&quot; issue #12/96. The
  +  german (original) version
  +  can be read online at 
  +  <A
  +      HREF="http://www.heise.de/ix/artikel/9612149/"
  +  >http://www.heise.de/ix/artikel/9612149/</A>,
  +  the English (translated) version can be found at 
  +  <A
  +      HREF="http://www.heise.de/ix/artikel/E/9612149/"
  +  >http://www.heise.de/ix/artikel/E/9612149/</A>.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-complexity">
  +          <STRONG>Why is mod_rewrite so difficult to learn and seems so
  +          complicated?</STRONG>
  +     </A>
  +  <P>
  +  Hmmm... there are a lot of reasons. First, mod_rewrite itself is a powerful
  +  module which can help you in really <b>all</b> aspects of URL rewriting, so
  +  it can be no trivial module per definition. To accomplish its hard job it
  +  uses software leverage and makes use of a powerful regular expression
  +  library by Henry Spencer which is an integral part of Apache since its
  +  version 1.2.  And regular expressions itself can be difficult to newbies,
  +  while providing the most flexible power to the advanced hacker. 
  +  </P>
  +  <P>
  +  On the other hand mod_rewrite has to work inside the Apache API environment
  +  and needs to do some tricks to fit there. For instance the Apache API as of
  +  1.x really was not designed for URL rewriting at the <tt>.htaccess</tt>
  +  level of processing. Or the problem of multiple rewrites in sequence, which
  +  is also not handled by the API per design. To provide this features
  +  mod_rewrite has to do some special (but API compliant!) handling which leads
  +  to difficult processing inside the Apache kernel. While the user usually
  +  doesn't see anything of this processing, it can be difficult to find
  +  problems when some of your RewriteRules seem not to work.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-dontwork">
  +          <STRONG>What can I do if my RewriteRules don't work as expected?
  +          </STRONG>
  +     </A>
  +  <P>
  +  Use &quot;<SAMP>RewriteLog somefile</SAMP>&quot; and
  +  &quot;<SAMP>RewriteLogLevel 9</SAMP>&quot; and have a precise look at the
  +  steps the rewriting engine performs. This is really the only one and best
  +  way to debug your rewriting configuration.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-prefixdocroot"><STRONG>Why don't some of my URLs
  +      get prefixed with DocumentRoot when using mod_rewrite?</STRONG>
  +     </A>
  +  <P>
  +  If the rule starts with <SAMP>/somedir/...</SAMP> make sure that really no
  +  <SAMP>/somedir</SAMP> exists on the filesystem if you don't want to lead the
  +  URL to match this directory, i.e. there must be no root directory named
  +  <SAMP>somedir</SAMP> on the filesystem. Because if there is such a
  +  directory, the URL will not get prefixed with DocumentRoot. This behaviour
  +  looks ugly, but is really important for some other aspects of URL
  +  rewriting.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-nocase">
  +          <STRONG>How can I make all my URLs case-insensitive with mod_rewrite?
  +          </STRONG>
  +     </A>
  +  <P>
  +  You can't! The reason is: First, case translations for arbitrary length URLs
  +  cannot be done via regex patterns and corresponding substitutions. One need
  +  a per-character pattern like sed/Perl <SAMP>tr|..|..|</SAMP> feature.  Second, just
  +  making URLs always upper or lower case will not resolve the complete problem
  +  of case-INSENSITIVE URLs, because actually the URLs had to be rewritten to
  +  the correct case-variant residing on the filesystem because in later
  +  processing Apache needs to access the file.  And Unix filesystem is always
  +  case-SENSITIVE.
  +  </P>
  +  <P>
  +  But there is a module named <CODE>mod_speling.c</CODE> (yes, it is named
  +  this way!) out there on the net. Try this one.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-virthost">
  +          <STRONG> Why are RewriteRules in my VirtualHost parts ignored?
  +          </STRONG>
  +     </A>
  +  <P>
  +  Because you have to enable the engine for every virtual host explicitly due
  +  to security concerns. Just add a &quot;RewriteEngine on&quot; to your
  +  virtual host configuration parts.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="rewrite-envwhitespace">
  +          <STRONG> How can I use strings with whitespaces in RewriteRule's ENV
  +          flag?</STRONG>
  +     </A>
  +  <P>
  +  There is only one ugly solution: You have to surround the complete flag
  +  argument by quotation marks (<SAMP>"[E=...]"</SAMP>). Notice: The argument
  +  to quote here is not the argument to the E-flag, it is the argument of the
  +  Apache config file parser, i.e. the third argument of the RewriteRule here.
  +  So you have to write <SAMP>"[E=any text with whitespaces]"</SAMP>.
  +  </P>
  +  <HR>
  + </LI>
  + <LI><A NAME="cgi-spec"><STRONG>Where can I find the &quot;CGI
  +      specification&quot;?</STRONG></A>
  +  <P>
  +  The Common Gateway Interface (CGI) specification currently lives in at
  +  least two versions:
  +  </P>
  +  <P>
  +  <OL>
  +   <LI>At the original NCSA site
  +    &lt;<A
  +         HREF="http://hoohoo.ncsa.uiuc.edu/cgi/interface.html"
  +        ><SAMP>http://hoohoo.ncsa.uiuc.edu/cgi/interface.html</SAMP></A>&gt;.
  +    This version hasn't been updated since 1995, and there have been
  +    some efforts to update it and replace it with
  +   </LI>
  +   <LI>The most current version, which is struggling to become an
  +    Internet RFC, found at
  +    &lt;<A
  +         HREF="http://www.ast.cam.ac.uk/~drtr/cgi-spec.html"
  +        ><SAMP>http://www.ast.cam.ac.uk/~drtr/cgi-spec.html</SAMP></A>&gt;.
  +   </LI>
  +  </OL>
  +  </P>
  +  <HR>
  + </LI>
  +
  +  <!-- Don't forget to add HR tags at the end of each list item.. -->
  +
   </OL>
    <!--#include virtual="footer.html" -->
   </BODY>
  
  
  
  1.8       +38 -23    apache-1.2/htdocs/manual/misc/compat_notes.html
  
  Index: compat_notes.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/compat_notes.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- compat_notes.html	1997/06/04 11:42:56	1.7
  +++ compat_notes.html	1998/01/30 09:13:07	1.8
  @@ -30,21 +30,10 @@
   
   <OL>
   
  -<LI>The basic mod_auth <CODE>AuthGroupFile</CODE>-specified group file 
  +<LI>The basic mod_auth <CODE>AuthGroupFile</CODE>-specified group file
       format allows commas between user names - Apache does not.<BR>
       <I>- added 12/1/96</I>
  -
  -<LI><CODE>AddType</CODE> only accepts one file extension per line, without
  -any dots (<code>.</code>) in the extension, and does not take full filenames.
  -If you need multiple extensions per type, use multiple lines, e.g.
  -<blockquote><code>
  -AddType application/foo foo<br>
  -AddType application/foo bar
  -</code></blockquote>
  -To map <code>.foo</code> and <code>.bar</code> to <code>application/foo</code>
  -<p>
  -
  -
  +  <p>
   
     <LI><P>If you follow the NCSA guidelines for setting up access restrictions
     based on client domain, you may well have added entries for,
  @@ -62,7 +51,7 @@
     <LI><CODE>AuthUserFile</CODE> requires a full pathname. In earlier
         versions of NCSA httpd and Apache, you could use a filename
         relative to the .htaccess file. This could be a major security hole,
  -      as it made it trivially easy to make a ".htpass" file in the a 
  +      as it made it trivially easy to make a ".htpass" file in the a
         directory easily accessible by the world. We recommend you store
         your passwords outside your document tree.
   
  @@ -89,18 +78,32 @@
   
     <P>
   
  -  <LI>Icons for FancyIndexing broken - well, no, they're not broken, we've just upgraded the
  -  icons from flat .xbm files to pretty and much smaller .gif files, courtesy of 
  +  <LI>Icons for FancyIndexing broken - well, no, they're not broken,
  +  we've just upgraded the
  +  icons from flat .xbm files to pretty and much smaller .gif files, courtesy of
   <a href="mailto:kevinh@eit.com">Kevin Hughes</a> at
  -<a href="http://www.eit.com">EIT</a>.
  -  If you are using the same srm.conf from an old distribution, make sure you add the new
  -  AddIcon, AddIconByType, and DefaultIcon commands.
  +<a href="http://www.eit.com/">EIT</a>.
  +  If you are using the same srm.conf from an old distribution, make sure
  +  you add the new
  +  <A
  +   HREF="../mod/mod_dir.html#addicon"
  +  >AddIcon</A>,
  +  <A
  +   HREF="../mod/mod_dir.html#addiconbytype"
  +  >AddIconByType</A>,
  +  and
  +  <A
  +   HREF="../mod/mod_dir.html#defaulticon"
  +  >DefaultIcon</A>
  +  directives.
   
     <P>
   
  -  <LI>Under IRIX, the "Group" directive in httpd.conf needs to be a valid group name 
  -  (i.e. "nogroup") not the numeric group ID.  The distribution httpd.conf, and earlier 
  -  ones, had the default Group be "#-1", which was causing silent exits at startup.<p>
  +  <LI>Under IRIX, the "Group" directive in httpd.conf needs to be a
  +  valid group name
  +  (<EM>i.e.</EM>, "nogroup") not the numeric group ID.  The distribution
  +  httpd.conf, and earlier  ones, had the default Group be "#-1", which
  +  was causing silent exits at startup.<p>
   
   <li><code>.asis</code> files: Apache 0.6.5 did not require a Status header;
   it added one automatically if the .asis file contained a Location header.
  @@ -111,7 +114,19 @@
     files if the last line does not have a trailing newline. This affects
     configuration files (httpd.conf, access.conf and srm.conf), and
     htpasswd and htgroup files.
  - 
  +  </LI>
  +
  +  <LI>Apache does not permit commas delimiting the methods in &lt;Limit&gt;.
  +
  +  <LI>Apache's <CODE>&lt;VirtualHost&gt;</CODE> treats all addresses as
  +  "optional" (i.e. the server should continue booting if it can't resolve
  +  the address).  Whereas in NCSA the default is to fail booting unless
  +  an added <code>optional</code> keyword is included.
  +
  +  <LI>Apache does not implement <CODE>OnDeny</CODE> use
  +  <a href="../mod/core.html#errordocument"><code>ErrorDocument</code></a>
  +  instead.
  +
   </OL>
   
   More to come when we notice them....
  
  
  
  1.8       +63 -57    apache-1.2/htdocs/manual/misc/fin_wait_2.html
  
  Index: fin_wait_2.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/fin_wait_2.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- fin_wait_2.html	1997/06/04 11:42:56	1.7
  +++ fin_wait_2.html	1998/01/30 09:13:09	1.8
  @@ -57,13 +57,13 @@
   connection stays in the FIN_WAIT_2 state until one of the following
   happens:<P>
   <UL>
  -	<LI>The client opens a new connection to the same or a different
  -	    site, which causes it to fully close the older connection on
  +        <LI>The client opens a new connection to the same or a different
  +            site, which causes it to fully close the older connection on
               that socket.
  -	<LI>The user exits the client, which on some (most?) clients
  -	    causes the OS to fully shutdown the connection.
  -	<LI>The FIN_WAIT_2 times out, on servers that have a timeout
  -	    for this state.
  +        <LI>The user exits the client, which on some (most?) clients
  +            causes the OS to fully shutdown the connection.
  +        <LI>The FIN_WAIT_2 times out, on servers that have a timeout
  +            for this state.
   </UL><P>
   If you are lucky, this means that the buggy client will fully close the
   connection and release the resources on your server.  However, there
  @@ -77,16 +77,16 @@
   
   The clients on which this problem has been verified to exist:<P>
   <UL>
  -	<LI>Mozilla/3.01 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  -	<LI>Mozilla/2.02 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  -	<LI>Mozilla/3.01Gold (X11; I; SunOS 5.5 sun4m)
  -	<LI>MSIE 3.01 on the Macintosh
  -	<LI>MSIE 3.01 on Windows 95
  +        <LI>Mozilla/3.01 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  +        <LI>Mozilla/2.02 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  +        <LI>Mozilla/3.01Gold (X11; I; SunOS 5.5 sun4m)
  +        <LI>MSIE 3.01 on the Macintosh
  +        <LI>MSIE 3.01 on Windows 95
   </UL><P>
   
   This does not appear to be a problem on:
   <UL>
  -	<LI>Mozilla/3.01 (Win95; I)
  +        <LI>Mozilla/3.01 (Win95; I)
   </UL>
   <P>
   
  @@ -155,56 +155,56 @@
   The following systems are known to have a timeout:
   <P>
   <UL>
  -	<LI><A HREF="http://www.freebsd.org/">FreeBSD</A> versions starting at 2.0 or possibly earlier.
  -	<LI><A HREF="http://www.netbsd.org/">NetBSD</A> version 1.2(?)
  -	<LI><A HREF="http://www.openbsd.org/">OpenBSD</A> all versions(?)
  -	<LI><A HREF="http://www.bsdi.com/">BSD/OS</A> 2.1, with the 
  -	    <A HREF="ftp://ftp.bsdi.com/bsdi/patches/patches-2.1/K210-027">
  -	    K210-027</A> patch installed.  
  -	<LI><A HREF="http://www.sun.com/">Solaris</A> as of around version
  -	    2.2.  The timeout can be tuned by using <CODE>ndd</CODE> to 
  -	    modify <CODE>tcp_fin_wait_2_flush_interval</CODE>, but the
  -	    default should be appropriate for most servers and improper 
  -	    tuning can have negative impacts.
  -	<LI><A HREF="http://www.sco.com/">SCO TCP/IP Release 1.2.1</A>
  -	    can be modified to have a timeout by following
  -	    <A HREF="http://www.sco.com/cgi-bin/waisgate?WAISdocID=2242622956+0+0+0&WAISaction=retrieve"> SCO's instructions</A>.
  -	<LI><A HREF="http://www.linux.org/">Linux</A> 2.0.x and
  -	    earlier(?)
  -	<LI><A HREF="http://www.hp.com/">HP-UX</A> 10.x defaults to 
  - 	    terminating connections in the FIN_WAIT_2 state after the 
  -	    normal keepalive timeouts.  This does not
  -	    refer to the persistent connection or HTTP keepalive
  -	    timeouts, but the <CODE>SO_LINGER</CODE> socket option 
  -	    which is enabled by Apache.  This parameter can be adjusted 
  -	    by using <CODE>nettune</CODE> to modify parameters such as
  -	    <CODE>tcp_keepstart</CODE> and <CODE>tcp_keepstop</CODE>.
  -	    In later revisions, there is an explicit timer for
  -	    connections in FIN_WAIT_2 that can be modified; contact HP
  -	    support for details.
  -	<LI><A HREF="http://www.sgi.com/">SGI IRIX</A> can be patched to
  -	    support a timeout.  For IRIX 5.3, 6.2, and 6.3, 
  -	    use patches 1654, 1703 and 1778 respectively.  If you
  -	    have trouble locating these patches, please contact your
  -	    SGI support channel for help.
  -	<LI><A HREF="http://www.ncr.com/">NCR's MP RAS Unix</A> 2.xx and
  -	    3.xx both have FIN_WAIT_2 timeouts.  In 2.xx it is non-tunable
  -	    at 600 seconds, while in 3.xx it defaults to 600 seconds and
  -	    is calculated based on the tunable "max keep alive probes" 
  -	    (default of 8) multiplied by the "keep alive interval" (default
  -	    75 seconds).
  -	<LI><A HREF="http://www.sequent.com">Squent's ptx/TCP/IP for
  -	    DYNIX/ptx</A> has had a FIN_WAIT_2 timeout since around
  -	    release 4.1 in mid-1994.
  +        <LI><A HREF="http://www.freebsd.org/">FreeBSD</A> versions starting at 2.0 or possibly earlier.
  +        <LI><A HREF="http://www.netbsd.org/">NetBSD</A> version 1.2(?)
  +        <LI><A HREF="http://www.openbsd.org/">OpenBSD</A> all versions(?)
  +        <LI><A HREF="http://www.bsdi.com/">BSD/OS</A> 2.1, with the 
  +            <A HREF="ftp://ftp.bsdi.com/bsdi/patches/patches-2.1/K210-027">
  +            K210-027</A> patch installed.  
  +        <LI><A HREF="http://www.sun.com/">Solaris</A> as of around version
  +            2.2.  The timeout can be tuned by using <CODE>ndd</CODE> to 
  +            modify <CODE>tcp_fin_wait_2_flush_interval</CODE>, but the
  +            default should be appropriate for most servers and improper 
  +            tuning can have negative impacts.
  +        <LI><A HREF="http://www.sco.com/">SCO TCP/IP Release 1.2.1</A>
  +            can be modified to have a timeout by following
  +            <A HREF="http://www.sco.com/cgi-bin/waisgate?WAISdocID=2242622956+0+0+0&WAISaction=retrieve"> SCO's instructions</A>.
  +        <LI><A HREF="http://www.linux.org/">Linux</A> 2.0.x and
  +            earlier(?)
  +        <LI><A HREF="http://www.hp.com/">HP-UX</A> 10.x defaults to 
  +            terminating connections in the FIN_WAIT_2 state after the 
  +            normal keepalive timeouts.  This does not
  +            refer to the persistent connection or HTTP keepalive
  +            timeouts, but the <CODE>SO_LINGER</CODE> socket option 
  +            which is enabled by Apache.  This parameter can be adjusted 
  +            by using <CODE>nettune</CODE> to modify parameters such as
  +            <CODE>tcp_keepstart</CODE> and <CODE>tcp_keepstop</CODE>.
  +            In later revisions, there is an explicit timer for
  +            connections in FIN_WAIT_2 that can be modified; contact HP
  +            support for details.
  +        <LI><A HREF="http://www.sgi.com/">SGI IRIX</A> can be patched to
  +            support a timeout.  For IRIX 5.3, 6.2, and 6.3, 
  +            use patches 1654, 1703 and 1778 respectively.  If you
  +            have trouble locating these patches, please contact your
  +            SGI support channel for help.
  +        <LI><A HREF="http://www.ncr.com/">NCR's MP RAS Unix</A> 2.xx and
  +            3.xx both have FIN_WAIT_2 timeouts.  In 2.xx it is non-tunable
  +            at 600 seconds, while in 3.xx it defaults to 600 seconds and
  +            is calculated based on the tunable "max keep alive probes" 
  +            (default of 8) multiplied by the "keep alive interval" (default
  +            75 seconds).
  +        <LI><A HREF="http://www.sequent.com">Squent's ptx/TCP/IP for
  +            DYNIX/ptx</A> has had a FIN_WAIT_2 timeout since around
  +            release 4.1 in mid-1994.
   </UL>
   <P>
   The following systems are known to not have a timeout:
   <P>
   <UL>
  -	<LI><A HREF="http://www.sun.com/">SunOS 4.x</A> does not and
  -	    almost certainly never will have one because it as at the
  -	    very end of its development cycle for Sun.  If you have kernel
  -	    source should be easy to patch.
  +        <LI><A HREF="http://www.sun.com/">SunOS 4.x</A> does not and
  +            almost certainly never will have one because it as at the
  +            very end of its development cycle for Sun.  If you have kernel
  +            source should be easy to patch.
   </UL>
   <P>
   There is a 
  @@ -266,6 +266,12 @@
   mbuf clusters you want to your kernel config file and rebuilding your 
   kernel.<P>
   </DL>
  +
  +<H3>Disable KeepAlive</H3>
  +<P>If you are unable to do any of the above then you should, as a last
  +resort, disable KeepAlive.  Edit your httpd.conf and change "KeepAlive On"
  +to "KeepAlive Off".
  +
   <H2><LI>Feedback</H2>
   
   If you have any information to add to this page, please contact me at
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/misc/footer.html
  
  Index: footer.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/footer.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- footer.html	1996/11/21 09:55:48	1.2
  +++ footer.html	1998/01/30 09:13:10	1.3
  @@ -1,4 +1,7 @@
   <HR>
  +<H3 ALIGN="CENTER">
  + Apache HTTP Server Version 1.2
  +</H3>
   
   <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A>
   <A HREF="../"><IMG SRC="../images/home.gif" ALT="Home"></A>
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/misc/header.html
  
  Index: header.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/header.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- header.html	1997/06/04 11:42:57	1.2
  +++ header.html	1998/01/30 09:13:12	1.3
  @@ -1,3 +1,6 @@
   <DIV ALIGN="CENTER">
    <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]">
  + <H3>
  +  Apache HTTP Server Version 1.2
  + </H3>
   </DIV>
  
  
  
  1.5       +14 -14    apache-1.2/htdocs/manual/misc/index.html
  
  Index: index.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/index.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- index.html	1997/06/04 11:42:57	1.4
  +++ index.html	1998/01/30 09:13:13	1.5
  @@ -21,92 +21,92 @@
     </P>
     <DL>
      <DT><A
  -       	HREF="API.html"
  +        HREF="API.html"
          >API</A>
      </DT>
      <DD>Description of Apache's Application Programming Interface.
      </DD>
      <DT><A
  -       	HREF="FAQ.html"
  +        HREF="FAQ.html"
          >FAQ</A>
      </DT>
      <DD>Frequently-Asked Questions concerning the Apache project and server
      </DD>
      <DT><A
  -       	HREF="client_block_api.html"
  +        HREF="client_block_api.html"
          >Reading Client Input in Apache 1.2</A>
      </DT>
      <DD>Describes differences between Apache 1.1 and 1.2 in how modules
       read information from the client
      </DD>
      <DT><A
  -       	HREF="compat_notes.html"
  +        HREF="compat_notes.html"
          >Compatibility with NCSA</A>
      </DT>
      <DD>Notes about Apache's compatibility with the NCSA server
      </DD>
      <DT><A
  -       	HREF="fin_wait_2.html"
  +        HREF="fin_wait_2.html"
          ><SAMP>FIN_WAIT_2</SAMP></A>
      </DT>
      <DD>A description of the causes of Apache processes going into the
       <SAMP>FIN_WAIT_2</SAMP> state, and what you can do about it
      </DD>
      <DT><A
  -       	HREF="howto.html"
  +        HREF="howto.html"
          >&quot;How-To&quot;</A>
      </DT>
      <DD>Instructions about how to accomplish some commonly-desired server
       functionality changes
      </DD>
      <DT><A
  -       	HREF="known_bugs.html"
  +        HREF="known_bugs.html"
          >Known Bugs</A>
      </DT>
      <DD>Just what it says - a list of known bugs in each of the Apache releases
      </DD>
      <DT><A
  -       	HREF="nopgp.html"
  +        HREF="nopgp.html"
          >No PGP</A>
      </DT>
      <DD>Why we took PEM and PGP support out of the base Apache distribution
      </DD>
      <DT><A
  -       	HREF="perf-bsd44.html"
  +        HREF="perf-bsd44.html"
          >Performance Notes (BSD 4.4)</A>
      </DT>
      <DD>Some notes about ways to improve/optimize Apache performance on
       BSD 4.4 systems
      </DD>
      <DT><A
  -       	HREF="perf-dec.html"
  +        HREF="perf-dec.html"
          >Performance Notes (Digital UNIX)</A>
      </DT>
      <DD>Extracts of USENET postings describing how to optimize Apache
       performance on Digital UNIX systems
      </DD>
      <DT><A
  -       	HREF="perf.html"
  +        HREF="perf.html"
          >Performance Notes (General)</A>
      </DT>
      <DD>Some generic notes about how to improve Apache performance
      </DD>
      <DT><A
  -       	HREF="security_tips.html"
  +        HREF="security_tips.html"
          >Security Tips</A>
      </DT>
      <DD>Some &quot;do&quot;s  - and &quot;don't&quot;s - for keeping your
       Apache web site secure
      </DD>
      <DT><A
  -       	HREF="vif-info.html"
  +        HREF="vif-info.html"
          >Virtual Hosts (IP-based)</A>
      </DT>
      <DD>Excerpts and notes about configuring and using Apache IP-based virtual
       hosts
      </DD>
      <DT><A
  -       	HREF="windoz_keepalive.html"
  +        HREF="windoz_keepalive.html"
          >Windows Bug with Web Keepalive</A>
      </DT>
      <DD>A brief description of a known problem with Microsoft Windows and
  
  
  
  1.15      +115 -267  apache-1.2/htdocs/manual/misc/known_bugs.html
  
  Index: known_bugs.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/known_bugs.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- known_bugs.html	1997/06/04 11:42:57	1.14
  +++ known_bugs.html	1998/01/30 09:13:15	1.15
  @@ -17,18 +17,51 @@
   
   The most up-to-date resource for bug tracking and information is the
   <A HREF="http://www.apache.org/bugdb.cgi">Apache bug database</A>.
  -All existing bugs will be noted there.  Below is a synopsis of
  -significant outstanding bugs at release time.  In fact you really
  -shouldn't trust anything this page says other than maybe the 1.2b8
  -information.
  +Significant bugs at release time will also be noted there.
  +If you are running a 1.2 beta release or version 1.1.3 or earlier
  +and thing you have found a bug, please upgrade to 1.2. Many bugs
  +in early versions have been fixed in 1.2.
   
   <P>See Also: <A HREF="compat_notes.html">Compatibility notes</A></P>
   <HR>
   
  -<H2>Version 1.2 (all)</H2>
  +<H2>Apache 1.2 Bugs</H2>
   
  -<OL><a name="listenbug"></a>
  -    <LI>On some architectures if your configuration uses multiple
  +<OL>
  +    <LI><b>Exists in 1.2.1 only.</b>
  +    On Solaris 2.x the server will stop running after receiving a
  +    SIGHUP.  Four workarounds exist (choose one):<p>
  +    <ul>
  +	<li>Retrieve <a href="http://www.apache.org/dist/patches/apply_to_1.2.1/solaris_hup.patch">this patch</a>.
  +	<code>cd</code> to your <code>apache_1.2.1</code> directory, and
  +	type <code>patch -s -p1 < /path/to/patchfile</code>.  Then rebuild
  +	Apache.<p>
  +	<li>Use SIGUSR1 instead of SIGHUP, see <a href="../stopping.html">
  +	Stopping and Restarting Apache</a> for more details.<p>
  +	<li>Add <code>-DNO_SLACK</code> to
  +	<code>EXTRA_CFLAGS</code> in
  +	your <code>Configuration</code> file, re-run <code>Configure</code>
  +	and rebuild your server.  This disables the
  +	<a href="descriptors.html">descriptor slack workaround</a><p>
  +	<li>(Least preferable) Use Apache 1.2.0 instead of 1.2.1.<p>
  +    </ul>
  +    This problem will be tracked as
  +    <a href="http://www.apache.org/bugdb.cgi/full/832">PR#832</a>.<p>
  +    </li>
  +
  +    <LI>(Exists in 1.2.0 and in 1.2.1 after either of the
  +    <code>NO_SLACK</code> or patch provided by the previous bug are applied.)
  +    Solaris 2.5.1 (and probably other versions of Solaris) appear to have
  +    a race condition completely unrelated to all the others.  It is possible
  +    during a SIGHUP that the server will fail to start because it will not
  +    be able to re-open its sockets.  To our knowledge this has only shown
  +    up during testing when we pummel the server with as many SIGHUP requests
  +    per second as we can.  This appears unrelated to the similar sounding bug
  +    described in <a href="http://www.apache.org/bugdb.cgi/full/832">PR#832</a>.
  +    <p>
  +
  +    <LI><a name="listenbug">On some architectures</A>
  +    if your configuration uses multiple
       <a href="../mod/core.html#listen">Listen</a> directives then it is possible
       that the server will starve one of the sockets while serving hits on
       another.  The work-around is to add
  @@ -39,268 +72,83 @@
       This affects any architecture that doesn't use one of the
       <code>USE_xxxxx_SERIALIZED_ACCEPT</code> definitions, see the
       source file <code>conf.h</code> for your architecture.
  -    <p>This will be tracked as
  +    This will be tracked as
       <a href="http://www.apache.org/bugdb.cgi/full/467">PR#467</a>.
  -    </LI>
  -</OL>
  -
  -<H2>Version 1.2b8</H2>
  -
  -There are several known bugs in 1.2b8.  See the
  -<A HREF="http://www.apache.org/dist/patches/apply_to_1.2b8/">1.2b8 patches
  -directory</A> for patches for some of the ones that have been fixed since
  -the release of 1.2b8.<P>
  -
  -<H2>Version 1.2b1</H2>
  -
  -<OL>
  -
  -	<LI>users have reported problems with many connections stuck in the
  -FIN_WAIT_2 state due to server timeouts. This is a quite complicated 
  -problem; see our <A HREF="fin_wait_2.html">FIN_WAIT_2</A> page for
  -details.
  -
  -	<LI>hard_timeout() for request reads uses incorrect logic, and
  -ends up waiting for an initial request read for the default "timeout"
  -number of seconds, 1200, yet only the "KeepAliveTimeout" number of
  -seconds on keepalive connections.  
  -
  -	<LI>mod_info output is not displaying current configuration as
  -it should.
  -
  -	<LI>Invalid commands in .htaccess files may cause segmentation faults.
  -
  -</OL>
  -
  -<H2>Version 1.1.1</H2>
  -
  -<OL>
  -
  -	<LI>Hostnames such as "123.hotwired.com" are valid, yet
  -find_allowdeny does not properly handle them.  This should be put on
  -Known Bugs.  Be careful when fixing this because just removing the
  -isalpha() check creates a security hole, consider the DNS map
  -"1.1.1.1.in-addr.arpa IN PTR 2.2.2."  if the user has a config line
  -"allow from 2.2.2" it will allow 1.1.1.1 in (unless -DMAXIMUM_DNS).
  --- which is bad because it breaks people who understand double reverse
  -lookup and are trying to avoid it by using only IP addresses on
  -allow/deny statements. - reported by Dean Gaudet, fixed in 1.2.
  -
  -</OL>
  -
  -
  -<H2>Version 1.1.0</H2>
  -
  -<OL>
  -	<LI>mod_auth_msql misbehaviors.  Grab a newer version from 
  -	<A HREF="http://www.apache.org/dist/contrib/modules/">the modules distribution
  -	directory</A>. -fixed in 1.1
  -
  -	<LI>Hanging on Netscape 2.0-3.0b4 on MSWindows (3.1 and 95) - 
  -	we investigated pretty seriously, and as best we can tell 
  -	this is a Netscape bug, and was fixed in 3.0b5.  Please read our
  -	<A HREF="windoz_keepalive.html">lab report</A>.
  -
  -</OL>
  -
  -<H2>Version 1.1b2 (beta)</h2>
  -<OL>
  -       <LI>SunOS has trouble compiling mod_status.c . It'll be fixed
  -       before 1.1 is released.</LI>
  -
  -       <LI>CGI which spawn background processes may fail to return immediately.
  -       No fix exists yet.</LI>
  -
  -       <LI>mod_dir appears to have problems when the DocumentRoot has a 
  -       trailing slash.</LI>
  -
  -</OL>
  -<H2>Version 1.1b1 (beta)</h2>
  -<OL>
  -	<LI>The logfile can sometimes contain only part of a host
  -	address.  This occurs if the Cookie module is compiled in
  -	and enabled.  
  -</OL>
  -
  -<H2>Version 0.8.16 (beta)</H2>
  -<OL>
  -  <LI>(Feature) You cannot use relative pathnames for the -f or -d flags
  - to httpd.<p>
  -  <LI><code>.asis</code> files cannot be used for content-negotiation.
  -</OL>
  -
  -<H2>Version 0.8.13 (beta)</H2>
  -
  -<OL>
  -  <LI><CODE>AddDescription</CODE> doesn't seem to work (a fix is imminent)</LI>
  -</OL>
  -
  -<H2>Version 0.8.11 (beta)</H2>
  -<OL>
  -  <LI><CODE>http_main.c</CODE> function <CODE>accept_mutex_init()</CODE>
  - horrible bug, <CODE>lock_fname</CODE> should be defined larger, e.g.
  - <CODE><BR>
  -     char lock_fname[30];
  - </CODE>
  - <BR><B>Ooops.</B>
  -
  -<P>
  -
  - <LI>There's a bug with <B>NeXT</B>. Restarting the server causes an
  -   infinite loop. A fix has been provided by a user and should be included
  -   in a future update.
  -
  -<P>
  -
  -</OL>
  -
  -
  -<H2>Version 0.8.10 (beta)</H2>
  -
  -<OL>
  -  <LI>Server side includes which include CGI output can have unbearable
  -   delays on some platforms. We're looking into a fix.
  -
  -<P>
  -
  -  <LI>NCSA 1.3 and beyond allow wildcards in &lt;Directory&gt; tags; e.g.
  -      &lt;Directory /home/*/public_html&gt; - Apache doesn't (yet),
  -      but we have a patch coming real soon now
  -
  -<P>
  -
  -  <LI>Buggy scripts can cause server misbehavior on Solaris at least.
  -
  -<P>
  -
  -  <LI>Some of the default directives in srm.conf-dist are outdated
  -
  -<P>
  -
  -  <LI>Descriptions of args to AddIcon and AddAlt are wrong
  -      in command table.
  -
  -<P>
  -
  -  <LI>DirectoryIndex sometimes gets spuriously reset to the default value.
  -
  -<P>
  -
  -  <LI>ErrorDocument is a little shaky, <CODE>" Some text %s</CODE> doesn't
  -    agree with the documentation.
  -
  -<P>
  -
  -  <LI>All Aliases are checked before any ScriptAliases --- the fully
  -      compatible behavior would be to check both in one pass, in the order
  -      in which they occur in srm.conf.
  -
  -<P>
  -</OL>
  -
  -<H2>Version 0.8.8 (beta)</H2>
  -
  -<OL>
  -  <LI>There's a known compilation problem with <B>NeXT</B>. Knock out the
  -   2nd argument to <CODE>setjmp</CODE> when your compiler complains.<BR><BR>
  -  </LI>
  -
  -  <LI><CODE>exec cgi=""</CODE> produces reasonable <B>malformed header</B>
  -  responses when used to invoke non-CGI scripts.<BR>
  -  The NCSA code ignores the missing header. (bad idea)<BR>
  -  Solution: write CGI to the CGI spec or use <CODE>exec cmd=""</CODE> instead.
  -  <P>We might add <CODE>virtual</CODE> support to <CODE>exec cmd</CODE> to
  -  make up for this difference.</P>
  -
  -  <LI>A <I>scoreboard</I> file for process management is currently
  -  created in <B>/tmp</B>. We now find this to be a bad idea, and have plans
  -  to move it into the <CODE>/logs</CODE> directory along with other
  -  files created by Apache.
  -  <P>If you have any <B>/tmp</B> cleaning scripts (e.g. from crontab), you
  -  should have them ignore the scoreboard file, which is named 
  -  <B>/tmp/htstatus.XXXXXXX</B>. If the scoreboard file is damaged, Apache
  -  can become very confused (a SIGHUP repairs the damage).  Furthermore, not
  -  having a /tmp at all can cause disastrous results, as there's no error 
  -  checking yet.<P>  
  -
  -  <LI>Putting authorization information (like AuthName and AuthType) into a 
  -  &lt;Directory&gt; directive without a "requires" field in the &lt;Limit&gt;
  -  directive can result in a core dump.<P>
  -
  -  <LI>AddIcon is broken. The fix is to change<BR>
  -  <CODE>
  -  { "AddIcon", add_icon, BY_<B>TYPE</B>, DIR_CMD_PERMS, ITERATE2,
  -  </CODE>
  -  <BR>to<BR>
  -  <CODE>
  -  { "AddIcon", add_icon, BY_<B>PATH</B>, DIR_CMD_PERMS, ITERATE2,
  -  </CODE>
  -  <P>in <CODE>mod_dir.c</CODE></P></LI>
  -
  -  <LI>Under IRIX, the "Group" directive in httpd.conf needs to be a valid group name 
  -  (i.e. "nogroup") not the numeric group ID.  The distribution httpd.conf, and earlier 
  -  ones, had the default Group be "#-1", which was causing silent exits at startup. 
  -
  -<P>
  -
  -
  -  <LI>Server push as regular CGI's don't work - actually, any normal CGI script 
  -  that outputs additional attributes to the Content-type line (separated by a 
  -  semicolon) gets that extra information chopped off, which means that the line
  -  <code>Content-type: multipart/x-mixed-replace; boundary=ThisRandomString</code>
  -  gets munged to just <code>Content-type: multipart/x-mixed-replace</code>, which 
  -  means it doesn't know what the boundary is, and fails.  You can get around this
  -  until 0.8.9 by making the CGI script a "No Parsed Header" script by prefixing the 
  -  name of the script with a "nph-", but then you have to be responsible for correct
  -  HTTP headers.  If the server-push animation is a constant, unchanging stream that
  -  terminates at some point, you could also put that stream into a whole file and 
  -  use the .asis file extension functionality.  
  -
  -<P>
  -
  -  <LI>ErrorDocument is a little shaky, <CODE>" Some text %s</CODE> doesn't
  -    agree with the documentation.
  -
  -<P>
  -
  -</OL>
  -
  -<HR>
  -
  -<H2>Version 0.6.4 </H2>
  -<OL>
  -<LI>As with NCSA 1.3 (and 1.4 ?), some <B>HEAD</B> requests on
  -directories without an <CODE>index.html</CODE> fail to be logged... harmless.</LI>
  -<LI>Typo in Virtual Host #defines (accidentally defined #VIRUAL_HOST").  0.6.4b fixes this.
  -</OL>
  -<H2>Version 0.6.2 (first beta)</H2>
  -<OL>
  -
  -<LI><P>Apache error_log might show <CODE>httpd: caught SIGBUS, dumping core</CODE> after a successful redirect. We hope to fix this in 0.6.3</P></LI>
  +    <P></LI>
   
  -<LI><P>If you see a lot of messages such as,
  -<PRE>access to /something: failed for foo.bar.com, reason: no multi in this directory</PRE>
  -in your error log, don't panic !. It means "File not found", and we will
  -fix it sooner or later.
  -
  -</P>
  -
  -<LI><P><B>WARNING</B>: Apache logs all URLs redirected <B>from</B> and
  -<B>to</B>.  This isn't bug, it's deliberate, but you should be aware
  -of it.  It's a recognition of the fact that the Common Log File format
  -doesn't have any place to log the real object that was returned for
  -the internally redirected request.  This will be changed soon.  
  -
  -</P>
  -
  -<LI><P>BSDI problems: One of the test machines (<a
  -href="http://www.hyperreal.org/">Hyperreal</a>) has noticed "flocks" of
  -child processes sucking up large amounts of resources when moderately
  -hit (on a Pentium 90 running 1.1 serving ~2 hits/second).  Killing and
  -restarting the daemon helps this disappear - it's being investigated,
  -it might be a kernel bug, but then every server developer likes to say
  -that.  Let us know how well it works for you if you are using BSDI and
  -have a high number of hits.</P></LI>
  +    <LI><b>Fixed in 1.2.1.</b>
  +    <a name="cnegbug">Apache's</A> <A HREF="../content-negotiation.html">Content
  +    Negotiation</A> should pick the smallest variant if there
  +    are several that are equally acceptable. A bug in 1.2 means it no
  +    longer does this unless all the variants have character sets.
  +    This <A HREF="../../dist/contrib/patches/1.2/conneg-bug.patch">patch</A>
  +    fixes this problem. It also fixes the problem which makes Apache
  +    pick the last equally acceptable variant instead of the first.
  +    This will be tracked as
  +    <a href="http://www.apache.org/bugdb.cgi/full/94">PR#94</a>.
  +    <P></LI>
  +
  +    <LI>
  +    The PATH_INFO part of a request URI cannot include the sequence
  +    <CODE>%2f</CODE>. This will be tracked as
  +    <A HREF="http://www.apache.org/bugdb.cgi/full/543">PR#543</A>.
  +    <P></LI>
  +
  +    <LI>Users of early 1.2 betas reported problems with many
  +    connections stuck in the FIN_WAIT_2 state due to server
  +    timeouts. Several changes were made during the beta testing of 1.2
  +    to reduce this problem as much as possible, although you may still
  +    see sockets in FIN_WAIT_2 state due to network or operating system
  +    issues outside the control of Apache. See our <A
  +    HREF="fin_wait_2.html">FIN_WAIT_2</A> page for more details.
  +
  +    <P>SunOS4 has a kernel bug in the allocation of memory for the mbuf table.
  +    When it fills up, the result is a Panic the next time any routine tries
  +    to set something in an imaginary mbuf beyond the range of the table.
  +    Due to buggy browser behavior and the lack of a FIN_WAIT_2 timeout
  +    on SunOS4, "KeepAlive Off" is necessary to avoid filling up the mbuf
  +    table on busy sites.
  +    <P></LI>
  +
  +    <LI>Compilation fails on SCO3 when using gcc instead of cc, complaining
  +    with "<CODE>gcc: noinline: No such file or directory</CODE>". Fix
  +    is given in <a href="http://www.apache.org/bugdb.cgi/full/695">PR#695</A>.
  +    <P></LI>
  +
  +    <LI>If compilation fails complaining about "unknown symbol __inet_ntoa()"
  +    then you have probably installed version 8 of bind. You will need to
  +    explicitly link with the bind library by adding <CODE>-lbind</CODE>
  +    to <CODE>EXTRA_LDFLAGS</CODE> in <CODE>Configuration</CODE>. See
  +    <A HREF="http://www.apache.org/bugdb.cgi/full/616">PR#616</A>
  +    and the
  +    <A HREF="FAQ.html#bind8.1">Apache FAQ</A>.
  +    <P></LI>
  +
  +    <LI>The message "<CODE>created shared memory segment #730499</CODE>"
  +    in error_log is not an error and should be ignored. See
  +    <a href="http://www.apache.org/bugdb.cgi/full/696">PR#696</A>.
  +    <P></LI>
  +
  +    <LI>
  +    Compiling on Solaris 2 with SunSoft's C compiler gives the warning
  +    <CODE>"mod_include.c", line 1123: warning: end-of-loop code not
  +    reached</CODE>. This is a bogus warning and can be ignored.
  +    See <A HREF="http://www.apache.org/bugdb.cgi/full/681">PR#681</A>.
  +    <P></LI>
  +
  +    <LI><a href="descriptors.html"><b>Workaround available in 1.2.1.</b></a>
  +    There appears to be a problem on BSDI 2.1 with large numbers of
  +    virtual hosts. This appears similar to a file-descriptor limit
  +    but BSDI should not have this problem. This will be tracked as
  +    <A HREF="http://www.apache.org/bugdb.cgi/full/611">PR#611</A>.
  +    See also the <A HREF="FAQ.html#fdlim">Apache FAQ</A>.
  +    <P></LI>
  +
  +    <LI><a href="descriptors.html"><b>Workaround available in 1.2.1.</b></a>
  +    Solaris 2 has problems with large numbers of virtual hosts. This is
  +    because of an operating system limit of 256 file pointers, not due
  +    to Apache.   See also the <A HREF="FAQ.html#fdlim">Apache FAQ</A>.
  +    <P></LI>
   
   </OL>
   
  
  
  
  1.4       +2 -2      apache-1.2/htdocs/manual/misc/nopgp.html
  
  Index: nopgp.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/nopgp.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- nopgp.html	1997/06/04 11:42:58	1.3
  +++ nopgp.html	1998/01/30 09:13:17	1.4
  @@ -69,7 +69,7 @@
   Thanks.
   
   <UL>
  -<LI><A HREF="http://www.yahoo.com/Science/Mathematics/Security_and_Encryption/">
  +<LI><A HREF="http://www.yahoo.com/Computers_and_Internet/Security_and_Encryption/">
   Yahoo - Science: Mathematics: Security and Encryption</A>
   <LI><A HREF="http://www.eff.org/pub/EFF/Policy/Crypto/">
   EFF Crypto/Privacy/Security Archive</A>
  @@ -81,7 +81,7 @@
   ICLU - Your Rights in Cyberspace</A>
   </UL>
   
  -	<a href="http://bong.com/~brian">Brian</a>, <a href="mailto:brian@hyperreal.org">brian@hyperreal.org</a>
  +        <a href="http://www.behlendorf.com/~brian/">Brian</a>, <a href="mailto:brian@hyperreal.org">brian@hyperreal.org</a>
   
   <!--#include virtual="footer.html" -->
   </BODY>
  
  
  
  1.7       +1 -1      apache-1.2/htdocs/manual/misc/perf-bsd44.html
  
  Index: perf-bsd44.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/perf-bsd44.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- perf-bsd44.html	1997/06/04 11:42:58	1.6
  +++ perf-bsd44.html	1998/01/30 09:13:22	1.7
  @@ -219,7 +219,7 @@
   <blockquote>It really does help if your kernel and frequently used utilities
   are fully optimized. Rebuilding the FreeBSD kernel on an AMD-133
   (486-class CPU) web-server with<BR>
  -<code>    -m486 -fexpensive-optimizations -fomit-frame-ponter -O2</code><BR>
  +<code>    -m486 -fexpensive-optimizations -fomit-frame-pointer -O2</code><BR>
   helped reduce the number of "unable" errors, because the CPU was
   often maxed out.</blockquote>
   <P>
  
  
  
  1.9       +3 -17     apache-1.2/htdocs/manual/misc/perf.html
  
  Index: perf.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/perf.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- perf.html	1997/06/04 11:42:58	1.8
  +++ perf.html	1998/01/30 09:13:24	1.9
  @@ -26,7 +26,6 @@
   <LI><A HREF="#AUX">A/UX (Apple's UNIX)</A>
   <LI><A HREF="#BSD">BSD-based (BSDI, FreeBSD, etc)</A>
   <LI><A HREF="#DEC">Digital UNIX</A>
  -<LI><A HREF="#HP">Hewlett-Packard</A>
   <LI><A HREF="#Linux">Linux</A>
   <LI><A HREF="#SGI">SGI</A>
   <LI><A HREF="#Solaris">Solaris</A>
  @@ -62,22 +61,13 @@
   
   <UL> 
     <LI><A HREF="http://www.digital.com/info/internet/document/ias/tuning.html">DIGITAL
  -  	UNIX Tuning Parameters for Web Servers</A> 
  +        UNIX Tuning Parameters for Web Servers</A> 
     <LI>We have some <A HREF="perf-dec.html">newsgroup postings</A> on how to tune 
  -	Digital UNIX 3.2 and 4.0. 
  +        Digital UNIX 3.2 and 4.0. 
   </UL>
   
   <P><HR>
   
  -<H3><A NAME="HP">
  -Hewlett-Packard
  -</A></H3>
  -
  -Some documentation on tuning HP machines can be found at <A
  -HREF="http://www.software.hp.com/internet/perf/tuning.html">http://www.software.hp.com/internet/perf/tuning.html</A>.
  -
  -<P><HR>
  -
   <H3><A NAME="Linux">
   Linux
   </A></H3>
  @@ -117,11 +107,7 @@
   
   <UL>
   
  -<LI><A href="http://www.sun.com/sun-on-net/Sun.Internet.Solutions/performance/">
  -World Wide Web Server Performance, 
  -&lt;http://www.sun.com/sun-on-net/Sun.Internet.Solutions/performance/&gt;</a>
  -<LI><A HREF="http://www.sun.com/solaris/products/siss/">
  -Solaris Internet Server Supplement for 2.5.1</A>
  +<LI><A href="http://www.sun.com/sun-on-net/performance.html">Sun Performance Information</a>
   </UL>
   
   <P><HR>
  
  
  
  1.9       +0 -1      apache-1.2/htdocs/manual/misc/security_tips.html
  
  Index: security_tips.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/security_tips.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- security_tips.html	1997/06/04 11:42:58	1.8
  +++ security_tips.html	1998/01/30 09:13:25	1.9
  @@ -170,7 +170,6 @@
   >UserDir</A>
   directive; setting it to something like <SAMP>&quot;./&quot;</SAMP>
   would have the same effect, for root, as the first example above.
  -</P>
   
   <HR>
   <P>Please send any other useful security tips to The Apache Group
  
  
  
  1.7       +137 -137  apache-1.2/htdocs/manual/misc/vif-info.html
  
  Index: vif-info.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/misc/vif-info.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- vif-info.html	1997/06/04 11:42:59	1.6
  +++ vif-info.html	1998/01/30 09:13:26	1.7
  @@ -49,15 +49,15 @@
   that these are three distinct class C addresses in three distinct
   class C nets). Here are the ifconfigs:
   
  -  ifconfig le0 198.3.2.1 up -trailers	# config primary interface
  +  ifconfig le0 198.3.2.1 up -trailers   # config primary interface
   
  -  ifconfig vif0 198.4.3.2 up 		# config first virtual interface
  -  route delete net 198.4.3 198.4.3.2	# delete spurious route 
  -  route add host 198.4.3.2 198.4.3.2 0	# add route for this i/f
  -
  -  ifconfig vif1 198.5.4.3 up		# config second virtual interface
  -  route delete net 198.5.4 198.5.4.3	# delete spurious route 
  -  route add host 198.5.4.3 198.5.4.3 0	# add route for this i/f
  +  ifconfig vif0 198.4.3.2 up            # config first virtual interface
  +  route delete net 198.4.3 198.4.3.2    # delete spurious route 
  +  route add host 198.4.3.2 198.4.3.2 0  # add route for this i/f
  +
  +  ifconfig vif1 198.5.4.3 up            # config second virtual interface
  +  route delete net 198.5.4 198.5.4.3    # delete spurious route 
  +  route add host 198.5.4.3 198.5.4.3 0  # add route for this i/f
   
   The route deletes are needed because the ifconfig creates a default
   route to the interface's network, which can cause problems; all that's
  @@ -91,11 +91,11 @@
   and netinet/if_vif.h, configure your kernel with the number of
   virtual interfaces you want using a line like:
   
  -pseudo-device	vif4		# Virtual IP interface
  +pseudo-device   vif4            # Virtual IP interface
   
   in your configuration file, and the line
   
  -netinet/if_vif.c	optional vif device-driver
  +netinet/if_vif.c        optional vif device-driver
   
   in the "files" file. Also, add the appropriate entries in conf.c, so
   that you can access the if_attach() routine when you open the device:
  @@ -122,9 +122,9 @@
   then, way down in the definition for cdevsw[]:
   
   --------------------
  -	vifopen,	vifclose,	vifread,	vifwrite,	/*14*/
  -	vifioctl,	nodev,		nodev,		0,
  -	0,	nodev,
  +        vifopen,        vifclose,       vifread,        vifwrite,       /*14*/
  +        vifioctl,       nodev,          nodev,          0,
  +        0,      nodev,
   --------------------
   
   Make sure you remember the correct major device number, 14 in this case!
  @@ -139,12 +139,12 @@
   ---------------------netinet/if_vif.h--------------------------------------
   typedef struct 
   {
  -	struct ifnet	vif_if;
  -	struct ifnet	*vif_sif;	/* slave interface */
  -	int		vif_flags;
  +        struct ifnet    vif_if;
  +        struct ifnet    *vif_sif;       /* slave interface */
  +        int             vif_flags;
   } vif_softc_t;
   
  -#define	VIFMTU	(1024+512)
  +#define VIFMTU  (1024+512)
   ---------------------------------------------------------------------------
   
   and
  @@ -165,7 +165,7 @@
   #include "../net/netisr.h"
   #include "../net/route.h"
   
  -#ifdef	INET
  +#ifdef  INET
   #include "../netinet/in.h"
   #include "../netinet/in_systm.h"
   #include "../netinet/in_var.h"
  @@ -191,125 +191,125 @@
   
   vifattach()
   {
  -	register int i;
  -	register struct ifnet *ifp;
  -        int	vifoutput(), vififioctl();
  -	
  -	for (i=0; i&lt;NVIF; i++)
  -	{
  -		ifp = &vif_softc[i].vif_if;
  -		ifp-&gt;if_name = "vif";
  -		ifp-&gt;if_unit = i;
  -		ifp-&gt;if_mtu = VIFMTU;
  -		ifp-&gt;if_flags = IFF_LOOPBACK | IFF_NOARP;
  -		ifp-&gt;if_ioctl = vififioctl;
  -		ifp-&gt;if_output = vifoutput;
  -		if_attach(ifp);
  -	}
  +        register int i;
  +        register struct ifnet *ifp;
  +        int     vifoutput(), vififioctl();
  +        
  +        for (i=0; i&lt;NVIF; i++)
  +        {
  +                ifp = &vif_softc[i].vif_if;
  +                ifp-&gt;if_name = "vif";
  +                ifp-&gt;if_unit = i;
  +                ifp-&gt;if_mtu = VIFMTU;
  +                ifp-&gt;if_flags = IFF_LOOPBACK | IFF_NOARP;
  +                ifp-&gt;if_ioctl = vififioctl;
  +                ifp-&gt;if_output = vifoutput;
  +                if_attach(ifp);
  +        }
   }
   
   vifopen(dev, flag)
   int dev, flag;
   {
  -	int unit;
  -	
  -	if (!vifs_inited)
  -	{
  -		vifattach();
  -		vifs_inited = 1;
  -		printf("vif initialized\n");
  -	}
  -	
  -	unit = minor(dev);
  -	if ((unit &lt; 0) || (unit &gt;= NVIF))
  -	{
  -		return ENXIO;
  -	}
  -	
  -	return 0;
  +        int unit;
  +        
  +        if (!vifs_inited)
  +        {
  +                vifattach();
  +                vifs_inited = 1;
  +                printf("vif initialized\n");
  +        }
  +        
  +        unit = minor(dev);
  +        if ((unit &lt; 0) || (unit &gt;= NVIF))
  +        {
  +                return ENXIO;
  +        }
  +        
  +        return 0;
   }
   
   vifclose(dev, flag)
   int dev, flag;
   {
  -	return 0;
  +        return 0;
   }
   
   vifread()
   {
  -	return ENXIO;
  +        return ENXIO;
   }
   
   vifwrite()
   {
  -	return ENXIO;
  +        return ENXIO;
   }
   
   vifselect()
   {
  -	return ENXIO;
  +        return ENXIO;
   }
   
   vifoutput(ifp, m0, dst)
  -	struct ifnet *ifp;
  -	register struct mbuf *m0;
  -	struct sockaddr *dst;
  -{
  -	int s;
  -	register struct ifqueue *ifq;
  -	struct mbuf *m;
  -	struct sockaddr_in *din;
  -	
  -	if (dst-&gt;sa_family != AF_INET)
  -	{
  -		printf("%s%d: can't handle af%d\n", 
  -		       ifp-&gt;if_name, ifp-&gt;if_unit,
  -		       dst-&gt;sa_family);
  -		m_freem(m0);
  -		return (EAFNOSUPPORT);
  -	}
  -
  -	din = (struct sockaddr_in *)dst;
  -	
  -	if (din-&gt;sin_addr.s_addr == IA_SIN(ifp-&gt;if_addrlist)-&gt;sin_addr.s_addr)
  -	{
  -		/* printf("%s%d: looping\n", ifp-&gt;if_name, ifp-&gt;if_unit); */
  -		
  -		/*
  -		 * Place interface pointer before the data
  -		 * for the receiving protocol.
  -		 */
  -		if (m0-&gt;m_off &lt;= MMAXOFF &&
  -		    m0-&gt;m_off &gt;= MMINOFF + sizeof(struct ifnet *)) {
  -			m0-&gt;m_off -= sizeof(struct ifnet *);
  -			m0-&gt;m_len += sizeof(struct ifnet *);
  -		} else {
  -			MGET(m, M_DONTWAIT, MT_HEADER);
  -			if (m == (struct mbuf *)0)
  -			  return (ENOBUFS);
  -			m-&gt;m_off = MMINOFF;
  -			m-&gt;m_len = sizeof(struct ifnet *);
  -			m-&gt;m_next = m0;
  -			m0 = m;
  -		}
  -		*(mtod(m0, struct ifnet **)) = ifp;
  -		s = splimp();
  -		ifp-&gt;if_opackets++;
  -		ifq = &ipintrq;
  -		if (IF_QFULL(ifq)) {
  -			IF_DROP(ifq);
  -			m_freem(m0);
  -			splx(s);
  -			return (ENOBUFS);
  -		}
  -		IF_ENQUEUE(ifq, m0);
  -		schednetisr(NETISR_IP);
  -		ifp-&gt;if_ipackets++;
  -		splx(s);
  -		return (0);
  -	}
  +        struct ifnet *ifp;
  +        register struct mbuf *m0;
  +        struct sockaddr *dst;
  +{
  +        int s;
  +        register struct ifqueue *ifq;
  +        struct mbuf *m;
  +        struct sockaddr_in *din;
  +        
  +        if (dst-&gt;sa_family != AF_INET)
  +        {
  +                printf("%s%d: can't handle af%d\n", 
  +                       ifp-&gt;if_name, ifp-&gt;if_unit,
  +                       dst-&gt;sa_family);
  +                m_freem(m0);
  +                return (EAFNOSUPPORT);
  +        }
  +
  +        din = (struct sockaddr_in *)dst;
  +        
  +        if (din-&gt;sin_addr.s_addr == IA_SIN(ifp-&gt;if_addrlist)-&gt;sin_addr.s_addr)
  +        {
  +                /* printf("%s%d: looping\n", ifp-&gt;if_name, ifp-&gt;if_unit); */
  +                
  +                /*
  +                 * Place interface pointer before the data
  +                 * for the receiving protocol.
  +                 */
  +                if (m0-&gt;m_off &lt;= MMAXOFF &&
  +                    m0-&gt;m_off &gt;= MMINOFF + sizeof(struct ifnet *)) {
  +                        m0-&gt;m_off -= sizeof(struct ifnet *);
  +                        m0-&gt;m_len += sizeof(struct ifnet *);
  +                } else {
  +                        MGET(m, M_DONTWAIT, MT_HEADER);
  +                        if (m == (struct mbuf *)0)
  +                          return (ENOBUFS);
  +                        m-&gt;m_off = MMINOFF;
  +                        m-&gt;m_len = sizeof(struct ifnet *);
  +                        m-&gt;m_next = m0;
  +                        m0 = m;
  +                }
  +                *(mtod(m0, struct ifnet **)) = ifp;
  +                s = splimp();
  +                ifp-&gt;if_opackets++;
  +                ifq = &ipintrq;
  +                if (IF_QFULL(ifq)) {
  +                        IF_DROP(ifq);
  +                        m_freem(m0);
  +                        splx(s);
  +                        return (ENOBUFS);
  +                }
  +                IF_ENQUEUE(ifq, m0);
  +                schednetisr(NETISR_IP);
  +                ifp-&gt;if_ipackets++;
  +                splx(s);
  +                return (0);
  +        }
   
  -	return EHOSTUNREACH;
  +        return EHOSTUNREACH;
   }
   
   /*
  @@ -317,25 +317,25 @@
    */
   /* ARGSUSED */
   vififioctl(ifp, cmd, data)
  -	register struct ifnet *ifp;
  -	int cmd;
  -	caddr_t data;
  -{
  -	int error = 0;
  -
  -	switch (cmd) {
  -
  -	case SIOCSIFADDR:
  -		ifp-&gt;if_flags |= IFF_UP;
  -		/*
  -		 * Everything else is done at a higher level.
  -		 */
  -		break;
  -
  -	default:
  -		error = EINVAL;
  -	}
  -	return (error);
  +        register struct ifnet *ifp;
  +        int cmd;
  +        caddr_t data;
  +{
  +        int error = 0;
  +
  +        switch (cmd) {
  +
  +        case SIOCSIFADDR:
  +                ifp-&gt;if_flags |= IFF_UP;
  +                /*
  +                 * Everything else is done at a higher level.
  +                 */
  +                break;
  +
  +        default:
  +                error = EINVAL;
  +        }
  +        return (error);
   }
   
   vifioctl(dev, cmd, arg, mode)
  @@ -344,13 +344,13 @@
   caddr_t arg;
   int mode;
   {
  -	int unit;
  -	
  -	unit = minor(dev);
  -	if ((unit &lt; 0) || (unit &gt;= NVIF))
  -	  return ENXIO;
  -	
  -	return EINVAL;
  +        int unit;
  +        
  +        unit = minor(dev);
  +        if ((unit &lt; 0) || (unit &gt;= NVIF))
  +          return ENXIO;
  +        
  +        return EINVAL;
   }
   ---------------------------------------------------------------------------- 
   
  
  
  
  1.57      +24 -4     apache-1.2/htdocs/manual/mod/core.html
  
  Index: core.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/core.html,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -r1.56 -r1.57
  --- core.html	1997/06/04 16:14:13	1.56
  +++ core.html	1998/01/30 09:13:30	1.57
  @@ -44,6 +44,7 @@
   <li><A HREF="#limit">&lt;Limit&gt;</A>
   <li><A HREF="#listen">Listen</A>
   <li><A HREF="#location">&lt;Location&gt;</A>
  +<li><A HREF="#lockfile">LockFile</A>
   <li><A HREF="#maxclients">MaxClients</A>
   <li><A HREF="#maxkeepaliverequests">MaxKeepAliveRequests</a>
   <li><A HREF="#maxrequestsperchild">MaxRequestsPerChild</A>
  @@ -714,7 +715,7 @@
      &lt;Location ~ &quot;/(extra|special)/data&quot;&gt;
   </pre>
   
  -would match URLs that contained the substring "/extra/data" or
  +<p>would match URLs that contained the substring "/extra/data" or
   "/special/data".</p>
   
   <p>The <code>Location</code> functionality is especially useful when
  @@ -732,7 +733,23 @@
   </pre>
   <hr>
   
  -<A name="maxclients"><h2>MaxClients directive</h2></A>
  +<A NAME="lockfile"><H2>LockFile</H2></A>
  +<strong>Syntax:</strong> LockFile <em>filename</em><BR>
  +<strong>Default:</strong> <code>LockFile logs/accept.lock</code><BR>
  +<strong>Context:</strong> server config<BR>
  +<strong>Status:</strong> core<P>
  +
  +The LockFile directive sets the path to the lockfile used when
  +Apache is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or
  +USE_FLOCK_SERIALIZED_ACCEPT.  This directive should normally be
  +left at its default value.  The main reason for changing it is if
  +the <code>logs</code> directory is NFS mounted, since the lockfile
  +should be stored on a local disk if possible.  The PID of the main
  +server process is automatically appended to the filename.
  +
  +<P><HR>
  +
  +<A name="maxclients"><h2>MaxClients</h2></A>
   <!--%plaintext &lt;?INDEX {\tt MaxClients} directive&gt; -->
   <strong>Syntax:</strong> MaxClients <em>number</em><br>
   <strong>Default:</strong> <code>MaxClients 256</code><br>
  @@ -836,6 +853,9 @@
   <dd>
   <!--%plaintext &lt;?INDEX {\tt FollowSymLinks} option&gt; -->
   The server will follow symbolic links in this directory.
  +<b>Note</b>: even though the server follows the symlink it does <i>not</i>
  +change the pathname used to match against <code>&lt;Directory&gt;</code>
  +sections.
   <dt>Includes
   <dd>
   <!--%plaintext &lt;?INDEX {\tt Includes} option&gt; -->
  @@ -1031,7 +1051,7 @@
   
   See also <A HREF="#accessconfig">AccessConfig</A>.<p><hr>
   
  -<A name="rlimit">
  +<A name="rlimit"> </A>
   <A name="rlimitcpu"><h2>RLimitCPU directive</h2></A>
   <!--%plaintext &lt;?INDEX {\tt RLimitCPU} directive&gt; -->
   <strong>Syntax:</strong> RLimitCPU <em># or 'max'</em> <em>[# or 'max']</em><br>
  @@ -1158,7 +1178,7 @@
   <A name="sendbuffersize"><h2>SendBufferSize directive</h2></A>
   <!--%plaintext &lt;?INDEX {\tt SendBufferSize} directive&gt; -->
   <strong>Syntax:</strong> SendBufferSize <em>bytes</em><br>
  -<strong>Context:</strong> server config, virtual host<br>
  +<strong>Context:</strong> server config<br>
   <strong>Status:</strong> core<p>
   
   The server will set the TCP buffer size to the number of bytes
  
  
  
  1.21      +1 -0      apache-1.2/htdocs/manual/mod/directives.html
  
  Index: directives.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/directives.html,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- directives.html	1997/06/04 16:14:14	1.20
  +++ directives.html	1998/01/30 09:13:31	1.21
  @@ -106,6 +106,7 @@
   <li><A HREF="mod_dld.html#loadfile">LoadFile</A>
   <li><A HREF="mod_dld.html#loadmodule">LoadModule</A>
   <li><A HREF="core.html#location">&lt;Location&gt;</A>
  +<li><A HREF="core.html#lockfile">LockFile</A>
   <li><A HREF="mod_log_config.html#logformat">LogFormat</A>
   <li><A HREF="core.html#maxclients">MaxClients</A>
   <li><A HREF="core.html#maxkeepaliverequests">MaxKeepAliveRequests</A>
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/mod/footer.html
  
  Index: footer.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/footer.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- footer.html	1996/11/21 10:30:35	1.2
  +++ footer.html	1998/01/30 09:13:31	1.3
  @@ -1,4 +1,7 @@
   <HR>
  +<H3 ALIGN="CENTER">
  + Apache HTTP Server Version 1.2
  +</H3>
   
   <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A>
   <A HREF="../"><IMG SRC="../images/home.gif" ALT="Home"></A>
  
  
  
  1.3       +3 -0      apache-1.2/htdocs/manual/mod/header.html
  
  Index: header.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/header.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- header.html	1997/06/04 16:14:14	1.2
  +++ header.html	1998/01/30 09:13:32	1.3
  @@ -1,3 +1,6 @@
   <DIV ALIGN="CENTER">
    <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]">
  + <H3>
  +  Apache HTTP Server Version 1.2
  + </H3>
   </DIV>
  
  
  
  1.9       +40 -40    apache-1.2/htdocs/manual/mod/mod_auth_anon.html
  
  Index: mod_auth_anon.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_auth_anon.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- mod_auth_anon.html	1997/06/04 16:14:15	1.8
  +++ mod_auth_anon.html	1998/01/30 09:13:32	1.9
  @@ -61,23 +61,23 @@
   <strong>Status:</strong> Extension<br>
   <strong>Module:</strong> mod_auth_anon<p>
   
  -	A list of one or more 'magic' userIDs which are allowed access
  -	without password verification. The userIDs are space separated.
  -	It is possible to use the ' and " quotes to allow a space in
  -	a userID as well as the \ escape character.
  -	<p>
  -	Please note that the comparison is <b>case-IN-sensitive</b>.
  -	<br>
  -	I strongly suggest that the magic username '<code>anonymous</code>'
  -	is always one of the allowed userIDs.
  -	<p>
  -	Example:<br>
  -	<code>
  -	Anonymous: anonymous "Not Registered" 'I don\'t know'
  -	</code><p>
  -	This would allow the user to enter without password verification
  -	by using the userId's 'anonymous', 'AnonyMous','Not Registered' and
  -	'I Don't Know'.
  +        A list of one or more 'magic' userIDs which are allowed access
  +        without password verification. The userIDs are space separated.
  +        It is possible to use the ' and " quotes to allow a space in
  +        a userID as well as the \ escape character.
  +        <p>
  +        Please note that the comparison is <b>case-IN-sensitive</b>.
  +        <br>
  +        I strongly suggest that the magic username '<code>anonymous</code>'
  +        is always one of the allowed userIDs.
  +        <p>
  +        Example:<br>
  +        <code>
  +        Anonymous: anonymous "Not Registered" 'I don\'t know'
  +        </code><p>
  +        This would allow the user to enter without password verification
  +        by using the userId's 'anonymous', 'AnonyMous','Not Registered' and
  +        'I Don't Know'.
   <HR>
   
   <A name="Authoritative"><h2>Anonymous_Authoritative</h2></A>
  @@ -91,12 +91,12 @@
           When set 'on', there is no
           fall-through to other authorization methods. So if a
           userID does not match the values specified in the
  -	<code>Anonymous</code> directive, access is denied.
  -	<p>
  -	Be sure you know what you are doing when you decide to switch 
  -	it on. And remember that it is the linking order of the modules
  -	(in the Configuration / Make file) which details the order
  -	in which the Authorization modules are queried.
  +        <code>Anonymous</code> directive, access is denied.
  +        <p>
  +        Be sure you know what you are doing when you decide to switch 
  +        it on. And remember that it is the linking order of the modules
  +        (in the Configuration / Make file) which details the order
  +        in which the Authorization modules are queried.
   <hr>
   
   <A name="LogEmail"><h2>Anonymous_LogEmail</h2></A>
  @@ -107,8 +107,8 @@
   <strong>Status:</strong> Extension<br>
   <strong>Module:</strong> mod_auth_anon<p>
   
  -	When set 'on', the default, the 'password' entered (which hopefully
  -	contains a sensible email address) is logged in the httpd-log file.
  +        When set 'on', the default, the 'password' entered (which hopefully
  +        contains a sensible email address) is logged in the httpd-log file.
   <hr>
   
   <A name="MustGiveEmail"><h2>Anonymous_MustGiveEmail</h2></a>
  @@ -120,8 +120,8 @@
   <strong>Status:</strong> Extension<br>
   <strong>Module:</strong> mod_auth_anon<p>
   
  -	Specifies whether the user must specify an email
  -	address as the password.  This prohibits blank passwords.
  +        Specifies whether the user must specify an email
  +        address as the password.  This prohibits blank passwords.
   <HR>
   
   <A name="NoUserID"><h2>Anonymous_NoUserID</h2></A>
  @@ -132,11 +132,11 @@
   <strong>Status:</strong> Extension<br>
   <strong>Module:</strong> mod_auth_anon<p>
   
  -	When set 'on', users can leave
  -	the userID (and perhaps the password field) empty. This
  -	can be very convenient for MS-Explorer users who can
  -	just hit return or click directly on the OK button; which
  -	seems a natural reaction.
  +        When set 'on', users can leave
  +        the userID (and perhaps the password field) empty. This
  +        can be very convenient for MS-Explorer users who can
  +        just hit return or click directly on the OK button; which
  +        seems a natural reaction.
   
   <hr>
   
  @@ -148,9 +148,9 @@
   <strong>Status:</strong> Extension<br>
   <strong>Module:</strong> mod_auth_anon<p>
   
  -	When set 'on' the 'password' entered is
  -	checked for at least one '@' and a '.' to encourage users to enter
  -	valid email addresses (see the above <code>Auth_LogEmail</code>).
  +        When set 'on' the 'password' entered is
  +        checked for at least one '@' and a '.' to encourage users to enter
  +        valid email addresses (see the above <code>Auth_LogEmail</code>).
   
   <hr><a name="Example"><h2>Example</h2></a>
   
  @@ -180,10 +180,10 @@
   <dl>
   <dt><code>
   Anonymous        anonymous guest www test welcome<p>
  -Anonymous_MustGiveEmail	on<br>
  +Anonymous_MustGiveEmail on<br>
   Anonymous_VerifyEmail    on<br>
  -Anonymous_NoUserId    	off<br>
  -Anonymous_LogEmail    	on<br>
  +Anonymous_NoUserId      off<br>
  +Anonymous_LogEmail      on<br>
   <p>
   AuthName                Use 'anonymous' & Email address for guest entry<br>
   AuthType                basic<p>
  @@ -217,8 +217,8 @@
       </dd>
   <dt>Version 0.5<br></dt>
       <dd>Added 'VerifyEmail' and 'LogEmail' options. Multiple
  -	'anonymous' tokens allowed. more docs. Added Authoritative
  -	functionality.
  +        'anonymous' tokens allowed. more docs. Added Authoritative
  +        functionality.
       </dd>
   </dl>
   
  
  
  
  1.7       +6 -6      apache-1.2/htdocs/manual/mod/mod_auth_msql.html
  
  Index: mod_auth_msql.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_auth_msql.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- mod_auth_msql.html	1997/06/04 16:14:17	1.6
  +++ mod_auth_msql.html	1998/01/30 09:13:33	1.7
  @@ -155,13 +155,13 @@
   <pre>
        % msqladmin create www               <br>
        % msql www                           <br>
  -     -> create table user_records (       <br>
  -     ->   User_id  char(32) primary key,  <br>
  -     ->   Cpasswd  char(32),              <br>
  -     ->   Xgroup   char(32)               <br>
  -     ->   ) \g                            <br>
  +     -&gt; create table user_records (       <br>
  +     -&gt;   User_id  char(32) primary key,  <br>
  +     -&gt;   Cpasswd  char(32),              <br>
  +     -&gt;   Xgroup   char(32)               <br>
  +     -&gt;   ) \g                            <br>
        query OK                             <br>
  -     -> \q                                <br>
  +     -&gt; \q                                <br>
        %                                    <br>
   </pre><br>
   
  
  
  
  1.10      +1 -1      apache-1.2/htdocs/manual/mod/mod_browser.html
  
  Index: mod_browser.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_browser.html,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- mod_browser.html	1997/06/04 16:14:18	1.9
  +++ mod_browser.html	1998/01/30 09:13:34	1.10
  @@ -13,7 +13,7 @@
    ALINK="#FF0000"
   >
   <!--#include virtual="header.html" -->
  -<H1 ALIGN="CENTER">Apache module mod_browser</h1>
  +<H1 ALIGN="CENTER">Module mod_browser</H1>
   
   This module is contained in the <code>mod_browser.c</code> file, and
   is compiled in by default with Apache 1.2 and above. It provides for
  
  
  
  1.7       +1 -1      apache-1.2/htdocs/manual/mod/mod_cern_meta.html
  
  Index: mod_cern_meta.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_cern_meta.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- mod_cern_meta.html	1997/06/04 16:14:18	1.6
  +++ mod_cern_meta.html	1998/01/30 09:13:34	1.7
  @@ -13,7 +13,7 @@
    ALINK="#FF0000"
   >
   <!--#include virtual="header.html" -->
  -<H1 ALIGN="CENTER">Apache module mod_cern_meta</h1>
  +<H1 ALIGN="CENTER">Module mod_cern_meta</H1>
   
   This module is contained in the <code>mod_cern_meta.c</code> file, and
   is not compiled in by default. It provides for CERN httpd metafile
  
  
  
  1.7       +1 -1      apache-1.2/htdocs/manual/mod/mod_env.html
  
  Index: mod_env.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_env.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- mod_env.html	1997/06/04 16:14:20	1.6
  +++ mod_env.html	1998/01/30 09:13:34	1.7
  @@ -13,7 +13,7 @@
    ALINK="#FF0000"
   >
   <!--#include virtual="header.html" -->
  -<H1 ALIGN="CENTER">Apache module mod_env</h1>
  +<H1 ALIGN="CENTER">Module mod_env</H1>
   
   This module is contained in the <code>mod_env.c</code> file, and
   is not compiled in by default. It provides for
  
  
  
  1.5       +1 -1      apache-1.2/htdocs/manual/mod/mod_headers.html
  
  Index: mod_headers.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_headers.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- mod_headers.html	1997/06/04 16:14:20	1.4
  +++ mod_headers.html	1998/01/30 09:13:35	1.5
  @@ -13,7 +13,7 @@
    ALINK="#FF0000"
   >
   <!--#include virtual="header.html" -->
  -<h1 ALIGN="CENTER">Headers Module</h1>
  +<h1 ALIGN="CENTER">Module mod_headers</h1>
   
   The optional headers module allows for the customization of HTTP
   response headers. Headers can be merged, replaced or removed. The
  
  
  
  1.14      +6 -6      apache-1.2/htdocs/manual/mod/mod_include.html
  
  Index: mod_include.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_include.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- mod_include.html	1997/06/04 16:14:21	1.13
  +++ mod_include.html	1998/01/30 09:13:35	1.14
  @@ -309,15 +309,15 @@
       Unix egrep command.
   
   <DT>( <I>test_condition</I> )
  -	<DD>true if <I>test_condition</I> is true 
  +        <DD>true if <I>test_condition</I> is true 
   <DT>! <I>test_condition</I>
  -	<DD>true if <I>test_condition</I> is false
  +        <DD>true if <I>test_condition</I> is false
   <DT><I>test_condition1</I> && <I>test_condition2</I>
  -	<DD>true if both <I>test_condition1</I> and
  -	<I>test_condition2</I> are true 
  +        <DD>true if both <I>test_condition1</I> and
  +        <I>test_condition2</I> are true 
   <DT><I>test_condition1</I> || <I>test_condition2</I>
  -	<DD>true if either <I>test_condition1</I> or
  -	<I>test_condition2</I> is true 
  +        <DD>true if either <I>test_condition1</I> or
  +        <I>test_condition2</I> is true 
   </DL>
   
   <P> "<I>=</I>" and "<I>!=</I>" bind more tightly than "<I>&&</I>" and
  
  
  
  1.12      +41 -19    apache-1.2/htdocs/manual/mod/mod_mime.html
  
  Index: mod_mime.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_mime.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- mod_mime.html	1997/06/04 16:14:22	1.11
  +++ mod_mime.html	1998/01/30 09:13:36	1.12
  @@ -20,22 +20,44 @@
   from the filename.
   
   <h2>Summary</h2>
  -This module is used to determine the mime types of documents. Some mime
  -types indicate special processing to be performed by the server, otherwise
  -the type is returned to the client so that the browser can deal with
  -the document appropriately.<p>
  -
  -The filename of a document is treated as being composed of a basename followed
  -by some extensions, in the following order:
  -<blockquote><em>base.type.language.enc</em></blockquote>
  -The <em>type</em> extension sets the type of the document; types are defined
  -in the <A HREF="#typesconfig">TypesConfig</A> file and by the
  -<A HREF="#addtype">AddType</A> directive. The <em>language</em> extension
  -sets the language of the document, as defined by the
  -<A HREF="#addlanguage">AddLanguage</A> directive. Finally, the
  -<em>enc</em> directive sets the encoding of the document, as defined by
  -the <A HREF="#addencoding">AddEncoding</A> directive.
   
  +This module is used to determine various bits of "meta information"
  +about documents. This information relates to the content of the
  +document and is returned to the browser or used in content-negotiation
  +within the server. In addition, a "handler" can be set for a document,
  +which determines how the document will be processed within the server.
  +
  +<P>
  +
  +The directives <A HREF="#addencoding">AddEncoding</A>, <A
  +HREF="#addhandler">AddHandler</A>, <A
  +HREF="#addlanguage">AddLanguage</A> and <A HREF="#addtype">AddType</A>
  +are all used to map file extensions onto the meta-information for that
  +file.  Respectively they set the content-encoding, handler,
  +content-language and mime-type (content-type) of documents.  The
  +directive <A HREF="#typesconfig">TypesConfig</A> is used to specify a
  +file which also maps extensions onto mime types. The directives <A
  +HREF="#forcetype">ForceType</A> and <A
  +HREF="#sethandler">SetHandler</A> are used to associated all the files
  +in a given location (e.g. a particular directory) onto a particular
  +mime type or handler.
  +
  +<P>
  +
  +Files can have more than one extension, and the order of the
  +extensions is normally irrelevant. For example, if the file
  +<CODE>welcome.html.fr</CODE> maps onto content type text/html and
  +language French then the file <CODE>welcome.fr.html</CODE> will map
  +onto exactly the same information. The only exception to this is if an
  +extension is given which Apache does not know how to handle. In this
  +case it will "forget" about any information it obtained from
  +extensions to the left of the unknown extension. So, for example, if
  +the extensions fr and html are mapped to the appropriate language and
  +type but extension xxx is not assigned to anything, then the file
  +<CODE>welcome.fr.xxx.html</CODE> will be associated with content-type
  +text/html but <i>no</i> language.
  +
  +<P>
   
   <h2> Directives</h2>
   <ul>
  @@ -72,14 +94,14 @@
   
   <h2><a name="addhandler">AddHandler</a></h2>
   
  -<strong>Syntax:</strong> &lt;AddHandler <em>handler-name extension</em>&gt;<br>
  +<strong>Syntax:</strong> AddHandler <em>handler-name extension extension...</em><br>
   <strong>Context:</strong> server config, virtual host, directory, .htaccess<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_mime<br>
   <strong>Compatibility:</strong> AddHandler is only available in Apache
   1.1 and later<p>
   
  -<p>AddHandler maps the filename extension <em>extension</em> to the
  +<p>AddHandler maps the filename extensions <em>extension</em> to the
   <a href="../handler.html">handler</a>
   <em>handler-name</em>. For example, to activate CGI scripts
   with the file extension "<code>.cgi</code>", you might use:
  @@ -138,7 +160,7 @@
   
   <h2><a name="forcetype">ForceType</a></h2>
   
  -<strong>Syntax:</strong> &lt;ForceType <em>media type</em>&gt;<br>
  +<strong>Syntax:</strong> ForceType <em>media type</em><br>
   <strong>Context:</strong> directory, .htaccess<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_mime<br>
  @@ -159,7 +181,7 @@
   
   <h2><a name="sethandler">SetHandler</a></h2>
   
  -<strong>Syntax:</strong> &lt;SetHandler <em>handler-name</em>&gt;<br>
  +<strong>Syntax:</strong> SetHandler <em>handler-name</em><br>
   <strong>Context:</strong> directory, .htaccess<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_mime<br>
  
  
  
  1.23      +18 -18    apache-1.2/htdocs/manual/mod/mod_proxy.html
  
  Index: mod_proxy.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_proxy.html,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- mod_proxy.html	1997/06/04 16:14:23	1.22
  +++ mod_proxy.html	1998/01/30 09:13:36	1.23
  @@ -13,7 +13,7 @@
    ALINK="#FF0000"
   >
   <!--#include virtual="header.html" -->
  -<H1 ALIGN="CENTER">Apache module mod_proxy</h1>
  +<H1 ALIGN="CENTER">Module mod_proxy</H1>
   
   This module is contained in the <code>mod_proxy.c</code> file for Apache 1.1.x,
   or the <code>modules/proxy</code> subdirectory for Apache 1.2, and
  @@ -28,7 +28,7 @@
   <h2>Summary</h2>
   
   This module implements a proxy/cache for Apache. It implements
  -proxying capability for 
  +proxying capability for
   <code>FTP</code>,
   <code>CONNECT</code> (for SSL),
   <code>HTTP/0.9</code>, and
  @@ -58,7 +58,7 @@
   <A name="proxyrequests"><h2>ProxyRequests</h2></A>
   <strong>Syntax:</strong> ProxyRequests <em>on/off</em><br>
   <strong>Default:</strong> <code>ProxyRequests Off</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> ProxyRequest is only available in
  @@ -70,7 +70,7 @@
   
   <A name="proxyremote"><h2>ProxyRemote</h2></A>
   <strong>Syntax:</strong> ProxyRemote <em>&lt;match&gt; &lt;remote-server&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> ProxyRemote is only available in
  @@ -102,7 +102,7 @@
   
   <A name="proxypass"><h2>ProxyPass</h2></A>
   <strong>Syntax:</strong> ProxyPass <em>&lt;path&gt; &lt;url&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> ProxyPass is only available in
  @@ -122,7 +122,7 @@
   
   <A name="proxyblock"><h2>ProxyBlock</h2></A>
   <strong>Syntax:</strong> ProxyBlock <em>&lt;word/host/domain list&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> ProxyBlock is only available in
  @@ -152,7 +152,7 @@
   
   <A name="cacheroot"><h2>CacheRoot</h2></A>
   <strong>Syntax:</strong> CacheRoot <em>&lt;directory&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheRoot is only available in
  @@ -165,7 +165,7 @@
   <A name="cachesize"><h2>CacheSize</h2></A>
   <strong>Syntax:</strong> CacheSize <em>&lt;size&gt;</em><br>
   <strong>Default:</strong> <code>CacheSize 5</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheSize is only available in
  @@ -177,7 +177,7 @@
   
   <A name="cachegcinterval"><h2>CacheGcInterval</h2></A>
   <strong>Syntax:</strong> CacheGcInterval <em>&lt;time&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheGcinterval is only available in
  @@ -189,7 +189,7 @@
   <A name="cachemaxexpire"><h2>CacheMaxExpire</h2></A>
   <strong>Syntax:</strong> CacheMaxExpire <em>&lt;time&gt;</em><br>
   <strong>Default:</strong> <code>CacheMaxExpire 24</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheMaxExpire is only available in
  @@ -203,7 +203,7 @@
   <A name="cachelastmodifiedfactor"><h2>CacheLastModifiedFactor</h2></A>
   <strong>Syntax:</strong> CacheLastModifiedFactor <em>&lt;factor&gt;</em><br>
   <strong>Default:</strong> <code>CacheLastModifiedFactor 0.1</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheLastModifiedFactor is only available in
  @@ -223,7 +223,7 @@
   <A name="cachedirlevels"><h2>CacheDirLevels</h2></A>
   <strong>Syntax:</strong> CacheDirLevels <em>&lt;levels&gt;</em><br>
   <strong>Default:</strong> <code>CacheDirLevels 3</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheDirLevels is only available in
  @@ -235,7 +235,7 @@
   <A name="cachedirlength"><h2>CacheDirLength</h2></A>
   <strong>Syntax:</strong> CacheDirLength <em>&lt;length&gt;</em><br>
   <strong>Default:</strong> <code>CacheDirLength 1</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheDirLength is only available in
  @@ -246,7 +246,7 @@
   <A name="cachedefaultexpire"><h2>CacheDefaultExpire</h2></A>
   <strong>Syntax:</strong> CacheDefaultExpire <em>&lt;time&gt;</em><br>
   <strong>Default:</strong> <code>CacheDefaultExpire 1</code><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> CacheDefaultExpire is only available in
  @@ -259,7 +259,7 @@
   
   <A name="nocache"><h2>NoCache</h2></A>
   <strong>Syntax:</strong> NoCache <em>&lt;word/host/domain list&gt;</em><br>
  -<strong>Context:</strong> server config<br>
  +<strong>Context:</strong> server config, virtual host<br>
   <strong>Status:</strong> Base<br>
   <strong>Module:</strong> mod_proxy<br>
   <strong>Compatibility:</strong> NoCache is only available in
  @@ -297,7 +297,7 @@
   <li><a href="#shortname">Using Netscape hostname shortcuts</a>
   <li><a href="#mimetypes">Why doesn't file type <i>xxx</i> download via FTP?</a>
   <li><a href="#startup">Why does Apache start more slowly when using the
  -	proxy module?</a>
  +        proxy module?</a>
   <li><a href="#socks">Can I use the Apache proxy module with my SOCKS proxy?</a>
   </ul>
   
  @@ -337,7 +337,7 @@
   </pre>
   
   <h2><a name="startup">Why does Apache start more slowly when using the
  -	proxy module?</a></h2>
  +        proxy module?</a></h2>
   
   If you're using the <code>ProxyBlock</code> or <code>NoCache</code>
   directives, hostnames' IP addresses are looked up and cached during
  @@ -347,7 +347,7 @@
   <h2><a name="socks">Can I use the Apache proxy module with my SOCKS proxy?</a></h2>
   
   Yes. Just build Apache with the rule <code>SOCKS4=yes</code> in your
  -<i>Configuration</i> file, and follow the instructions there. SOCKS5 
  +<i>Configuration</i> file, and follow the instructions there. SOCKS5
   capability can be added in a similar way (there's no <code>SOCKS5</code>
   rule yet), so use the <code>EXTRA_LFLAGS</code> definition, or build Apache
   normally and run it with the <i>runsocks</i> wrapper provided with SOCKS5,
  
  
  
  1.10      +129 -72   apache-1.2/htdocs/manual/mod/mod_rewrite.html
  
  Index: mod_rewrite.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_rewrite.html,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- mod_rewrite.html	1997/06/04 16:14:23	1.9
  +++ mod_rewrite.html	1998/01/30 09:13:37	1.10
  @@ -17,7 +17,7 @@
   >
   <!--#include virtual="header.html" -->
   
  -<h1 ALIGN="CENTER">Module mod_rewrite (Version 3.0)</h1>
  +<h1 ALIGN="CENTER">Module mod_rewrite</h1>
   
   This module is contained in the <code>mod_rewrite.c</code> file, with Apache
   1.2 and later.  It provides a rule-based rewriting engine to rewrite requested
  @@ -31,7 +31,7 @@
   <h2>Summary</h2>
   
   This module uses a rule-based rewriting engine (based on a
  -regular-expression parser) to rewrite requested URLs on the fly. 
  +regular-expression parser) to rewrite requested URLs on the fly.
   
   <p>
   It supports an unlimited number of additional rule conditions (which can
  @@ -41,25 +41,19 @@
   substitution.
   
   <p>
  -It operates on the full URLs (including the PATH_INFO part) both in
  -per-server context (httpd.conf) and per-dir context (.htaccess) and even
  -can generate QUERY_STRING parts on result.   The rewritten result can lead to internal sub-processing, external request redirection or to internal proxy throughput.
  -</b>
  +It operates on the full URLs (including the PATH_INFO part) both in per-server
  +context (httpd.conf) and per-dir context (.htaccess) and even can generate
  +QUERY_STRING parts on result.   The rewritten result can lead to internal
  +sub-processing, external request redirection or to internal proxy throughput.
   
   <p>
  -The latest version can be found on<br>
  -<a href="http://www.engelschall.com/sw/mod_rewrite/">
  -<code><b>http://www.engelschall.com/sw/mod_rewrite/</b></code></a>
  -
  -<p>
  -Copyright &copy; 1996,1997 <b>The Apache Group</b>, All rights reserved.<br>
  -Copyright &copy; 1996,1997 <i>Ralf S. Engelschall</i>, All rights reserved.
  +This module was originally written in April 1996 and 
  +gifted exclusively to the The Apache Group in July 1997 by
   <p>
  -Written for <b>The Apache Group</b> by
   <blockquote>
       <i>Ralf S. Engelschall</i><br>
       <a href="mailto:rse@engelschall.com"><tt>rse@engelschall.com</tt></a><br>
  -    <a href="http://www.engelschall.com/"><tt>www.engelschall.com</tt></a> 
  +    <a href="http://www.engelschall.com/"><tt>www.engelschall.com</tt></a>
   </blockquote>
   
   <!--%hypertext -->
  @@ -100,7 +94,7 @@
   The <tt>RewriteEngine</tt> directive enables or disables the
   runtime rewriting engine. If it is set to <code>off</code> this module does
   no runtime processing at all. It does not even update the <tt>SCRIPT_URx</tt>
  -environment variables. 
  +environment variables.
   
   <p>
   Use this directive to disable the module instead of commenting out
  @@ -127,7 +121,6 @@
       conditions and rules of the main server gets inherited. In per-directory
       context this means that conditions and rules of the parent directory's
       <tt>.htaccess</tt> configuration gets inherited.
  -<p>
   </ul>
   
   <p>
  @@ -144,10 +137,10 @@
   server logs any rewriting actions it performs. If the name does not begin
   with a slash ('<tt>/</tt>') then it is assumed to be relative to the
   <em>Server Root</em>.  The directive should occur only once per server
  -config. 
  +config.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   To disable the logging of rewriting actions it is not recommended
   to set <em>Filename</em>
  @@ -161,7 +154,7 @@
   </table>
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   SECURITY: See the <a
   href="../misc/security_tips.html">Apache Security
  @@ -198,7 +191,7 @@
   This disables all rewrite action logs.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   <b>Notice:</b> Using a high value for <i>Level</i> will slow down your Apache
   server dramatically! Use the rewriting logfile only for debugging or at least
  @@ -267,19 +260,19 @@
       string as in the following example:
   
   <p>
  -<table border=2 cellspacing=1 cellpadding=5 bgcolor="#d0d0d0">
  +<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0">
   <tr><td><pre>
   #
   #   map.real-to-user -- maps realnames to usernames
   #
   
  -Ralf.S.Engelschall    rse   # Bastard Operator From Hell 
  +Ralf.S.Engelschall    rse   # Bastard Operator From Hell
   Dr.Fred.Klabuster     fred  # Mr. DAU
   </pre></td></tr>
   </table>
   
   <p>
  -<table border=2 cellspacing=1 cellpadding=5 bgcolor="#d0d0d0">
  +<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0">
   <tr><td><pre>
   RewriteMap real-to-host txt:/path/to/file/map.real-to-user
   </pre></td></tr>
  @@ -289,7 +282,7 @@
   <li><b>DBM Hashfile Format</b>
       <p>
       This is a binary NDBM format file containing the
  -    same contents as the <em>Plain Text Format</b> files. You can create
  +    same contents as the <em>Plain Text Format</em> files. You can create
       such a file with any NDBM tool or with the <tt>dbmmanage</tt> program
       from the <tt>support</tt> directory of the Apache distribution.
       <p>
  @@ -313,12 +306,12 @@
       for the given key). A trivial program which will implement a 1:1 map
       (i.e. key == value) could be:
       <p>
  -<table border=2 cellspacing=1 cellpadding=5 bgcolor="#d0d0d0">
  +<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0">
   <tr><td><pre>
   #!/usr/bin/perl
   $| = 1;
   while (&lt;STDIN&gt;) {
  -    # ...here any transformations 
  +    # ...here any transformations
       # or lookups should occur...
       print $_;
   }
  @@ -343,10 +336,10 @@
   mapping-function use one <tt>RewriteMap</tt> directive to declare its
   rewriting mapfile. While you cannot <b>declare</b> a map in per-directory
   context it is of course possible to <b>use</b> this map in per-directory
  -context.  
  +context.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   For plain text and DBM format files the looked-up keys are cached in-core
   until the <tt>mtime</tt> of the mapfile changes or the server does a
  @@ -381,10 +374,10 @@
   prefix is the corresponding filepath itself. <b>But at most websites URLs are
   <b>NOT</b> directly related to physical filename paths, so this assumption
   will be usually be wrong!</b> There you have to use the <tt>RewriteBase</tt>
  -directive to specify the correct URL-prefix. 
  +directive to specify the correct URL-prefix.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   So, if your webserver's URLs are <b>not</b> directly
   related to physical file paths, you have to use <tt>RewriteBase</tt> in every
  @@ -400,7 +393,7 @@
      Assume the following per-directory config file:
   
   <p>
  -<table border=2 cellspacing=1 cellpadding=5 bgcolor="#d0d0d0">
  +<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0">
   <tr><td><pre>
   #
   #  /abc/def/.htaccess -- per-dir config file for directory /abc/def
  @@ -410,7 +403,7 @@
   
   RewriteEngine On
   
  -#  let the server know that we are reached via /xyz and not 
  +#  let the server know that we are reached via /xyz and not
   #  via the physical path prefix /abc/def
   RewriteBase   /xyz
   
  @@ -421,10 +414,10 @@
   
   <p>
   In the above example, a request to <tt>/xyz/oldstuff.html</tt> gets correctly
  -rewritten to the physical file <tt>/abc/def/newstuff.html</tt>. 
  +rewritten to the physical file <tt>/abc/def/newstuff.html</tt>.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   <font size=-1>
   <b>For the Apache hackers:</b><br>
  @@ -437,10 +430,10 @@
     /xyz/oldstuff.html
   
   Internal Processing:
  -  /xyz/oldstuff.html     -> /abc/def/oldstuff.html    (per-server Alias)
  -  /abc/def/oldstuff.html -> /abc/def/newstuff.html    (per-dir    RewriteRule)
  -  /abc/def/newstuff.html -> /xyz/newstuff.html        (per-dir    RewriteBase)
  -  /xyz/newstuff.html     -> /abc/def/newstuff.html    (per-server Alias)
  +  /xyz/oldstuff.html     -&gt; /abc/def/oldstuff.html    (per-server Alias)
  +  /abc/def/oldstuff.html -&gt; /abc/def/newstuff.html    (per-dir    RewriteRule)
  +  /abc/def/newstuff.html -&gt; /xyz/newstuff.html        (per-dir    RewriteBase)
  +  /xyz/newstuff.html     -&gt; /abc/def/newstuff.html    (per-server Alias)
   
   Result:
     /abc/def/newstuff.html
  @@ -451,7 +444,7 @@
   when it occurs the (rewritten) request has to be re-injected into the Apache
   kernel! BUT: While this seems like a serious overhead, it really isn't, because
   this re-injection happens fully internal to the Apache server and the same
  -procedure is used by many other operations inside Apache. So, you can be 
  +procedure is used by many other operations inside Apache. So, you can be
   sure the design and implementation is correct.
   </font>
   </td></tr>
  @@ -471,7 +464,7 @@
   <p>
   
   The <tt>RewriteCond</tt> directive defines a rule condition. Precede a
  -<tt>RewriteRule</tt> directive with one or more <t>RewriteCond</tt>
  +<tt>RewriteRule</tt> directive with one or more <tt>RewriteCond</tt>
   directives.
   
   The following rewriting rule is only used if its pattern matches the current
  @@ -481,14 +474,14 @@
   <em>TestString</em> is a string which contains server-variables of the form
   
   <blockquote><strong>
  -<tt>%{</tt> <em>NAME_OF_VARIABLE</em> <tt>}</tt> 
  +<tt>%{</tt> <em>NAME_OF_VARIABLE</em> <tt>}</tt>
   </strong></blockquote>
   
   where <em>NAME_OF_VARIABLE</em> can be a string
   of the following list:
   
   <p>
  -<table bgcolor="#d0d0d0" cellspacing=0 cellpadding=5>
  +<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5>
   <tr>
   <td valign=top>
   <b>HTTP headers:</b><p>
  @@ -544,6 +537,7 @@
   TIME_MIN<br>
   TIME_SEC<br>
   TIME_WDAY<br>
  +TIME<br>
   </font>
   </td>
   
  @@ -562,7 +556,7 @@
   
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   These variables all correspond to the similar named HTTP MIME-headers, C
   variables of the Apache server or <tt>struct tm</tt> fields of the Unix
  @@ -607,7 +601,7 @@
   <em>CondPattern</em> is the condition pattern, i.e. a regular expression
   which gets applied to the current instance of the <em>TestString</em>, i.e.
   <em>TestString</em> gets evaluated and then matched against
  -<em>CondPattern</em>. 
  +<em>CondPattern</em>.
   
   <p>
   <b>Remember:</b> <em>CondPattern</em> is a standard
  @@ -623,6 +617,22 @@
   regular expression strings you can also use one of the following:
   <p>
   <ul>
  +<li>'<b>&lt;CondPattern</b>' (is lexicographically lower)<br>
  +Treats the <i>CondPattern</i> as a plain string and compares it
  +lexicographically to <i>TestString</i> and results in a true expression if
  +<i>TestString</i> is lexicographically lower then <i>CondPattern</i>.
  +<p>
  +<li>'<b>&gt;CondPattern</b>' (is lexicographically greater)<br>
  +Treats the <i>CondPattern</i> as a plain string and compares it
  +lexicographically to <i>TestString</i> and results in a true expression if
  +<i>TestString</i> is lexicographically greater then <i>CondPattern</i>.
  +<p>
  +<li>'<b>=CondPattern</b>' (is lexicographically equal)<br>
  +Treats the <i>CondPattern</i> as a plain string and compares it
  +lexicographically to <i>TestString</i> and results in a true expression if
  +<i>TestString</i> is lexicographically equal to <i>CondPattern</i>, i.e the
  +two strings are exactly equal (character by character).
  +<p>
   <li>'<b>-d</b>' (is <b>d</b>irectory)<br>
   Treats the <i>TestString</i> as a pathname and
   tests if it exists and is a directory.
  @@ -679,11 +689,10 @@
   <blockquote><pre>
   RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
   RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
  -RewriteCond %{REMOTE_HOST}  ^host3.*  
  +RewriteCond %{REMOTE_HOST}  ^host3.*
   RewriteRule ...some special stuff for any of these hosts...
   </pre></blockquote>
       Without this flag you had to write down the cond/rule three times.
  -<p>
   </ul>
   
   <p>
  @@ -709,7 +718,6 @@
   get the min homepage, which contains no images, no tables, etc.  If you
   use any other browser you get the standard homepage.
   </blockquote>
  -<p>
   
   <p>
   <hr noshade size=1>
  @@ -739,21 +747,21 @@
   Some hints about the syntax of regular expressions:
   
   <p>
  -<table bgcolor="#d0d0d0" cellspacing=0 cellpadding=5>
  +<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5>
   <tr>
   <td valign=top>
   <pre>
   <strong><code>^</code></strong>           Start of line
   <strong><code>$</code></strong>           End of line
   <strong><code>.</code></strong>           Any single character
  -<strong><code>[</code></strong>chars<strong><code>]</code></strong>     One of chars 
  -<strong><code>[^</code></strong>chars<strong><code>]</code></strong>    None of chars 
  +<strong><code>[</code></strong>chars<strong><code>]</code></strong>     One of chars
  +<strong><code>[^</code></strong>chars<strong><code>]</code></strong>    None of chars
   
   <strong><code>?</code></strong>           0 or 1 of the preceding char
   <strong><code>*</code></strong>           0 or N of the preceding char
   <strong><code>+</code></strong>           1 or N of the preceding char
   
  -<strong><code>\</code></strong>char       escape that specific char 
  +<strong><code>\</code></strong>char       escape that specific char
               (e.g. for specifying the chars "<code>.[]()</code>" etc.)
   
   <strong><code>(</code></strong>string<strong><code>)</code></strong>    Grouping of chars (the <b>N</b>th group can be used on the RHS with <code>$</code><b>N</b>)
  @@ -770,7 +778,7 @@
   last default rule.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   <b>Notice!</b> When using the NOT character to negate a pattern you cannot
   have grouped wildcard parts in the pattern. This is impossible because when
  @@ -783,7 +791,7 @@
   <p>
   <a name="rhs"><em>Substitution</em></a> of a rewriting rule is the string
   which is substituted for (or replaces) the original URL for which
  -<em>Pattern</em> matched.  Beside plain text you can use 
  +<em>Pattern</em> matched.  Beside plain text you can use
   
   <ol>
   <li>pattern-group back-references (<code>$N</code>)
  @@ -814,7 +822,14 @@
   pattern to be applied before a substitution occurs.
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +One more note: You can even create URLs in the substitution string containing
  +a query string part. Just use a question mark inside the substitution string
  +to indicate that the following stuff should be re-injected into the
  +QUERY_STRING.  When you want to erase an existing query string, end the
  +substitution string with just the question mark.
  +
  +<p>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   <b>Notice</b>: There is a special feature. When you prefix a substitution
   field with <tt>http://</tt><em>thishost</em>[<em>:thisport</em>] then
  @@ -843,14 +858,14 @@
   
   <ul>
   <li>'<strong><code>redirect|R</code>[=<i>code</i>]</strong>' (force <a name="redirect"><b>r</b>edirect</a>)<br>
  -    Prefix <em>Substitution</em> 
  +    Prefix <em>Substitution</em>
       with <code>http://thishost[:thisport]/</code> (which makes the new URL a URI) to
       force a external redirection. If no <i>code</i> is given a HTTP response
       of 302 (MOVED TEMPORARILY) is used. If you want to use other response
       codes in the range 300-400 just specify them as a number or use
       one of the following symbolic names: <tt>temp</tt> (default), <tt>permanent</tt>,
       <tt>seeother</tt>.
  -    Use it for rules which should 
  +    Use it for rules which should
       canonicalize the URL and gives it back to the client, e.g. translate
       ``<code>/~</code>'' into ``<code>/u/</code>'' or always append a slash to
       <code>/u/</code><em>user</em>, etc.<br>
  @@ -903,7 +918,7 @@
       from the last rewriting rule.  This corresponds to the Perl
       <code>next</code> command or the <code>continue</code> command from the C
       language. Use this flag to restart the rewriting process, i.e.  to
  -    immediately go to the top of the loop. <br> 
  +    immediately go to the top of the loop. <br>
       <b>But be careful not to create a deadloop!</b>
   <p>
   <li>'<strong><code>chain|C</code></strong>' (<b>c</b>hained with next rule)<br>
  @@ -936,6 +951,13 @@
       chance is high that you will run into problems (or even overhead) on sub-requests.
       In these cases, use this flag.
   <p>
  +<li>'<strong><code>qsappend|QSA</code></strong>' (<b>q</b>uery <b>s</b>tring
  +    <b>a</b>ppend)<br> 
  +    This flag forces the rewriting engine to append a query
  +    string part in the substitution string to the existing one instead of
  +    replacing it.  Use this when you want to add more data to the query string
  +    via a rewrite rule.
  +<p>
   <li>'<strong><code>passthrough|PT</code></strong>' (<b>p</b>ass <b>t</b>hrough to next handler)<br>
       This flag forces the rewriting engine to set the <code>uri</code> field
       of the internal <code>request_rec</code> structure to the value
  @@ -949,7 +971,7 @@
       with <tt>mod_alias</tt>:
       <pre>
       RewriteRule ^/abc(.*)  /def$1 [PT]
  -    Alias       /def       /ghi   
  +    Alias       /def       /ghi
       </pre>
       If you omit the <tt>PT</tt> flag then <tt>mod_rewrite</tt>
       will do its job fine, i.e. it rewrites <tt>uri=/abc/...</tt> to
  @@ -962,7 +984,7 @@
       typical example is the use of <tt>mod_alias</tt> and
       <tt>mod_rewrite</tt>..
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   <font size=-1>
       <b>For the Apache hackers:</b><br>
  @@ -988,14 +1010,14 @@
       which will be expanded. You can use this flag more than once to set more
       than one variable. The variables can be later dereferenced at a lot of
       situations, but the usual location will be from within XSSI (via
  -	<tt>&lt;!--#echo var="VAR"--&gt;</tt>) or CGI (e.g. <tt>$ENV{'VAR'}</tt>).
  -	But additionally you can also dereference it in a following RewriteCond
  -	pattern via <tt>%{ENV:VAR}</tt>. Use this to strip but remember
  -	information from URLs. 
  +        <tt>&lt;!--#echo var="VAR"--&gt;</tt>) or CGI (e.g. <tt>$ENV{'VAR'}</tt>).
  +        But additionally you can also dereference it in a following RewriteCond
  +        pattern via <tt>%{ENV:VAR}</tt>. Use this to strip but remember
  +        information from URLs.
   </ul>
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   Remember: Never forget that <em>Pattern</em> gets applied to a complete URL
   in per-server configuration files. <b>But in per-directory configuration
  @@ -1012,7 +1034,7 @@
   </table>
   
   <p>
  -<table width=70% border=2 bgcolor="#c0c0e0" cellspacing=0 cellpadding=10>
  +<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10>
   <tr><td>
   Notice!  To enable the rewriting engine for per-directory configuration files
   you need to set ``<tt>RewriteEngine On</tt>'' in these files <b>and</b>
  @@ -1031,7 +1053,7 @@
   for request ``<tt>GET /somepath/pathinfo</tt>'':</b><br>
   
   <p>
  -<table bgcolor="#d0d0d0" cellspacing=0 cellpadding=5>
  +<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5>
   <tr>
   <td>
   <pre>
  @@ -1078,7 +1100,7 @@
   request ``<tt>GET /somepath/localpath/pathinfo</tt>'':</b><br>
   
   <p>
  -<table bgcolor="#d0d0d0" cellspacing=0 cellpadding=5>
  +<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5>
   <tr>
   <td>
   <pre>
  @@ -1120,10 +1142,6 @@
   </table>
   
   
  -</td>
  -</tr>
  -</table>
  -
   <p>
   <b>Example:</b>
   <p>
  @@ -1152,6 +1170,45 @@
   RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1
   </pre>
   </blockquote>
  +</blockquote>
  +
  +
  +<!--%hypertext -->
  +<hr>
  +<!--/%hypertext -->
  +
  +<center>
  +<a name="Additional">
  +<h1>Additional Features</h1>
  +</a>
  +</center>
  +
  +<a name="EnvVar">
  +<h2>Environment Variables</h2>
  +</a>
  +
  +This module keeps track of two additional (non-standard) CGI/SSI environment
  +variables named <tt>SCRIPT_URL</tt> and <tt>SCRIPT_URI</tt>. These contain
  +the <em>logical</em> Web-view to the current resource, while the standard CGI/SSI
  +variables <tt>SCRIPT_NAME</tt> and <tt>SCRIPT_FILENAME</tt> contain the
  +<em>physical</em> System-view. 
  +
  +<p>
  +Notice: These variables hold the URI/URL <em>as they were initially
  +requested</em>, i.e. in a state <em>before</em> any rewriting. This is
  +important because the rewriting process is primarily used to rewrite logical
  +URLs to physical pathnames.
  +
  +<p>
  +<b>Example:</b>
  +
  +<blockquote>
  +<pre>
  +SCRIPT_NAME=/v/sw/free/lib/apache/global/u/rse/.www/index.html
  +SCRIPT_FILENAME=/u/rse/.www/index.html
  +SCRIPT_URL=/u/rse/
  +SCRIPT_URI=http://en2.en.sdm.de/u/rse/
  +</pre>
   </blockquote>
   
   
  
  
  
  1.7       +1 -1      apache-1.2/htdocs/manual/mod/mod_status.html
  
  Index: mod_status.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_status.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- mod_status.html	1997/06/04 16:14:24	1.6
  +++ mod_status.html	1998/01/30 09:13:38	1.7
  @@ -90,7 +90,7 @@
   Do this by adding the following to the AUX_CFLAGS line in the
   "Configuration" file and then recompiling as usual.
   <pre>
  -	AUX_CFLAGS= (something) -DSTATUS
  +        AUX_CFLAGS= (something) -DSTATUS
   </pre>
   
   <BLOCKQUOTE>
  
  
  
  1.8       +6 -6      apache-1.2/htdocs/manual/mod/mod_userdir.html
  
  Index: mod_userdir.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/htdocs/manual/mod/mod_userdir.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- mod_userdir.html	1997/06/04 16:14:24	1.7
  +++ mod_userdir.html	1998/01/30 09:13:38	1.8
  @@ -42,15 +42,15 @@
   patterns. If not disabled, then a request for
   <code>http://www.foo.com/~bob/one/two.html</code> will be translated to:
   <pre>
  -UserDir public_html     -> ~bob/public_html/one/two.html
  -UserDir /usr/web        -> /usr/web/bob/one/two.html
  -UserDir /home/*/www     -> /home/bob/www/one/two.html
  +UserDir public_html     -&gt; ~bob/public_html/one/two.html
  +UserDir /usr/web        -&gt; /usr/web/bob/one/two.html
  +UserDir /home/*/www     -&gt; /home/bob/www/one/two.html
   </pre>
   The following directives will send redirects to the client:
   <pre>
  -UserDir http://www.foo.com/users   -> http//www.foo.com/users/bob/one/two.html
  -UserDir http://www.foo.com/*/usr   -> http://www.foo.com/bob/usr/one/two.html
  -UserDir http://www.foo.com/~*/     -> http://www.foo.com/~bob/one/two.html
  +UserDir http://www.foo.com/users   -&gt; http//www.foo.com/users/bob/one/two.html
  +UserDir http://www.foo.com/*/usr   -&gt; http://www.foo.com/bob/usr/one/two.html
  +UserDir http://www.foo.com/~*/     -&gt; http://www.foo.com/~bob/one/two.html
   </pre>
   
   <P>
  
  
  
  1.287     +341 -3    apache-1.2/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/CHANGES,v
  retrieving revision 1.286
  retrieving revision 1.287
  diff -u -r1.286 -r1.287
  --- CHANGES	1997/06/05 09:32:46	1.286
  +++ CHANGES	1998/01/30 09:13:43	1.287
  @@ -1,3 +1,341 @@
  +Changes with Apache 1.2.6
  +
  +  *) SIGURG doesn't exist on all platforms.
  +     [Mark Andrew Heinrich <he...@tinderbox.Stanford.EDU>]
  +
  +  *) When an error occurs during a POST, or other operation with a
  +     request body, the body has to be read from the net before allowing
  +     a keepalive session to continue.  [Roy Fielding] PR#1399
  +
  +  *) When an error occurs in fcntl() locking suggest the user look up
  +     the docs for LockFile.  [Dean Gaudet]
  +
  +  *) table_set() and table_unset() did not deal correctly with
  +     multiple occurrences of the same key. [Stephen Scheck
  +     <ss...@infonex.net>, Ben Laurie] PR#1604
  +  
  +  *) send_fd_length() did not calculate total_bytes_sent properly in error
  +     cases.  [Ben Reser <br...@regnow.com>] PR#1366
  +
  +  *) r->connection->user was allocated in the wrong pool causing corruption
  +     in some cases when used with mod_cern_meta.  [Dean Gaudet] PR#1500
  +
  +  *) mod_proxy was sending HTTP/1.1 responses to ftp requests by mistake.
  +     Also removed the auto-generated link to www.apache.org that was the
  +     source of so many misdirected bug reports.  [Roy Fielding, Marc Slemko]
  +
  +  *) Multiple "close" tokens may have been set in the "Connection"
  +     header, not an error, but a waste.
  +     [Ronald.Tschalaer@psi.ch] PR#1683
  +
  +  *) "basic" and "digest" auth tokens should be tested case-insensitive.
  +     [Ronald.Tschalaer@psi.ch] PR#1599, PR#1666
  +
  +  *) It appears the "257th byte" bug (see
  +     htdocs/manual/misc/known_client_problems.html#257th-byte) can happen
  +     at the 256th byte as well.  Fixed.  [Dean Gaudet]
  +
  +  *) mod_rewrite would not handle %3f properly in some situations.
  +     [Ralf Engelschall]
  +
  +  *) Apache could generate improperly chunked HTTP/1.1 responses when
  +     the bputc() or rputc() functions were used by modules (such as
  +     mod_include).  [Dean Gaudet]
  +
  +  *) #ifdef wrap a few #defines in httpd.h to make life easier on
  +     some ports.  [Ralf Engelschall]
  +
  +  *) Fix MPE compilation error in mod_usertrack.c.  [Mark Bixby]
  +
  +  *) Quote CC='$(CC)' to improve recurse make calls.  [Martin Kraemer]
  +
  +  *) Avoid B_ERROR redeclaration on sysvr4 systems.  [Martin Kraemer]
  +
  +Changes with Apache 1.2.5
  +
  +  *) SECURITY: Fix a possible buffer overflow in logresolve.  This is
  +     only an issue on systems without a MAXDNAME define or where 
  +     the resolver returns domain names longer than MAXDNAME.  [Marc Slemko]
  +
  +  *) Fix an improper length in an ap_snprintf call in proxy_date_canon().
  +     [Marc Slemko]
  +
  +  *) Fix core dump in the ftp proxy when reading incorrectly formatted
  +     directory listings.  [Marc Slemko]
  +
  +  *) SECURITY: Fix possible minor buffer overflow in the proxy cache.
  +     [Marc Slemko]
  +
  +  *) SECURITY: Eliminate possible buffer overflow in cfg_getline, which
  +     is used to read various types of files such as htaccess and 
  +     htpasswd files.  [Marc Slemko]
  +
  +  *) SECURITY: Ensure that the buffer returned by ht_time is always
  +     properly null terminated.  [Marc Slemko]
  +
  +  *) SECURITY: General mod_include cleanup, including fixing several
  +     possible buffer overflows and a possible infinite loop.  This cleanup
  +     was done against 1.3 code and then backported to 1.2, the result
  +     is a large difference (due to indentation cleanup in 1.3 code).
  +     Users interested in seeing a smaller set of relevant differences
  +     should consider comparing against src/modules/standard/mod_include.c
  +     from the 1.3b3 release.  Non-indentation changes to mod_include
  +     between 1.2 and 1.3 were minimal.  [Dean Gaudet, Marc Slemko]
  +
  +  *) SECURITY: Numerous changes to mod_imap in a general cleanup
  +     including fixing a possible buffer overflow.  This cleanup also
  +     was done with 1.3 code as a basis, see the the previous note
  +     about mod_include.  [Dean Gaudet]
  +
  +  *) SECURITY: If a htaccess file can not be read due to bad 
  +     permissions, deny access to the directory with a HTTP_FORBIDDEN.  
  +     The previous behavior was to ignore the htaccess file if it could not
  +     be read.  This change may make some setups with unreadable
  +     htaccess files stop working.  PR#817  [Marc Slemko]
  +
  +  *) SECURITY: no2slash() was O(n^2) in the length of the input.  
  +     Make it O(n).  This inefficiency could be used to mount a denial 
  +     of service attack against the Apache server.  Thanks to 
  +     Michal Zalewski <lc...@boss.staszic.waw.pl> for reporting
  +     this.  [Dean Gaudet]
  +
  +  *) mod_include used uninitialized data for some uses of && and ||.
  +     [Brian Slesinsky <bs...@wired.com>] PR#1139
  +
  +  *) mod_imap should decline all non-GET methods.
  +     [Jay Bloodworth <ja...@pathways.sde.state.sc.us>]
  +
  +  *) suexec.c wouldn't build without -DLOG_EXEC. [Jason A. Dour]
  +
  +  *) mod_userdir was modifying r->finfo in cases where it wasn't setting
  +     r->filename.  Since those two are meant to be in sync with each other
  +     this is a bug.  ["Paul B. Henson" <he...@intranet.csupomona.edu>]
  +
  +  *) mod_include did not properly handle all possible redirects from sub-
  +     requests.  [Ken Coar]
  +
  +  *) Inetd mode (which is buggy) uses timeouts without having setup the
  +     jmpbuffer. [Dean Gaudet] PR#1064
  +
  +  *) Work around problem under Linux where a child will start looping
  +     reporting a select error over and over.
  +     [Rick Franchuk <ri...@transpect.net>] PR#1107
  +
  +Changes with Apache 1.2.4
  +
  +  *) The ProxyRemote change in 1.2.3 introduced a bug resulting in the proxy
  +     always making requests with the full-URI instead of just the URI path.
  +     [Marc Slemko, Roy Fielding]
  +
  +  *) Add -lm for AIX versions >= 4.2 to allow Apache to link properly
  +     on this platform.  [Marc Slemko]
  +
  +Changes with Apache 1.2.3
  +
  +  *) The request to a remote proxy was mangled if it was generated as the
  +     result of a ProxyPass directive. URL schemes other than http:// were not
  +     supported when ProxyRemote was used. PR#260, PR#656, PR#699, PR#713,
  +     PR#812 [Lars Eilebrecht]
  +
  +  *) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
  +     information for case where proxy module is not available. [Marc Slemko]
  +
  +  *) Force proxy to always respond as HTTP/1.0, which it was failing to
  +     do for errors and cached responses.  [Roy Fielding]
  +
  +  *) PORT: Improved support for ConvexOS 11.  [Jeff Venters]
  +
  +Changes with Apache 1.2.2 [not released]
  +
  +  *) Fixed another long-standing bug in sub_req_lookup_file where it would
  +     happily skip past access checks on subdirectories looked up with relative
  +     paths.  (It's used by mod_dir, mod_negotiation, and mod_include.)
  +     [Dean Gaudet]
  +
  +  *) Add lockfile name to error message printed out when
  +     USE_FLOCK_SERIALIZED_ACCEPT is defined.
  +     [Marc Slemko]
  +
  +  *) Enhanced the chunking and error handling inside the buffer functions.
  +     [Dean Gaudet, Roy Fielding]
  +
  +  *) When merging the main server's <Directory> and <Location> sections into
  +     a vhost, put the main server's first and the vhost's second.  Otherwise
  +     the vhost can't override the main server.  [Dean Gaudet] PR#717
  +
  +  *) The <Directory> code would merge and re-merge the same section after
  +     a match was found, possibly causing problems with some modules.
  +     [Dean Gaudet]
  +
  +  *) Fixed an infinite loop in mod_imap for references above the server root.
  +     [Dean Gaudet] PR#748
  +
  +  *) mod_include cleanup showed that handle_else was being used to handle
  +     endif.  It didn't cause problems, but it was cleaned up too.
  +     [Howard Fear]
  +
  +  *) Last official synchonisation of mod_rewrite with author version (because
  +     mod_rewrite is now directly developed by the author at the Apache Group):
  +     o added diff between mod_rewrite 3.0.6+ and 3.0.9
  +       minus WIN32/NT stuff, but plus copyright removement.
  +       In detail:
  +       - workaround for detecting infinite rewriting loops
  +       - fixed setting of env vars when "-" is used as subst string
  +       - fixed forced response code on redirects (PR#777)
  +       - fixed cases where r->args is ""
  +       - kludge to disable locking on pipes under braindead SunOS
  +       - fix for rewritelog in cases where remote hostname is unknown
  +       - fixed totally damaged request_rec walk-back loop
  +     o remove static from local data and add static to global ones.
  +     o replaced ugly proxy finding stuff by simple
  +       find_linked_module("mod_proxy") call.
  +     o added missing negation char on rewritelog()
  +     o fixed a few comment typos
  +     [Ralf S. Engelschall]
  +
  +  *) Anonymous_LogEmail was logging on each subrequest.
  +     [Dean Gaudet] PR#421, PR#868
  +
  +  *) "force-response-1.0" now only applies to requests which are HTTP/1.0 to
  +     begin with.  "nokeepalive" now works for HTTP/1.1 clients.  Added
  +     "downgrade-1.0" which causes Apache to pretend it received a 1.0.
  +     Additionally mod_browser now triggers during translate_name to workaround
  +     a deficiency in the header_parse phase.
  +     [Dean Gaudet] PR#875
  +
  +  *) get_client_block() returns wrong length if policy is 
  +     REQUEST_CHUNKED_DECHUNK.
  +     [Kenichi Hori <ke...@d2.bs1.fc.nec.co.jp>] PR#815
  +
  +  *) Properly treat <files> container like other containers in mod_info.
  +     [Marc Slemko] PR#848
  +
  +  *) The proxy didn't treat the "Host:" keyword of the host header as case-
  +     insensitive.  The proxy would corrupt the first line of a response from
  +     an HTTP/0.9 server.  [Kenichi Hori <ke...@d2.bs1.fc.nec.co.jp>] PR#813,814
  +
  +  *) mod_include would log some bogus values occasionally.
  +     [Skip Montanaro <sk...@calendar.com>, Marc Slemko] PR#797
  +
  +  *) PORT: The slack fd changes in 1.2.1 introduced a problem with SIGHUP
  +     under Solaris 2.x (up through 2.5.1).  It has been fixed.
  +     [Dean Gaudet] PR#832
  +
  +  *) API: In HTTP/1.1, whether or not a request message contains a body
  +     is independent of the request method and based solely on the presence
  +     of a Content-Length or Transfer-Encoding.  Therefore, our default
  +     handlers need to be prepared to read a body even if they don't know
  +     what to do with it; otherwise, the body would be mistaken for the
  +     next request on a persistent connection.  discard_request_body()
  +     has been added to take care of that.  [Roy Fielding] PR#378
  +
  +  *) API: Symbol APACHE_RELEASE provides a numeric form of the Apache
  +     release version number, such that it always increases along the
  +     same lines as our source code branching.  [Roy Fielding]
  +
  +  *) Minor oversight on multiple variants fixed.  [Paul Sutton] PR#94
  +
  +Changes with Apache 1.2.1
  +
  +  *) SECURITY: Don't serve file system objects unless they are plain files,
  +     symlinks, or directories.  This prevents local users from using pipes
  +     or named sockets to invoke programs for an extremely crude form of
  +     CGI.  [Dean Gaudet]
  +
  +  *) SECURITY: HeaderName and ReadmeName were settable in .htaccess and
  +     could contain "../" allowing a local user to "publish" any file on
  +     the system.  No slashes are allowed now.  [Dean Gaudet]
  +
  +  *) SECURITY: It was possible to violate the symlink Options using mod_dir
  +     (headers, readmes, titles), mod_negotiation (type maps), or
  +     mod_cern_meta (meta files).  [Dean Gaudet]
  +
  +  *) SECURITY: Apache will refuse to run as "User root" unless
  +     BIG_SECURITY_HOLE is defined at compile time.  [Dean Gaudet]
  +
  +  *) CONFIG: If a symlink pointed to a directory then it would be disallowed
  +     if it contained a .htaccess disallowing symlinks.  This is contrary
  +     to the rule that symlink permissions are tested with the symlink
  +     options of the parent directory.  [Dean Gaudet] PR#353
  +
  +  *) CONFIG: The LockFile directive can be used to place the serializing
  +     lockfile in any location.  It previously defaulted to /usr/tmp/htlock.
  +     [Somehow it took four of us: Randy Terbush, Jim Jagielski, Dean Gaudet,
  +     Marc Slemko]
  +
  +  *) Request processing now retains state of whether or not the request
  +     body has been read, so that internal redirects and subrequests will
  +     not try to read it twice (and block). [Roy Fielding]
  +
  +  *) Add a placeholder in modules/Makefile to avoid errors with certain
  +     makes. [Marc Slemko]
  +
  +  *) QUERY_STRING was unescaped in mod_include, it shouldn't be.
  +     [Dean Gaudet] PR#644
  +
  +  *) mod_include was not properly changing the current directory.
  +     [Marc Slemko] PR#742
  +
  +  *) Attempt to work around problems with third party libraries that do not
  +     handle high numbered descriptors (examples include bind, and
  +     solaris libc).  On all systems apache attempts to keep all permanent
  +     descriptors above 15 (called the low slack line).  Solaris users
  +     can also benefit from adding -DHIGH_SLACK_LINE=256 to EXTRA_CFLAGS
  +     which keeps all non-FILE * descriptors above 255.  On all systems
  +     this should make supporting large numbers of vhosts with many open
  +     log files more feasible.  If this causes trouble please report it,
  +     you can disable this workaround by adding -DNO_SLACK to EXTRA_CFLAGS.
  +     [Dean Gaudet] various PRs
  +
  +  *) Related to the last entry, network sockets are now opened before
  +     log files are opened.  The only known case where this can cause
  +     problems is under Solaris with many virtualhosts and many Listen
  +     directives.  But using -DHIGH_SLACK_LINE=256 described above will
  +     work around this problem.  [Dean Gaudet]
  +
  +  *) USE_FLOCK_SERIALIZED_ACCEPT is now default for FreeBSD, A/UX, and
  +     SunOS 4.
  +
  +  *) Improved unix error response logging.  [Marc Slemko]
  +
  +  *) Update mod_rewrite from 3.0.5 to 3.0.6.  New ruleflag
  +     QSA=query_string_append.  Also fixed a nasty bug in per-dir context:
  +     when a URL http://... was used in concunction with a special
  +     redirect flag, e.g. R=permanent, the permanent status was lost.
  +     [Ronald Tschalaer <Ro...@psi.ch>, Ralf S. Engelschall]
  +
  +  *) If an object has multiple variants that are otherwise equal Apache
  +     would prefer the last listed variant rather than the first.
  +     [Paul Sutton] PR#94
  +
  +  *) "make clean" at the top level now removes *.o.  [Dean Gaudet] PR#752
  +
  +  *) mod_status dumps core in inetd mode.  [Marc Slemko and Roy Fielding]
  +     PR#566
  +
  +  *) pregsub had an off-by-1 in its error checking code. [Alexei Kosut]
  +
  +  *) PORT: fix rlim_t problems with AIX 4.2. [Marc Slemko] PR#333
  +
  +  *) PORT: Update Unixware support for 2.1.2.
  +     [Lawrence Rosenman <le...@lerctr.org>] PR#511
  +
  +  *) PORT: NonStop-UX [Joachim Schmitz <sc...@tandem.com>] PR#327
  +
  +  *) PORT: Update ConvexOS support for 11.5.
  +     [David DeSimone <fo...@convex.com>] PR#399
  +
  +  *) PORT: Support for dec cc compiler under ultrix.
  +     ["P. Alejandro Lopez-Valencia" <al...@ideam.gov.co>] PR#388
  +
  +  *) PORT: Support for Maxion/OS SVR4.2 Real Time Unix. [no name given] PR#383
  +
  +  *) PORT: Workaround for AIX 3.x compiler bug in http_bprintf.c.  
  +     [Marc Slemko] PR#725
  +  
  +  *) PORT: fix problem compiling http_bprintf.c with gcc under SCO
  +     [Marc Slemko] PR#695
  +
   Changes with Apache 1.2
   
   Changes with Apache 1.2b11
  @@ -1361,7 +1699,7 @@
     *) Check if scoreboard file couldn't be opened, and say so, rather
        then going insane [David Robinson]
   
  -  *) POST to CGI works on A/UX [Jim Jaglieski]
  +  *) POST to CGI works on A/UX [Jim Jagielski]
   
     *) AddIcon and AddAlt commands work properly [Rob Hartill]
   
  @@ -1373,7 +1711,7 @@
        content negotiation.  (NB this will all have to be reworked anyway
        for the new HTTP draft).  [Florent Guillaume]
   
  -  *) Don't dump core when trying to log timed-out requests [Jim Jaglieski]
  +  *) Don't dump core when trying to log timed-out requests [Jim Jagielski]
   
     *) Really honor CacheNegotiatedDocs [Florent Guillaume]
   
  @@ -1397,7 +1735,7 @@
     *) Further de-Berklize mod_cookies.c; change the bogus #include.  [Brian
        Behlendorf/Eric Hagberg]
   
  -  *) More improvements to default Configuration for A/UX [Jim Jaglieski]
  +  *) More improvements to default Configuration for A/UX [Jim Jagielski]
   
     *) Compiles clean on NEXT [Rob Hartill]
   
  
  
  
  1.64      +5 -2      apache-1.2/src/Configuration.tmpl
  
  Index: Configuration.tmpl
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/Configuration.tmpl,v
  retrieving revision 1.63
  retrieving revision 1.64
  diff -u -r1.63 -r1.64
  --- Configuration.tmpl	1997/05/10 17:14:36	1.63
  +++ Configuration.tmpl	1998/01/30 09:13:44	1.64
  @@ -18,8 +18,8 @@
   # control Configure's behavior as far as how to create Makefile.
   #
   # Module selection lines, distinguished by having 'Module' at the front.
  -# These list the configured modules, in priority order (highest priority
  -# first).  They're down at the bottom.
  +# These list the configured modules, in reverse priority order (lowest
  +# priority first).  They're down at the bottom.
   #
   # Optional module selection lines, distinguished by having `%Module'
   # at the front.  These specify a module that is to be compiled in (but
  @@ -40,6 +40,9 @@
   # You can also set the compiler and Optimization used here as well.
   # Settings here have priority; If not set, Configure will attempt to guess
   # the C compiler, and set OPTIM to '-O2'
  +#
  +# REDHAT LINUX 5.0 USERS PLEASE NOTE!  You have to add -lcrypt to
  +# EXTRA_LIBS.  This is fixed in 1.3 but will not be fixed in 1.2.
   #
   EXTRA_CFLAGS=
   EXTRA_LFLAGS=
  
  
  
  1.97      +49 -8     apache-1.2/src/Configure
  
  Index: Configure
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/Configure,v
  retrieving revision 1.96
  retrieving revision 1.97
  diff -u -r1.96 -r1.97
  --- Configure	1997/05/13 00:20:30	1.96
  +++ Configure	1998/01/30 09:13:44	1.97
  @@ -205,10 +205,15 @@
   	CFLAGS="$CFLAGS -DAIX -U__STR__ -DUSEBCOPY"
   	DEF_WANTHSREGEX=no
   	;;
  +    *-ibm-aix[1-3].*|*-ibm-aix4.[0-1])
  +        OS='IBM AIX < v4.2'
  +        CFLAGS="$CFLAGS -DAIX -DNEED_RLIM_T -U__STR__"
  +        ;;
       *-ibm-aix*)
  -	OS='IBM AIX'
  -	CFLAGS="$CFLAGS -DAIX -U__STR__"
  -	;;
  +        OS='IBM AIX >= 4.2'
  +        CFLAGS="$CFLAGS -DAIX -U__STR__"
  +	LFLAGS="$LFLAGS -lm"
  +        ;;
       *-apollo-*)
   	OS='Apollo Domain'
   	CFLAGS="$CFLAGS -DAPOLLO"
  @@ -280,6 +285,18 @@
   	    CFLAGS="$CFLAGS -DIRIX"
   	fi
   	;;
  +    alpha-*-linux2)
  +	DEF_WANTHSREGEX=yes
  +	OS='Linux'
  +	CFLAGS="$CFLAGS -DLINUX=2"
  +	LIBS="$LIBS -lcrypt"
  +	;;
  +    sparc-*-linux2)
  +	DEF_WANTHSREGEX=yes
  +	OS='Linux'
  +	CFLAGS="$CFLAGS -DLINUX=2"
  +	LIBS="$LIBS -lm"
  +	;;
       *-linux2)
   	DEF_WANTHSREGEX=yes
   	OS='Linux'
  @@ -359,7 +376,9 @@
   	OS='SCO 5'
   	CFLAGS="$CFLAGS -DSCO5"
   	LIBS="$LIBS -lsocket -lmalloc -lprot"
  -	OSBPRINTF="-K noinline"
  +	if [ "$CC" = "cc" ] || [ "$COMPILER" = "cc" ]; then
  +	    OSBPRINTF="-K noinline"
  +	fi
   	DEF_WANTHSREGEX=no
   	;;
       *-solaris2*)
  @@ -391,9 +410,21 @@
   	CFLAGS="$CFLAGS -DUW"
   	LIBS="$LIBS -lsocket -lnsl -lcrypt"
   	;;
  +    *-unixware212)
  +	OS='Unixware 2.1.2'
  +	CFLAGS="$CFLAGS -DUW"
  +	LIBS="$LIBS -lsocket -lnsl -lcrypt"
  +	DBM_LIB=""
  +	;;
  +    maxion-*-sysv4*)
  +    	OS='SVR4'
  +	CFLAGS="$CFLAGS -DSVR4"
  +	DEF_WANTHSREGEX=yes
  +	LIBS="$LIBS -lsocket -lnsl -lc -lgen"
  +	;;
       *-sni-sysv4*)
   	OS='SVR4'
  -	CFLAGS="$CFLAGS -DSVR4"
  +	CFLAGS="$CFLAGS -DSVR4 -D_XPG_IV -DUSE_MMAP_FILES"
   	DEF_WANTHSREGEX=yes
   	LIBS="$LIBS -lsocket -lnsl -lc"
   	;;
  @@ -403,6 +434,12 @@
   	LIBS="$LIBS -lsocket -lnsl"
   	DEF_WANTHSREGEX=yes
   	;;
  +    *-tandem-sysv4*)
  +	OS='SVR4'
  +	CFLAGS="$CFLAGS -DSVR4"
  +	LIBS="$LIBS -lsocket -lnsl"
  +	DEF_WANTHSREGEX=yes
  +	;;
       *-sysv4*)
   	OS='SVR4'
   	CFLAGS="$CFLAGS -DSVR4"
  @@ -418,6 +455,9 @@
   	CFLAGS="-DULTRIX"
   	DEF_WANTHSREGEX=yes
   	SHELL="/bin/sh5"
  +	if [ "$CC" = "cc" ] || [ "$COMPILER" = "cc" ]; then
  +	    CFLAGS="$CFLAGS -std"
  +	fi
   	;;
       *powerpc-tenon-machten*)
   	OS='MachTen PPC'
  @@ -430,7 +470,8 @@
   	;;
       *convex-v11*)
   	OS='CONVEXOS11'
  -	CFLAGS="$CFLAGS -DCONVEXOS11"
  +	CFLAGS="$CFLAGS -ext -DCONVEXOS11"
  +	OPTIM="-O1" # scalar optimization only
   	CC='cc'
   	DEF_WANTHSREGEX=yes
   	;;
  @@ -632,8 +673,8 @@
   clean: \$(CLEANERS)
   	@echo "Done cleaning module subdirectories"
   
  -\$(MODULES): ForceMe
  -	(cd \$@; \$(MAKE) CC=\$(CC) AUX_CFLAGS='\$(MOD_CFLAGS)' RANLIB='\$(RANLIB)')
  +placeholder \$(MODULES): ForceMe
  +	(cd \$@; \$(MAKE) CC='\$(CC)' AUX_CFLAGS='\$(MOD_CFLAGS)' RANLIB='\$(RANLIB)')
   
   ForceMe:
   
  
  
  
  1.15      +1 -1      apache-1.2/src/INSTALL
  
  Index: INSTALL
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/INSTALL,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- INSTALL	1997/04/14 12:45:03	1.14
  +++ INSTALL	1998/01/30 09:13:45	1.15
  @@ -46,7 +46,7 @@
         % 
   
      (*: Depending on Configuration and your system, Configure
  -       make not print these lines. That's OK)
  +       may not print these lines. That's OK.)
   
   3) Type "make".
   
  
  
  
  1.47      +108 -72   apache-1.2/src/Makefile.tmpl
  
  Index: Makefile.tmpl
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/Makefile.tmpl,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- Makefile.tmpl	1997/06/04 20:21:15	1.46
  +++ Makefile.tmpl	1998/01/30 09:13:46	1.47
  @@ -29,14 +29,14 @@
   	$(CC) $(LFLAGS)  -o httpd $(OBJS) $(REGLIB) $(LIBS)
   
   regex/libregex.a:
  -	(cd regex; $(MAKE) lib CC=$(CC) AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)')
  +	(cd regex; $(MAKE) lib CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)')
   
   modules/last-built:
   	(cd modules; \
  -	$(MAKE) CC=$(CC) AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)')
  +	$(MAKE) CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)')
   
   clean:
  -	rm -f httpd $(OBJS) 
  +	rm -f httpd *.o core
   	cd regex; $(MAKE) clean
   	cd modules; $(MAKE) clean
   
  @@ -51,76 +51,112 @@
   http_bprintf.o: http_bprintf.c
   	$(CC) -c $(INCLUDES) $(CFLAGS) $(BROKEN_BPRINTF_FLAGS) http_bprintf.c
   
  +# We really don't expect end users to use this rule.  It works only with
  +# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
  +# using it.
  +depend:
  +	sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
  +	    && $(CC) -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
  +	    && mv Makefile.tmpl Makefile.tmpl.bak \
  +	    && mv Makefile.new Makefile.tmpl
  +
   #Dependencies
   
   $(OBJS): Makefile
   
  -alloc.o: conf.h alloc.h
  -buff.o: conf.h alloc.h buff.h
  -explain.o: explain.h
  -http_bprintf.o: conf.h alloc.h buff.h
  -http_config.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
  -               http_conf_globals.h explain.h
  -http_core.o: httpd.h http_config.h http_core.h http_protocol.h scoreboard.h \
  -             http_conf_globals.h http_main.h http_log.h rfc1413.h util_md5.h
  -http_log.o: httpd.h http_config.h http_core.h http_log.h
  -http_main.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
  -             http_conf_globals.h http_protocol.h http_main.h scoreboard.h \
  -             explain.h
  -http_protocol.o: httpd.h http_config.h http_core.h http_protocol.h \
  -                 http_main.h http_log.h util_date.h
  -http_request.o: httpd.h http_config.h http_request.h http_core.h \
  -                http_protocol.h http_log.h http_main.h scoreboard.h
  -md5c.o: md5.h
  -mod_access.o: httpd.h http_core.h http_config.h http_log.h
  -mod_actions.o: httpd.h http_config.h http_request.h http_core.h \
  -               http_protocol.h http_main.h http_log.h util_script.h
  -mod_alias.o: httpd.h http_config.h
  -mod_asis.o: httpd.h http_config.h http_protocol.h http_log.h util_script.h \
  -            http_main.h http_request.h
  -mod_auth.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  -mod_auth_anon.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  -mod_auth_db.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  -mod_auth_dbm.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  -mod_auth_msql.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  -mod_browser.o: httpd.h http_config.h
  -mod_cern_meta.o: httpd.h http_config.h util_script.h http_log.h
  -mod_cgi.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
  -           http_main.h http_log.h util_script.h
  -mod_digest.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h \
  -              util_md5.h
  -mod_dir.o: httpd.h http_config.h http_core.h http_request.h http_protocol.h \
  -           http_log.h http_main.h util_script.h
  -mod_dld.o: httpd.h http_config.h http_conf_globals.h
  -mod_env.o: httpd.h http_config.h
  -mod_expires.o: httpd.h http_config.h http_log.h
  -mod_headers.o: httpd.h http_config.h
  -mod_imap.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
  -            http_main.h http_log.h util_script.h
  -mod_include.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
  -               http_protocol.h http_main.h util_script.h
  -mod_info.o: httpd.h http_config.h http_core.h http_log.h http_main.h \
  -            http_protocol.h util_script.h
  -mod_log_agent.o: httpd.h http_config.h
  -mod_log_config.o: httpd.h http_config.h http_core.h
  -mod_log_referer.o: httpd.h http_config.h
  -mod_mime.o: httpd.h http_config.h
  -mod_negotiation.o: httpd.h http_config.h http_request.h http_core.h http_log.h
  -mod_rewrite.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
  -               mod_rewrite.h
  -mod_status.o: httpd.h http_config.h http_core.h http_protocol.h http_main.h \
  -              util_script.h scoreboard.h
  -mod_userdir.o: httpd.h http_config.h
  -mod_usertrack.o: httpd.h http_config.h http_core.h
  -modules.o: httpd.h http_config.h
  -rfc1413.o: httpd.h http_log.h rfc1413.h
  -util.o: httpd.h http_conf_globals.h
  -util_date.o: util_date.h
  -util_md5.o: httpd.h util_md5.h
  -util_script.o: httpd.h http_config.h http_conf_globals.h http_main.h \
  -               http_log.h http_protocol.h http_core.h http_request.h \
  -               util_script.h
  -util_snprintf.o: httpd.h
  -
  -httpd.h: conf.h alloc.h buff.h
  -util_md5.h: md5.h
  +# DO NOT REMOVE
  +alloc.o: alloc.c httpd.h conf.h alloc.h buff.h
  +buff.o: buff.c conf.h alloc.h buff.h
  +explain.o: explain.c explain.h
  +http_bprintf.o: http_bprintf.c conf.h alloc.h buff.h
  +http_config.o: http_config.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_log.h http_request.h \
  + http_conf_globals.h explain.h
  +http_core.o: http_core.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_protocol.h http_conf_globals.h http_main.h \
  + http_log.h rfc1413.h util_md5.h md5.h scoreboard.h
  +http_log.o: http_log.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_log.h
  +http_main.o: http_main.c httpd.h conf.h alloc.h buff.h http_main.h \
  + http_log.h http_config.h http_protocol.h http_request.h \
  + http_conf_globals.h http_core.h scoreboard.h explain.h
  +http_protocol.o: http_protocol.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_protocol.h http_main.h http_log.h \
  + util_date.h
  +http_request.o: http_request.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_request.h http_core.h http_protocol.h http_log.h \
  + http_main.h scoreboard.h
  +md5c.o: md5c.c md5.h
  +mod_access.o: mod_access.c httpd.h conf.h alloc.h buff.h http_core.h \
  + http_config.h http_log.h http_request.h
  +mod_actions.o: mod_actions.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_request.h http_core.h http_protocol.h http_main.h \
  + http_log.h util_script.h
  +mod_alias.o: mod_alias.c httpd.h conf.h alloc.h buff.h http_config.h
  +mod_asis.o: mod_asis.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_protocol.h http_log.h util_script.h http_main.h http_request.h
  +mod_auth.o: mod_auth.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_log.h http_protocol.h
  +mod_auth_anon.o: mod_auth_anon.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_log.h http_protocol.h
  +mod_auth_db.o: mod_auth_db.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_log.h http_protocol.h
  +mod_auth_dbm.o: mod_auth_dbm.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_log.h http_protocol.h
  +mod_auth_msql.o: mod_auth_msql.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h http_log.h http_protocol.h
  +mod_browser.o: mod_browser.c httpd.h conf.h alloc.h buff.h \
  + http_config.h
  +mod_cern_meta.o: mod_cern_meta.c httpd.h conf.h alloc.h buff.h \
  + http_config.h util_script.h http_log.h http_request.h
  +mod_cgi.o: mod_cgi.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_request.h http_core.h http_protocol.h http_main.h http_log.h \
  + util_script.h http_conf_globals.h
  +mod_digest.o: mod_digest.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_log.h http_protocol.h util_md5.h md5.h
  +mod_dir.o: mod_dir.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_request.h http_protocol.h http_log.h http_main.h \
  + util_script.h
  +mod_dld.o: mod_dld.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_conf_globals.h
  +mod_env.o: mod_env.c httpd.h conf.h alloc.h buff.h http_config.h
  +mod_expires.o: mod_expires.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_log.h
  +mod_headers.o: mod_headers.c httpd.h conf.h alloc.h buff.h \
  + http_config.h
  +mod_imap.o: mod_imap.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_request.h http_core.h http_protocol.h http_main.h http_log.h \
  + util_script.h
  +mod_include.o: mod_include.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_request.h http_core.h http_protocol.h http_log.h \
  + http_main.h util_script.h
  +mod_info.o: mod_info.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_log.h http_main.h http_protocol.h util_script.h
  +mod_log_agent.o: mod_log_agent.c httpd.h conf.h alloc.h buff.h \
  + http_config.h
  +mod_log_config.o: mod_log_config.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h
  +mod_log_referer.o: mod_log_referer.c httpd.h conf.h alloc.h buff.h \
  + http_config.h
  +mod_mime.o: mod_mime.c httpd.h conf.h alloc.h buff.h http_config.h
  +mod_negotiation.o: mod_negotiation.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_request.h http_core.h http_log.h util_script.h
  +mod_rewrite.o: mod_rewrite.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_request.h http_core.h http_log.h mod_rewrite.h
  +mod_status.o: mod_status.c httpd.h conf.h alloc.h buff.h http_config.h \
  + http_core.h http_protocol.h http_main.h util_script.h scoreboard.h \
  + http_log.h
  +mod_userdir.o: mod_userdir.c httpd.h conf.h alloc.h buff.h \
  + http_config.h
  +mod_usertrack.o: mod_usertrack.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_core.h
  +modules.o: modules.c httpd.h conf.h alloc.h buff.h http_config.h
  +rfc1413.o: rfc1413.c httpd.h conf.h alloc.h buff.h http_log.h \
  + rfc1413.h
  +util.o: util.c httpd.h conf.h alloc.h buff.h http_conf_globals.h
  +util_date.o: util_date.c util_date.h
  +util_md5.o: util_md5.c httpd.h conf.h alloc.h buff.h util_md5.h md5.h
  +util_script.o: util_script.c httpd.h conf.h alloc.h buff.h \
  + http_config.h http_conf_globals.h http_main.h http_log.h \
  + http_protocol.h http_core.h http_request.h util_script.h
  +util_snprintf.o: util_snprintf.c conf.h
  
  
  
  1.5       +3 -0      apache-1.2/src/PORTING
  
  Index: PORTING
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/PORTING,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- PORTING	1997/02/25 21:04:42	1.4
  +++ PORTING	1998/01/30 09:13:46	1.5
  @@ -227,6 +227,9 @@
         NO_LINGCLOSE:
          Do not use Apache's soft, "lingering" close feature to
          terminate connections.
  +      NO_SLACK:
  +       Do not use the "slack" fd feature which requires a working fcntl
  +       F_DUPFD.
   --
   
     MISC #DEFINES:
  
  
  
  1.29      +18 -6     apache-1.2/src/alloc.c
  
  Index: alloc.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/alloc.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- alloc.c	1997/05/27 04:14:20	1.28
  +++ alloc.c	1998/01/30 09:13:47	1.29
  @@ -58,8 +58,7 @@
    * rst --- 4/95 --- 6/95
    */
   
  -#include "conf.h"
  -#include "alloc.h"
  +#include "httpd.h"
   
   #include <stdarg.h>
   
  @@ -579,11 +578,12 @@
       table_entry *elts = (table_entry *)t->elts;
       int done = 0;
   
  -    for (i = 0; i < t->nelts; ++i)
  +    for (i = 0; i < t->nelts;) {
   	if (!strcasecmp (elts[i].key, key)) {
   	    if (!done) {
   	        elts[i].val = pstrdup(t->pool, val);
   	        done = 1;
  +		++i;
   	    }
   	    else {     /* delete an extraneous element */
                   for (j = i, k = i + 1; k < t->nelts; ++j, ++k) {
  @@ -593,6 +593,10 @@
                   --t->nelts;
   	    }
   	}
  +	else {
  +	    ++i;
  +	}
  +    }
   
       if (!done) {
           elts = (table_entry *)push_array(t);
  @@ -606,7 +610,7 @@
       register int i, j, k;   
       table_entry *elts = (table_entry *)t->elts;
    
  -    for (i = 0; i < t->nelts; ++i)
  +    for (i = 0; i < t->nelts;) {
           if (!strcasecmp (elts[i].key, key)) {
    
               /* found an element to skip over
  @@ -620,7 +624,11 @@
               }
               --t->nelts;
           }
  -}     
  +	else {
  +	    ++i;
  +	}
  +    }
  +}
   
   void table_merge (table *t, const char *key, const char *val)
   {
  @@ -801,7 +809,10 @@
     block_alarms();
     fd = open(name, flg, mode);
     save_errno = errno;
  -  if (fd >= 0) note_cleanups_for_fd (a, fd);
  +  if (fd >= 0) {
  +    fd = ap_slack (fd, AP_SLACK_HIGH);
  +    note_cleanups_for_fd (a, fd);
  +  }
     unblock_alarms();
     errno = save_errno;
     return fd;
  @@ -846,6 +857,7 @@
       desc = open(name, baseFlag | O_APPEND | O_CREAT,
   		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
       if (desc >= 0) {
  +      desc = ap_slack(desc, AP_SLACK_LOW);
         fd = fdopen(desc, mode);
       }
     } else {
  
  
  
  1.27      +55 -31    apache-1.2/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/buff.c,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- buff.c	1997/05/29 05:21:15	1.26
  +++ buff.c	1998/01/30 09:13:47	1.27
  @@ -187,7 +187,13 @@
   }
   
   /*
  - * start chunked encoding
  + * Start chunked encoding.
  + *
  + * Note that in order for bputc() to be an efficient macro we have to
  + * guarantee that start_chunk() has always been called on the buffer before we
  + * leave any routine in this file.  Said another way, if a routine here uses
  + * end_chunk() and writes something on the wire, then it has to call
  + * start_chunk() or set an error condition before returning.
    */
   static void
   start_chunk( BUFF *fb )
  @@ -624,6 +630,7 @@
   	i = write(fb->fd, buf, nbyte);
   	if (i < 0) {
   	    if (errno != EAGAIN && errno != EINTR) {
  +		doerror (fb, B_WR);
   		return -1;
   	    }
   	}
  @@ -648,16 +655,28 @@
   bcwrite(BUFF *fb, const void *buf, int nbyte)
   {
       char chunksize[16];	/* Big enough for practically anything */
  +    int rv;
   #ifndef NO_WRITEV
       struct iovec vec[3];
  -    int i, rv;
  +    int i;
   #endif
   
       if (fb->flags & (B_WRERR|B_EOUT))
   	return -1;
   
  -    if (!(fb->flags & B_CHUNK))
  -	return write(fb->fd, buf, nbyte);
  +    if (!(fb->flags & B_CHUNK)) {
  +	do rv = write(fb->fd, buf, nbyte);
  +	while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  +	if (rv == -1) {
  +	    if (errno != EAGAIN) {
  +		doerror (fb, B_WR);
  +	    }
  +	    return -1;
  +	} else if (rv == 0) {
  +	    errno = EAGAIN;
  +	}
  +	return rv;
  +    }
   
   #ifdef NO_WRITEV
       /* without writev() this has poor performance, too bad */
  @@ -685,10 +704,15 @@
        * to deal with a partial writev()
        */
       for( i = 0; i < NVEC; ) {
  -	do rv = writev( fb->fd, &vec[i], NVEC - i );
  -	while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  -	if (rv == -1)
  +	do {
  +	    rv = writev( fb->fd, &vec[i], NVEC - i );
  +	} while ((rv <= 0)
  +	         && !(fb->flags & B_EOUT)
  +	         && (errno == EINTR || errno == EAGAIN || rv == 0));
  +	if (rv == -1) {
  +	    doerror (fb, B_WR);
   	    return -1;
  +	}
   	/* recalculate vec to deal with partial writes */
   	while (rv > 0) {
   	    if( rv <= vec[i].iov_len ) {
  @@ -732,15 +756,8 @@
       {
   /* unbuffered write -- have to use bcwrite since we aren't taking care
    * of chunking any other way */
  -	do i = bcwrite(fb, buf, nbyte);
  -	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  -	if (i == 0) {  /* return of 0 means non-blocking */
  -	    errno = EAGAIN;
  -	    return -1;
  -	}
  -	else if (i < 0) {
  -	    if (errno != EAGAIN)
  -	        doerror(fb, B_WR);
  +	i = bcwrite(fb, buf, nbyte);
  +	if (i <= 0) {
   	    return -1;
   	}
   	fb->bytes_sent += i;
  @@ -776,13 +793,17 @@
   	    /* it is just too painful to try to re-cram the buffer while
   	     * chunking
   	     */
  -	    i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
  -	            -1 : fb->outcnt;
  -	}
  -	else {
  -	    do i = write(fb->fd, fb->outbase, fb->outcnt);
  -	    while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  +	    if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
  +		/* we cannot continue after a chunked error */
  +		return -1;
  +	    }
  +	    fb->bytes_sent += fb->outcnt;
  +	    fb->outcnt = 0;
  +	    break;
   	}
  +	do {
  +	    i = write(fb->fd, fb->outbase, fb->outcnt);
  +	} while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
   	if (i <= 0) {
   	    if (i == 0) /* return of 0 means non-blocking */
   	        errno = EAGAIN;
  @@ -815,13 +836,9 @@
    */
       while (nbyte >= fb->bufsiz)
       {
  -	do i = bcwrite(fb, buf, nbyte);
  -	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  +	i = bcwrite(fb, buf, nbyte);
   	if (i <= 0) {
  -	    if (i == 0) /* return of 0 means non-blocking */
  -	        errno = EAGAIN;
   	    if (nwr == 0) {
  -		if (errno != EAGAIN) doerror(fb, B_WR);
   		return -1;
   	    }
   	    else return nwr;
  @@ -861,12 +878,15 @@
   
       while (fb->outcnt > 0)
       {
  -	/* the buffer must be full */
  -	do i = write(fb->fd, fb->outbase, fb->outcnt);
  -	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  +	do {
  +	    i = write(fb->fd, fb->outbase, fb->outcnt);
  +	} while ((i <= 0)
  +	         && !(fb->flags & B_EOUT)
  +	         && (errno == EINTR || errno == EAGAIN || i == 0));
  +
   	if (i == 0) {
   	    errno = EAGAIN;
  -	    return -1;  /* return of 0 means non-blocking */
  +	    return -1;  /* return of 0 means B_EOUT and non-blocking */
   	}
   	else if (i < 0) {
   	    if (errno != EAGAIN) doerror(fb, B_WR);
  @@ -892,6 +912,10 @@
   	if (fb->flags & B_EOUT)
   	    return -1;
       }
  +
  +    if (fb->flags & B_CHUNK)
  +	start_chunk(fb);
  +
       return 0;
   }
   
  
  
  
  1.13      +3 -0      apache-1.2/src/buff.h
  
  Index: buff.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/buff.h,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- buff.h	1997/02/10 15:49:54	1.12
  +++ buff.h	1998/01/30 09:13:48	1.13
  @@ -65,6 +65,9 @@
   #define B_RDERR (16)
   /* A write error has occurred */
   #define B_WRERR (32)
  +#ifdef B_ERROR  /* in SVR4: sometimes defined in /usr/include/sys/buf.h */
  +#undef B_ERROR  /* avoid "warning: `B_ERROR' redefined" */
  +#endif
   #define B_ERROR (48)
   /* Use chunked writing */
   #define B_CHUNK (64)
  
  
  
  1.100     +16 -8     apache-1.2/src/conf.h
  
  Index: conf.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/conf.h,v
  retrieving revision 1.99
  retrieving revision 1.100
  diff -u -r1.99 -r1.100
  --- conf.h	1997/06/04 07:03:11	1.99
  +++ conf.h	1998/01/30 09:13:49	1.100
  @@ -73,6 +73,7 @@
   extern void GETPRIVMODE();
   extern void GETUSERMODE();
   extern char *inet_ntoa();
  +#define NO_SLACK
   
   #elif defined(SUNOS4)
   #define HAVE_GMTOFF
  @@ -88,6 +89,7 @@
   typedef int rlim_t;
   #define memmove(a,b,c) bcopy(b,a,c)
   #define NO_LINGCLOSE
  +#define USE_FLOCK_SERIALIZED_ACCEPT
   
   #elif defined(SOLARIS2)
   #undef HAVE_GMTOFF
  @@ -153,7 +155,9 @@
   #define DEFAULT_GROUP "nobody"
   #endif
   #define DEFAULT_USER "nobody"
  +#ifdef NEED_RLIM_T
   typedef int rlim_t;
  +#endif
   
   #elif defined(ULTRIX)
   #define HAVE_GMTOFF
  @@ -291,10 +295,6 @@
   extern int strcasecmp(const char *,const char *);
   extern int strncasecmp(const char *,const char *,unsigned);
   
  -#elif defined(CONVEXOS)
  -#define HAVE_GMTOFF
  -#define NEED_STRDUP
  -
   #elif defined(AUX)
   /* These are to let -Wall compile more cleanly */
   extern int strcasecmp(const char *, const char *);
  @@ -316,17 +316,18 @@
   #define NEED_STRDUP
   #define JMP_BUF sigjmp_buf
   /* fcntl() locking is expensive with NFS */
  -#undef USE_FLOCK_SERIALIZED_ACCEPT
  +#define USE_FLOCK_SERIALIZED_ACCEPT
   #define HAVE_SHMGET
  -#define MOVEBREAK		0x4000000
   /*
    * NOTE: If when you run Apache under A/UX and you get a warning
  - * that httpd couldn't move break, then the above value for
  + * that httpd couldn't move break, then the below value for
    * MOVEBREAK (64megs) is too large for your setup. Try reducing
    * to 0x2000000 which is still PLENTY of space. I doubt if
    * even on heavy systems sbrk() would be called at all...
    */
  +#define MOVEBREAK		0x4000000
   #define NO_LINGCLOSE
  +#define NO_SLACK
   
   #elif defined(SVR4)
   #define NO_KILLPG
  @@ -409,6 +410,7 @@
   (defined(__FreeBSD_version) && (__FreeBSD_version < 220000))
   typedef quad_t rlim_t;
   #endif
  +#define USE_FLOCK_SERIALIZED_ACCEPT
   
   #elif defined(QNX)
   #ifndef crypt
  @@ -485,6 +487,12 @@
   
   /* Convex OS v11 */
   #elif defined(CONVEXOS11)
  +#undef HAVE_GMTOFF
  +#undef NO_KILLPG
  +#undef NO_SETSID
  +#undef NEED_STRDUP
  +#define HAVE_MMAP
  +
   #define NO_TIMEZONE
   #include <stdio.h>
   #include <sys/types.h>
  @@ -545,7 +553,7 @@
   int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap);
   #endif
   
  -#if !defined(NEXT) && !defined(CONVEXOS)
  +#if !defined(NEXT)
   #include <dirent.h>
   #define DIR_TYPE dirent
   #else
  
  
  
  1.9       +4 -1      apache-1.2/src/http_bprintf.c
  
  Index: http_bprintf.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_bprintf.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- http_bprintf.c	1997/02/16 07:44:14	1.8
  +++ http_bprintf.c	1998/01/30 09:13:49	1.9
  @@ -289,7 +289,10 @@
   		    else
   			{
   			p = memchr(charPtrArg, '\0', precision);
  -			buffReqd=(p == NULL) ? precision : p - charPtrArg;
  +			if (p == NULL)
  +				buffReqd = precision;
  +			else
  +				buffReqd = p - charPtrArg;
   			}
   		    break;
   
  
  
  
  1.10      +1 -0      apache-1.2/src/http_conf_globals.h
  
  Index: http_conf_globals.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_conf_globals.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- http_conf_globals.h	1997/01/01 18:10:16	1.9
  +++ http_conf_globals.h	1998/01/30 09:13:50	1.10
  @@ -72,6 +72,7 @@
   
   extern char *pid_fname;
   extern char *scoreboard_fname;
  +extern char *lock_fname;
   extern char *server_argv0;
   
   /* Trying to allocate these in the config pool gets us into some *nasty*
  
  
  
  1.50      +20 -5     apache-1.2/src/http_config.c
  
  Index: http_config.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_config.c,v
  retrieving revision 1.49
  retrieving revision 1.50
  diff -u -r1.49 -r1.50
  --- http_config.c	1997/05/15 23:39:20	1.49
  +++ http_config.c	1998/01/30 09:13:53	1.50
  @@ -821,8 +821,16 @@
   	}
   	
   	*result = dc;
  -    } else
  -	dc = NULL;
  +    } else {
  +	if (errno == ENOENT || errno == ENOTDIR)
  +	    dc = NULL;
  +	else {
  +	    log_unixerr("pfopen", filename,
  +		"unable to check htaccess file, ensure it is readable",
  +		r->server);
  +	    return HTTP_FORBIDDEN;
  +	}
  +    }
   
   /* cache it */
       new = palloc(r->pool, sizeof(struct htaccess_result));
  @@ -1040,6 +1048,7 @@
       daemons_limit = HARD_SERVER_LIMIT;
       pid_fname = DEFAULT_PIDLOG;
       scoreboard_fname = DEFAULT_SCOREBOARD;
  +    lock_fname = DEFAULT_LOCKFILE;
       max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
       bind_address.s_addr = htonl(INADDR_ANY);
       listeners = NULL;
  @@ -1077,7 +1086,6 @@
   server_rec *read_config(pool *p, pool *ptemp, char *confname)
   {
       server_rec *s = init_server_config(p);
  -    module *m;
       
       init_config_globals(p);
       
  @@ -1089,12 +1097,19 @@
       
       fixup_virtual_hosts (p, s);
       
  +    return s;
  +}
  +    
  +
  +void init_modules(pool *p, server_rec *s)
  +{
  +    module *m;
  +
       for (m = top_module; m; m = m->next)
           if (m->init)
   	    (*m->init) (s, p);
  -    
  -    return s;
   }
  +
   
   /********************************************************************
    * Configuration directives are restricted in terms of where they may
  
  
  
  1.30      +2 -1      apache-1.2/src/http_config.h
  
  Index: http_config.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_config.h,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- http_config.h	1997/05/27 04:41:49	1.29
  +++ http_config.h	1998/01/30 09:13:54	1.30
  @@ -226,7 +226,7 @@
    * handle it back-compatibly, or at least signal an error).
    */
   
  -#define MODULE_MAGIC_NUMBER 19970526
  +#define MODULE_MAGIC_NUMBER 19970622
   #define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
   
   /* Generic accessors for other modules to get at their own module-specific
  @@ -261,6 +261,7 @@
   /* For http_main.c... */
   
   server_rec *read_config (pool *conf_pool, pool *temp_pool, char *config_name);
  +void init_modules(pool *p, server_rec *s);
   void setup_prelinked_modules();
   void show_directives();
   void show_modules();
  
  
  
  1.82      +36 -9     apache-1.2/src/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_core.c,v
  retrieving revision 1.81
  retrieving revision 1.82
  diff -u -r1.81 -r1.82
  --- http_core.c	1997/05/08 13:09:24	1.81
  +++ http_core.c	1998/01/30 09:13:55	1.82
  @@ -200,8 +200,8 @@
       *conf = *virt;
       if (!conf->access_name) conf->access_name = base->access_name;
       if (!conf->document_root) conf->document_root = base->document_root;
  -    conf->sec = append_arrays (p, virt->sec, base->sec);
  -    conf->sec_url = append_arrays (p, virt->sec_url, base->sec_url);
  +    conf->sec = append_arrays (p, base->sec, virt->sec);
  +    conf->sec_url = append_arrays (p, base->sec_url, virt->sec_url);
   
       return conf;
   }
  @@ -886,9 +886,23 @@
   	else {
   	    cmd->server->server_uid = user_id;
   	    fprintf(stderr,
  -		    "Warning: User directive in <VirtualHost> requires SUEXEC wrapper.\n");
  +		"Warning: User directive in <VirtualHost> "
  +		"requires SUEXEC wrapper.\n");
   	}
       }
  +#if !defined (BIG_SECURITY_HOLE)
  +    if (cmd->server->server_uid == 0) {
  +	fprintf (stderr,
  +"Error:\tApache has not been designed to serve pages while running\n"
  +"\tas root.  There are known race conditions that will allow any\n"
  +"\tlocal user to read any file on the system.  Should you still\n"
  +"\tdesire to serve pages as root then add -DBIG_SECURITY_HOLE to\n"
  +"\tthe EXTRA_CFLAGS line in your src/Configuration file and rebuild\n"
  +"\tthe server.  It is strongly suggested that you instead modify the\n"
  +"\tUser directive in your httpd.conf file to list a non-root user.\n");
  +	exit (1);
  +    }
  +#endif
   
       return NULL;
   }
  @@ -953,6 +967,11 @@
       return NULL;
   }
   
  +const char *set_lockfile (cmd_parms *cmd, void *dummy, char *arg) {
  +    lock_fname = pstrdup (cmd->pool, arg);
  +    return NULL;
  +}
  +
   const char *set_idcheck (cmd_parms *cmd, core_dir_config *d, int arg) {
       d->do_rfc1413 = arg;
       return NULL;
  @@ -1000,10 +1019,11 @@
   const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg) {
       daemons_limit = atoi (arg);
       if (daemons_limit > HARD_SERVER_LIMIT) {
  -       fprintf(stderr, "WARNING: Compile-time limit of %d servers\n",
  -        HARD_SERVER_LIMIT);
  -       fprintf(stderr, " Adjusting as required (to increase, please read\n");
  -       fprintf(stderr, " the documentation)\n");
  +       fprintf(stderr, "WARNING: MaxClients of %d exceeds compile time limit "
  +           "of %d servers,\n", daemons_limit, HARD_SERVER_LIMIT);
  +       fprintf(stderr, " lowering MaxClients to %d.  To increase, please "
  +           "see the\n", HARD_SERVER_LIMIT);
  +       fprintf(stderr, " HARD_SERVER_LIMIT define in src/httpd.h.\n");
          daemons_limit = HARD_SERVER_LIMIT;
       } else if (daemons_limit < 1) {
   	fprintf (stderr, "WARNING: Require MaxClients > 0, setting to 1\n");
  @@ -1202,6 +1222,8 @@
       "A file for logging the server process ID"},
   { "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
       "A file for Apache to maintain runtime process management information"},
  +{ "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
  +    "The lockfile used when Apache needs to lock the accept() call"},
   { "AccessConfig", set_server_string_slot,
     (void *)XtOffsetOf (server_rec, access_confname), RSRC_CONF, TAKE1,
     "The filename of the access config file" },
  @@ -1303,9 +1325,14 @@
         (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
       int rangestatus, errstatus;
       FILE *f;
  -    
  +
  +    /* This handler has no use for a request body (yet), but we still
  +     * need to read and discard it if the client sent one.
  +     */
  +    if ((errstatus = discard_request_body(r)) != OK)
  +        return errstatus;
  +
       r->allowed |= (1 << M_GET);
  -    r->allowed |= (1 << M_TRACE);
       r->allowed |= (1 << M_OPTIONS);
   
       if (r->method_number == M_INVALID) {
  
  
  
  1.150     +100 -45   apache-1.2/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_main.c,v
  retrieving revision 1.149
  retrieving revision 1.150
  diff -u -r1.149 -r1.150
  --- http_main.c	1997/05/29 04:50:27	1.149
  +++ http_main.c	1998/01/30 09:13:55	1.150
  @@ -138,6 +138,7 @@
   int max_requests_per_child;
   char *pid_fname;
   char *scoreboard_fname;
  +char *lock_fname;
   char *server_argv0;
   struct in_addr bind_address;
   listen_rec *listeners;
  @@ -181,6 +182,16 @@
   #define ap_killpg(x, y)		(killpg ((x), (y)))
   #endif
   
  +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT)
  +static void expand_lock_fname(pool *p)
  +{
  +    char buf[20];
  +
  +    ap_snprintf( buf, sizeof(buf), ".%u", getpid() );
  +    lock_fname = pstrcat (p, server_root_relative (p, lock_fname), buf, NULL);
  +}
  +#endif
  +
   #if defined(USE_FCNTL_SERIALIZED_ACCEPT)
   static struct flock lock_it;
   static struct flock unlock_it;
  @@ -193,8 +204,7 @@
    */
   void
   accept_mutex_init(pool *p)
  -    {
  -    char lock_fname[256];
  +{
   
       lock_it.l_whence = SEEK_SET;   /* from current point */
       lock_it.l_start  = 0;          /* -"- */
  @@ -207,19 +217,7 @@
       unlock_it.l_type   = F_UNLCK;  /* set exclusive/write lock */
       unlock_it.l_pid    = 0;        /* pid not actually interesting */
   
  -#ifdef __MACHTEN__
  -    strncpy(lock_fname, "/var/tmp/htlock.XXXXXX", sizeof(lock_fname)-1);
  -#else
  -    strncpy(lock_fname, "/usr/tmp/htlock.XXXXXX", sizeof(lock_fname)-1);
  -#endif
  -    lock_fname[sizeof(lock_fname)-1] = '\0';
  -
  -    if (mktemp(lock_fname) == NULL || lock_fname[0] == '\0')
  -    {
  -	fprintf (stderr, "Cannot assign name to lock file!\n");
  -	exit (1);
  -    }
  -
  +    expand_lock_fname (p);
       lock_fd = popenf(p, lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
       if (lock_fd == -1)
       {
  @@ -238,8 +236,9 @@
   	continue;
   
       if (ret < 0) {
  -	log_unixerr("fcntl", "F_SETLKW", "Error getting accept lock. Exiting!",
  -		    server_conf);
  +	log_unixerr("fcntl", "F_SETLKW", "Error getting accept lock. Exiting!"
  +		    "Perhaps you need to use the LockFile directive to place "
  +		    "your lock file on a local disk!", server_conf);
   	exit(1);
       }
   }
  @@ -248,8 +247,9 @@
   {
       if (fcntl (lock_fd, F_SETLKW, &unlock_it) < 0)
       {
  -	log_unixerr("fcntl", "F_SETLKW", "Error freeing accept lock. Exiting!",
  -		    server_conf);
  +	log_unixerr("fcntl", "F_SETLKW", "Error freeing accept lock. Exiting!"
  +		    "Perhaps you need to use the LockFile directive to place "
  +		    "your lock file on a local disk!", server_conf);
   	exit(1);
       }
   }
  @@ -264,22 +264,13 @@
   void
   accept_mutex_init(pool *p)
   {
  -    char lock_fname[256];
  -
  -    strncpy(lock_fname, "/usr/tmp/htlock.XXXXXX", sizeof(lock_fname)-1);
  -    lock_fname[sizeof(lock_fname)-1] = '\0';
  -    
  -    if (mktemp(lock_fname) == NULL || lock_fname[0] == '\0')
  -    {
  -	fprintf (stderr, "Cannot assign name to lock file!\n");
  -	exit (1);
  -    }
   
  +    expand_lock_fname (p);
       lock_fd = popenf(p, lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
       if (lock_fd == -1)
       {
   	perror ("open");
  -	fprintf (stderr, "Cannot open lock file\n");
  +	fprintf (stderr, "Cannot open lock file: %s\n", lock_fname);
   	exit (1);
       }
       unlink(lock_fname);
  @@ -677,8 +668,27 @@
   
   #elif defined(MAP_ANON) || defined(MAP_FILE)
   /* BSD style */
  +#ifdef CONVEXOS11
  +    /*
  +     * 9-Aug-97 - Jeff Venters (venters@convex.hp.com)
  +     * ConvexOS maps address space as follows:
  +     *   0x00000000 - 0x7fffffff : Kernel
  +     *   0x80000000 - 0xffffffff : User
  +     * Start mmapped area 1GB above start of text.
  +     *
  +     * Also, the length requires a pointer as the actual length is
  +     * returned (rounded up to a page boundary).
  +     */
  +    {
  +	unsigned len = SCOREBOARD_SIZE;
  +	
  +	m = mmap((caddr_t)0xC0000000, &len,
  +		PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, NOFD, 0);
  +    }
  +#else
       m = mmap((caddr_t)0, SCOREBOARD_SIZE,
   	     PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
  +#endif
       if (m == (caddr_t)-1)
       {
   	perror("mmap");
  @@ -725,6 +735,13 @@
   
       if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT|SHM_R|SHM_W)) == -1)
       {
  +#ifdef LINUX
  +	if (errno == ENOSYS) {
  +	    fprintf(stderr,
  +		"httpd: Your kernel was built without CONFIG_SYSVIPC\n"
  +		"httpd: please consult the Apache FAQ for details\n");
  +	}
  +#endif
   	perror("shmget");
   	fprintf(stderr, "httpd: Could not call shmget\n");
   	exit(1);
  @@ -941,6 +958,11 @@
   #endif
   }
   
  +int exists_scoreboard_image ()
  +{
  +    return (scoreboard_image ? 1 : 0);
  +}
  +
   int update_child_status (int child_num, int status, request_rec *r)
   {
       int old_status;
  @@ -1692,7 +1714,9 @@
        */
       ap_setjmp (jmpbuffer);
   #ifndef __EMX__
  +#ifdef SIGURG
       signal(SIGURG, timeout);
  +#endif
   #endif    
   
       while (1) {
  @@ -1756,8 +1780,16 @@
                   exit(0);
   
               errno = errsave;
  -            if (srv < 0 && errno != EINTR)
  +            if (srv < 0 && errno != EINTR) {
  +#ifdef LINUX
  +		if (errno == EFAULT) {
  +		    log_unixerr("select", "(listen) fatal, exiting",
  +				NULL, server_conf);
  +		    exit(1);
  +		}
  +#endif
                   log_unixerr("select", "(listen)", NULL, server_conf);
  +	    }
   
               if (srv <= 0)
                   continue;
  @@ -1981,7 +2013,16 @@
           exit(1);
       }
   
  +    /* Solaris (probably versions 2.4, 2.5, and 2.5.1 with various levels
  +     * of tcp patches) has some really weird bugs where if you dup the
  +     * socket now it breaks things across SIGHUP restarts.  It'll either
  +     * be unable to bind, or it won't respond.
  +     */
  +#ifndef SOLARIS2
  +    s = ap_slack(s, AP_SLACK_HIGH);
  +
       note_cleanups_for_fd(pconf, s); /* arrange to close on exec or restart */
  +#endif
       
   #ifndef MPE
   /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
  @@ -2050,6 +2091,12 @@
       if (ntohs(server->sin_port) < 1024) GETUSERMODE();
   #endif
       listen(s, 512);
  +
  +#ifdef SOLARIS2
  +    s = ap_slack(s, AP_SLACK_HIGH);
  +
  +    note_cleanups_for_fd(pconf, s); /* arrange to close on exec or restart */
  +#endif
       return s;
   }
   
  @@ -2135,20 +2182,6 @@
   	ptrans = make_sub_pool (pconf);
   
   	server_conf = read_config (pconf, ptrans, server_confname); 
  -	open_logs (server_conf, pconf);
  -	set_group_privs ();
  -	accept_mutex_init (pconf);
  -	if (!is_graceful) {
  -	    reinit_scoreboard(pconf);
  -	}
  -#ifdef SCOREBOARD_FILE
  -	else {
  -	    scoreboard_fname = server_root_relative (pconf, scoreboard_fname);
  -	    note_cleanups_for_fd (pconf, scoreboard_fd);
  -	}
  -#endif
  -
  -	default_server_hostnames (server_conf);
   
   	if (listeners == NULL) {
   	    if (!is_graceful) {
  @@ -2183,6 +2216,22 @@
   	    sd = -1;
   	}
   
  +	init_modules (pconf, server_conf);
  +	open_logs (server_conf, pconf);
  +	set_group_privs ();
  +	accept_mutex_init (pconf);
  +	if (!is_graceful) {
  +	    reinit_scoreboard(pconf);
  +	}
  +#ifdef SCOREBOARD_FILE
  +	else {
  +	    scoreboard_fname = server_root_relative (pconf, scoreboard_fname);
  +	    note_cleanups_for_fd (pconf, scoreboard_fd);
  +	}
  +#endif
  +
  +	default_server_hostnames (server_conf);
  +
   	set_signals ();
   	log_pid (pconf, pid_fname);
   
  @@ -2273,6 +2322,8 @@
   	}
   
   	/* we've been told to restart */
  +        signal (SIGHUP, SIG_IGN);
  +        signal (SIGUSR1, SIG_IGN);
   
   	if (one_process) {
   	    /* not worth thinking about */
  @@ -2391,6 +2442,7 @@
   
       suexec_enabled = init_suexec();
       server_conf = read_config (pconf, ptrans, server_confname);
  +    init_modules (pconf, server_conf);
       
       if(standalone) {
           clear_pool (pconf);	/* standalone_main rereads... */
  @@ -2423,6 +2475,9 @@
             GETUSERMODE();
         }
   #endif
  +        if (ap_setjmp (jmpbuffer)) {
  +	    exit (0);
  +        }
   
   	c = sizeof(sa_client);
   	if ((getpeername(fileno(stdin), &sa_client, &c)) < 0)
  
  
  
  1.127     +81 -32    apache-1.2/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_protocol.c,v
  retrieving revision 1.126
  retrieving revision 1.127
  diff -u -r1.126 -r1.127
  --- http_protocol.c	1997/05/29 03:44:31	1.126
  +++ http_protocol.c	1998/01/30 09:13:56	1.127
  @@ -281,8 +281,9 @@
        *   and the response status does not require a close;
        *   and the response generator has not already indicated close;
        *   and the client did not request non-persistence (Connection: close);
  +     *   and    we haven't been configured to ignore the buggy twit
  +     *       or they're a buggy twit coming through a HTTP/1.1 proxy
        *   and    the client is requesting an HTTP/1.0-style keep-alive
  -     *          and we haven't been configured to ignore the buggy twit,
        *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
        *   THEN we can be persistent, which requires more headers be output.
        *
  @@ -304,9 +305,10 @@
           !status_drops_connection(r->status) &&
           !wimpy &&
           !find_token(r->pool, conn, "close") &&
  -        (((ka_sent = find_token(r->pool, conn, "keep-alive")) &&
  -          !table_get(r->subprocess_env, "nokeepalive")) ||
  -         (r->proto_num >= 1001))
  +	(!table_get(r->subprocess_env, "nokeepalive") ||
  +	 table_get(r->headers_in, "Via")) &&
  +	((ka_sent = find_token(r->pool, conn, "keep-alive")) ||
  +	   (r->proto_num >= 1001))
          ) {
   	char header[256];
   	int left = r->server->keep_alive_max - r->connection->keepalives;
  @@ -337,7 +339,8 @@
        * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
        * to a HTTP/1.1 client. Better safe than sorry.
        */
  -    table_merge(r->headers_out, "Connection", "close");
  +    if (!wimpy)
  +	table_merge(r->headers_out, "Connection", "close");
   
       r->connection->keepalive = 0;
   
  @@ -925,7 +928,7 @@
   	return AUTH_REQUIRED;
       }
   
  -    if (strcmp(getword (r->pool, &auth_line, ' '), "Basic")) {
  +    if (strcasecmp(getword (r->pool, &auth_line, ' '), "Basic")) {
           /* Client tried to authenticate using wrong auth scheme */
           log_reason ("client used wrong authentication scheme", r->uri, r);
           note_basic_auth_failure (r);
  @@ -933,7 +936,7 @@
       }
   
       t = uudecode (r->pool, auth_line);
  -    r->connection->user = getword_nulls_nc (r->pool, &t, ':');
  +    r->connection->user = getword_nulls_nc (r->connection->pool, &t, ':');
       r->connection->auth_type = "Basic";
   
       *pw = t;
  @@ -1041,9 +1044,17 @@
       
       if (!r->status_line)
           r->status_line = status_lines[index_of_response(r->status)];
  -    
  -    if (table_get(r->subprocess_env,"force-response-1.0"))
  +
  +    /* mod_proxy is only HTTP/1.0, so avoid sending HTTP/1.1 error response;
  +     * kluge around broken browsers when indicated by force-response-1.0
  +     */
  +    if (r->proxyreq
  +	|| (r->proto_num == 1000
  +	    && table_get(r->subprocess_env,"force-response-1.0"))) {
  +
   	protocol = "HTTP/1.0";
  +	r->connection->keepalive = -1;
  +    }
       else
   	protocol = SERVER_PROTOCOL;
   
  @@ -1081,40 +1092,37 @@
       long int bs;
   
       bgetopt(client, BO_BYTECT, &bs);
  -    if (bs == 256 || bs == 257)
  +    if (bs >= 255 && bs <= 257)
           bputs("X-Pad: avoid browser bug\015\012", client);
   
       bputs("\015\012", client);    /* Send the terminating empty line */
   }
   
  +/* Build the Allow field-value from the request handler method mask.
  + * Note that we always allow TRACE, since it is handled below.
  + */
   static char *make_allow(request_rec *r)
   {
  -    int allowed = r->allowed;
  -
  -    if( allowed == 0 ) {
  -	/* RFC2068 #14.7, Allow must contain at least one method.  So rather
  -	 * than deal with the possibility of trying not to emit an Allow:
  -	 * header, i.e. #10.4.6 says 405 Method Not Allowed MUST include
  -	 * an Allow header, we'll just say TRACE is valid.
  -	 */
  -	return( "TRACE" );
  -    }
  -
  -    return 2 + pstrcat(r->pool, (allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
  -		       (allowed & (1 << M_POST)) ? ", POST" : "",
  -		       (allowed & (1 << M_PUT)) ? ", PUT" : "",
  -		       (allowed & (1 << M_DELETE)) ? ", DELETE" : "",
  -		       (allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
  -		       (allowed & (1 << M_TRACE)) ? ", TRACE" : "",
  -		       NULL);
  -    
  +    return 2 + pstrcat(r->pool,
  +                       (r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
  +                       (r->allowed & (1 << M_POST)) ? ", POST" : "",
  +                       (r->allowed & (1 << M_PUT)) ? ", PUT" : "",
  +                       (r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
  +                       (r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
  +                       ", TRACE",
  +                       NULL);
   }
   
   int send_http_trace (request_rec *r)
   {
  +    int rv;
  +
       /* Get the original request */
       while (r->prev) r = r->prev;
   
  +    if ((rv = setup_client_block(r, REQUEST_NO_BODY)))
  +        return rv;
  +
       hard_timeout("send TRACE", r);
   
       r->content_type = "message/http";
  @@ -1345,7 +1353,7 @@
   
   int should_client_block (request_rec *r)
   {
  -    if (is_HTTP_ERROR(r->status))
  +    if (r->read_length || is_HTTP_ERROR(r->status))
           return 0;
   
       if (!r->read_chunked && (r->remaining <= 0))
  @@ -1447,7 +1455,11 @@
               buffer[chunk_start++] = LF;
               buffer += chunk_start;       /* and pass line on to caller   */
               bufsiz -= chunk_start;
  -        }
  +        } else {
  +	    /* REQUEST_CHUNKED_DECHUNK -- do not include the length of
  +	     * the header in the return value */
  +	    chunk_start = 0;
  +	}
       }
                                        /* When REQUEST_CHUNKED_PASS, we are */
       if (r->remaining == -1) {        /* reading footers until empty line  */
  @@ -1514,6 +1526,43 @@
       return (chunk_start + len_read);
   }
   
  +/* In HTTP/1.1, any method can have a body.  However, most GET handlers
  + * wouldn't know what to do with a request body if they received one.
  + * This helper routine tests for and reads any message body in the request,
  + * simply discarding whatever it receives.  We need to do this because
  + * failing to read the request body would cause it to be interpreted
  + * as the next request on a persistent connection.  
  + *
  + * Since we return an error status if the request is malformed, this
  + * routine should be called at the beginning of a no-body handler, e.g.,
  + *
  + *    if ((retval = discard_request_body(r)) != OK)
  + *        return retval;
  + */
  +int discard_request_body(request_rec *r)
  +{
  +    int rv;
  +
  +    if ((rv = setup_client_block(r, REQUEST_CHUNKED_PASS)))
  +        return rv;
  +
  +    if (should_client_block(r)) {
  +        char dumpbuf[HUGE_STRING_LEN];
  +
  +        hard_timeout("reading request body", r);
  +        while ((rv = get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
  +            continue;
  +        kill_timeout(r);
  +
  +        if (rv < 0)
  +            return HTTP_BAD_REQUEST;
  +    }
  +    return OK;
  +}
  +
  +/*
  + * Send the body of a response to the client.
  + */
   long send_fd(FILE *f, request_rec *r) { return send_fd_length(f, r, -1); }
   
   long send_fd_length(FILE *f, request_rec *r, long length)
  @@ -1539,12 +1588,12 @@
               break;
           }
           o=0;
  -	total_bytes_sent += n;
   
           while (n && !r->connection->aborted) {
               w = bwrite(r->connection->client, &buf[o], n);
               if (w > 0) {
                   reset_timeout(r); /* reset timeout after successful write */
  +		total_bytes_sent += w;
                   n-=w;
                   o+=w;
               }
  
  
  
  1.20      +1 -0      apache-1.2/src/http_protocol.h
  
  Index: http_protocol.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_protocol.h,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- http_protocol.h	1997/04/07 10:58:38	1.19
  +++ http_protocol.h	1998/01/30 09:13:57	1.20
  @@ -134,6 +134,7 @@
   int setup_client_block (request_rec *r, int read_policy);
   int should_client_block (request_rec *r);
   long get_client_block (request_rec *r, char *buffer, int bufsiz);
  +int discard_request_body (request_rec *r);
   
   /* Sending a byterange */
   
  
  
  
  1.51      +90 -22    apache-1.2/src/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/http_request.c,v
  retrieving revision 1.50
  retrieving revision 1.51
  diff -u -r1.50 -r1.51
  --- http_request.c	1997/05/14 19:22:52	1.50
  +++ http_request.c	1998/01/30 09:13:58	1.51
  @@ -85,6 +85,24 @@
    * they change, all the way down.
    */
   
  +
  +/*
  + * We don't want people able to serve up pipes, or unix sockets, or other
  + * scary things.  Note that symlink tests are performed later.
  + */
  +static int check_safe_file(request_rec *r)
  +{
  +    if (r->finfo.st_mode == 0		/* doesn't exist */
  +	|| S_ISDIR (r->finfo.st_mode)
  +	|| S_ISREG (r->finfo.st_mode)
  +	|| S_ISLNK (r->finfo.st_mode)) {
  +	return OK;
  +    }
  +    log_reason("object is not a file, directory or symlink", r->filename, r);
  +    return HTTP_FORBIDDEN;
  +}
  +
  +
   int check_symlinks (char *d, int opts)
   {
       struct stat lfi, fi;
  @@ -310,17 +328,23 @@
       if (res != OK) {
   	return res;
       }
  -    
  +
  +    if ((res = check_safe_file(r))) {
  +	return res;
  +    }
  +
       if (test_filename[strlen(test_filename)-1] == '/')
   	--num_dirs;
   
  -    if (S_ISDIR (r->finfo.st_mode)) ++num_dirs;
  +    if (S_ISDIR (r->finfo.st_mode)) {
  +	++num_dirs;
  +    }
   
       for (i = 1; i <= num_dirs; ++i) {
           core_dir_config *core_dir =
   	  (core_dir_config *)get_module_config(per_dir_defaults, &core_module);
   	int overrides_here;
  -        void *this_conf = NULL, *htaccess_conf = NULL;
  +        void *this_conf, *htaccess_conf = NULL;
   	char *this_dir = make_dirstr (r->pool, test_filename, i);
   	int j;
         
  @@ -349,6 +373,7 @@
   	      (core_dir_config *)get_module_config(entry_config, &core_module);
   	    entry_dir = entry_core->d;
   	
  +	    this_conf = NULL;
   	    if (entry_core->r) {
   		if (!regexec(entry_core->r, this_dir, 0, NULL,
   			     (j == num_sec) ? 0 : REG_NOTEOL)) {
  @@ -399,8 +424,16 @@
   
       r->per_dir_config = per_dir_defaults;
   
  -    if ((res = check_symlinks (r->filename, allow_options(r))))
  -    {
  +    /* Symlink permissions are determined by the parent.  If the request is for
  +     * a directory then applying the symlink test here would use the
  +     * permissions of the directory as opposed to its parent.  Consider a
  +     * symlink pointing to a dir with a .htaccess disallowing symlinks.  If you
  +     * access /symlink (or /symlink/) you would get a 403 without this S_ISDIR
  +     * test.  But if you accessed /symlink/index.html, for example, you would
  +     * *not* get the 403.
  +     */
  +    if (!S_ISDIR (r->finfo.st_mode)
  +	&& (res = check_symlinks (r->filename, allow_options(r)))) {
   	log_reason("Symbolic link not allowed", r->filename, r);
   	return res;
       }
  @@ -669,24 +702,38 @@
   	    rnew->finfo.st_mode = 0;
   	}
   
  -	rnew->per_dir_config = r->per_dir_config;
  -
  -	if ((res = check_symlinks (rnew->filename, allow_options (rnew)))) {
  -	    log_reason ("Symbolic link not allowed", rnew->filename, rnew);
  +	if ((res = check_safe_file(rnew))) {
   	    rnew->status = res;
   	    return rnew;
   	}
  -	/* do a file_walk, if it doesn't change the per_dir_config then
  -	 * we know that we don't have to redo all the access checks */
  -	if ((res = file_walk (rnew))) {
  -	    rnew->status = res;
  -	    return rnew;
  -	}
  -	if (rnew->per_dir_config == r->per_dir_config) {
  -	    if ((res = find_types (rnew)) || (res = run_fixups (rnew))) {
  +
  +	rnew->per_dir_config = r->per_dir_config;
  +
  +	/* no matter what, if it's a subdirectory, we need to re-run
  +	 * directory_walk */
  +	if (S_ISDIR (rnew->finfo.st_mode)) {
  +	    res = directory_walk (rnew);
  +	    if (!res) {
  +		res = file_walk (rnew);
  +	    }
  +	} else {
  +	    if ((res = check_symlinks (rnew->filename, allow_options (rnew)))) {
  +		log_reason ("Symbolic link not allowed", rnew->filename, rnew);
   		rnew->status = res;
  +		return rnew;
  +	    }
  +	    /* do a file_walk, if it doesn't change the per_dir_config then
  +	     * we know that we don't have to redo all the access checks */
  +	    if ((res = file_walk (rnew))) {
  +		rnew->status = res;
  +		return rnew;
  +	    }
  +	    if (rnew->per_dir_config == r->per_dir_config) {
  +		if ((res = find_types (rnew)) || (res = run_fixups (rnew))) {
  +		    rnew->status = res;
  +		}
  +		return rnew;
   	    }
  -	    return rnew;
   	}
       } else {
   	/* XXX: this should be set properly like it is in the same-dir case
  @@ -764,6 +811,16 @@
          
       r->status = type;
   
  +    /*
  +     * If we want to keep the connection, be sure that the request body
  +     * (if any) has been read.
  +     */
  +    if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
  +        && !status_drops_connection(r->status)
  +        && r->connection && (r->connection->keepalive != -1)) {
  +        (void) discard_request_body(r);
  +    }
  +
       /* Two types of custom redirects --- plain text, and URLs.
        * Plain text has a leading '"', so the URL code, here, is triggered
        * on its absence
  @@ -859,9 +916,12 @@
   	((r->proto_num == 1001) && !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
  +	 * 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.
   	 */
  -        log_reason ("client sent HTTP/1.1 request without hostname",
  +        log_reason ("client sent HTTP/1.1 request without hostname (see RFC2068 sections 9 and 14.23)",
   		    r->uri, r);
   	die (BAD_REQUEST, r);
   	return;
  @@ -873,8 +933,10 @@
            * we handle it specially.
            */
           if (r->method_number == M_TRACE) {
  -            send_http_trace(r);
  -            finalize_request_protocol(r);
  +            if ((access_status = send_http_trace(r)))
  +	        die(access_status, r);
  +            else
  +                finalize_request_protocol(r);
               return;
           }
   
  @@ -898,6 +960,10 @@
   	return;
       }
   
  +    if (r->proto_num > 1000 && table_get (r->subprocess_env, "downgrade-1.0")) {
  +	r->proto_num = 1000;
  +    }
  +
       /* NB: directory_walk() clears the per_dir_config, so we don't inherit from
          location_walk() above */
   
  @@ -1057,6 +1123,8 @@
   				  * about this, don't change 'em back!
   				  */
       new->no_local_copy = r->no_local_copy;
  +
  +    new->read_length = r->read_length;  /* We can only read it once */
   
       ap_snprintf (t, sizeof(t), "%d", r->status);
       table_set (new->subprocess_env, "REDIRECT_STATUS", pstrdup (r->pool, t));
  
  
  
  1.112     +54 -1     apache-1.2/src/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/httpd.h,v
  retrieving revision 1.111
  retrieving revision 1.112
  diff -u -r1.111 -r1.112
  --- httpd.h	1997/06/05 22:53:27	1.111
  +++ httpd.h	1998/01/30 09:13:59	1.112
  @@ -74,6 +74,7 @@
   #endif
   #endif
   
  +#ifndef DOCUMENT_LOCATION
   /* Root of server */
   #ifdef __EMX__
   /* Set default for OS/2 file system */ 
  @@ -81,6 +82,7 @@
   #else
   #define DOCUMENT_LOCATION "/usr/local/etc/httpd/htdocs"
   #endif
  +#endif
   
   /* Max. number of dynamically loaded modules */
   #define DYNAMIC_MODULE_LIMIT 64
  @@ -112,20 +114,31 @@
   #endif
   
   /* The name of the log files */
  +#ifndef DEFAULT_XFERLOG
   #ifdef __EMX__
   /* Set default for OS/2 file system */ 
   #define DEFAULT_XFERLOG "logs/access.log"
   #else
   #define DEFAULT_XFERLOG "logs/access_log"
   #endif
  +#endif /* DEFAULT_XFERLOG */
  +#ifndef DEFAULT_ERRORLOG
   #ifdef __EMX__
   /* Set default for OS/2 file system */ 
   #define DEFAULT_ERRORLOG "logs/error.log"
   #else
   #define DEFAULT_ERRORLOG "logs/error_log"
   #endif
  +#endif /* DEFAULT_ERRORLOG */
  +#ifndef DEFAULT_PIDLOG
   #define DEFAULT_PIDLOG "logs/httpd.pid"
  +#endif
  +#ifndef DEFAULT_SCOREBOARD
   #define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
  +#endif
  +#ifndef DEFAULT_LOCKFILE
  +#define DEFAULT_LOCKFILE "logs/accept.lock"
  +#endif
   
   /* Define this to be what your HTML directory content files are called */
   #define DEFAULT_INDEX "index.html"
  @@ -150,14 +163,20 @@
   #define SERVER_CONFIG_FILE "conf/httpd.conf"
   #endif
   
  +#ifndef RESOURCE_CONFIG_FILE
   /* The name of the document config file */
   #define RESOURCE_CONFIG_FILE "conf/srm.conf"
  +#endif
   
  +#ifndef TYPES_CONFIG_FILE
   /* The name of the MIME types file */
   #define TYPES_CONFIG_FILE "conf/mime.types"
  +#endif
   
  +#ifndef ACCESS_CONFIG_FILE
   /* The name of the access file */
   #define ACCESS_CONFIG_FILE "conf/access.conf"
  +#endif
   
   /* Whether we should enable rfc1413 identity checking */
   #define DEFAULT_RFC1413 0
  @@ -255,19 +274,25 @@
    * Example: "Apache/1.1.0 MrWidget/0.1-alpha" 
    */
   
  -#define SERVER_BASEVERSION "Apache/1.2.1-dev" /* SEE COMMENTS ABOVE */
  +#define SERVER_BASEVERSION "Apache/1.2.6-dev" /* SEE COMMENTS ABOVE */
   #ifdef SERVER_SUBVERSION
   #define SERVER_VERSION	SERVER_BASEVERSION " " SERVER_SUBVERSION
   #else
   #define SERVER_VERSION	SERVER_BASEVERSION
   #endif
   
  +/* Numeric release version identifier: major minor bugfix betaseq
  + * Always increases along the same track as the source branch.
  + */
  +#define APACHE_RELEASE 1020501
  +
   #define SERVER_PROTOCOL "HTTP/1.1"
   #define SERVER_SUPPORT "http://www.apache.org/"
   
   #define DECLINED -1		/* Module declines to handle */
   #define OK 0			/* Module has handled this stage. */
   
  +
   /* ----------------------- HTTP Status Codes  ------------------------- */
   
   #define RESPONSE_CODES 38
  @@ -711,3 +736,31 @@
   unsigned long get_virthost_addr (const char *hostname, unsigned short *port);
   
   extern time_t restart_time;
  +
  +/*
  + * Apache tries to keep all of its long term filehandles (such as log files,
  + * and sockets) above this number.  This is to workaround problems in many
  + * third party libraries that are compiled with a small FD_SETSIZE.  There
  + * should be no reason to lower this, because it's only advisory.  If a file
  + * can't be allocated above this number then it will remain in the "slack"
  + * area.
  + *
  + * Only the low slack line is used by default.  If HIGH_SLACK_LINE is defined
  + * then an attempt is also made to keep all non-FILE * files above the high
  + * slack line.  This is to work around a Solaris C library limitation, where it
  + * uses an unsigned char to store the file descriptor.
  + */
  +#ifndef LOW_SLACK_LINE
  +#define LOW_SLACK_LINE	15
  +#endif
  +/* #define HIGH_SLACK_LINE	255 */
  +
  +/*
  + * The ap_slack() function takes a fd, and tries to move it above the indicated
  + * line.  It returns an fd which may or may not have moved above the line, and
  + * never fails.  If the high line was requested and it fails it will also try
  + * the low line.
  + */
  +int ap_slack (int fd, int line);
  +#define AP_SLACK_LOW	1
  +#define AP_SLACK_HIGH	2
  
  
  
  1.16      +1 -1      apache-1.2/src/mod_auth_anon.c
  
  Index: mod_auth_anon.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_auth_anon.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- mod_auth_anon.c	1997/03/19 03:12:52	1.15
  +++ mod_auth_anon.c	1998/01/30 09:14:01	1.16
  @@ -239,7 +239,7 @@
   	      (strpbrk(".",send_pw) != NULL))
   	  ) 
   	) {
  -      if (sec->auth_anon_logemail) {
  +      if (sec->auth_anon_logemail && r->prev == NULL && r->main == NULL) {
   	ap_snprintf(errstr, sizeof(errstr), "Anonymous: Passwd <%s> Accepted", 
   			send_pw ? send_pw : "\'none\'");
   	log_error (errstr, r->server );
  
  
  
  1.10      +4 -4      apache-1.2/src/mod_browser.c
  
  Index: mod_browser.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_browser.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- mod_browser.c	1997/04/24 23:35:21	1.9
  +++ mod_browser.c	1998/01/30 09:14:02	1.10
  @@ -139,7 +139,7 @@
   { NULL },
   };
   
  -int parse_headers_browser_module(request_rec *r)
  +static int browser_match(request_rec *r)
   {
       server_rec *s = r->server;
       browser_server_config_rec *sconf = get_module_config (s->module_config,
  @@ -166,7 +166,7 @@
   	}
       }
   
  -    return OK;  
  +    return DECLINED;  
   }
   
   module browser_module = {
  @@ -178,12 +178,12 @@
      merge_browser_config,     	/* merge server configs */
      browser_module_cmds,		/* command table */
      NULL,			/* handlers */
  -   NULL,			/* filename translation */
  +   browser_match,		/* filename translation */
      NULL,			/* check_user_id */
      NULL,			/* check auth */
      NULL,			/* check access */
      NULL,			/* type_checker */
      NULL,			/* fixups */
      NULL,			/* logger */
  -   parse_headers_browser_module	/* header parser */
  +   NULL				/* header parser */
   };
  
  
  
  1.11      +14 -20    apache-1.2/src/mod_cern_meta.c
  
  Index: mod_cern_meta.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_cern_meta.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- mod_cern_meta.c	1997/03/07 14:15:39	1.10
  +++ mod_cern_meta.c	1998/01/30 09:14:02	1.11
  @@ -131,6 +131,7 @@
   #include <sys/stat.h>
   #include "util_script.h"
   #include "http_log.h"
  +#include "http_request.h"
   
   #define DEFAULT_METADIR		".web"
   #define DEFAULT_METASUFFIX	".meta"
  @@ -238,10 +239,10 @@
       char *last_slash;
       char *real_file;
       char *scrap_book;
  -    struct stat meta_stat;
       FILE *f;   
       cern_meta_config *cmc ;
       int rv;
  +    request_rec *rr;
   
       cmc = get_module_config (r->server->module_config,
                              &cern_meta_module); 
  @@ -276,30 +277,23 @@
   
       metafilename = pstrcat(r->pool, "/", scrap_book, "/", cmc->metadir, "/", real_file, cmc->metasuffix, NULL);
   
  -    /*
  -     * stat can legitimately fail for a bewildering number of reasons,
  -     * only one of which implies the file isn't there.  A hardened
  -     * version of this module should test for all conditions, but later...
  +    /* XXX: it sucks to require this subrequest to complete, because this
  +     * means people must leave their meta files accessible to the world.
  +     * A better solution might be a "safe open" feature of pfopen to avoid
  +     * pipes, symlinks, and crap like that.
        */
  -    if (stat(metafilename, &meta_stat) == -1) {
  -	/* stat failed, possibly file missing */
  +    rr = sub_req_lookup_file (metafilename, r);
  +    if (rr->status != HTTP_OK) {
  +	destroy_sub_req (rr);
   	return DECLINED;
  -    };
  -
  -    /*
  -     * this check is to be found in other Jan/96 Apache code, I've
  -     * not been able to find any corroboration in the man pages but
  -     * I've been wrong before so I'll put it in anyway.  Never
  -     * admit to being clueless...
  -     */
  -    if ( meta_stat.st_mode == 0 ) {
  -	/* stat failed, definately file missing */
  -	return DECLINED;
  -    };
  +    }
  +    destroy_sub_req (rr);
   
       f = pfopen (r->pool, metafilename, "r");
  -    
       if (f == NULL) {
  +	if (errno == ENOENT) {
  +	    return DECLINED;
  +	}
           log_reason("meta file permissions deny server access", metafilename, r);
           return FORBIDDEN;
       };
  
  
  
  1.40      +2 -1      apache-1.2/src/mod_cgi.c
  
  Index: mod_cgi.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_cgi.c,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- mod_cgi.c	1997/04/21 20:29:09	1.39
  +++ mod_cgi.c	1998/01/30 09:14:03	1.40
  @@ -333,7 +333,8 @@
        */
       
       ap_snprintf(err_string, sizeof(err_string),
  -	    "exec of %s failed, errno is %d\n", r->filename, errno);
  +	    "exec of %s failed, reason: %s (errno = %d)\n", 
  +            r->filename, strerror(errno), errno);
       write(2, err_string, strlen(err_string));
       exit(0);
   }
  
  
  
  1.15      +1 -1      apache-1.2/src/mod_digest.c
  
  Index: mod_digest.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_digest.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- mod_digest.c	1997/03/07 14:15:39	1.14
  +++ mod_digest.c	1998/01/30 09:14:04	1.15
  @@ -145,7 +145,7 @@
       return AUTH_REQUIRED;
     }
   
  -  if (strcmp(getword (r->pool, &auth_line, ' '), "Digest")) {
  +  if (strcasecmp(getword (r->pool, &auth_line, ' '), "Digest")) {
       /* Client tried to authenticate using wrong auth scheme */
       log_reason ("client used wrong authentication scheme", r->uri, r);
       note_digest_auth_failure (r);
  
  
  
  1.27      +19 -0     apache-1.2/src/mod_dir.c
  
  Index: mod_dir.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_dir.c,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- mod_dir.c	1997/05/13 04:01:50	1.26
  +++ mod_dir.c	1998/01/30 09:14:04	1.27
  @@ -164,11 +164,17 @@
   }
   
   const char *add_header(cmd_parms *cmd, void *d, char *name) {
  +    if (strchr (name, '/')) {
  +	return "HeaderName cannot contain a /";
  +    }
       push_item(((dir_config_rec *)d)->hdr_list, 0, NULL, cmd->path, name);
       return NULL;
   }
   
   const char *add_readme(cmd_parms *cmd, void *d, char *name) {
  +    if (strchr (name, '/')) {
  +	return "ReadmeName cannot contain a /";
  +    }
       push_item(((dir_config_rec *)d)->rdme_list, 0, NULL, cmd->path, name);
       return NULL;
   }
  @@ -408,7 +414,9 @@
       FILE *f;
       struct stat finfo;
       int plaintext=0;
  +    request_rec *rr;
   
  +    /* XXX: this is a load of crap, it needs to do a full sub_req_lookup_uri */
       fn = make_full_path(r->pool, name, readme_fname);
       fn = pstrcat(r->pool, fn, ".html", NULL);
       if(stat(fn,&finfo) == -1) {
  @@ -421,6 +429,14 @@
           rputs("<PRE>\n", r);
       }
       else if (rule) rputs("<HR>\n", r);
  +    /* XXX: when the above is rewritten properly, this necessary security
  +     * check will be redundant. -djg */
  +    rr = sub_req_lookup_file (fn, r);
  +    if (rr->status != HTTP_OK) {
  +	destroy_sub_req (rr);
  +	return 0;
  +    }
  +    destroy_sub_req (rr);
       if(!(f = pfopen(r->pool,fn,"r")))
           return 0;
       if (!plaintext)
  @@ -462,6 +478,9 @@
       FILE *thefile = NULL;
       int x,y,n,p;
   
  +    if (r->status != HTTP_OK) {
  +	return NULL;
  +    }
       if (r->content_type && !strcmp(r->content_type,"text/html") && !r->content_encoding) {
           if(!(thefile = pfopen(r->pool, r->filename,"r")))
               return NULL;
  
  
  
  1.22      +655 -615  apache-1.2/src/mod_imap.c
  
  Index: mod_imap.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_imap.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- mod_imap.c	1997/04/12 04:24:58	1.21
  +++ mod_imap.c	1998/01/30 09:14:05	1.22
  @@ -20,7 +20,8 @@
    *
    * 4. The names "Apache Server" and "Apache Group" must not be used to
    *    endorse or promote products derived from this software without
  - *    prior written permission.
  + *    prior written permission. For written permission, please contact
  + *    apache@apache.org.
    *
    * 5. Redistributions of any form whatsoever must retain the following
    *    acknowledgment:
  @@ -96,8 +97,6 @@
   #include "util_script.h"
   
   #define IMAP_MAGIC_TYPE "application/x-httpd-imap"
  -#define LARGEBUF 500
  -#define SMALLBUF 256
   #define MAXVERTS 100
   #define X 0
   #define Y 1
  @@ -107,62 +106,65 @@
   #define IMAP_BASE_DEFAULT "map"
   
   #ifdef SUNOS4
  -double strtod();   /* SunOS needed this */
  +double strtod();                /* SunOS needed this */
   #endif
   
   module imap_module;
   
  -typedef struct { 
  -  char *imap_menu;
  -  char *imap_default;
  -  char *imap_base;
  +typedef struct {
  +    char *imap_menu;
  +    char *imap_default;
  +    char *imap_base;
   } imap_conf_rec;
   
  -void *create_imap_dir_config (pool *p, char *dummy) { 
  -  imap_conf_rec *icr = 
  -    (imap_conf_rec *)palloc(p, sizeof(imap_conf_rec));
  -
  -  icr->imap_menu = NULL;
  -  icr->imap_default = NULL;
  -  icr->imap_base = NULL;
  -
  -  return icr;
  -}
  -
  -void *merge_imap_dir_configs (pool *p, void *basev, void *addv)
  -{
  -  imap_conf_rec *new=(imap_conf_rec *)pcalloc (p, sizeof(imap_conf_rec));
  -  imap_conf_rec *base = (imap_conf_rec *)basev;
  -  imap_conf_rec *add = (imap_conf_rec *)addv;
  - 
  -  new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
  -  new->imap_default=add->imap_default ? add->imap_default : base->imap_default;
  -  new->imap_base =add-> imap_base ? add->imap_base : base->imap_base;
  -
  -  return new;
  +static void *create_imap_dir_config(pool *p, char *dummy)
  +{
  +    imap_conf_rec *icr =
  +    (imap_conf_rec *) palloc(p, sizeof(imap_conf_rec));
  +
  +    icr->imap_menu = NULL;
  +    icr->imap_default = NULL;
  +    icr->imap_base = NULL;
  +
  +    return icr;
  +}
  +
  +static void *merge_imap_dir_configs(pool *p, void *basev, void *addv)
  +{
  +    imap_conf_rec *new = (imap_conf_rec *) pcalloc(p, sizeof(imap_conf_rec));
  +    imap_conf_rec *base = (imap_conf_rec *) basev;
  +    imap_conf_rec *add = (imap_conf_rec *) addv;
  +
  +    new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
  +    new->imap_default = add->imap_default ? add->imap_default : base->imap_default;
  +    new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
  +
  +    return new;
   }
   
   
  -command_rec imap_cmds[] = {
  -{ "ImapMenu", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
  -    "the type of menu generated: none, formatted, semiformatted, unformatted"},
  -{ "ImapDefault", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
  -    "the action taken if no match: error, nocontent, referer, menu, URL" },
  -{ "ImapBase", set_string_slot, 
  -    (void*)XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
  -    "the base for all URL's: map, referer, URL (or start of)" },
  -{ NULL }
  +static command_rec imap_cmds[] =
  +{
  +    {"ImapMenu", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
  + "the type of menu generated: none, formatted, semiformatted, unformatted"},
  +    {"ImapDefault", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
  +     "the action taken if no match: error, nocontent, referer, menu, URL"},
  +    {"ImapBase", set_string_slot,
  +     (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
  +     "the base for all URL's: map, referer, URL (or start of)"},
  +    {NULL}
   };
   
  -int pointinrect(double point[2], double coords[MAXVERTS][2])
  +static int pointinrect(const double point[2], double coords[MAXVERTS][2])
   {
       double max[2], min[2];
       if (coords[0][X] > coords[1][X]) {
           max[0] = coords[0][X];
           min[0] = coords[1][X];
  -    } else {
  +    }
  +    else {
           max[0] = coords[1][X];
           min[0] = coords[0][X];
       }
  @@ -170,33 +172,35 @@
       if (coords[0][Y] > coords[1][Y]) {
           max[1] = coords[0][Y];
           min[1] = coords[1][Y];
  -    } else {
  +    }
  +    else {
           max[1] = coords[1][Y];
           min[1] = coords[0][Y];
       }
   
       return ((point[X] >= min[0] && point[X] <= max[0]) &&
  -	    (point[Y] >= min[1] && point[Y] <= max[1]));
  +            (point[Y] >= min[1] && point[Y] <= max[1]));
   }
   
  -int pointincircle(double point[2], double coords[MAXVERTS][2])
  +static int pointincircle(const double point[2], double coords[MAXVERTS][2])
   {
  -    int radius1, radius2;
  +    double radius1, radius2;
   
       radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
  -	+ ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
  -    
  +        + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
  +
       radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
  -	+ ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  +        + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
   
       return (radius2 <= radius1);
   }
   
  -int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  +static int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
   {
       int i, numverts, inside_flag, xflag0;
       int crossings;
  -    double *p, *stop;
  +    double *p;
  +    const double *stop;
       double tx, ty, y;
   
       for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++);
  @@ -211,54 +215,54 @@
       p = (double *) pgon + 1;
       if ((y >= ty) != (*p >= ty)) {
   
  -	if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) {
  -	    if (xflag0)
  -		crossings++;
  -	}
  -	else {
  -	    crossings += (pgon[numverts - 1][X] - (y - ty) *
  -			  (*(double *) pgon - pgon[numverts - 1][X]) /
  -			  (*p - y)) >= tx;
  -	}
  +        if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx)) {
  +            if (xflag0)
  +                crossings++;
  +        }
  +        else {
  +            crossings += (pgon[numverts - 1][X] - (y - ty) *
  +                          (*(double *) pgon - pgon[numverts - 1][X]) /
  +                          (*p - y)) >= tx;
  +        }
       }
   
       stop = pgon[numverts];
   
       for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  -	
  -	if (y >= ty) {
  -        
  -	    while ((p < stop) && (*p >= ty))
  -		p += 2;
  -	    
  -	    if (p >= stop)
  -		break;
  -	    if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  -		
  -		if (xflag0)
  -		    crossings++;
  -	    }
  -	    else {
  -		crossings += (*(p - 3) - (*(p - 2) - ty) *
  -			      (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  -	    }
  -	}
  -	else {
  -	    while ((p < stop) && (*p < ty))
  -		p += 2;
   
  -	    if (p >= stop)
  -		break;
  +        if (y >= ty) {
   
  -	    if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  -		if (xflag0)
  -		    crossings++;
  -	    }
  -	    else {
  -		crossings += (*(p - 3) - (*(p - 2) - ty) *
  -			      (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  -	    }
  -	}
  +            while ((p < stop) && (*p >= ty))
  +                p += 2;
  +
  +            if (p >= stop)
  +                break;
  +            if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  +
  +                if (xflag0)
  +                    crossings++;
  +            }
  +            else {
  +                crossings += (*(p - 3) - (*(p - 2) - ty) *
  +                              (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  +            }
  +        }
  +        else {
  +            while ((p < stop) && (*p < ty))
  +                p += 2;
  +
  +            if (p >= stop)
  +                break;
  +
  +            if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  +                if (xflag0)
  +                    crossings++;
  +            }
  +            else {
  +                crossings += (*(p - 3) - (*(p - 2) - ty) *
  +                              (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  +            }
  +        }
       }
   
       inside_flag = crossings & 0x01;
  @@ -266,572 +270,608 @@
   }
   
   
  -int is_closer(double point[2], double coords[MAXVERTS][2], double *closest)
  +static int is_closer(const double point[2], double coords[MAXVERTS][2],
  +                     double *closest)
   {
  -  double dist_squared =((point[X] - coords[0][X]) * (point[X] - coords[0][X]))
  -	     + ((point[Y] - coords[0][Y]) * (point[Y] - coords[0][Y]));
  +    double dist_squared = ((point[X] - coords[0][X]) * (point[X] - coords[0][X]))
  +    + ((point[Y] - coords[0][Y]) * (point[Y] - coords[0][Y]));
  +
  +    if (point[X] < 0 || point[Y] < 0)
  +        return (0);             /* don't mess around with negative coordinates */
   
  -  if (point[X] < 0 || point[Y] < 0 ) 
  -    return(0);          /* don't mess around with negative coordinates */
  +    if (*closest < 0 || dist_squared < *closest) {
  +        *closest = dist_squared;
  +        return (1);             /* if this is the first point or is the closest yet
  +                                   set 'closest' equal to this distance^2 */
  +    }
   
  -  if ( *closest < 0 || dist_squared < *closest ) {
  -    *closest = dist_squared;
  -    return(1);         /* if this is the first point or is the closest yet
  -			  set 'closest' equal to this distance^2 */
  -  }
  -  
  -  return(0);           /* if it's not the first or closest */
  +    return (0);                 /* if it's not the first or closest */
   
   }
   
  -double get_x_coord(char *args) 
  +static double get_x_coord(const char *args)
   {
  -  char *endptr;           /* we want it non-null */
  -  double x_coord = -1;    /* -1 is returned if no coordinate is given */
  +    char *endptr;               /* we want it non-null */
  +    double x_coord = -1;        /* -1 is returned if no coordinate is given */
   
  -  if (args == NULL)
  -    return(-1);           /* in case we aren't passed anything */
  +    if (args == NULL)
  +        return (-1);            /* in case we aren't passed anything */
   
  -  while( *args && !isdigit(*args) && *args != ',') 
  -    args++;   /* jump to the first digit, but not past a comma or end */
  +    while (*args && !isdigit(*args) && *args != ',')
  +        args++;                 /* jump to the first digit, but not past a comma or end */
   
  -  x_coord = strtod(args, &endptr);
  +    x_coord = strtod(args, &endptr);
   
  -  if (endptr > args)   /* if a conversion was made */
  -    return(x_coord); 
  +    if (endptr > args)          /* if a conversion was made */
  +        return (x_coord);
   
  -  return(-1);  /* else if no conversion was made, or if no args was given */
  +    return (-1);                /* else if no conversion was made, or if no args was given */
   }
   
  -double get_y_coord(char *args) 
  +static double get_y_coord(const char *args)
   {
  -  char *endptr;        /* we want it non-null */
  -  char *start_of_y = NULL;
  -  double y_coord = -1;    /* -1 is returned on error */
  +    char *endptr;               /* we want it non-null */
  +    char *start_of_y = NULL;
  +    double y_coord = -1;        /* -1 is returned on error */
   
  -  if (args == NULL)
  -    return(-1);           /* in case we aren't passed anything */
  +    if (args == NULL)
  +        return (-1);            /* in case we aren't passed anything */
   
  -  start_of_y = strchr(args, ',');  /* the comma */
  +    start_of_y = strchr(args, ',');     /* the comma */
   
  -  if (start_of_y) {
  -    
  -    start_of_y++;    /* start looking at the character after the comma */
  +    if (start_of_y) {
   
  -    while( *start_of_y && !isdigit(*start_of_y))  
  -      start_of_y++;  /* jump to the first digit, but not past the end */
  +        start_of_y++;           /* start looking at the character after the comma */
   
  -    y_coord = strtod(start_of_y, &endptr);
  +        while (*start_of_y && !isdigit(*start_of_y))
  +            start_of_y++;       /* jump to the first digit, but not past the end */
  +
  +        y_coord = strtod(start_of_y, &endptr);
  +
  +        if (endptr > start_of_y)
  +            return (y_coord);
  +    }
   
  -    if (endptr > start_of_y) 
  -      return(y_coord); 
  -  }
  -  
  -  return(-1);   /* if no conversion was made, or no comma was found in args */
  +    return (-1);                /* if no conversion was made, or no comma was found in args */
   }
  -  
   
  -int read_quoted(char *string, char *quoted_part)
  -{ 
  -  char *starting_pos = string;
  -  
  -  while ( isspace(*string) )
  -    string++;    /* go along string until non-whitespace */
   
  -  if ( *string == '"' ) { /* if that character is a double quote */
  +/* See if string has a "quoted part", and if so set *quoted_part to
  + * the first character of the quoted part, then hammer a \0 onto the
  + * trailing quote, and set *string to point at the first character
  + * past the second quote.
  + *
  + * Otherwise set *quoted_part to NULL, and leave *string alone.
  + */
  +static void read_quoted(char **string, char **quoted_part)
  +{
  +    char *strp = *string;
   
  -    string++;  /* step over it */
  +    /* assume there's no quoted part */
  +    *quoted_part = NULL;
   
  -    while ( *string && *string != '"' ) {
  -      *quoted_part++ = *string++;  /* copy the quoted portion */
  -    }
  +    while (isspace(*strp))
  +        strp++;               	/* go along string until non-whitespace */
  +
  +    if (*strp == '"') {       	/* if that character is a double quote */
  +        strp++;               	/* step over it */
  +	*quoted_part = strp;  	/* note where the quoted part begins */
  +
  +        while (*strp && *strp != '"') {
  +	    ++strp;		/* skip the quoted portion */
  +        }
   
  -    *quoted_part = '\0';  /* end the string with a SNUL */
  -	
  -    string++;  /* step over the last double quote */
  -  }
  +        *strp = '\0';    	/* end the string with a NUL */
   
  -  return(string - starting_pos); /* return the total characters read */
  +        strp++;               	/* step over the last double quote */
  +	*string = strp;
  +    }
   }
   
   /*
  - * url needs to point to a string with at least SMALLBUF memory allocated
  + * returns the mapped URL or NULL.
    */
  -void imap_url(request_rec *r, char *base, char *value, char *url) 
  +static char *imap_url(request_rec *r, const char *base, const char *value)
   {
   /* translates a value into a URL. */
  -  int slen, clen;
  -  char *string_pos = NULL;
  -  char *directory = NULL;
  -  char *referer = NULL;
  -  char my_base[SMALLBUF] = {'\0'};
  -
  -  if ( ! strcasecmp(value, "map" ) || ! strcasecmp(value, "menu") ) {
  -    if (r->server->port == DEFAULT_PORT ) { 
  -      ap_snprintf(url, SMALLBUF,
  -		"http://%s%s", r->server->server_hostname, r->uri);
  +    int slen, clen;
  +    char *string_pos = NULL;
  +    const char *string_pos_const = NULL;
  +    char *directory = NULL;
  +    char *referer = NULL;
  +    char *my_base;
  +
  +    if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
  +	return construct_url(r->pool, r->uri, r->server);
  +    }
  +
  +    if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
  +        return pstrdup(r->pool, value);                 /* these are handled elsewhere, so just copy them */
  +    }
  +
  +    if (!strcasecmp(value, "referer")) {
  +        referer = table_get(r->headers_in, "Referer");
  +        if (referer && *referer) {
  +	    return pstrdup(r->pool, referer);
  +        }
  +        else {
  +	    /* XXX:  This used to do *value = '\0'; ... which is totally bogus
  +	     * because it hammers the passed in value, which can be a string constant,
  +	     * or part of a config, or whatever.  Total garbage.  This works around
  +	     * that without changing the rest of this code much
  +	     */
  +            value = "";      /* if 'referer' but no referring page, null the value */
  +        }
  +    }
  +
  +    string_pos_const = value;
  +    while (isalpha(*string_pos_const))
  +	string_pos_const++;           /* go along the URL from the map until a non-letter */
  +    if (*string_pos_const == ':') {
  +	/* if letters and then a colon (like http:) */
  +	/* it's an absolute URL, so use it! */
  +	return pstrdup(r->pool, value);
  +    }
  +
  +    if (!base || !*base) {
  +        if (value && *value) {
  +	    return pstrdup(r->pool, value); /* no base: use what is given */
  +        }
  +	/* no base, no value: pick a simple default */
  +	return construct_url(r->pool, "/", r->server);
  +    }
  +
  +    /* must be a relative URL to be combined with base */
  +    if (strchr(base, '/') == NULL && (!strncmp(value, "../", 3) || !strcmp(value, ".."))) {
  +        log_reason("invalid base directive in map file: %s", r->uri, r);
  +        return NULL;
  +    }
  +    my_base = pstrdup(r->pool, base);
  +    string_pos = my_base;
  +    while (*string_pos) {
  +        if (*string_pos == '/' && *(string_pos + 1) == '/') {
  +            string_pos += 2;    /* if there are two slashes, jump over them */
  +            continue;
  +        }
  +        if (*string_pos == '/') {       /* the first single slash */
  +            if (value[0] == '/') {
  +                *string_pos = '\0';
  +            }                   /* if the URL from the map starts from root, end the
  +                                   base URL string at the first single slash */
  +            else {
  +                directory = string_pos;         /* save the start of the directory portion */
  +
  +                string_pos = strrchr(string_pos, '/');  /* now reuse string_pos */
  +                string_pos++;   /* step over that last slash */
  +                *string_pos = '\0';
  +            }                   /* but if the map url is relative, leave the
  +                                   slash on the base (if there is one) */
  +            break;
  +        }
  +        string_pos++;           /* until we get to the end of my_base without finding
  +                                   a slash by itself */
  +    }
  +
  +    while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
  +
  +        if (directory && (slen = strlen(directory))) {
  +
  +            /* for each '..',  knock a directory off the end 
  +               by ending the string right at the last slash.
  +               But only consider the directory portion: don't eat
  +               into the server name.  And only try if a directory
  +               portion was found */
  +
  +            clen = slen - 1;
  +
  +            while ((slen - clen) == 1) {
  +
  +                if ((string_pos = strrchr(directory, '/')))
  +                    *string_pos = '\0';
  +                clen = strlen(directory);
  +                if (clen == 0)
  +                    break;
  +            }
  +
  +            value += 2;         /* jump over the '..' that we found in the value */
  +        }
  +        else if (directory) {
  +            log_reason("invalid directory name in map file: %s", r->uri, r);
  +            return NULL;
  +        }
  +
  +        if (!strncmp(value, "/../", 4) || !strcmp(value, "/.."))
  +            value++;            /* step over the '/' if there are more '..' to do.
  +                                   this way, we leave the starting '/' on value after
  +                                   the last '..', but get rid of it otherwise */
  +
  +    }                           /* by this point, value does not start with '..' */
  +
  +    if (value && *value) {
  +	return pstrcat(r->pool, my_base, value, NULL);
  +    }
  +    return my_base;
  +}
  +
  +static int imap_reply(request_rec *r, char *redirect)
  +{
  +    if (!strcasecmp(redirect, "error")) {
  +        return SERVER_ERROR;    /* they actually requested an error! */
  +    }
  +    if (!strcasecmp(redirect, "nocontent")) {
  +        return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
  +    }
  +    if (redirect && *redirect) {
  +        table_set(r->headers_out, "Location", redirect);
  +        return REDIRECT;        /* must be a URL, so redirect to it */
  +    }
  +    return SERVER_ERROR;
  +}
  +
  +static void menu_header(request_rec *r, char *menu)
  +{
  +    r->content_type = "text/html";
  +    send_http_header(r);
  +    hard_timeout("send menu", r);       /* killed in menu_footer */
  +
  +    rvputs(r, "<html><head>\n<title>Menu for ", r->uri,
  +           "</title>\n</head><body>\n", NULL);
  +
  +    if (!strcasecmp(menu, "formatted")) {
  +        rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
       }
  -    else {
  -      ap_snprintf(url, SMALLBUF, "http://%s:%d%s", r->server->server_hostname,
  -	      r->server->port, r->uri);      
  +
  +    return;
  +}
  +
  +static void menu_blank(request_rec *r, char *menu)
  +{
  +    if (!strcasecmp(menu, "formatted")) {
  +        rputs("\n", r);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rputs("<br>\n", r);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rputs("\n", r);
  +    }
  +    return;
  +}
  +
  +static void menu_comment(request_rec *r, char *menu, char *comment)
  +{
  +    if (!strcasecmp(menu, "formatted")) {
  +        rputs("\n", r);         /* print just a newline if 'formatted' */
  +    }
  +    if (!strcasecmp(menu, "semiformatted") && *comment) {
  +        rvputs(r, comment, "\n", NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted") && *comment) {
  +        rvputs(r, comment, "\n", NULL);
       }
  -    return;  
  -  }
  +    return;                     /* comments are ignored in the 'formatted' form */
  +}
   
  -  if ( ! strcasecmp(value, "nocontent") || ! strcasecmp(value, "error") ) {
  -    strncpy(url, value, SMALLBUF-1);
  -    url[SMALLBUF-1] = '\0';
  -    return;    /* these are handled elsewhere, so just copy them */
  -  }
  -
  -  if ( ! strcasecmp(value, "referer" ) ) {
  -    referer = table_get(r->headers_in, "Referer");
  -    if ( referer && *referer ) {
  -      strncpy(url, referer, SMALLBUF-1);
  -      url[SMALLBUF-1] = '\0';
  -      return;
  +static void menu_default(request_rec *r, char *menu, char *href, char *text)
  +{
  +    if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
  +        return;                 /* don't print such lines, these aren'te really href's */
  +    }
  +    if (!strcasecmp(menu, "formatted")) {
  +        rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
       }
  -    else {
  -      *value = '\0';  /* if 'referer' but no referring page, null the value */
  -    }                 
  -  }         
  -
  -  string_pos = value;
  -  while ( isalpha(*string_pos) )
  -    string_pos++;    /* go along the URL from the map until a non-letter */
  -  if ( *string_pos == ':' ) { 
  -    strncpy(url, value, SMALLBUF-1);        /* if letters and then a colon (like http:) */
  -    url[SMALLBUF-1] = '\0';
  -    return;                    /* it's an absolute URL, so use it! */
  -  }
  -
  -  if ( ! base || ! *base ) {
  -    if ( value && *value ) {  
  -      strncpy(url, value, SMALLBUF-1);   /* no base: use what is given */
  -      url[SMALLBUF-1] = '\0';
  -    }         
  -    else {                  
  -      if (r->server->port == DEFAULT_PORT ) {  
  -	ap_snprintf(url, SMALLBUF, "http://%s/", r->server->server_hostname);
  -      }            
  -      if (r->server->port != DEFAULT_PORT ) {
  -	ap_snprintf(url, SMALLBUF, "http://%s:%d/",
  -		r->server->server_hostname, r->server->port);
  -      }                     /* no base, no value: pick a simple default */
  -    }
  -    return;  
  -  }
  -
  -  strncpy(my_base, base, sizeof(my_base)-1);  /* must be a relative URL to be combined with base */
  -  my_base[sizeof(my_base)-1] = '\0';
  -  if (strchr(my_base, '/') == NULL && (!strncmp(value, "../", 3) || !strcmp(value, "..")) ) {
  -    url[0] = '\0';
  -    log_reason("invalid base directive in map file", r->uri, r);
       return;
  -  }
  -  string_pos = my_base; 
  -  while (*string_pos) {  
  -    if (*string_pos == '/' && *(string_pos+1) == '/') {
  -      string_pos += 2;  /* if there are two slashes, jump over them */
  -      continue;
  -    }
  -    if (*string_pos == '/') {  /* the first single slash */
  -	if ( value[0] == '/' ) {
  -	  *string_pos = '\0';  
  -	}              /* if the URL from the map starts from root, end the
  -			  base URL string at the first single slash */
  -	else {
  -	  directory = string_pos; /* save the start of the directory portion */
  +}
  +
  +static void menu_directive(request_rec *r, char *menu, char *href, char *text)
  +{
  +    if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
  +        return;                 /* don't print such lines, as this isn't really an href */
  +    }
  +    if (!strcasecmp(menu, "formatted")) {
  +        rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "semiformatted")) {
  +        rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  +               NULL);
  +    }
  +    if (!strcasecmp(menu, "unformatted")) {
  +        rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  +    }
  +    return;
  +}
  +
  +static void menu_footer(request_rec *r)
  +{
  +    rputs("\n\n</body>\n</html>\n", r);         /* finish the menu */
  +    kill_timeout(r);
  +}
   
  -	  string_pos = strrchr(string_pos, '/');  /* now reuse string_pos */
  -	  string_pos++;  /* step over that last slash */
  -	  *string_pos = '\0';
  -	}              /* but if the map url is relative, leave the
  -			slash on the base (if there is one) */
  -	break;
  -      }
  -    string_pos++;   /* until we get to the end of my_base without finding
  -		       a slash by itself */
  -  }
  -
  -  while ( ! strncmp(value, "../", 3) || ! strcmp(value, "..") ) { 
  -
  -      if (directory && (slen = strlen (directory))) {
  -
  -	  /* for each '..',  knock a directory off the end 
  -	     by ending the string right at the last slash.
  -	     But only consider the directory portion: don't eat
  -	     into the server name.  And only try if a directory
  -	     portion was found */    
  -	  
  -	  clen = slen - 1;
  -	
  -	  while ((slen - clen) == 1) {
  -	
  -	      if ((string_pos = strrchr(directory, '/')))
  -		  *string_pos = '\0';
  -	      clen = strlen (directory);
  -	      if (clen == 0) break;
  -	  }
  -
  -	  value += 2;      /* jump over the '..' that we found in the value */
  -      }
  -      
  -      if (! strncmp(value, "/../", 4) || ! strcmp(value, "/..") )
  -
  -	  value++;       /* step over the '/' if there are more '..' to do.
  -			   this way, we leave the starting '/' on value after
  -			   the last '..', but get rid of it otherwise */ 
  -     
  -  }                   /* by this point, value does not start with '..' */
  -
  -  if ( value && *value ) {
  -    ap_snprintf(url, SMALLBUF, "%s%s", my_base, value);   
  -  }
  -  else {
  -    ap_snprintf(url, SMALLBUF, "%s", my_base);   
  -  }
  -  return;
  -}
  -
  -int imap_reply(request_rec *r, char *redirect)
  -{ 
  -  if ( ! strcasecmp(redirect, "error") ) {
  -    return SERVER_ERROR;  /* they actually requested an error! */
  -  }
  -  if ( ! strcasecmp(redirect, "nocontent") ) {
  -    return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
  -  }
  -  if (redirect && *redirect ) { 
  -    table_set(r->headers_out, "Location", redirect);
  -    return REDIRECT;      /* must be a URL, so redirect to it */
  -  }    
  -  return SERVER_ERROR;
  -}
  -
  -void menu_header(request_rec *r, char *menu)
  -{
  -  r->content_type = "text/html";
  -  send_http_header(r);
  -  hard_timeout("send menu", r);   /* killed in menu_footer */
  -
  -  rvputs(r, "<html><head>\n<title>Menu for ", r->uri,
  -	    "</title>\n</head><body>\n", NULL);
  -
  -  if (!strcasecmp(menu, "formatted")) {
  -    rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
  -  } 
  -
  -  return;
  -}
  -
  -void menu_blank(request_rec *r, char *menu)
  -{
  -  if (! strcasecmp(menu, "formatted") ) {
  -    rputs("\n", r);
  -  }
  -  if (! strcasecmp(menu, "semiformatted") ) {
  -    rputs("<br>\n", r);
  -  }
  -  if (! strcasecmp(menu, "unformatted") ) {
  -    rputs("\n", r);  
  -  }
  -  return;  
  -}
  -
  -void menu_comment(request_rec *r, char *menu, char *comment)
  -{
  -  if (! strcasecmp(menu, "formatted") ) {
  -    rputs("\n", r);  /* print just a newline if 'formatted' */
  -  }
  -  if (! strcasecmp(menu, "semiformatted") && *comment ) {
  -    rvputs(r, comment, "\n", NULL);
  -  }             
  -  if (! strcasecmp(menu, "unformatted") && *comment ) {
  -    rvputs(r, comment, "\n", NULL);
  -  }             
  -  return;    /* comments are ignored in the 'formatted' form */
  -}
  -
  -void menu_default(request_rec *r, char *menu, char *href, char *text)
  -{
  -  if ( ! strcasecmp(href, "error") || ! strcasecmp(href, "nocontent") ) {
  -    return;   /* don't print such lines, these aren'te really href's */
  -  }
  -  if ( ! strcasecmp(menu, "formatted" ) ) {
  -    rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "semiformatted" ) ) {
  -    rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "unformatted" ) ) {
  -    rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  -  }
  -  return;
  -}
  -
  -void menu_directive(request_rec *r, char *menu, char *href, char *text)
  -{
  -  if ( ! strcasecmp(href, "error") || ! strcasecmp(href, "nocontent") ) {
  -    return;   /* don't print such lines, as this isn't really an href */
  -  }
  -  if ( ! strcasecmp(menu, "formatted" ) ) {
  -    rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "semiformatted" ) ) {
  -    rvputs(r, "<pre>          <a href=\"", href, "\">", text, "</a></pre>\n",
  -	   NULL);
  -  }
  -  if ( ! strcasecmp(menu, "unformatted" ) ) {
  -    rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
  -  }
  -  return;
  -}
  -
  -void menu_footer(request_rec *r)
  -{
  -  rputs("\n\n</body>\n</html>\n", r);  /* finish the menu */
  -  kill_timeout(r);
  -}
  -
  -int imap_handler(request_rec *r)
  -{
  -  char input[LARGEBUF] = {'\0'};
  -	/* size of input can not be lowered without changing hard-coded
  -	 * checks
  +static int imap_handler(request_rec *r)
  +{
  +    char input[MAX_STRING_LEN];
  +    char *directive;
  +    char *value;
  +    char *href_text;
  +    char *base;
  +    char *redirect;
  +    char *mapdflt;
  +    char *closest = NULL;
  +    double closest_yet = -1;
  +
  +    double testpoint[2];
  +    double pointarray[MAXVERTS + 1][2];
  +    int vertex;
  +
  +    char *string_pos;
  +    int showmenu = 0;
  +
  +    imap_conf_rec *icr = get_module_config(r->per_dir_config, &imap_module);
  +
  +    char *imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
  +    char *imap_default = icr->imap_default
  +			    ?  icr->imap_default : IMAP_DEFAULT_DEFAULT;
  +    char *imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
  +
  +    FILE *imap; 
  +
  +    if (r->method_number != M_GET)
  +	return DECLINED;
  +
  +    imap = pfopen(r->pool, r->filename, "r"); 
  +
  +    if (!imap)
  +        return NOT_FOUND;
  +
  +    base = imap_url(r, NULL, imap_base);         /* set base according to default */
  +    if (!base)
  +	return HTTP_INTERNAL_SERVER_ERROR;
  +    mapdflt = imap_url(r, NULL, imap_default);   /* and default to global default */
  +    if (!mapdflt)
  +	return HTTP_INTERNAL_SERVER_ERROR;
  +
  +    testpoint[X] = get_x_coord(r->args);
  +    testpoint[Y] = get_y_coord(r->args);
  +
  +    if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
  +        (testpoint[X] == 0 && testpoint[Y] == 0)) {
  +        /* if either is -1 or if both are zero (new Lynx) */
  +        /* we don't have valid coordinates */
  +        testpoint[X] = -1;
  +        testpoint[Y] = -1;
  +        if (strncasecmp(imap_menu, "none", 2))
  +            showmenu = 1;       /* show the menu _unless_ ImapMenu is 'none' or 'no' */
  +    }
  +
  +    if (showmenu) {             /* send start of imagemap menu if we're going to */
  +        menu_header(r, imap_menu);
  +    }
  +
  +    while (!cfg_getline(input, sizeof(input), imap)) {
  +        if (!input[0]) {
  +            if (showmenu) {
  +                menu_blank(r, imap_menu);
  +            }
  +            continue;
  +        }
  +
  +        if (input[0] == '#') {
  +            if (showmenu) {
  +                menu_comment(r, imap_menu, input + 1);
  +            }
  +            continue;
  +        }                       /* blank lines and comments are ignored if we aren't printing a menu */
  +
  +	/* find the first two space delimited fields, recall that
  +	 * cfg_getline has removed leading/trailing whitespace and
  +	 * compressed the other whitespace down to one space a piece
  +	 *
  +	 * note that we're tokenizing as we go... if we were to use the
  +	 * getword() class of functions we would end up allocating extra
  +	 * memory for every line of the map file
   	 */
  -  char href_text[SMALLBUF] = {'\0'};
  -  char base[SMALLBUF] = {'\0'};
  -  char redirect[SMALLBUF] = {'\0'};
  -  char directive[SMALLBUF] = {'\0'};
  -  char value[SMALLBUF] = {'\0'};
  -  char mapdflt[SMALLBUF] = {'\0'};
  -  char closest[SMALLBUF] = {'\0'};
  -  double closest_yet = -1;
  -
  -  double testpoint[2] = { -1,-1 }; 
  -  double pointarray[MAXVERTS + 1][2] = { {-1,-1} };
  -  int vertex = 0;
  -
  -  char *string_pos = NULL;
  -  int chars_read = 0;
  -  int showmenu = 0;
  -
  -  imap_conf_rec *icr = get_module_config(r->per_dir_config, &imap_module);
  -
  -  char *imap_menu = icr->imap_menu ? 
  -    icr->imap_menu : IMAP_MENU_DEFAULT;
  -  char *imap_default = icr->imap_default ? 
  -    icr->imap_default : IMAP_DEFAULT_DEFAULT;
  -  char *imap_base = icr->imap_base ?
  -    icr->imap_base : IMAP_BASE_DEFAULT;
  -
  -  FILE *imap = pfopen(r->pool, r->filename, "r"); 
  -
  -  if ( ! imap ) 
  -    return NOT_FOUND;
  -
  -  imap_url(r, NULL, imap_base, base);       /* set base according to default */
  -  imap_url(r, NULL, imap_default, mapdflt); /* and default to global default */
  -
  -  testpoint[X] = get_x_coord(r->args);
  -  testpoint[Y] = get_y_coord(r->args);
  -
  -  if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
  -      (testpoint[X] == 0  && testpoint[Y] == 0) ) {
  -              /* if either is -1 or if both are zero (new Lynx) */
  -              /* we don't have valid coordinates */
  -    testpoint[X] = -1;
  -    testpoint[Y] = -1;
  -    if ( strncasecmp(imap_menu, "none", 2) )
  -      showmenu = 1;    /* show the menu _unless_ ImapMenu is 'none' or 'no' */
  -  }
  -
  -  if (showmenu) {        /* send start of imagemap menu if we're going to */
  -    menu_header(r, imap_menu);
  -  }
  -
  -  while (!cfg_getline(input, LARGEBUF, imap)) {
  -    string_pos = input;   /* always start at the beginning of line */
  -
  -    directive[0] = '\0';
  -    value[0] = '\0';  
  -    href_text[0] = '\0';
  -    redirect[0] = '\0';
  -    chars_read = 0; /* clear these before using */
  -
  -    if ( ! input[0] ) {     
  -      if (showmenu) {
  -	menu_blank(r, imap_menu);
  -      }
  -      continue;                           
  -    }
  -
  -    if ( input[0] == '#' ) {
  -      if (showmenu) {
  -	menu_comment(r, imap_menu, input + 1); 
  -      }           
  -      continue;
  -    } /* blank lines and comments are ignored if we aren't printing a menu */
  -
  -
  -    if (sscanf(input, "%255s %255s", directive, value) != 2) {
  -      continue;                           /* make sure we read two fields */
  -    }
  -    /* Now skip what we just read... we can't use ANSIism %n */
  -    while (!(isspace(*string_pos)))	/* past directive */
  -	string_pos++;
  -    while (isspace(*string_pos))	/* and whitespace */
  -	string_pos++;
  -    while (!(isspace(*string_pos)))	/* and value... have to watch it */
  -	string_pos++;			/* can have punctuation and stuff */
  -    
  -    if ( ! strncasecmp(directive, "base", 4 ) ) {       /* base, base_uri */
  -      imap_url(r, NULL, value, base);
  -      continue; /* base is never printed to a menu */
  -    }	
  -
  -    chars_read = read_quoted(string_pos, href_text);
  -    string_pos += chars_read;      /* read the quoted href text if present */
  -
  -    if ( ! strcasecmp(directive, "default" ) ) {        /* default */
  -      imap_url(r, NULL, value, mapdflt);
  -      if (showmenu) {              /* print the default if there's a menu */
  -	if (! *href_text) {           /* if we didn't find a "href text" */
  -	  strncpy(href_text, mapdflt, sizeof(href_text)-1); /* use the href itself as text */
  -	  href_text[sizeof(href_text)-1] = '\0';
  +        string_pos = input;
  +	if (!*string_pos)		/* need at least two fields */
  +	    goto need_2_fields;
  +
  +	directive = string_pos;
  +	while (*string_pos && *string_pos != ' ')	/* past directive */
  +	    ++string_pos;
  +	if (!*string_pos)		/* need at least two fields */
  +	    goto need_2_fields;
  +	*string_pos++ = '\0';
  +
  +	if (!*string_pos)		/* need at least two fields */
  +	    goto need_2_fields;
  +	value = string_pos;
  +	while (*string_pos && *string_pos != ' ')	/* past value */
  +	    ++string_pos;
  +	if (*string_pos == ' ') {
  +	    *string_pos++ = '\0';
  +	}
  +	else {
  +	    /* end of input, don't advance past it */
  +	    *string_pos = '\0';
   	}
  -	imap_url(r, base, mapdflt, redirect); 
  -	menu_default(r, imap_menu, redirect, href_text);
  -      }
  -      continue;
  -    }
  -
  -    vertex = 0;
  -    while ( vertex < MAXVERTS &&  
  -     sscanf(string_pos, "%lf, %lf",
  -     &pointarray[vertex][X], &pointarray[vertex][Y])   == 2)
  -    {
  -	/* Now skip what we just read... we can't use ANSIism %n */
  -	while(isspace(*string_pos))	/* past whitespace */
  -	    string_pos++;
  -	while(isdigit(*string_pos))	/* and the 1st number */
  -	    string_pos++;
  -	string_pos++;			/* skip the ',' */
  -	while(isspace(*string_pos))	/* past any more whitespace */
  -	    string_pos++;
  -	while(isdigit(*string_pos))	/* 2nd number */
  -	    string_pos++;
  -	vertex++;
  -    }                /* so long as there are more vertices to read, and
  -			we have room, read them in.  We start where we left
  -			off of the last sscanf, not at the beginning.*/
  -                  
  -    pointarray[vertex][X] = -1;  /* signals the end of vertices */
   
  +        if (!strncasecmp(directive, "base", 4)) {       /* base, base_uri */
  +            base = imap_url(r, NULL, value);
  +	    if (!base)
  +		goto menu_bail;
  +            continue;           /* base is never printed to a menu */
  +        }
  +
  +        read_quoted(&string_pos, &href_text);
  +
  +        if (!strcasecmp(directive, "default")) {        /* default */
  +            mapdflt = imap_url(r, NULL, value);
  +	    if (!mapdflt)
  +		goto menu_bail;
  +            if (showmenu) {     /* print the default if there's a menu */
  +                redirect = imap_url(r, base, mapdflt);
  +		if (!redirect)
  +		    goto menu_bail;
  +                menu_default(r, imap_menu, redirect, href_text ? href_text : mapdflt);
  +            }
  +            continue;
  +        }
  +
  +        vertex = 0;
  +        while (vertex < MAXVERTS &&
  +               sscanf(string_pos, "%lf%*[, ]%lf",
  +                      &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
  +            /* Now skip what we just read... we can't use ANSIism %n */
  +            while (isspace(*string_pos))        /* past whitespace */
  +                string_pos++;
  +            while (isdigit(*string_pos))        /* and the 1st number */
  +                string_pos++;
  +            string_pos++;       /* skip the ',' */
  +            while (isspace(*string_pos))        /* past any more whitespace */
  +                string_pos++;
  +            while (isdigit(*string_pos))        /* 2nd number */
  +                string_pos++;
  +            vertex++;
  +        }                       /* so long as there are more vertices to read, and
  +                                   we have room, read them in.  We start where we left
  +                                   off of the last sscanf, not at the beginning. */
  +
  +        pointarray[vertex][X] = -1;     /* signals the end of vertices */
  +
  +        if (showmenu) {
  +	    if (!href_text) {
  +		read_quoted(&string_pos, &href_text);         /* href text could be here instead */
  +	    }
  +            redirect = imap_url(r, base, value);
  +	    if (!redirect)
  +		goto menu_bail;
  +            menu_directive(r, imap_menu, redirect, href_text ? href_text : value);
  +            continue;
  +        }
  +        /* note that we don't make it past here if we are making a menu */
  +
  +        if (testpoint[X] == -1 || pointarray[0][X] == -1)
  +            continue;           /* don't try the following tests if testpoints
  +                                   are invalid, or if there are no coordinates */
  +
  +        if (!strcasecmp(directive, "poly")) {   /* poly */
  +
  +            if (pointinpoly(testpoint, pointarray)) {
  +		pfclose(r->pool, imap);
  +                redirect = imap_url(r, base, value);
  +		if (!redirect)
  +		    return HTTP_INTERNAL_SERVER_ERROR;
  +                return (imap_reply(r, redirect));
  +            }
  +            continue;
  +        }
  +
  +        if (!strcasecmp(directive, "circle")) {         /* circle */
  +
  +            if (pointincircle(testpoint, pointarray)) {
  +		pfclose(r->pool, imap);
  +                redirect = imap_url(r, base, value);
  +		if (!redirect)
  +		    return HTTP_INTERNAL_SERVER_ERROR;
  +                return (imap_reply(r, redirect));
  +            }
  +            continue;
  +        }
  +
  +        if (!strcasecmp(directive, "rect")) {   /* rect */
  +
  +            if (pointinrect(testpoint, pointarray)) {
  +		pfclose(r->pool, imap);
  +                redirect = imap_url(r, base, value);
  +		if (!redirect)
  +		    return HTTP_INTERNAL_SERVER_ERROR;
  +                return (imap_reply(r, redirect));
  +            }
  +            continue;
  +        }
  +
  +        if (!strcasecmp(directive, "point")) {  /* point */
  +
  +            if (is_closer(testpoint, pointarray, &closest_yet)) {
  +		closest = pstrdup(r->pool, value);
  +            }
  +
  +            continue;
  +        }                       /* move on to next line whether it's closest or not */
  +
  +    }                           /* nothing matched, so we get another line! */
  +
  +    pfclose(r->pool, imap);     /* we are done with the map file, so close it */
  +
  +    if (showmenu) {
  +        menu_footer(r);         /* finish the menu and we are done */
  +        return OK;
  +    }
  +
  +    if (closest) {             /* if a 'point' directive has been seen */
  +        redirect = imap_url(r, base, closest);
  +	if (!redirect)
  +	    return HTTP_INTERNAL_SERVER_ERROR;
  +        return (imap_reply(r, redirect));
  +    }
  +
  +    if (mapdflt) {             /* a default should be defined, even if only 'nocontent' */
  +        redirect = imap_url(r, base, mapdflt);
  +	if (!redirect)
  +	    return HTTP_INTERNAL_SERVER_ERROR;
  +        return (imap_reply(r, redirect));
  +    }
  +
  +    return SERVER_ERROR;        /* If we make it this far, we failed. They lose! */
  +
  +need_2_fields:
  +    log_reason("all map file lines require at least two fields", r->uri, r);
  +    /* fall through */
  +menu_bail:
  +    pfclose(r->pool, imap);
       if (showmenu) {
  -      read_quoted(string_pos, href_text); /* href text could be here instead */
  -      if (! *href_text) {           /* if we didn't find a "href text" */
  -	strncpy(href_text, value, sizeof(href_text)-1);  /* use the href itself in the menu */
  -	href_text[sizeof(href_text)-1] = '\0';
  -      }
  -      imap_url(r, base, value, redirect); 
  -      menu_directive(r, imap_menu, redirect, href_text);
  -      continue;
  -    }
  -    /* note that we don't make it past here if we are making a menu */
  -
  -    if (testpoint[X] == -1 || pointarray[0][X] == -1 )
  -      continue;    /* don't try the following tests if testpoints
  -		    are invalid, or if there are no coordinates */
  -
  -    if ( ! strcasecmp(directive, "poly" ) ) {        /* poly */
  -
  -      if (pointinpoly (testpoint, pointarray) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -
  -    if ( ! strcasecmp(directive, "circle" ) ) {        /* circle */
  -	
  -      if (pointincircle (testpoint, pointarray) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -    
  -    if ( ! strcasecmp(directive, "rect" ) ) {        /* rect */
  -      
  -      if (pointinrect (testpoint, pointarray) ) {
  -	pfclose(r->pool, imap); 
  -	imap_url(r, base, value, redirect);     
  -	return (imap_reply(r, redirect));
  -      }
  -      continue;
  -    }
  -    
  -    if ( ! strcasecmp(directive, "point" ) ) {         /* point */
  -      
  -      if (is_closer(testpoint, pointarray, &closest_yet) ) {
  -	strncpy(closest, value, sizeof(closest)-1);  /* if the closest point yet save it */
  -	closest[sizeof(closest)-1] = '\0';
  -      }
  -      
  -      continue;    
  -    }     /* move on to next line whether it's closest or not */
  -    
  -  }       /* nothing matched, so we get another line! */
  -
  -  pfclose(r->pool, imap);   /* we are done with the map file, so close it */
  -
  -  if (showmenu) {
  -    menu_footer(r);   /* finish the menu and we are done */
  -    return OK;                
  -  }
  -
  -  if (*closest) {    /* if a 'point' directive has been seen */
  -    imap_url(r, base, closest, redirect);     
  -    return (imap_reply(r, redirect));
  -  }    
  -
  -  if (*mapdflt ) {   /* a default should be defined, even if only 'nocontent'*/
  -    imap_url(r, base, mapdflt, redirect);
  -    return(imap_reply(r, redirect));
  -  }    
  -
  -  return SERVER_ERROR;   /* If we make it this far, we failed. They lose! */
  -}
  -
  -
  -handler_rec imap_handlers[] = {
  -{ IMAP_MAGIC_TYPE, imap_handler },
  -{ "imap-file", imap_handler },
  -{ NULL }
  +	/* There's not much else we can do ... we've already sent the headers
  +	 * to the client.
  +	 */
  +	rputs("\n\n[an internal server error occured]\n", r);
  +	menu_footer(r);
  +	return OK;
  +    }
  +    return HTTP_INTERNAL_SERVER_ERROR;
  +}
  +
  +
  +static handler_rec imap_handlers[] =
  +{
  +    {IMAP_MAGIC_TYPE, imap_handler},
  +    {"imap-file", imap_handler},
  +    {NULL}
   };
   
  -module imap_module = {
  -   STANDARD_MODULE_STUFF,
  -   NULL,			/* initializer */
  -   create_imap_dir_config,	/* dir config creater */
  -   merge_imap_dir_configs,	/* dir merger --- default is to override */
  -   NULL,			/* server config */
  -   NULL,			/* merge server config */
  -   imap_cmds,			/* command table */
  -   imap_handlers,		/* handlers */
  -   NULL,			/* filename translation */
  -   NULL,			/* check_user_id */
  -   NULL,			/* check auth */
  -   NULL,			/* check access */
  -   NULL,			/* type_checker */
  -   NULL,			/* fixups */
  -   NULL,			/* logger */
  -   NULL				/* header parser */
  +module imap_module =
  +{
  +    STANDARD_MODULE_STUFF,
  +    NULL,                       /* initializer */
  +    create_imap_dir_config,     /* dir config creater */
  +    merge_imap_dir_configs,     /* dir merger --- default is to override */
  +    NULL,                       /* server config */
  +    NULL,                       /* merge server config */
  +    imap_cmds,                  /* command table */
  +    imap_handlers,              /* handlers */
  +    NULL,                       /* filename translation */
  +    NULL,                       /* check_user_id */
  +    NULL,                       /* check auth */
  +    NULL,                       /* check access */
  +    NULL,                       /* type_checker */
  +    NULL,                       /* fixups */
  +    NULL,                       /* logger */
  +    NULL                        /* header parser */
   };
  
  
  
  1.34      +1317 -886 apache-1.2/src/mod_include.c
  
  Index: mod_include.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_include.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- mod_include.c	1997/06/05 00:57:45	1.33
  +++ mod_include.c	1998/01/30 09:14:05	1.34
  @@ -20,7 +20,8 @@
    *
    * 4. The names "Apache Server" and "Apache Group" must not be used to
    *    endorse or promote products derived from this software without
  - *    prior written permission.
  + *    prior written permission. For written permission, please contact
  + *    apache@apache.org.
    *
    * 5. Redistributions of any form whatsoever must retain the following
    *    acknowledgment:
  @@ -91,18 +92,20 @@
   #define STARTING_SEQUENCE "<!--#"
   #define ENDING_SEQUENCE "-->"
   #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
  -#define DEFAULT_TIME_FORMAT "%A, %d-%b-%y %T %Z"
  +#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
   #define SIZEFMT_BYTES 0
   #define SIZEFMT_KMG 1
   
  -static void decodehtml(char *s);
  -static char *get_tag(pool *p, FILE *in, char *tag, int tag_len, int dodecode);
  -static int get_directive(FILE *in, char *d, pool *p);
   
  +static void safe_copy(char *dest, const char *src, size_t max_len)
  +{
  +    strncpy(dest, src, max_len - 1);
  +    dest[max_len - 1] = '\0';
  +}
   
   /* ------------------------ Environment function -------------------------- */
   
  -void add_include_vars(request_rec *r, char *timefmt)
  +static void add_include_vars(request_rec *r, char *timefmt)
   {
       struct passwd *pw;
       table *e = r->subprocess_env;
  @@ -111,26 +114,33 @@
   
       table_set(e, "DATE_LOCAL", ht_time(r->pool, date, timefmt, 0));
       table_set(e, "DATE_GMT", ht_time(r->pool, date, timefmt, 1));
  -    table_set(e, "LAST_MODIFIED",ht_time(r->pool,r->finfo.st_mtime,timefmt,0));
  +    table_set(e, "LAST_MODIFIED",
  +              ht_time(r->pool, r->finfo.st_mtime, timefmt, 0));
       table_set(e, "DOCUMENT_URI", r->uri);
       table_set(e, "DOCUMENT_PATH_INFO", r->path_info);
       pw = getpwuid(r->finfo.st_uid);
       if (pw) {
  -      table_set(e, "USER_NAME", pw->pw_name);
  -    } else {
  -      char uid[16];
  -      ap_snprintf(uid, sizeof(uid), "user#%lu", (unsigned long)r->finfo.st_uid);
  -      table_set(e, "USER_NAME", uid);
  +        table_set(e, "USER_NAME", pw->pw_name);
  +    }
  +    else {
  +        char uid[16];
  +        ap_snprintf(uid, sizeof(uid), "user#%lu",
  +                    (unsigned long) r->finfo.st_uid);
  +        table_set(e, "USER_NAME", uid);
       }
   
  -    if((t = strrchr(r->filename, '/')))
  -        table_set (e, "DOCUMENT_NAME", ++t);
  -    else
  -        table_set (e, "DOCUMENT_NAME", r->uri);
  +    if ((t = strrchr(r->filename, '/'))) {
  +        table_set(e, "DOCUMENT_NAME", ++t);
  +    }
  +    else {
  +        table_set(e, "DOCUMENT_NAME", r->uri);
  +    }
       if (r->args) {
  -        unescape_url (r->args);
  -	  table_set (e, "QUERY_STRING_UNESCAPED",
  -		   escape_shell_cmd (r->pool, r->args));
  +        char *arg_copy = pstrdup(r->pool, r->args);
  +
  +        unescape_url(arg_copy);
  +        table_set(e, "QUERY_STRING_UNESCAPED",
  +                  escape_shell_cmd(r->pool, arg_copy));
       }
   }
   
  @@ -146,9 +156,11 @@
    */
   #define PUT_CHAR(c,r) \
    { \
  -   outbuf[outind++] = c; \
  -   if (outind == OUTBUFSIZE) { FLUSH_BUF(r) }; \
  - } 
  +    outbuf[outind++] = c; \
  +    if (outind == OUTBUFSIZE) { \
  +        FLUSH_BUF(r) \
  +    }; \
  + }
   
   /* there SHOULD be some error checking on the return value of
    * rwrite, however it is unclear what the API for rwrite returning
  @@ -174,39 +186,42 @@
   #define GET_CHAR(f,c,ret,r) \
    { \
      int i = getc(f); \
  -   if(i == EOF) { /* either EOF or error -- needs error handling if latter */ \
  -       if (ferror(f)) \
  -	   fprintf(stderr, "encountered error in GET_CHAR macro, mod_include.\n"); \
  +   if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \
  +       if (ferror(f)) { \
  +           fprintf(stderr, "encountered error in GET_CHAR macro, " \
  +                   "mod_include.\n"); \
  +       } \
          FLUSH_BUF(r); \
  -       pfclose(r->pool,f); \
  +       pfclose(r->pool, f); \
          return ret; \
      } \
      c = (char)i; \
    }
   
  -int find_string(FILE *in,char *str, request_rec *r, int printing) {
  -    int x,l=strlen(str),p;
  +static int find_string(FILE *in, const char *str, request_rec *r, int printing)
  +{
  +    int x, l = strlen(str), p;
       char outbuf[OUTBUFSIZE];
       int outind = 0;
       char c;
   
  -    p=0;
  -    while(1) {
  -        GET_CHAR(in,c,1,r);
  -        if(c == str[p]) {
  -            if((++p) == l) {
  -		FLUSH_BUF(r);
  +    p = 0;
  +    while (1) {
  +        GET_CHAR(in, c, 1, r);
  +        if (c == str[p]) {
  +            if ((++p) == l) {
  +                FLUSH_BUF(r);
                   return 0;
  -	    }
  +            }
           }
           else {
               if (printing) {
  -                for(x=0;x<p;x++) {
  -                    PUT_CHAR(str[x],r);
  +                for (x = 0; x < p; x++) {
  +                    PUT_CHAR(str[x], r);
                   }
  -                PUT_CHAR(c,r);
  +                PUT_CHAR(c, r);
               }
  -            p=0;
  +            p = 0;
           }
       }
   }
  @@ -217,10 +232,12 @@
   #define GET_CHAR(f,c,r,p) \
    { \
      int i = getc(f); \
  -   if(i == EOF) { /* either EOF or error -- needs error handling if latter */ \
  -       if (ferror(f)) \
  -	   fprintf(stderr, "encountered error in GET_CHAR macro, mod_include.\n"); \
  -       pfclose(p,f); \
  +   if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \
  +       if (ferror(f)) { \
  +           fprintf(stderr, "encountered error in GET_CHAR macro, " \
  +                   "mod_include.\n"); \
  +       } \
  +       pfclose(p, f); \
          return r; \
      } \
      c = (char)i; \
  @@ -242,69 +259,79 @@
   
   /* The following is a shrinking transformation, therefore safe. */
   
  -static void
  -decodehtml(char *s)
  +static void decodehtml(char *s)
   {
       int val, i, j;
  -    char *p=s;
  -    char *ents;
  -    static char *entlist[MAXENTLEN+1]={
  -	NULL,  /* 0 */
  -	NULL,  /* 1 */
  -	"lt\074gt\076", /* 2 */
  -	"amp\046ETH\320eth\360", /* 3 */
  -	"quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\
  -iuml\357ouml\366uuml\374yuml\377", /* 4 */
  -	"Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\
  +    char *p = s;
  +    const char *ents;
  +    static const char * const entlist[MAXENTLEN + 1] =
  +    {
  +        NULL,                   /* 0 */
  +        NULL,                   /* 1 */
  +        "lt\074gt\076",         /* 2 */
  +        "amp\046ETH\320eth\360",        /* 3 */
  +        "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\
  +iuml\357ouml\366uuml\374yuml\377",      /* 4 */
  +        "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\
   THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\
  -ucirc\373thorn\376", /* 5 */
  -	"Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\
  +ucirc\373thorn\376",            /* 5 */
  +        "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\
   Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\
   Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\
   egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\
  -otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */
  +otilde\365oslash\370ugrave\371uacute\372yacute\375"     /* 6 */
       };
   
       for (; *s != '\0'; s++, p++) {
  -	if (*s != '&') {
  -	    *p = *s;
  -	    continue;
  -	}
  -	/* find end of entity */
  -	for (i=1; s[i] != ';' && s[i] != '\0'; i++)
  -	    continue;
  -
  -	if (s[i] == '\0') {	/* treat as normal data */
  -	    *p = *s;
  -	    continue;
  -	}
  +        if (*s != '&') {
  +            *p = *s;
  +            continue;
  +        }
  +        /* find end of entity */
  +        for (i = 1; s[i] != ';' && s[i] != '\0'; i++) {
  +            continue;
  +        }
   
  -	/* is it numeric ? */
  -	if (s[1] == '#') {
  -	    for (j=2, val=0; j < i && isdigit(s[j]); j++)
  -		val = val * 10 + s[j] - '0';
  -	    s += i;
  -	    if (j < i || val <= 8 || (val >= 11 && val <= 31) ||
  -		(val >= 127 && val <= 160) || val >= 256)
  -		p--;  /* no data to output */
  -	    else
  -		*p = val;
  -	} else{
  -	    j = i-1;
  -	    if (i-1 > MAXENTLEN || entlist[i-1] == NULL) { /* wrong length */
  -		*p = '&';
  -		continue;  /* skip it */
  -	    }
  -	    for (ents=entlist[i-1]; *ents != '\0'; ents += i)
  -		if (strncmp(s+1, ents, i-1) == 0) break;
  +        if (s[i] == '\0') {     /* treat as normal data */
  +            *p = *s;
  +            continue;
  +        }
   
  -	    if (*ents == '\0')
  -		*p = '&';  /* unknown */
  -	    else {
  -		*p = ((const unsigned char *)ents)[i-1];
  -		s += i;
  -	    }
  -	}
  +        /* is it numeric ? */
  +        if (s[1] == '#') {
  +            for (j = 2, val = 0; j < i && isdigit(s[j]); j++) {
  +                val = val * 10 + s[j] - '0';
  +            }
  +            s += i;
  +            if (j < i || val <= 8 || (val >= 11 && val <= 31) ||
  +                (val >= 127 && val <= 160) || val >= 256) {
  +                p--;            /* no data to output */
  +            }
  +            else {
  +                *p = val;
  +            }
  +        }
  +        else {
  +            j = i - 1;
  +            if (i - 1 > MAXENTLEN || entlist[i - 1] == NULL) {
  +                /* wrong length */
  +                *p = '&';
  +                continue;       /* skip it */
  +            }
  +            for (ents = entlist[i - 1]; *ents != '\0'; ents += i) {
  +                if (strncmp(s + 1, ents, i - 1) == 0) {
  +                    break;
  +                }
  +            }
  +
  +            if (*ents == '\0') {
  +                *p = '&';       /* unknown */
  +            }
  +            else {
  +                *p = ((const unsigned char *) ents)[i - 1];
  +                s += i;
  +            }
  +        }
       }
   
       *p = '\0';
  @@ -316,97 +343,117 @@
    * the tag value is html decoded if dodecode is non-zero
    */
   
  -static char *
  -get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode) {
  +static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode)
  +{
       char *t = tag, *tag_val, c, term;
  -    int n;
   
  -    n = 0;
  +    /* makes code below a little less cluttered */
  +    --tagbuf_len;
   
  -    do { /* skip whitespace */
  -	GET_CHAR(in,c,NULL,p);
  +    do {                        /* skip whitespace */
  +        GET_CHAR(in, c, NULL, p);
       } while (isspace(c));
   
       /* tags can't start with - */
  -    if(c == '-') {
  -        GET_CHAR(in,c,NULL,p);
  -        if(c == '-') {
  +    if (c == '-') {
  +        GET_CHAR(in, c, NULL, p);
  +        if (c == '-') {
               do {
  -		GET_CHAR(in,c,NULL,p);
  -	    } while (isspace(c));
  -            if(c == '>') {
  -                strncpy(tag,"done", tagbuf_len-1);
  -		tag[tagbuf_len-1] = '\0';
  +                GET_CHAR(in, c, NULL, p);
  +            } while (isspace(c));
  +            if (c == '>') {
  +                safe_copy(tag, "done", tagbuf_len);
                   return tag;
               }
           }
  -	return NULL; /* failed */
  +        return NULL;            /* failed */
       }
   
       /* find end of tag name */
  -    while(1) {
  -        if(++n == tagbuf_len) {
  -            t[tagbuf_len - 1] = '\0';
  +    while (1) {
  +        if (t - tag == tagbuf_len) {
  +            *t = '\0';
               return NULL;
           }
  -	if(c == '=' || isspace(c)) break;
  -	*(t++) = tolower(c);
  -        GET_CHAR(in,c,NULL,p);
  +        if (c == '=' || isspace(c)) {
  +            break;
  +        }
  +        *(t++) = tolower(c);
  +        GET_CHAR(in, c, NULL, p);
       }
   
       *t++ = '\0';
       tag_val = t;
   
  -    while (isspace(c)) GET_CHAR(in, c, NULL,p); /* space before = */
  +    while (isspace(c)) {
  +        GET_CHAR(in, c, NULL, p);       /* space before = */
  +    }
       if (c != '=') {
           ungetc(c, in);
           return NULL;
       }
   
       do {
  -	GET_CHAR(in,c,NULL,p);  /* space after = */
  +        GET_CHAR(in, c, NULL, p);       /* space after = */
       } while (isspace(c));
   
       /* we should allow a 'name' as a value */
  -    
  -    if (c != '"' && c != '\'') return NULL;
  +
  +    if (c != '"' && c != '\'') {
  +        return NULL;
  +    }
       term = c;
  -    while(1) {
  -	GET_CHAR(in,c,NULL,p);
  -	if(++n == tagbuf_len) {
  -	    t[tagbuf_len - 1] = '\0';
  -	    return NULL;
  -	}
  +    while (1) {
  +        GET_CHAR(in, c, NULL, p);
  +        if (t - tag == tagbuf_len) {
  +            *t = '\0';
  +            return NULL;
  +        }
   /* Want to accept \" as a valid character within a string. */
  -	if (c == '\\') {
  -	    *(t++) = c; /* Add backslash */
  -	    GET_CHAR(in,c,NULL,p);
  -	    if (c == term) /* Only if */
  -		*(--t) = c; /* Replace backslash ONLY for terminator */
  -	} else if (c == term) break;
  -	*(t++) = c;
  +        if (c == '\\') {
  +            *(t++) = c;         /* Add backslash */
  +            GET_CHAR(in, c, NULL, p);
  +            if (c == term) {    /* Only if */
  +                *(--t) = c;     /* Replace backslash ONLY for terminator */
  +            }
  +        }
  +        else if (c == term) {
  +            break;
  +        }
  +        *(t++) = c;
       }
       *t = '\0';
  -    if (dodecode) decodehtml(tag_val);
  -    return pstrdup (p, tag_val);
  +    if (dodecode) {
  +        decodehtml(tag_val);
  +    }
  +    return pstrdup(p, tag_val);
   }
   
  -static int
  -get_directive(FILE *in, char *d, pool *p) {
  +static int get_directive(FILE *in, char *dest, size_t len, pool *p)
  +{
  +    char *d = dest;
       char c;
   
  +    /* make room for nul terminator */
  +    --len;
  +
       /* skip initial whitespace */
  -    while(1) {
  -        GET_CHAR(in,c,1,p);
  -        if(!isspace(c))
  +    while (1) {
  +        GET_CHAR(in, c, 1, p);
  +        if (!isspace(c)) {
               break;
  +        }
       }
       /* now get directive */
  -    while(1) {
  +    while (1) {
  +	if (d - dest == len) {
  +	    return 1;
  +	}
           *d++ = tolower(c);
  -        GET_CHAR(in,c,1,p);
  -        if(isspace(c))
  +        GET_CHAR(in, c, 1, p);
  +        if (isspace(c)) {
               break;
  +        }
       }
       *d = '\0';
       return 0;
  @@ -415,73 +462,95 @@
   /*
    * Do variable substitution on strings
    */
  -void parse_string(request_rec *r, char *in, char *out, int length,
  -                  int leave_name)
  +static void parse_string(request_rec *r, const char *in, char *out,
  +			size_t length, int leave_name)
   {
       char ch;
       char *next = out;
  -    int numchars = 0;
  +    char *end_out;
  +
  +    /* leave room for nul terminator */
  +    end_out = out + length - 1;
   
       while ((ch = *in++) != '\0') {
  -        switch(ch) {
  -          case '\\':
  -	    if(*in == '$')
  -		*next++=*in++;
  -	    else
  -		*next++=ch;
  -            break;
  -          case '$':
  -          {
  -            char var[MAX_STRING_LEN];
  -            char vtext[MAX_STRING_LEN];
  -            char *val;
  -            int braces=0;
  -            int vlen, vtlen;
  -            /* 
  -             * Keep the $ and { around because we do no substitution
  -             * if the variable isn't found
  -             */
  -            vlen = vtlen = 0;
  -            vtext[vtlen++] = ch;
  -            if (*in == '{') { braces = 1; vtext[vtlen++] = *in++; }
  -            while (*in != '\0') {
  -                if (vlen == (MAX_STRING_LEN - 1)) continue;
  -                if (braces == 1) {
  -                    if (*in == '}') break;
  -                }
  -                else if (! (isalpha((int)*in) || (*in == '_') || isdigit((int)*in)) ) break;
  -                if (vtlen < (MAX_STRING_LEN - 1)) vtext[vtlen++] = *in;
  -                var[vlen++] = *in++;
  -            }
  -            var[vlen] = vtext[vtlen] = '\0';
  -            if (braces == 1) {
  -                if (*in != '}') {
  -                    log_printf(r->server, "Invalid variable %s%s", vtext,in);
  -                    *next = '\0';
  -                    return;
  -                } else
  -                    in++;
  -            } 
  -
  -            val = (char *)NULL;
  -            if (var[0] == '\0') {
  -                val = &vtext[0];
  -            } else {
  -                val = table_get (r->subprocess_env, &var[0]);
  -                if (!val && leave_name)
  -                    val = &vtext[0];
  -            }
  -            while ((val != (char *)NULL) && (*val != '\0')) {
  -                *next++ = *val++;
  -                if (++numchars == (length -1)) break;
  +        switch (ch) {
  +        case '\\':
  +	    if (next == end_out) {
  +		/* truncated */
  +		*next = '\0';
  +		return;
  +	    }
  +            if (*in == '$') {
  +                *next++ = *in++;
  +            }
  +            else {
  +                *next++ = ch;
               }
               break;
  -          }
  -          default:
  +        case '$':
  +            {
  +		char var[MAX_STRING_LEN];
  +		const char *start_of_var_name;
  +		const char *end_of_var_name;	/* end of var name + 1 */
  +		const char *expansion;
  +		const char *val;
  +		size_t l;
  +
  +		/* guess that the expansion won't happen */
  +		expansion = in - 1;
  +		if (*in == '{') {
  +		    ++in;
  +		    start_of_var_name = in;
  +		    in = strchr(in, '}');
  +		    if (in == NULL) {
  +			log_printf(r->server,
  +				    "Missing '}' on variable \"%s\" in %s",
  +				    expansion, r->filename);
  +                        *next = '\0';
  +                        return;
  +                    }
  +		    end_of_var_name = in;
  +		    ++in;
  +		}
  +		else {
  +		    start_of_var_name = in;
  +		    while (isalnum(*in) || *in == '_') {
  +			++in;
  +		    }
  +		    end_of_var_name = in;
  +		}
  +		/* what a pain, too bad there's no table_getn where you can
  +		 * pass a non-nul terminated string */
  +		l = end_of_var_name - start_of_var_name;
  +		l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l;
  +		memcpy(var, start_of_var_name, l);
  +		var[l] = '\0';
  +
  +		val = table_get(r->subprocess_env, var);
  +		if (val) {
  +		    expansion = val;
  +		    l = strlen(expansion);
  +		}
  +		else if (leave_name) {
  +		    l = in - expansion;
  +		}
  +		else {
  +		    break;	/* no expansion to be done */
  +		}
  +		l = (l > end_out - next) ? (end_out - next) : l;
  +		memcpy(next, expansion, l);
  +		next += l;
  +                break;
  +            }
  +        default:
  +	    if (next == end_out) {
  +		/* truncated */
  +		*next = '\0';
  +		return;
  +	    }
               *next++ = ch;
               break;
           }
  -        if (++numchars == (length -1)) break;
       }
       *next = '\0';
       return;
  @@ -489,22 +558,29 @@
   
   /* --------------------------- Action handlers ---------------------------- */
   
  -int include_cgi(char *s, request_rec *r)
  +static int include_cgi(char *s, request_rec *r)
   {
  -    request_rec *rr = sub_req_lookup_uri (s, r);
  -    
  -    if (rr->status != 200) return -1;
  -    
  +    request_rec *rr = sub_req_lookup_uri(s, r);
  +    int rr_status;
  +
  +    if (rr->status != HTTP_OK) {
  +        return -1;
  +    }
  +
       /* No hardwired path info or query allowed */
  -    
  -    if ((rr->path_info && rr->path_info[0]) || rr->args) return -1;
  -    if (rr->finfo.st_mode == 0) return -1;
  +
  +    if ((rr->path_info && rr->path_info[0]) || rr->args) {
  +        return -1;
  +    }
  +    if (rr->finfo.st_mode == 0) {
  +        return -1;
  +    }
   
       /* Script gets parameters of the *document*, for back compatibility */
  -    
  -    rr->path_info = r->path_info; /* painful to get right; see mod_cgi.c */
  +
  +    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
       rr->args = r->args;
  -    
  +
       /* Force sub_req to be treated as a CGI request, even if ordinary
        * typing rules would have called it something else.
        */
  @@ -512,74 +588,117 @@
       rr->content_type = CGI_MAGIC_TYPE;
   
       /* Run it. */
  -    
  -    if (run_sub_req (rr) == REDIRECT) {
  -        char *location = table_get (rr->headers_out, "Location");
  +
  +    rr_status = run_sub_req(rr);
  +    if (is_HTTP_REDIRECT(rr_status)) {
  +        char *location = table_get(rr->headers_out, "Location");
           location = escape_html(rr->pool, location);
  -	rvputs(r,"<A HREF=\"", location, "\">", location, "</A>", NULL);
  +        rvputs(r, "<A HREF=\"", location, "\">", location, "</A>", NULL);
       }
  -    
  -    destroy_sub_req (rr);
  -    
  +
  +    destroy_sub_req(rr);
  +    chdir_file(r->filename);
  +
       return 0;
   }
   
  -int handle_include(FILE *in, request_rec *r, char *error, int noexec) {
  +/* ensure that path is relative, and does not contain ".." elements
  + * ensentially ensure that it does not match the regex:
  + * (^/|(^|/)\.\.(/|$))
  + * XXX: this needs os abstraction... consider c:..\foo in win32
  + */
  +static int is_only_below(const char *path)
  +{
  +    if (path[0] == '/') {
  +	return 0;
  +    }
  +    if (path[0] == '.' && path[1] == '.'
  +	&& (path[2] == '\0' || path[2] == '/')) {
  +	return 0;
  +    }
  +    while (*path) {
  +	if (*path == '/' && path[1] == '.' && path[2] == '.'
  +	    && (path[3] == '\0' || path[3] == '/')) {
  +	    return 0;
  +	}
  +	++path;
  +    }
  +    return 1;
  +}
  +
  +static int handle_include(FILE *in, request_rec *r, const char *error, int noexec)
  +{
       char tag[MAX_STRING_LEN];
       char parsed_string[MAX_STRING_LEN];
       char *tag_val;
   
  -    while(1) {
  -        if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        if(!strcmp(tag,"file") || !strcmp (tag, "virtual")) {
  -	    request_rec *rr=NULL;
  -	    char *error_fmt = NULL;
  -
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -	    if (tag[0] == 'f')
  -	    { /* be safe; only files in this directory or below allowed */
  -		char tmp[MAX_STRING_LEN+2];
  -		ap_snprintf(tmp, sizeof(tmp), "/%s/", parsed_string);
  -		if (parsed_string[0] == '/' || strstr(tmp, "/../") != NULL)
  -		    error_fmt = "unable to include file %s in parsed file %s";
  -		else
  -		    rr = sub_req_lookup_file (parsed_string, r);
  -	    } else
  -		rr = sub_req_lookup_uri (parsed_string, r);
  -	    
  -	    if (!error_fmt && rr->status != 200)
  -	        error_fmt = "unable to include %s in parsed file %s";
  -
  -	    if (!error_fmt && noexec && rr->content_type
  -		&& (strncmp (rr->content_type, "text/", 5)))
  -	        error_fmt =
  -		  "unable to include potential exec %s in parsed file %s";
  -            if (error_fmt == NULL)
  -            {
  +        }
  +        if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) {
  +            request_rec *rr = NULL;
  +            char *error_fmt = NULL;
  +
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            if (tag[0] == 'f') {
  +                /* be safe; only files in this directory or below allowed */
  +		if (!is_only_below(parsed_string)) {
  +                    error_fmt = "unable to include file \"%s\" "
  +                        "in parsed file %s";
  +                }
  +                else {
  +                    rr = sub_req_lookup_file(parsed_string, r);
  +                }
  +            }
  +            else {
  +                rr = sub_req_lookup_uri(parsed_string, r);
  +            }
  +
  +            if (!error_fmt && rr->status != HTTP_OK) {
  +                error_fmt = "unable to include \"%s\" in parsed file %s";
  +            }
  +
  +            if (!error_fmt && noexec && rr->content_type
  +                && (strncmp(rr->content_type, "text/", 5))) {
  +                error_fmt = "unable to include potential exec \"%s\" "
  +                    "in parsed file %s";
  +            }
  +            if (error_fmt == NULL) {
                   request_rec *p;
   
  -                for (p=r; p != NULL; p=p->main)
  -                    if (strcmp(p->filename, rr->filename) == 0) break;
  -                if (p != NULL)
  -                    error_fmt = "Recursive include of %s in parsed file %s";
  -            }
  -	    
  -	    if (!error_fmt && run_sub_req (rr))
  -	        error_fmt = "unable to include %s in parsed file %s";
  -		    
  +                for (p = r; p != NULL; p = p->main) {
  +                    if (strcmp(p->filename, rr->filename) == 0) {
  +                        break;
  +                    }
  +                }
  +                if (p != NULL) {
  +                    error_fmt = "Recursive include of \"%s\" "
  +                        "in parsed file %s";
  +                }
  +            }
  +
  +            if (!error_fmt && run_sub_req(rr)) {
  +                error_fmt = "unable to include \"%s\" in parsed file %s";
  +            }
  +            chdir_file(r->filename);
  +
               if (error_fmt) {
                   log_printf(r->server, error_fmt, tag_val, r->filename);
                   rputs(error, r);
  -            }            
  +            }
   
  -	    if (rr != NULL) destroy_sub_req (rr);
  -        } 
  -        else if(!strcmp(tag,"done"))
  +            if (rr != NULL) {
  +                destroy_sub_req(rr);
  +            }
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            log_printf(r->server, "unknown parameter %s to tag include in %s",
  -                       tag, r->filename);
  +            log_printf(r->server,
  +                        "unknown parameter \"%s\" to tag include in %s",
  +                        tag, r->filename);
               rputs(error, r);
           }
       }
  @@ -590,168 +709,194 @@
       char *s;
   } include_cmd_arg;
   
  -void include_cmd_child (void *arg)
  +static void include_cmd_child(void *arg)
   {
  -    request_rec *r =  ((include_cmd_arg *)arg)->r;
  -    char *s = ((include_cmd_arg *)arg)->s;
  +    request_rec *r = ((include_cmd_arg *) arg)->r;
  +    char *s = ((include_cmd_arg *) arg)->s;
       table *env = r->subprocess_env;
  -#ifdef DEBUG_INCLUDE_CMD    
  -    FILE *dbg = fopen ("/dev/tty", "w");
  -#endif    
  -    char err_string [MAX_STRING_LEN];
  +#ifdef DEBUG_INCLUDE_CMD
  +    FILE *dbg = fopen("/dev/tty", "w");
  +#endif
  +    char err_string[MAX_STRING_LEN];
   
  -#ifdef DEBUG_INCLUDE_CMD    
  +#ifdef DEBUG_INCLUDE_CMD
   #ifdef __EMX__
       /* under OS/2 /dev/tty is referenced as con */
  -    FILE *dbg = fopen ("con", "w");
  +    FILE *dbg = fopen("con", "w");
   #else
  -    fprintf (dbg, "Attempting to include command '%s'\n", s);
  -#endif    
  -#endif    
  +    fprintf(dbg, "Attempting to include command '%s'\n", s);
  +#endif
  +#endif
   
  -    if (r->path_info && r->path_info[0] != '\0')
  -    {
  -	request_rec *pa_req;
  +    if (r->path_info && r->path_info[0] != '\0') {
  +        request_rec *pa_req;
  +
  +        table_set(env, "PATH_INFO", escape_shell_cmd(r->pool, r->path_info));
   
  -	table_set (env, "PATH_INFO", escape_shell_cmd (r->pool, r->path_info));
  -	
  -	pa_req = sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r);
  -	if (pa_req->filename)
  -	    table_set(env, "PATH_TRANSLATED",
  -		      pstrcat(r->pool, pa_req->filename, pa_req->path_info,
  -			      NULL));
  +        pa_req = sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r);
  +        if (pa_req->filename) {
  +            table_set(env, "PATH_TRANSLATED",
  +                      pstrcat(r->pool, pa_req->filename, pa_req->path_info,
  +                              NULL));
  +        }
       }
   
       if (r->args) {
  -        table_set (env, "QUERY_STRING", r->args);
  -	unescape_url (r->args);
  -	table_set (env, "QUERY_STRING_UNESCAPED",
  -		   escape_shell_cmd (r->pool, r->args));
  -    }
  -    
  -    error_log2stderr (r->server);
  -    
  -#ifdef DEBUG_INCLUDE_CMD    
  -    fprintf (dbg, "Attempting to exec '%s'\n", s);
  -#endif    
  +        char *arg_copy = pstrdup(r->pool, r->args);
  +
  +        table_set(env, "QUERY_STRING", r->args);
  +        unescape_url(arg_copy);
  +        table_set(env, "QUERY_STRING_UNESCAPED",
  +                  escape_shell_cmd(r->pool, arg_copy));
  +    }
  +
  +    error_log2stderr(r->server);
  +
  +#ifdef DEBUG_INCLUDE_CMD
  +    fprintf(dbg, "Attempting to exec '%s'\n", s);
  +#endif
       cleanup_for_exec();
       /* set shellcmd flag to pass arg to SHELL_PATH */
  -    call_exec(r, s, create_environment (r->pool, env), 1);
  -    
  +    call_exec(r, s, create_environment(r->pool, env), 1);
       /* Oh, drat.  We're still here.  The log file descriptors are closed,
        * so we have to whimper a complaint onto stderr...
        */
  -    
  -#ifdef DEBUG_INCLUDE_CMD    
  -    fprintf (dbg, "Exec failed\n");
  -#endif    
  +
  +#ifdef DEBUG_INCLUDE_CMD
  +    fprintf(dbg, "Exec failed\n");
  +#endif
       ap_snprintf(err_string, sizeof(err_string),
  -	"httpd: exec of %s failed, errno is %d\n",
  -	SHELL_PATH,errno);
  -    write (2, err_string, strlen(err_string));
  +                "httpd: exec of %s failed, reason: %s (errno = %d)\n",
  +                SHELL_PATH, strerror(errno), errno);
  +    write(STDERR_FILENO, err_string, strlen(err_string));
       exit(0);
   }
   
  -int include_cmd(char *s, request_rec *r) {
  +static int include_cmd(char *s, request_rec *r)
  +{
       include_cmd_arg arg;
       FILE *f;
   
  -    arg.r = r; arg.s = s;
  +    arg.r = r;
  +    arg.s = s;
   
  -    if (!spawn_child (r->pool, include_cmd_child, &arg,
  -		      kill_after_timeout, NULL, &f))
  +    if (!spawn_child(r->pool, include_cmd_child, &arg,
  +                     kill_after_timeout, NULL, &f)) {
           return -1;
  -    
  -    send_fd(f,r);
  -    pfclose(r->pool, f);	/* will wait for zombie when
  -				 * r->pool is cleared
  -				 */
  +    }
  +
  +    send_fd(f, r);
  +    pfclose(r->pool, f);        /* will wait for zombie when
  +                                 * r->pool is cleared
  +                                 */
       return 0;
   }
   
   
  -int handle_exec(FILE *in, request_rec *r, char *error)
  +static int handle_exec(FILE *in, request_rec *r, const char *error)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
       char *file = r->filename;
       char parsed_string[MAX_STRING_LEN];
   
  -    while(1) {
  -        if(!(tag_val = get_tag (r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        if(!strcmp(tag,"cmd")) {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 1);
  -            if(include_cmd(parsed_string, r) == -1) {
  -                log_printf(r->server, "unknown parameter %s to tag include in %s",
  -                           tag, r->filename);
  +        }
  +        if (!strcmp(tag, "cmd")) {
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1);
  +            if (include_cmd(parsed_string, r) == -1) {
  +                log_printf(r->server,
  +                            "execution failure for parameter \"%s\" "
  +                            "to tag exec in file %s",
  +                            tag, r->filename);
                   rputs(error, r);
               }
               /* just in case some stooge changed directories */
               chdir_file(r->filename);
  -        } 
  -        else if(!strcmp(tag,"cgi")) {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            if(include_cgi(parsed_string, r) == -1) {
  -                log_printf(r->server, "invalid CGI ref %s in %s",tag_val,file);
  +        }
  +        else if (!strcmp(tag, "cgi")) {
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            if (include_cgi(parsed_string, r) == -1) {
  +                log_printf(r->server,
  +                            "invalid CGI ref \"%s\" in %s", tag_val, file);
                   rputs(error, r);
               }
               /* grumble groan */
               chdir_file(r->filename);
           }
  -        else if(!strcmp(tag,"done"))
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            log_printf(r->server, "unknown parameter %s to tag exec in %s",
  -                       tag, file);
  +            log_printf(r->server,
  +                        "unknown parameter \"%s\" to tag exec in %s",
  +                        tag, file);
               rputs(error, r);
           }
       }
   
   }
   
  -int handle_echo (FILE *in, request_rec *r, char *error) {
  +static int handle_echo(FILE *in, request_rec *r, const char *error)
  +{
       char tag[MAX_STRING_LEN];
       char *tag_val;
   
  -    while(1) {
  -        if(!(tag_val = get_tag (r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        if(!strcmp(tag,"var")) {
  -	    char *val = table_get (r->subprocess_env, tag_val);
  +        }
  +        if (!strcmp(tag, "var")) {
  +            char *val = table_get(r->subprocess_env, tag_val);
   
  -	    if (val) rputs(val, r);
  -	    else rputs("(none)", r);
  -        } else if(!strcmp(tag,"done"))
  +            if (val) {
  +                rputs(val, r);
  +            }
  +            else {
  +                rputs("(none)", r);
  +            }
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            log_printf(r->server, "unknown parameter %s to tag echo in %s",
  -                tag, r->filename);
  +            log_printf(r->server,
  +                        "unknown parameter \"%s\" to tag echo in %s",
  +                        tag, r->filename);
               rputs(error, r);
           }
       }
   }
  +
   #ifdef USE_PERL_SSI
  -int handle_perl (FILE *in, request_rec *r, char *error) {
  +static int handle_perl(FILE *in, request_rec *r, const char *error)
  +{
       char tag[MAX_STRING_LEN];
       char *tag_val;
       SV *sub = Nullsv;
  -    AV *av  = newAV();
  +    AV *av = newAV();
   
  -    if (!(allow_options (r) & OPT_INCLUDES)) {
  +    if (!(allow_options(r) & OPT_INCLUDES)) {
           log_printf(r->server,
  -            "httpd: #perl SSI disallowed by IncludesNoExec in %s", r->filename);
  -	return DECLINED;
  +                    "httpd: #perl SSI disallowed by IncludesNoExec in %s",
  +                    r->filename);
  +        return DECLINED;
       }
  -    while(1) {
  -	if(!(tag_val = get_tag (r->pool, in, tag, MAX_STRING_LEN, 1))) 
  -	    break;
  -	if(strnEQ(tag, "sub", 3)) 
  -	    sub = newSVpv(tag_val,0);
  -	else if(strnEQ(tag, "arg", 3)) 
  -	    av_push(av, newSVpv(tag_val,0));	
  -	else if(strnEQ(tag,"done", 4))
  -	    break;
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
  +            break;
  +        }
  +        if (strnEQ(tag, "sub", 3)) {
  +            sub = newSVpv(tag_val, 0);
  +        }
  +        else if (strnEQ(tag, "arg", 3)) {
  +            av_push(av, newSVpv(tag_val, 0));
  +        }
  +        else if (strnEQ(tag, "done", 4)) {
  +            break;
  +        }
       }
       perl_stdout2client(r);
       perl_call_handler(sub, r, av);
  @@ -762,124 +907,134 @@
   /* error and tf must point to a string with room for at 
    * least MAX_STRING_LEN characters 
    */
  -int handle_config(FILE *in, request_rec *r, char *error, char *tf,
  -                  int *sizefmt) {
  +static int handle_config(FILE *in, request_rec *r, char *error, char *tf,
  +                         int *sizefmt)
  +{
       char tag[MAX_STRING_LEN];
       char *tag_val;
       char parsed_string[MAX_STRING_LEN];
       table *env = r->subprocess_env;
   
  -    while(1) {
  -        if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 0)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0))) {
               return 1;
  -        if(!strcmp(tag,"errmsg")) {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            strncpy(error,parsed_string,MAX_STRING_LEN-1);
  -	    error[MAX_STRING_LEN-1] = '\0';
  -        } else if(!strcmp(tag,"timefmt")) {
  -  	    time_t date = r->request_time;
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            strncpy(tf,parsed_string,MAX_STRING_LEN-1);
  -	    tf[MAX_STRING_LEN-1] = '\0';
  -            table_set (env, "DATE_LOCAL", ht_time(r->pool,date,tf,0));
  -            table_set (env, "DATE_GMT", ht_time(r->pool,date,tf,1));
  -            table_set (env, "LAST_MODIFIED", ht_time(r->pool,r->finfo.st_mtime,tf,0));
  -        }
  -        else if(!strcmp(tag,"sizefmt")) {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -	    decodehtml(parsed_string);
  -            if(!strcmp(parsed_string,"bytes"))
  +        }
  +        if (!strcmp(tag, "errmsg")) {
  +            parse_string(r, tag_val, error, MAX_STRING_LEN, 0);
  +        }
  +        else if (!strcmp(tag, "timefmt")) {
  +            time_t date = r->request_time;
  +
  +            parse_string(r, tag_val, tf, MAX_STRING_LEN, 0);
  +            table_set(env, "DATE_LOCAL", ht_time(r->pool, date, tf, 0));
  +            table_set(env, "DATE_GMT", ht_time(r->pool, date, tf, 1));
  +            table_set(env, "LAST_MODIFIED",
  +                      ht_time(r->pool, r->finfo.st_mtime, tf, 0));
  +        }
  +        else if (!strcmp(tag, "sizefmt")) {
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            decodehtml(parsed_string);
  +            if (!strcmp(parsed_string, "bytes")) {
                   *sizefmt = SIZEFMT_BYTES;
  -            else if(!strcmp(parsed_string,"abbrev"))
  +            }
  +            else if (!strcmp(parsed_string, "abbrev")) {
                   *sizefmt = SIZEFMT_KMG;
  -        } 
  -        else if(!strcmp(tag,"done"))
  +            }
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            log_printf(r->server,"unknown parameter %s to tag config in %s",
  -                    tag, r->filename);
  +            log_printf(r->server,
  +                        "unknown parameter \"%s\" to tag config in %s",
  +                        tag, r->filename);
               rputs(error, r);
           }
       }
   }
   
   
  -
  -int find_file(request_rec *r, char *directive, char *tag, 
  -              char *tag_val, struct stat *finfo, char *error)
  +static int find_file(request_rec *r, const char *directive, const char *tag,
  +                     char *tag_val, struct stat *finfo, const char *error)
   {
  -    char *dir = "./";
       char *to_send;
   
  -    if(!strcmp(tag,"file")) {
  -        getparents(tag_val); /* get rid of any nasties */
  -        to_send = make_full_path (r->pool, dir, tag_val);
  -        if(stat(to_send,finfo) == -1) {
  +    if (!strcmp(tag, "file")) {
  +        getparents(tag_val);    /* get rid of any nasties */
  +        to_send = make_full_path(r->pool, "./", tag_val);
  +        if (stat(to_send, finfo) == -1) {
               log_printf(r->server,
  -                    "unable to get information about %s in parsed file %s",
  -                    to_send, r->filename);
  +                        "unable to get information about \"%s\" "
  +                        "in parsed file %s",
  +                        to_send, r->filename);
               rputs(error, r);
               return -1;
           }
           return 0;
       }
  -    else if(!strcmp(tag,"virtual")) {
  -	request_rec *rr = sub_req_lookup_uri (tag_val, r);
  -	
  -	if (rr->status == 200 && rr->finfo.st_mode != 0) {
  -	    memcpy ((char*)finfo, (const char *)&rr->finfo, sizeof (struct stat));
  -	    destroy_sub_req (rr);
  -	    return 0;
  -        } else {
  +    else if (!strcmp(tag, "virtual")) {
  +        request_rec *rr = sub_req_lookup_uri(tag_val, r);
  +
  +        if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
  +            memcpy((char *) finfo, (const char *) &rr->finfo,
  +                   sizeof(struct stat));
  +            destroy_sub_req(rr);
  +            return 0;
  +        }
  +        else {
               log_printf(r->server,
  -                    "unable to get information about %s in parsed file %s",
  -                    tag_val, r->filename);
  +                        "unable to get information about \"%s\" "
  +                        "in parsed file %s",
  +                        tag_val, r->filename);
               rputs(error, r);
  -	    destroy_sub_req (rr);
  +            destroy_sub_req(rr);
               return -1;
           }
       }
       else {
  -        log_printf(r->server,"unknown parameter %s to tag %s in %s",
  -                tag, directive, r->filename);
  +        log_printf(r->server,
  +                    "unknown parameter \"%s\" to tag %s in %s",
  +                    tag, directive, r->filename);
           rputs(error, r);
           return -1;
       }
   }
   
   
  -int handle_fsize(FILE *in, request_rec *r, char *error, int sizefmt) 
  +static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
       struct stat finfo;
       char parsed_string[MAX_STRING_LEN];
   
  -    while(1) {
  -        if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        else if(!strcmp(tag,"done"))
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            if(!find_file(r,"fsize",tag,parsed_string,&finfo,error)) {
  -                if(sizefmt == SIZEFMT_KMG) {
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            if (!find_file(r, "fsize", tag, parsed_string, &finfo, error)) {
  +                if (sizefmt == SIZEFMT_KMG) {
                       send_size(finfo.st_size, r);
                   }
                   else {
  -                    int l,x;
  +                    int l, x;
   #if defined(BSD) && BSD > 199305
  -		    /* ap_snprintf can't handle %qd */
  -                    sprintf(tag,"%qd", finfo.st_size);
  +                    /* ap_snprintf can't handle %qd */
  +                    sprintf(tag, "%qd", finfo.st_size);
   #else
  -                    ap_snprintf(tag, sizeof(tag), "%ld",finfo.st_size);
  +                    ap_snprintf(tag, sizeof(tag), "%ld", finfo.st_size);
   #endif
  -                    l = strlen(tag); /* grrr */
  -                    for(x=0;x<l;x++) {
  -                        if(x && (!((l-x) % 3))) {
  +                    l = strlen(tag);    /* grrr */
  +                    for (x = 0; x < l; x++) {
  +                        if (x && (!((l - x) % 3))) {
                               rputc(',', r);
                           }
  -                        rputc (tag[x],r);
  +                        rputc(tag[x], r);
                       }
                   }
               }
  @@ -887,136 +1042,204 @@
       }
   }
   
  -int handle_flastmod(FILE *in, request_rec *r, char *error, char *tf) 
  +static int handle_flastmod(FILE *in, request_rec *r, const char *error, const char *tf)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
       struct stat finfo;
       char parsed_string[MAX_STRING_LEN];
   
  -    while(1) {
  -        if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    while (1) {
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        else if(!strcmp(tag,"done"))
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  +        }
           else {
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            if(!find_file(r,"flastmod",tag,parsed_string,&finfo,error))
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            if (!find_file(r, "flastmod", tag, parsed_string, &finfo, error)) {
                   rputs(ht_time(r->pool, finfo.st_mtime, tf, 0), r);
  +            }
           }
       }
  -}    
  +}
   
  -int re_check(request_rec *r, char *string, char *rexp) 
  +static int re_check(request_rec *r, char *string, char *rexp)
   {
       regex_t *compiled;
       int regex_error;
   
  -    compiled = pregcomp (r->pool, rexp, REG_EXTENDED|REG_NOSUB);
  +    compiled = pregcomp(r->pool, rexp, REG_EXTENDED | REG_NOSUB);
       if (compiled == NULL) {
  -        log_printf(r->server, "unable to compile pattern %s", rexp);
  +        log_printf(r->server, "unable to compile pattern \"%s\"", rexp);
           return -1;
       }
  -    regex_error = regexec(compiled, string, 0, (regmatch_t *)NULL, 0);
  -    pregfree (r->pool, compiled);
  -    return(!regex_error);
  +    regex_error = regexec(compiled, string, 0, (regmatch_t *) NULL, 0);
  +    pregfree(r->pool, compiled);
  +    return (!regex_error);
   }
   
  -enum token_type { token_string,
  +enum token_type {
  +    token_string,
       token_and, token_or, token_not, token_eq, token_ne,
  -    token_rbrace, token_lbrace, token_group
  +    token_rbrace, token_lbrace, token_group,
  +    token_ge, token_le, token_gt, token_lt
   };
   struct token {
       enum token_type type;
       char value[MAX_STRING_LEN];
   };
   
  -char *get_ptoken(request_rec *r, char *string, struct token *token) {
  +/* there is an implicit assumption here that string is at most MAX_STRING_LEN-1
  + * characters long...
  + */
  +static const char *get_ptoken(request_rec *r, const char *string, struct token *token)
  +{
       char ch;
  -    int next=0;
  -    int qs=0;
  +    int next = 0;
  +    int qs = 0;
   
       /* Skip leading white space */
  -    if (string == (char *)NULL) return (char *)NULL;
  -    while ((ch = *string++))
  -        if (!isspace(ch)) break;
  -    if (ch == '\0') return (char *)NULL;
  +    if (string == (char *) NULL) {
  +        return (char *) NULL;
  +    }
  +    while ((ch = *string++)) {
  +        if (!isspace(ch)) {
  +            break;
  +        }
  +    }
  +    if (ch == '\0') {
  +        return (char *) NULL;
  +    }
   
  -    switch(ch) {
  -      case '(':
  +    token->type = token_string; /* the default type */
  +    switch (ch) {
  +    case '(':
           token->type = token_lbrace;
  -        return(string);
  -      case ')':
  +        return (string);
  +    case ')':
           token->type = token_rbrace;
  -        return(string);
  -      case '=':
  +        return (string);
  +    case '=':
           token->type = token_eq;
  -        return(string);
  -      case '!':
  +        return (string);
  +    case '!':
           if (*string == '=') {
               token->type = token_ne;
  -            return(string+1);
  -        } else {
  +            return (string + 1);
  +        }
  +        else {
               token->type = token_not;
  -            return(string);
  +            return (string);
           }
  -      case '\'':
  +    case '\'':
           token->type = token_string;
           qs = 1;
           break;
  -      case '|':
  +    case '|':
           if (*string == '|') {
               token->type = token_or;
  -            return(string+1);
  +            return (string + 1);
           }
  -      case '&':
  +        break;
  +    case '&':
           if (*string == '&') {
               token->type = token_and;
  -            return(string+1);
  +            return (string + 1);
  +        }
  +        break;
  +    case '>':
  +        if (*string == '=') {
  +            token->type = token_ge;
  +            return (string + 1);
  +        }
  +        else {
  +            token->type = token_gt;
  +            return (string);
  +        }
  +    case '<':
  +        if (*string == '=') {
  +            token->type = token_le;
  +            return (string + 1);
  +        }
  +        else {
  +            token->type = token_lt;
  +            return (string);
           }
  -      default:
  +    default:
           token->type = token_string;
           break;
       }
       /* We should only be here if we are in a string */
  -    if (!qs) token->value[next++] = ch;
  +    if (!qs) {
  +        token->value[next++] = ch;
  +    }
   
       /* 
        * Yes I know that goto's are BAD.  But, c doesn't allow me to
        * exit a loop from a switch statement.  Yes, I could use a flag,
        * but that is (IMHO) even less readable/maintainable than the goto.
  -     */ 
  +     */
       /* 
        * I used the ++string throughout this section so that string
        * ends up pointing to the next token and I can just return it
  -     */ 
  +     */
       for (ch = *string; ch != '\0'; ch = *++string) {
           if (ch == '\\') {
  -            if ((ch = *++string) == '\0') goto TOKEN_DONE;
  +            if ((ch = *++string) == '\0') {
  +                goto TOKEN_DONE;
  +            }
               token->value[next++] = ch;
               continue;
           }
           if (!qs) {
  -            if (isspace(ch)) goto TOKEN_DONE;
  -            switch(ch) {
  -              case '(': goto TOKEN_DONE;
  -              case ')': goto TOKEN_DONE;
  -              case '=': goto TOKEN_DONE;
  -              case '!': goto TOKEN_DONE;
  -              case '|': if (*(string+1) == '|') goto TOKEN_DONE;
  -              case '&': if (*(string+1) == '&') goto TOKEN_DONE;
  +            if (isspace(ch)) {
  +                goto TOKEN_DONE;
  +            }
  +            switch (ch) {
  +            case '(':
  +                goto TOKEN_DONE;
  +            case ')':
  +                goto TOKEN_DONE;
  +            case '=':
  +                goto TOKEN_DONE;
  +            case '!':
  +                goto TOKEN_DONE;
  +            case '|':
  +                if (*(string + 1) == '|') {
  +                    goto TOKEN_DONE;
  +                }
  +                break;
  +            case '&':
  +                if (*(string + 1) == '&') {
  +                    goto TOKEN_DONE;
  +                }
  +                break;
  +            case '<':
  +                goto TOKEN_DONE;
  +            case '>':
  +                goto TOKEN_DONE;
               }
               token->value[next++] = ch;
  -        } else {
  -            if (ch == '\'') { qs=0; ++string; goto TOKEN_DONE; }
  +        }
  +        else {
  +            if (ch == '\'') {
  +                qs = 0;
  +                ++string;
  +                goto TOKEN_DONE;
  +            }
               token->value[next++] = ch;
           }
       }
  -TOKEN_DONE:
  +  TOKEN_DONE:
       /* If qs is still set, I have an unmatched ' */
  -    if (qs) { rputs("\nUnmatched '\n", r); next=0; }
  +    if (qs) {
  +        rputs("\nUnmatched '\n", r);
  +        next = 0;
  +    }
       token->value[next] = '\0';
  -    return(string);
  +    return (string);
   }
   
   
  @@ -1027,112 +1250,124 @@
    * cases.  And, without rewriting this completely, the easiest way
    * is to just branch to the return code which cleans it up.
    */
  -int parse_expr(request_rec *r, char *expr, char *error)
  +/* there is an implicit assumption here that expr is at most MAX_STRING_LEN-1
  + * characters long...
  + */
  +static int parse_expr(request_rec *r, const char *expr, const char *error)
   {
       struct parse_node {
           struct parse_node *left, *right, *parent;
           struct token token;
           int value, done;
  -    } *root, *current, *new;
  -    char *parse;
  +    }         *root, *current, *new;
  +    const char *parse;
       char buffer[MAX_STRING_LEN];
  -    struct pool *expr_pool;
  +    pool *expr_pool;
       int retval = 0;
   
  -    if ((parse = expr) == (char *)NULL) return(0);
  -    root = current = (struct parse_node*)NULL;
  -    if ((expr_pool = make_sub_pool(r->pool)) == (struct pool *)NULL) {
  -        log_printf(r->server, "out of memory", r->filename);
  -        rputs(error, r);
  -        return(0);
  +    if ((parse = expr) == (char *) NULL) {
  +        return (0);
       }
  +    root = current = (struct parse_node *) NULL;
  +    expr_pool = make_sub_pool(r->pool);
   
       /* Create Parse Tree */
       while (1) {
  -        new = (struct parse_node*)palloc(expr_pool, sizeof (struct parse_node));
  -        if (new == (struct parse_node*)NULL) {
  -            log_printf(r->server,"out of memory", r->filename);
  -            rputs(error, r);
  -            goto RETURN;
  -        }
  -        new->parent = new->left = new->right = (struct parse_node*)NULL;
  +        new = (struct parse_node *) palloc(expr_pool,
  +                                           sizeof(struct parse_node));
  +        new->parent = new->left = new->right = (struct parse_node *) NULL;
           new->done = 0;
  -        if ((parse = get_ptoken(r, parse, &new->token)) == (char *)NULL)
  +        if ((parse = get_ptoken(r, parse, &new->token)) == (char *) NULL) {
               break;
  -        switch(new->token.type) {
  +        }
  +        switch (new->token.type) {
   
  -          case token_string:
  +        case token_string:
   #ifdef DEBUG_INCLUDE
  -            rvputs(r,"     Token: string (", new->token.value, ")\n", NULL);
  +            rvputs(r, "     Token: string (", new->token.value, ")\n", NULL);
   #endif
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   root = current = new;
                   break;
               }
  -            switch(current->token.type) {
  -              case token_string:
  -                if (current->token.value[0] != '\0')
  -                    strncat(current->token.value, " ", 
  -			MAX_STRING_LEN-strlen(current->token.value)-1);
  -                strncat(current->token.value, new->token.value, 
  -			MAX_STRING_LEN-strlen(current->token.value)-1);
  +            switch (current->token.type) {
  +            case token_string:
  +                if (current->token.value[0] != '\0') {
  +                    strncat(current->token.value, " ",
  +                         MAX_STRING_LEN - strlen(current->token.value) - 1);
  +                }
  +                strncat(current->token.value, new->token.value,
  +                        MAX_STRING_LEN - strlen(current->token.value) - 1);
  +		current->token.value[sizeof(current->token.value) - 1] = '\0';
                   break;
  -              case token_eq:
  -              case token_ne:
  -              case token_and:
  -              case token_or:
  -              case token_lbrace:
  -              case token_not:
  +            case token_eq:
  +            case token_ne:
  +            case token_and:
  +            case token_or:
  +            case token_lbrace:
  +            case token_not:
  +            case token_ge:
  +            case token_gt:
  +            case token_le:
  +            case token_lt:
                   new->parent = current;
                   current = current->right = new;
                   break;
  -              default:
  +            default:
                   log_printf(r->server,
  -                    "Invalid expression %s", expr, r->filename);
  +                            "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               break;
   
  -          case token_and:
  -          case token_or:
  +        case token_and:
  +        case token_or:
   #ifdef DEBUG_INCLUDE
  -rputs ("     Token: and/or\n", r);
  +            rputs("     Token: and/or\n", r);
   #endif
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   log_printf(r->server,
  -                    "Invalid expression %s", expr, r->filename);
  +                            "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               /* Percolate upwards */
  -            while (current != (struct parse_node *)NULL) {
  -                switch(current->token.type) {
  -                  case token_string:
  -                  case token_group:
  -                  case token_not:
  -                  case token_eq:
  -                  case token_ne:
  -                  case token_and:
  -                  case token_or:
  +            while (current != (struct parse_node *) NULL) {
  +                switch (current->token.type) {
  +                case token_string:
  +                case token_group:
  +                case token_not:
  +                case token_eq:
  +                case token_ne:
  +                case token_and:
  +                case token_or:
  +                case token_ge:
  +                case token_gt:
  +                case token_le:
  +                case token_lt:
                       current = current->parent;
                       continue;
  -                  case token_lbrace:
  +                case token_lbrace:
                       break;
  -                  default:
  +                default:
                       log_printf(r->server,
  -                        "Invalid expression %s", expr, r->filename);
  +                                "Invalid expression \"%s\" in file %s",
  +                                expr, r->filename);
                       rputs(error, r);
                       goto RETURN;
                   }
                   break;
               }
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   new->left = root;
                   new->left->parent = new;
  -                new->parent = (struct parse_node*)NULL;
  +                new->parent = (struct parse_node *) NULL;
                   root = new;
  -            } else {
  +            }
  +            else {
                   new->left = current->right;
                   current->right = new;
                   new->parent = current;
  @@ -1140,38 +1375,44 @@
               current = new;
               break;
   
  -          case token_not:
  +        case token_not:
   #ifdef DEBUG_INCLUDE
  -rputs("     Token: not\n", r);
  +            rputs("     Token: not\n", r);
   #endif
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   root = current = new;
                   break;
               }
               /* Percolate upwards */
  -            while (current != (struct parse_node *)NULL) {
  -                switch(current->token.type) {
  -                  case token_not:
  -                  case token_eq:
  -                  case token_ne:
  -                  case token_and:
  -                  case token_or:
  -                  case token_lbrace:
  +            while (current != (struct parse_node *) NULL) {
  +                switch (current->token.type) {
  +                case token_not:
  +                case token_eq:
  +                case token_ne:
  +                case token_and:
  +                case token_or:
  +                case token_lbrace:
  +                case token_ge:
  +                case token_gt:
  +                case token_le:
  +                case token_lt:
                       break;
  -                  default:
  +                default:
                       log_printf(r->server,
  -                        "Invalid expression %s", expr, r->filename);
  +                                "Invalid expression \"%s\" in file %s",
  +                                expr, r->filename);
                       rputs(error, r);
                       goto RETURN;
                   }
                   break;
               }
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   new->left = root;
                   new->left->parent = new;
  -                new->parent = (struct parse_node*)NULL;
  +                new->parent = (struct parse_node *) NULL;
                   root = new;
  -            } else {
  +            }
  +            else {
                   new->left = current->right;
                   current->right = new;
                   new->parent = current;
  @@ -1179,45 +1420,56 @@
               current = new;
               break;
   
  -          case token_eq:
  -          case token_ne:
  +        case token_eq:
  +        case token_ne:
  +        case token_ge:
  +        case token_gt:
  +        case token_le:
  +        case token_lt:
   #ifdef DEBUG_INCLUDE
  -rputs("     Token: eq/ne\n", r);
  +            rputs("     Token: eq/ne/ge/gt/le/lt\n", r);
   #endif
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   log_printf(r->server,
  -                    "Invalid expression %s", expr, r->filename);
  +                            "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               /* Percolate upwards */
  -            while (current != (struct parse_node *)NULL) {
  -                switch(current->token.type) {
  -                  case token_string:
  -                  case token_group:
  +            while (current != (struct parse_node *) NULL) {
  +                switch (current->token.type) {
  +                case token_string:
  +                case token_group:
                       current = current->parent;
                       continue;
  -                  case token_lbrace:
  -                  case token_and:
  -                  case token_or:
  +                case token_lbrace:
  +                case token_and:
  +                case token_or:
                       break;
  -                  case token_not:
  -                  case token_eq:
  -                  case token_ne:
  -                  default:
  +                case token_not:
  +                case token_eq:
  +                case token_ne:
  +                case token_ge:
  +                case token_gt:
  +                case token_le:
  +                case token_lt:
  +                default:
                       log_printf(r->server,
  -                        "Invalid expression %s", expr, r->filename);
  +                                "Invalid expression \"%s\" in file %s",
  +                                expr, r->filename);
                       rputs(error, r);
                       goto RETURN;
                   }
                   break;
               }
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   new->left = root;
                   new->left->parent = new;
  -                new->parent = (struct parse_node*)NULL;
  +                new->parent = (struct parse_node *) NULL;
                   root = new;
  -            } else {
  +            }
  +            else {
                   new->left = current->right;
                   current->right = new;
                   new->parent = current;
  @@ -1225,416 +1477,536 @@
               current = new;
               break;
   
  -          case token_rbrace:
  +        case token_rbrace:
   #ifdef DEBUG_INCLUDE
  -rputs("     Token: rbrace\n", r);
  +            rputs("     Token: rbrace\n", r);
   #endif
  -            while (current != (struct parse_node*)NULL) {
  +            while (current != (struct parse_node *) NULL) {
                   if (current->token.type == token_lbrace) {
                       current->token.type = token_group;
                       break;
                   }
                   current = current->parent;
               }
  -            if (current == (struct parse_node*)NULL) {
  -                log_printf(r->server,"Unmatched ')'in %s\n", expr, r->filename);
  +            if (current == (struct parse_node *) NULL) {
  +                log_printf(r->server, "Unmatched ')' in \"%s\" in file %s",
  +			    expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               break;
   
  -          case token_lbrace:
  +        case token_lbrace:
   #ifdef DEBUG_INCLUDE
  -rputs("     Token: lbrace\n", r);
  +            rputs("     Token: lbrace\n", r);
   #endif
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   root = current = new;
                   break;
               }
               /* Percolate upwards */
  -            while (current != (struct parse_node *)NULL) {
  -                switch(current->token.type) {
  -                  case token_not:
  -                  case token_eq:
  -                  case token_ne:
  -                  case token_and:
  -                  case token_or:
  -                  case token_lbrace:
  +            while (current != (struct parse_node *) NULL) {
  +                switch (current->token.type) {
  +                case token_not:
  +                case token_eq:
  +                case token_ne:
  +                case token_and:
  +                case token_or:
  +                case token_lbrace:
  +                case token_ge:
  +                case token_gt:
  +                case token_le:
  +                case token_lt:
                       break;
  -                  case token_string:
  -                  case token_group:
  -                  default:
  +                case token_string:
  +                case token_group:
  +                default:
                       log_printf(r->server,
  -                        "Invalid expression %s", expr, r->filename);
  +                                "Invalid expression \"%s\" in file %s",
  +                                expr, r->filename);
                       rputs(error, r);
                       goto RETURN;
                   }
                   break;
               }
  -            if (current == (struct parse_node*)NULL) {
  +            if (current == (struct parse_node *) NULL) {
                   new->left = root;
                   new->left->parent = new;
  -                new->parent = (struct parse_node*)NULL;
  +                new->parent = (struct parse_node *) NULL;
                   root = new;
  -            } else {
  +            }
  +            else {
                   new->left = current->right;
                   current->right = new;
                   new->parent = current;
               }
               current = new;
               break;
  -	  default:
  -	    break;
  +        default:
  +            break;
           }
       }
   
       /* Evaluate Parse Tree */
       current = root;
  -    while (current != (struct parse_node *)NULL) {
  -        switch(current->token.type) {
  -          case token_string:
  -#ifdef DEBUG_INCLUDE
  -rputs("     Evaluate string\n", r);
  -#endif
  -            parse_string(r, current->token.value, buffer, MAX_STRING_LEN, 0);
  -            strncpy(current->token.value, buffer, MAX_STRING_LEN-1);
  -	    current->token.value[MAX_STRING_LEN-1] = '\0';
  +    while (current != (struct parse_node *) NULL) {
  +        switch (current->token.type) {
  +        case token_string:
  +#ifdef DEBUG_INCLUDE
  +            rputs("     Evaluate string\n", r);
  +#endif
  +            parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
  +	    safe_copy(current->token.value, buffer, sizeof(current->token.value));
               current->value = (current->token.value[0] != '\0');
               current->done = 1;
               current = current->parent;
               break;
   
  -          case token_and:
  -          case token_or:
  +        case token_and:
  +        case token_or:
   #ifdef DEBUG_INCLUDE
  -rputs("     Evaluate and/or\n", r);
  +            rputs("     Evaluate and/or\n", r);
   #endif
  -            if (current->left == (struct parse_node*)NULL ||
  -                        current->right == (struct parse_node*)NULL) {
  -                log_printf(r->server,
  -                    "Invalid expression %s", expr, r->filename);
  +            if (current->left == (struct parse_node *) NULL ||
  +                current->right == (struct parse_node *) NULL) {
  +                log_printf(r->server, "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               if (!current->left->done) {
  -                switch(current->left->token.type) {
  -                  case token_string:
  +                switch (current->left->token.type) {
  +                case token_string:
                       parse_string(r, current->left->token.value,
  -                            buffer, MAX_STRING_LEN, 0);
  -                    strncpy(current->left->token.value, buffer,
  -                            MAX_STRING_LEN-1);
  -		    current->left->token.value[MAX_STRING_LEN-1] = '\0';
  +                                 buffer, sizeof(buffer), 0);
  +                    safe_copy(current->left->token.value, buffer,
  +                            sizeof(current->left->token.value));
  +		    current->left->value = (current->left->token.value[0] != '\0');
                       current->left->done = 1;
                       break;
  -                  default:
  +                default:
                       current = current->left;
                       continue;
                   }
               }
               if (!current->right->done) {
  -                switch(current->right->token.type) {
  -                  case token_string:
  +                switch (current->right->token.type) {
  +                case token_string:
                       parse_string(r, current->right->token.value,
  -                            buffer, MAX_STRING_LEN, 0);
  -                    strncpy(current->right->token.value, buffer,
  -                            MAX_STRING_LEN-1);
  -		    current->right->token.value[MAX_STRING_LEN-1] = '\0';
  +                                 buffer, sizeof(buffer), 0);
  +                    safe_copy(current->right->token.value, buffer,
  +                            sizeof(current->right->token.value));
  +		    current->right->value = (current->right->token.value[0] != '\0');
                       current->right->done = 1;
                       break;
  -                  default:
  +                default:
                       current = current->right;
                       continue;
                   }
               }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Left: ", current->left->value ? "1" : "0", "\n", NULL);
  -rvputs(r,"     Right: ", current->right->value ? "1" : "0", "\n", NULL);
  +            rvputs(r, "     Left: ", current->left->value ? "1" : "0",
  +                   "\n", NULL);
  +            rvputs(r, "     Right: ", current->right->value ? "1" : "0",
  +                   "\n", NULL);
   #endif
  -            if (current->token.type == token_and)
  -                current->value =
  -                    current->left->value && current->right->value;
  -            else
  -                current->value =
  -                    current->left->value || current->right->value;
  +            if (current->token.type == token_and) {
  +                current->value = current->left->value && current->right->value;
  +            }
  +            else {
  +                current->value = current->left->value || current->right->value;
  +            }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Returning ", current->value ? "1" : "0", "\n", NULL);
  +            rvputs(r, "     Returning ", current->value ? "1" : "0",
  +                   "\n", NULL);
   #endif
               current->done = 1;
               current = current->parent;
               break;
   
  -          case token_eq:
  -          case token_ne:
  +        case token_eq:
  +        case token_ne:
   #ifdef DEBUG_INCLUDE
  -rputs("     Evaluate eq/ne\n", r);
  +            rputs("     Evaluate eq/ne\n", r);
   #endif
  -            if ((current->left == (struct parse_node*)NULL) ||
  -                        (current->right == (struct parse_node*)NULL) ||
  -                        (current->left->token.type != token_string) ||
  -                        (current->right->token.type != token_string)) {
  -                log_printf(r->server,
  -                    "Invalid expression %s", expr, r->filename);
  +            if ((current->left == (struct parse_node *) NULL) ||
  +                (current->right == (struct parse_node *) NULL) ||
  +                (current->left->token.type != token_string) ||
  +                (current->right->token.type != token_string)) {
  +                log_printf(r->server, "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
                   rputs(error, r);
                   goto RETURN;
               }
               parse_string(r, current->left->token.value,
  -                         buffer, MAX_STRING_LEN, 0);
  -            strncpy(current->left->token.value, buffer, MAX_STRING_LEN-1);
  -	    current->left->token.value[MAX_STRING_LEN-1] = '\0';
  +                         buffer, sizeof(buffer), 0);
  +            safe_copy(current->left->token.value, buffer,
  +			sizeof(current->left->token.value));
               parse_string(r, current->right->token.value,
  -                         buffer, MAX_STRING_LEN, 0);
  -            strncpy(current->right->token.value, buffer, MAX_STRING_LEN-1);
  -	    current->right->token.value[MAX_STRING_LEN-1] = '\0';
  +                         buffer, sizeof(buffer), 0);
  +            safe_copy(current->right->token.value, buffer,
  +			sizeof(current->right->token.value));
               if (current->right->token.value[0] == '/') {
                   int len;
                   len = strlen(current->right->token.value);
  -                if (current->right->token.value[len-1] == '/') {
  -                    current->right->token.value[len-1] = '\0';
  -                } else {
  -                    log_printf(r->server,"Invalid rexp %s",
  -                            current->right->token.value, r->filename);
  +                if (current->right->token.value[len - 1] == '/') {
  +                    current->right->token.value[len - 1] = '\0';
  +                }
  +                else {
  +                    log_printf(r->server, "Invalid rexp \"%s\" in file %s",
  +                                current->right->token.value, r->filename);
                       rputs(error, r);
                       goto RETURN;
                   }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Re Compare (", current->left->token.value,
  -         ") with /", &current->right->token.value[1], "/\n", NULL);
  +                rvputs(r, "     Re Compare (", current->left->token.value,
  +                  ") with /", &current->right->token.value[1], "/\n", NULL);
   #endif
                   current->value =
                       re_check(r, current->left->token.value,
  -                            &current->right->token.value[1]);
  -            } else {
  +                             &current->right->token.value[1]);
  +            }
  +            else {
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Compare (", current->left->token.value,
  -         ") with (", current->right->token.value, ")\n", NULL);
  +                rvputs(r, "     Compare (", current->left->token.value,
  +                       ") with (", current->right->token.value, ")\n", NULL);
   #endif
                   current->value =
  -                        (strcmp(current->left->token.value,
  -                         current->right->token.value) == 0);
  +                    (strcmp(current->left->token.value,
  +                            current->right->token.value) == 0);
               }
  -            if (current->token.type == token_ne)
  +            if (current->token.type == token_ne) {
                   current->value = !current->value;
  +            }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Returning ", current->value ? "1" : "0", "\n", NULL);
  +            rvputs(r, "     Returning ", current->value ? "1" : "0",
  +                   "\n", NULL);
  +#endif
  +            current->done = 1;
  +            current = current->parent;
  +            break;
  +        case token_ge:
  +        case token_gt:
  +        case token_le:
  +        case token_lt:
  +#ifdef DEBUG_INCLUDE
  +            rputs("     Evaluate ge/gt/le/lt\n", r);
  +#endif
  +            if ((current->left == (struct parse_node *) NULL) ||
  +                (current->right == (struct parse_node *) NULL) ||
  +                (current->left->token.type != token_string) ||
  +                (current->right->token.type != token_string)) {
  +                log_printf(r->server, "Invalid expression \"%s\" in file %s",
  +                            expr, r->filename);
  +                rputs(error, r);
  +                goto RETURN;
  +            }
  +            parse_string(r, current->left->token.value,
  +                         buffer, sizeof(buffer), 0);
  +            safe_copy(current->left->token.value, buffer,
  +			sizeof(current->left->token.value));
  +            parse_string(r, current->right->token.value,
  +                         buffer, sizeof(buffer), 0);
  +            safe_copy(current->right->token.value, buffer,
  +			sizeof(current->right->token.value));
  +#ifdef DEBUG_INCLUDE
  +            rvputs(r, "     Compare (", current->left->token.value,
  +                   ") with (", current->right->token.value, ")\n", NULL);
  +#endif
  +            current->value =
  +                strcmp(current->left->token.value,
  +                       current->right->token.value);
  +            if (current->token.type == token_ge) {
  +                current->value = current->value >= 0;
  +            }
  +            else if (current->token.type == token_gt) {
  +                current->value = current->value > 0;
  +            }
  +            else if (current->token.type == token_le) {
  +                current->value = current->value <= 0;
  +            }
  +            else if (current->token.type == token_lt) {
  +                current->value = current->value < 0;
  +            }
  +            else {
  +                current->value = 0;     /* Don't return -1 if unknown token */
  +            }
  +#ifdef DEBUG_INCLUDE
  +            rvputs(r, "     Returning ", current->value ? "1" : "0",
  +                   "\n", NULL);
   #endif
               current->done = 1;
               current = current->parent;
               break;
   
  -          case token_not:
  -            if (current->right != (struct parse_node *)NULL) {
  +        case token_not:
  +            if (current->right != (struct parse_node *) NULL) {
                   if (!current->right->done) {
                       current = current->right;
                       continue;
                   }
                   current->value = !current->right->value;
  -            } else {
  +            }
  +            else {
                   current->value = 0;
               }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Evaluate !: ", current->value ? "1" : "0", "\n", NULL);
  +            rvputs(r, "     Evaluate !: ", current->value ? "1" : "0",
  +                   "\n", NULL);
   #endif
               current->done = 1;
               current = current->parent;
               break;
   
  -          case token_group:
  -            if (current->right != (struct parse_node *)NULL) {
  +        case token_group:
  +            if (current->right != (struct parse_node *) NULL) {
                   if (!current->right->done) {
                       current = current->right;
                       continue;
                   }
                   current->value = current->right->value;
  -            } else {
  +            }
  +            else {
                   current->value = 1;
               }
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"     Evaluate (): ", current->value ? "1" : "0", "\n", NULL);
  +            rvputs(r, "     Evaluate (): ", current->value ? "1" : "0",
  +                   "\n", NULL);
   #endif
               current->done = 1;
               current = current->parent;
               break;
   
  -          case token_lbrace:
  -            log_printf(r->server,"Unmatched '(' in %s\n", expr, r->filename);
  +        case token_lbrace:
  +            log_printf(r->server, "Unmatched '(' in \"%s\" in file %s",
  +                        expr, r->filename);
               rputs(error, r);
               goto RETURN;
   
  -          case token_rbrace:
  -            log_printf(r->server,"Unmatched ')' in %s\n", expr, r->filename);
  +        case token_rbrace:
  +            log_printf(r->server, "Unmatched ')' in \"%s\" in file %s\n",
  +                        expr, r->filename);
               rputs(error, r);
               goto RETURN;
   
  -          default:
  -            log_printf(r->server,"bad token type");
  +        default:
  +            log_printf(r->server, "bad token type");
               rputs(error, r);
               goto RETURN;
           }
       }
   
  -    retval =  (root == (struct parse_node *)NULL) ? 0 : root->value;
  -RETURN:
  +    retval = (root == (struct parse_node *) NULL) ? 0 : root->value;
  +  RETURN:
       destroy_pool(expr_pool);
       return (retval);
  -}    
  +}
   
  -int handle_if(FILE *in, request_rec *r, char *error,
  -              int *conditional_status, int *printing) 
  +static int handle_if(FILE *in, request_rec *r, const char *error,
  +                     int *conditional_status, int *printing)
   {
       char tag[MAX_STRING_LEN];
  -    char *tag_val = '\0';
  -    char *expr = '\0';
  +    char *tag_val;
  +    char *expr;
   
  -    while(1) {
  -        tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 0);
  -        if(*tag == '\0')
  +    expr = NULL;
  +    while (1) {
  +        tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0);
  +        if (*tag == '\0') {
               return 1;
  -        else if(!strcmp(tag,"done")) {
  +        }
  +        else if (!strcmp(tag, "done")) {
  +	    if (expr == NULL) {
  +		log_printf(r->server, "missing expr in if statement: %s",
  +			    r->filename);
  +		rputs(error, r);
  +		return 1;
  +	    }
               *printing = *conditional_status = parse_expr(r, expr, error);
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** if conditional_status=\"", *conditional_status ? "1" : "0", "\"\n", NULL);
  +            rvputs(r, "**** if conditional_status=\"",
  +                   *conditional_status ? "1" : "0", "\"\n", NULL);
   #endif
               return 0;
  -        } else if(!strcmp(tag,"expr")) {
  -	    expr = tag_val;
  +        }
  +        else if (!strcmp(tag, "expr")) {
  +            expr = tag_val;
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** if expr=\"", expr, "\"\n", NULL);
  +            rvputs(r, "**** if expr=\"", expr, "\"\n", NULL);
   #endif
  -        } else {
  -            log_printf(r->server,"unknown parameter %s to tag if in %s",
  -                    tag, r->filename);
  +        }
  +        else {
  +            log_printf(r->server, "unknown parameter \"%s\" to tag if in %s",
  +                        tag, r->filename);
               rputs(error, r);
           }
       }
  -}    
  +}
   
  -int handle_elif(FILE *in, request_rec *r, char *error,
  -              int *conditional_status, int *printing) 
  +static int handle_elif(FILE *in, request_rec *r, const char *error,
  +                       int *conditional_status, int *printing)
   {
       char tag[MAX_STRING_LEN];
  -    char *tag_val = '\0';
  -    char *expr = '\0';
  +    char *tag_val;
  +    char *expr;
   
  -    while(1) {
  -        tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 0);
  -        if(*tag == '\0')
  +    expr = NULL;
  +    while (1) {
  +        tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0);
  +        if (*tag == '\0') {
               return 1;
  -        else if(!strcmp(tag,"done")) {
  +        }
  +        else if (!strcmp(tag, "done")) {
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** elif conditional_status=\"", *conditional_status ? "1" : "0", "\"\n", NULL);
  +            rvputs(r, "**** elif conditional_status=\"",
  +                   *conditional_status ? "1" : "0", "\"\n", NULL);
   #endif
               if (*conditional_status) {
                   *printing = 0;
  -                return(0);
  +                return (0);
               }
  +	    if (expr == NULL) {
  +		log_printf(r->server, "missing expr in elif statement: %s",
  +			    r->filename);
  +		rputs(error, r);
  +		return 1;
  +	    }
               *printing = *conditional_status = parse_expr(r, expr, error);
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** elif conditional_status=\"", *conditional_status ? "1" : "0", "\"\n", NULL);
  +            rvputs(r, "**** elif conditional_status=\"",
  +                   *conditional_status ? "1" : "0", "\"\n", NULL);
   #endif
               return 0;
  -        } else if(!strcmp(tag,"expr")) {
  -	    expr = tag_val;
  +        }
  +        else if (!strcmp(tag, "expr")) {
  +            expr = tag_val;
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** if expr=\"", expr, "\"\n", NULL);
  +            rvputs(r, "**** if expr=\"", expr, "\"\n", NULL);
   #endif
  -        } else {
  -            log_printf(r->server,"unknown parameter %s to tag if in %s",
  -                    tag, r->filename);
  +        }
  +        else {
  +            log_printf(r->server, "unknown parameter \"%s\" to tag if in %s",
  +                        tag, r->filename);
               rputs(error, r);
           }
       }
   }
   
  -int handle_else(FILE *in, request_rec *r, char *error,
  -              int *conditional_status, int *printing) 
  +static int handle_else(FILE *in, request_rec *r, const char *error,
  +                       int *conditional_status, int *printing)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
   
  -    if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
           return 1;
  -    else if(!strcmp(tag,"done")) {
  +    }
  +    else if (!strcmp(tag, "done")) {
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** else conditional_status=\"", *conditional_status ? "1" : "0", "\"\n", NULL);
  +        rvputs(r, "**** else conditional_status=\"",
  +               *conditional_status ? "1" : "0", "\"\n", NULL);
   #endif
           *printing = !(*conditional_status);
           *conditional_status = 1;
           return 0;
  -    } else {
  -        log_printf(r->server, "else directive does not take tags");
  -        if (*printing) rputs(error, r);
  +    }
  +    else {
  +        log_printf(r->server, "else directive does not take tags in %s",
  +		    r->filename);
  +        if (*printing) {
  +            rputs(error, r);
  +        }
           return -1;
       }
  -}    
  +}
   
  -int handle_endif(FILE *in, request_rec *r, char *error, 
  -              int *conditional_status, int *printing) 
  +static int handle_endif(FILE *in, request_rec *r, const char *error,
  +                        int *conditional_status, int *printing)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
   
  -    if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1))) {
  +    if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
           return 1;
  -    } else if(!strcmp(tag,"done")) {
  +    }
  +    else if (!strcmp(tag, "done")) {
   #ifdef DEBUG_INCLUDE
  -rvputs(r,"**** endif conditional_status=\"", *conditional_status ? "1" : "0", "\"\n", NULL);
  +        rvputs(r, "**** endif conditional_status=\"",
  +               *conditional_status ? "1" : "0", "\"\n", NULL);
   #endif
  +        *printing = 1;
           *conditional_status = 1;
           return 0;
  -    } else {
  -        log_printf(r->server, "endif directive does not take tags");
  +    }
  +    else {
  +        log_printf(r->server, "endif directive does not take tags in %s",
  +		    r->filename);
           rputs(error, r);
           return -1;
       }
  -}    
  +}
   
  -int handle_set(FILE *in, request_rec *r, char *error) 
  +static int handle_set(FILE *in, request_rec *r, const char *error)
   {
       char tag[MAX_STRING_LEN];
       char parsed_string[MAX_STRING_LEN];
       char *tag_val;
       char *var;
   
  -    var = (char *)NULL;
  +    var = (char *) NULL;
       while (1) {
  -        if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
               return 1;
  -        else if(!strcmp(tag,"done"))
  +        }
  +        else if (!strcmp(tag, "done")) {
               return 0;
  -        else if (!strcmp(tag,"var")) {
  +        }
  +        else if (!strcmp(tag, "var")) {
               var = tag_val;
  -        } else if (!strcmp(tag,"value")) {
  -            if (var == (char *)NULL) {
  +        }
  +        else if (!strcmp(tag, "value")) {
  +            if (var == (char *) NULL) {
                   log_printf(r->server,
  -                    "variable must precede value in set directive");
  +                            "variable must precede value in set directive in %s",
  +			    r->filename);
                   rputs(error, r);
                   return -1;
  -            } 
  -            parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0);
  -            table_set (r->subprocess_env, var, parsed_string);
  +            }
  +            parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +            table_set(r->subprocess_env, var, parsed_string);
  +        }
  +        else {
  +            log_printf(r->server, "Invalid tag for set directive in %s",
  +			r->filename);
  +            rputs(error, r);
  +            return -1;
           }
       }
  -}    
  +}
   
  -int handle_printenv(FILE *in, request_rec *r, char *error) 
  +static int handle_printenv(FILE *in, request_rec *r, const char *error)
   {
       char tag[MAX_STRING_LEN];
       char *tag_val;
       table_entry *elts = (table_entry *) r->subprocess_env->elts;
       int i;
   
  -    if(!(tag_val = get_tag(r->pool, in, tag, MAX_STRING_LEN, 1)))
  +    if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
           return 1;
  -    else if(!strcmp(tag,"done")) {
  -            for (i = 0; i < r->subprocess_env->nelts; ++i)
  -                rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL);
  -            return 0;
  -    } else {
  -        log_printf(r->server, "printenv directive does not take tags");
  +    }
  +    else if (!strcmp(tag, "done")) {
  +        for (i = 0; i < r->subprocess_env->nelts; ++i) {
  +            rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL);
  +        }
  +        return 0;
  +    }
  +    else {
  +        log_printf(r->server, "printenv directive does not take tags in %s",
  +		    r->filename);
           rputs(error, r);
           return -1;
       }
  -}    
  +}
   
   
   
  @@ -1642,104 +2014,139 @@
   
   /* This is a stub which parses a file descriptor. */
   
  -void send_parsed_content(FILE *f, request_rec *r)
  +static void send_parsed_content(FILE *f, request_rec *r)
   {
       char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
       char timefmt[MAX_STRING_LEN];
  -    int noexec = allow_options (r) & OPT_INCNOEXEC;
  +    int noexec = allow_options(r) & OPT_INCNOEXEC;
       int ret, sizefmt;
       int if_nesting;
       int printing;
       int conditional_status;
   
  -    strncpy(error,DEFAULT_ERROR_MSG, sizeof(error)-1);
  -    error[sizeof(error)-1] = '\0';
  -    strncpy(timefmt,DEFAULT_TIME_FORMAT, sizeof(timefmt)-1);
  -    timefmt[sizeof(timefmt)-1] = '\0';
  +    safe_copy(error, DEFAULT_ERROR_MSG, sizeof(error));
  +    safe_copy(timefmt, DEFAULT_TIME_FORMAT, sizeof(timefmt));
       sizefmt = SIZEFMT_KMG;
   
   /*  Turn printing on */
       printing = conditional_status = 1;
       if_nesting = 0;
   
  -    chdir_file (r->filename);
  -    if (r->args) { /* add QUERY stuff to env cause it ain't yet */
  -        table_set (r->subprocess_env, "QUERY_STRING", r->args);
  -        unescape_url (r->args);
  -        table_set (r->subprocess_env, "QUERY_STRING_UNESCAPED",
  -                escape_shell_cmd (r->pool, r->args));
  +    chdir_file(r->filename);
  +    if (r->args) {              /* add QUERY stuff to env cause it ain't yet */
  +        char *arg_copy = pstrdup(r->pool, r->args);
  +
  +        table_set(r->subprocess_env, "QUERY_STRING", r->args);
  +        unescape_url(arg_copy);
  +        table_set(r->subprocess_env, "QUERY_STRING_UNESCAPED",
  +                  escape_shell_cmd(r->pool, arg_copy));
       }
   
  -    while(1) {
  -        if(!find_string(f,STARTING_SEQUENCE,r,printing)) {
  -            if(get_directive(f,directive,r->pool))
  +    while (1) {
  +        if (!find_string(f, STARTING_SEQUENCE, r, printing)) {
  +            if (get_directive(f, directive, sizeof(directive), r->pool)) {
  +		log_printf(r->server,
  +			    "mod_include: error reading directive in %s",
  +			    r->filename);
  +		rputs(error, r);
                   return;
  -            if(!strcmp(directive,"if")) {
  +            }
  +            if (!strcmp(directive, "if")) {
                   if (!printing) {
                       if_nesting++;
  -                } else {
  -                    ret=handle_if(f, r, error, &conditional_status, &printing);
  +                }
  +                else {
  +                    ret = handle_if(f, r, error, &conditional_status,
  +                                    &printing);
                       if_nesting = 0;
                   }
                   continue;
  -            } else if(!strcmp(directive,"else")) {
  -                if (!if_nesting)
  -                    ret=handle_else(f, r, error, &conditional_status, &printing);
  +            }
  +            else if (!strcmp(directive, "else")) {
  +                if (!if_nesting) {
  +                    ret = handle_else(f, r, error, &conditional_status,
  +                                      &printing);
  +                }
                   continue;
  -            } else if(!strcmp(directive,"elif")) {
  -                if (!if_nesting)
  -                    ret = handle_elif(f, r, error, &conditional_status, &printing);
  +            }
  +            else if (!strcmp(directive, "elif")) {
  +                if (!if_nesting) {
  +                    ret = handle_elif(f, r, error, &conditional_status,
  +                                      &printing);
  +                }
                   continue;
  -            } else if(!strcmp(directive,"endif")) {
  +            }
  +            else if (!strcmp(directive, "endif")) {
                   if (!if_nesting) {
  -                    ret=handle_else(f, r, error, &conditional_status, &printing);
  -                    printing = 1;
  -                } else {
  +                    ret = handle_endif(f, r, error, &conditional_status,
  +                                       &printing);
  +                }
  +                else {
                       if_nesting--;
                   }
                   continue;
  -            } 
  -            if (!printing) continue;
  -            if(!strcmp(directive,"exec")) {
  -                if(noexec) {
  -                    log_printf(r->server,"httpd: exec used but not allowed in %s",
  -                            r->filename);
  -                    if (printing) rputs(error, r);
  -                    ret = find_string(f,ENDING_SEQUENCE,r,0);
  -                } else 
  -                    ret=handle_exec(f, r, error);
  -            } else if(!strcmp(directive,"config"))
  -                ret=handle_config(f, r, error, timefmt, &sizefmt);
  -            else if(!strcmp(directive,"set"))
  -                ret=handle_set(f, r, error);
  -            else if(!strcmp(directive,"include"))
  -                ret=handle_include(f, r, error, noexec);
  -            else if(!strcmp(directive,"echo"))
  -                ret=handle_echo(f, r, error);
  -            else if(!strcmp(directive,"fsize"))
  -                ret=handle_fsize(f, r, error, sizefmt);
  -            else if(!strcmp(directive,"flastmod"))
  -                ret=handle_flastmod(f, r, error, timefmt);
  -            else if(!strcmp(directive,"printenv"))
  -                ret=handle_printenv(f, r, error);
  +            }
  +            if (!printing) {
  +                continue;
  +            }
  +            if (!strcmp(directive, "exec")) {
  +                if (noexec) {
  +                    log_printf(r->server,
  +                                "httpd: exec used but not allowed in %s",
  +                                r->filename);
  +                    if (printing) {
  +                        rputs(error, r);
  +                    }
  +                    ret = find_string(f, ENDING_SEQUENCE, r, 0);
  +                }
  +                else {
  +                    ret = handle_exec(f, r, error);
  +                }
  +            }
  +            else if (!strcmp(directive, "config")) {
  +                ret = handle_config(f, r, error, timefmt, &sizefmt);
  +            }
  +            else if (!strcmp(directive, "set")) {
  +                ret = handle_set(f, r, error);
  +            }
  +            else if (!strcmp(directive, "include")) {
  +                ret = handle_include(f, r, error, noexec);
  +            }
  +            else if (!strcmp(directive, "echo")) {
  +                ret = handle_echo(f, r, error);
  +            }
  +            else if (!strcmp(directive, "fsize")) {
  +                ret = handle_fsize(f, r, error, sizefmt);
  +            }
  +            else if (!strcmp(directive, "flastmod")) {
  +                ret = handle_flastmod(f, r, error, timefmt);
  +            }
  +            else if (!strcmp(directive, "printenv")) {
  +                ret = handle_printenv(f, r, error);
  +            }
   #ifdef USE_PERL_SSI
  -            else if(!strcmp(directive,"perl")) 
  -                ret=handle_perl(f, r, error);
  +            else if (!strcmp(directive, "perl")) {
  +                ret = handle_perl(f, r, error);
  +            }
   #endif
               else {
  -                log_printf(r->server,
  -                        "httpd: unknown directive %s in parsed doc %s",
  -                        directive,r->filename);
  -                if (printing) rputs(error, r);
  -                ret=find_string(f,ENDING_SEQUENCE,r,0);
  +                log_printf(r->server, "httpd: unknown directive \"%s\" "
  +                            "in parsed doc %s",
  +                            directive, r->filename);
  +                if (printing) {
  +                    rputs(error, r);
  +                }
  +                ret = find_string(f, ENDING_SEQUENCE, r, 0);
               }
  -            if(ret) {
  -                log_printf(r->server,"httpd: premature EOF in parsed file %s",
  -			r->filename);
  +            if (ret) {
  +                log_printf(r->server, "httpd: premature EOF in parsed file %s",
  +                            r->filename);
                   return;
               }
  -        } else 
  +        }
  +        else {
               return;
  +        }
       }
   }
   
  @@ -1750,52 +2157,68 @@
    */
   
   module includes_module;
  -enum xbithack { xbithack_off, xbithack_on, xbithack_full };
  +enum xbithack {
  +    xbithack_off, xbithack_on, xbithack_full
  +};
   
  -#ifdef XBITHACK	
  +#ifdef XBITHACK
   #define DEFAULT_XBITHACK xbithack_full
   #else
   #define DEFAULT_XBITHACK xbithack_off
   #endif
   
  -void *create_includes_dir_config (pool *p, char *dummy)
  +static void *create_includes_dir_config(pool *p, char *dummy)
   {
  -    enum xbithack *result = (enum xbithack*)palloc(p, sizeof (enum xbithack));
  +    enum xbithack *result = (enum xbithack *) palloc(p, sizeof(enum xbithack));
       *result = DEFAULT_XBITHACK;
       return result;
   }
   
  -const char *set_xbithack (cmd_parms *cmd, void *xbp, char *arg)
  +static const char *set_xbithack(cmd_parms *cmd, void *xbp, char *arg)
   {
  -   enum xbithack *state = (enum xbithack *)xbp;
  +    enum xbithack *state = (enum xbithack *) xbp;
   
  -   if (!strcasecmp (arg, "off")) *state = xbithack_off;
  -   else if (!strcasecmp (arg, "on")) *state = xbithack_on;
  -   else if (!strcasecmp (arg, "full")) *state = xbithack_full;
  -   else return "XBitHack must be set to Off, On, or Full";
  +    if (!strcasecmp(arg, "off")) {
  +        *state = xbithack_off;
  +    }
  +    else if (!strcasecmp(arg, "on")) {
  +        *state = xbithack_on;
  +    }
  +    else if (!strcasecmp(arg, "full")) {
  +        *state = xbithack_full;
  +    }
  +    else {
  +        return "XBitHack must be set to Off, On, or Full";
  +    }
   
  -   return NULL;
  +    return NULL;
   }
   
  -int send_parsed_file(request_rec *r)
  +static int send_parsed_file(request_rec *r)
   {
       FILE *f;
       enum xbithack *state =
  -	(enum xbithack *)get_module_config(r->per_dir_config,&includes_module);
  +    (enum xbithack *) get_module_config(r->per_dir_config, &includes_module);
       int errstatus;
   
  -    if (!(allow_options (r) & OPT_INCLUDES)) return DECLINED;
  -    if (r->method_number != M_GET) return DECLINED;
  +    if (!(allow_options(r) & OPT_INCLUDES)) {
  +        return DECLINED;
  +    }
  +    if (r->method_number != M_GET) {
  +        return DECLINED;
  +    }
       if (r->finfo.st_mode == 0) {
  -        log_reason("File does not exist",
  -            r->path_info ? pstrcat(r->pool, r->filename, r->path_info, NULL)
  -                : r->filename, r);
  -	return NOT_FOUND;
  +        log_printf(r->server, "File does not exist: %s",
  +                    (r->path_info
  +                     ? pstrcat(r->pool, r->filename, r->path_info, NULL)
  +                     : r->filename));
  +        return HTTP_NOT_FOUND;
       }
   
  -    if(!(f=pfopen(r->pool, r->filename, "r"))) {
  -        log_reason("file permissions deny server access", r->filename, r);
  -	return FORBIDDEN;
  +    if (!(f = pfopen(r->pool, r->filename, "r"))) {
  +        log_printf(r->server,
  +                    "file permissions deny server access: %s", r->filename);
  +        return HTTP_FORBIDDEN;
       }
   
       if (*state == xbithack_full
  @@ -1809,84 +2232,92 @@
       send_http_header(r);
   
       if (r->header_only) {
  -	pfclose (r->pool, f);
  -	return OK;
  +        pfclose(r->pool, f);
  +        return OK;
       }
  -   
  +
       if (r->main) {
  -	/* Kludge --- for nested includes, we want to keep the
  -	 * subprocess environment of the base document (for compatibility);
  -	 * that means torquing our own last_modified date as well so that
  -	 * the LAST_MODIFIED variable gets reset to the proper value if
  -	 * the nested document resets <!--#config timefmt-->
  -	 */
  -	r->subprocess_env = r->main->subprocess_env;
  -	r->finfo.st_mtime= r->main->finfo.st_mtime;
  -    } else { 
  -	add_common_vars (r);
  -	add_cgi_vars(r);
  -	add_include_vars (r, DEFAULT_TIME_FORMAT);
  +        /* Kludge --- for nested includes, we want to keep the
  +         * subprocess environment of the base document (for compatibility);
  +         * that means torquing our own last_modified date as well so that
  +         * the LAST_MODIFIED variable gets reset to the proper value if
  +         * the nested document resets <!--#config timefmt-->
  +         */
  +        r->subprocess_env = r->main->subprocess_env;
  +        r->finfo.st_mtime = r->main->finfo.st_mtime;
  +    }
  +    else {
  +        add_common_vars(r);
  +        add_cgi_vars(r);
  +        add_include_vars(r, DEFAULT_TIME_FORMAT);
       }
       hard_timeout("send SSI", r);
   
  -    send_parsed_content (f, r);
  -    
  -    kill_timeout (r);
  +    send_parsed_content(f, r);
  +
  +    kill_timeout(r);
       return OK;
   }
   
  -int send_shtml_file (request_rec *r)
  +static int send_shtml_file(request_rec *r)
   {
       r->content_type = "text/html";
       return send_parsed_file(r);
   }
   
  -int xbithack_handler (request_rec *r)
  +static int xbithack_handler(request_rec *r)
   {
  -    enum xbithack *state;
  -	
   #ifdef __EMX__
       /* OS/2 dosen't currently support the xbithack. This is being worked on. */
       return DECLINED;
   #else
  -    if (!(r->finfo.st_mode & S_IXUSR)) return DECLINED;
  +    enum xbithack *state;
  +
  +    if (!(r->finfo.st_mode & S_IXUSR)) {
  +        return DECLINED;
  +    }
  +
  +    state = (enum xbithack *) get_module_config(r->per_dir_config,
  +                                                &includes_module);
   
  -    state = (enum xbithack *)get_module_config(r->per_dir_config,
  -					       &includes_module);
  -    
  -    if (*state == xbithack_off) return DECLINED;
  -    return send_parsed_file (r);
  +    if (*state == xbithack_off) {
  +        return DECLINED;
  +    }
  +    return send_parsed_file(r);
   #endif
   }
   
  -command_rec includes_cmds[] = {
  -{ "XBitHack", set_xbithack, NULL, OR_OPTIONS, TAKE1, "Off, On, or Full" },
  -{ NULL }    
  +static command_rec includes_cmds[] =
  +{
  +    {"XBitHack", set_xbithack, NULL, OR_OPTIONS, TAKE1, "Off, On, or Full"},
  +    {NULL}
   };
   
  -handler_rec includes_handlers[] = {
  -{ INCLUDES_MAGIC_TYPE, send_shtml_file },
  -{ INCLUDES_MAGIC_TYPE3, send_shtml_file },
  -{ "server-parsed", send_parsed_file },
  -{ "text/html", xbithack_handler },
  -{ NULL }
  +static handler_rec includes_handlers[] =
  +{
  +    {INCLUDES_MAGIC_TYPE, send_shtml_file},
  +    {INCLUDES_MAGIC_TYPE3, send_shtml_file},
  +    {"server-parsed", send_parsed_file},
  +    {"text/html", xbithack_handler},
  +    {NULL}
   };
   
  -module includes_module = {
  -   STANDARD_MODULE_STUFF,
  -   NULL,			/* initializer */
  -   create_includes_dir_config,	/* dir config creater */
  -   NULL,			/* dir merger --- default is to override */
  -   NULL,			/* server config */
  -   NULL,			/* merge server config */
  -   includes_cmds,		/* command table */
  -   includes_handlers,		/* handlers */
  -   NULL,			/* filename translation */
  -   NULL,			/* check_user_id */
  -   NULL,			/* check auth */
  -   NULL,			/* check access */
  -   NULL,			/* type_checker */
  -   NULL,			/* fixups */
  -   NULL,			/* logger */
  -   NULL				/* header parser */
  +module includes_module =
  +{
  +    STANDARD_MODULE_STUFF,
  +    NULL,                       /* initializer */
  +    create_includes_dir_config, /* dir config creater */
  +    NULL,                       /* dir merger --- default is to override */
  +    NULL,                       /* server config */
  +    NULL,                       /* merge server config */
  +    includes_cmds,              /* command table */
  +    includes_handlers,          /* handlers */
  +    NULL,                       /* filename translation */
  +    NULL,                       /* check_user_id */
  +    NULL,                       /* check auth */
  +    NULL,                       /* check access */
  +    NULL,                       /* type_checker */
  +    NULL,                       /* fixups */
  +    NULL,                       /* logger */
  +    NULL                        /* header parser */
   };
  
  
  
  1.17      +9 -4      apache-1.2/src/mod_info.c
  
  Index: mod_info.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_info.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- mod_info.c	1997/04/12 04:24:59	1.16
  +++ mod_info.c	1998/01/30 09:14:06	1.17
  @@ -164,15 +164,19 @@
   	int lab=0, nest=0;
   
   	while(li) {
  -		if(!strncasecmp(li->cmd,"<directory",10) || !strncasecmp(li->cmd,"<location",9) ||
  -		  !strncasecmp(li->cmd,"<limit",6)) { 
  +		if(!strncasecmp(li->cmd,"<directory",10) || 
  +		   !strncasecmp(li->cmd,"<location",9) ||
  +		   !strncasecmp(li->cmd,"<limit",6) ||
  +		   !strncasecmp(li->cmd,"<files",6)) { 
   			if(nest) li_se=li;
   			else li_st=li; 
   			li=li->next; 
   			nest++;
   			continue; 
   		} else if(nest && (!strncasecmp(li->cmd,"</limit",7) ||
  -		  !strncasecmp(li->cmd,"</location",10) || !strncasecmp(li->cmd,"</directory",11))) { 
  +		                   !strncasecmp(li->cmd,"</location",10) || 
  +		                   !strncasecmp(li->cmd,"</directory",11) ||
  +		                   !strncasecmp(li->cmd,"</files",7))) { 
   			if(block_start) {
   				if((nest==1 && block_start==li_st) || (nest==2 && block_start==li_se)) {
   					rputs("<dd><tt>",r);
  @@ -220,7 +224,8 @@
   					  && (strncasecmp(li->cmd,"<directory",10) &&
   					  strncasecmp(li->cmd,"<location",9) && strncasecmp(li->cmd,"<limit",6) &&
   					  strncasecmp(li->cmd,"</limit",7) && strncasecmp(li->cmd,"</location",10) &&
  -					  strncasecmp(li->cmd,"</directory",11))) {
  +					  strncasecmp(li->cmd,"</directory",11) &&
  +					  strncasecmp(li->cmd,"</files",7))) {
   						rputs("<dd><tt>",r);
   						rputs(mod_info_html_cmd_string(li_st->cmd),r);
   						rputs(" ",r);
  
  
  
  1.41      +24 -13    apache-1.2/src/mod_negotiation.c
  
  Index: mod_negotiation.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_negotiation.c,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- mod_negotiation.c	1997/04/17 02:50:20	1.40
  +++ mod_negotiation.c	1998/01/30 09:14:07	1.41
  @@ -623,8 +623,9 @@
   {
       char *cp = header;
       
  -    while (*cp && *cp != ':')
  -        *cp++ = tolower(*cp);
  +    for ( ; *cp && *cp != ':' ; ++cp) {
  +        *cp = tolower(*cp);
  +    }
       
       if (!*cp) {
   	log_reason ("Syntax error in type map --- no ':'", r->filename, r);
  @@ -642,17 +643,20 @@
       return cp;
   }
   
  -int read_type_map (negotiation_state *neg, char *map_name)
  +static int read_type_map (negotiation_state *neg, request_rec *rr)
   {
       request_rec *r = neg->r;
  -    FILE *map = pfopen (neg->pool, map_name, "r");
  -
  +    FILE *map;
       char buffer[MAX_STRING_LEN];
       enum header_state hstate;
       struct var_rec mime_info;
       
  +    if (rr->status != HTTP_OK) {
  +	return rr->status;
  +    }
  +    map = pfopen (neg->pool, rr->filename, "r");
       if (map == NULL) {
  -        log_reason("cannot access type map file", map_name, r);
  +        log_reason("cannot access type map file", rr->filename, r);
   	return FORBIDDEN;
       }
   
  @@ -780,7 +784,7 @@
   	    closedir(dirp);
   	    
   	    neg->avail_vars->nelts = 0;
  -	    return read_type_map (neg, sub_req->filename);
  +	    return read_type_map (neg, sub_req);
   	}
   	
   	/* Have reasonable variant --- gather notes.
  @@ -1439,8 +1443,12 @@
           /* If the best variant's charset is ISO-8859-1 and this variant has
              the same charset quality, then we prefer this variant */
           if (variant->charset_quality == best->charset_quality &&
  -            (best->content_charset == NULL || *best->content_charset == 0 ||
  -            strcmp(best->content_charset, "iso-8859-1") == 0)) {
  +            (variant->content_charset != NULL &&
  +             *variant->content_charset != '\0' &&
  +             strcmp(variant->content_charset, "iso-8859-1") != 0) &&
  +            (best->content_charset == NULL ||
  +             *best->content_charset == '\0' ||
  +             strcmp(best->content_charset, "iso-8859-1") == 0)) {
               *p_bestq = q;
               return 1;
   	}
  @@ -1538,9 +1546,12 @@
       /* If the best variant's charset is ISO-8859-1 and this variant has
          the same charset quality, then we prefer this variant */
       if (variant->charset_quality > best->charset_quality ||
  -        (variant->charset_quality == best->charset_quality &&
  -        (best->content_charset == NULL || *best->content_charset == 0 ||
  -        strcmp(best->content_charset, "iso-8859-1") == 0))) {
  +	((variant->content_charset != NULL &&
  +          *variant->content_charset != '\0' &&
  +	  strcmp(variant->content_charset, "iso-8859-1") != 0) &&
  +	 (best->content_charset == NULL ||
  +	  *best->content_charset == '\0' ||
  +	  strcmp(best->content_charset, "iso-8859-1") == 0))) {
           *p_bestq = q;
           return 1;
       }
  @@ -1850,7 +1861,7 @@
       
       char *udir;
       
  -    if ((res = read_type_map (neg, r->filename))) return res;
  +    if ((res = read_type_map (neg, r))) return res;
       
       maybe_add_default_encodings(neg, 0);
       
  
  
  
  1.29      +89 -48    apache-1.2/src/mod_rewrite.c
  
  Index: mod_rewrite.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_rewrite.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- mod_rewrite.c	1997/04/24 23:35:22	1.28
  +++ mod_rewrite.c	1998/01/30 09:14:08	1.29
  @@ -52,16 +52,14 @@
    */
   
   
  -/*
  -**  mod_rewrite.c -- The Main Module Code
  -**                       _                            _ _ 
  +/*                       _                            _ _ 
   **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___ 
   **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
   **  | | | | | | (_) | (_| |   | | |  __/\ V  V /| |  | | ||  __/
   **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
   **                       |_____|
   **
  -**  URL Rewriting Module, Version 3.0.5 (16-Apr-1997)
  +**  URL Rewriting Module
   **
   **  This module uses a rule-based rewriting engine (based on a
   **  regular-expression parser) to rewrite requested URLs on the fly. 
  @@ -78,12 +76,9 @@
   **  can lead to internal subprocessing, external request redirection or even
   **  to internal proxy throughput.
   **
  -**  The documentation and latest release can be found on
  -**  http://www.engelschall.com/sw/mod_rewrite/
  -**
  -**  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
  +**  This module was originally written in April 1996 and 
  +**  gifted exclusively to the The Apache Group in July 1997 by
   **
  -**  Written for The Apache Group by
   **      Ralf S. Engelschall
   **      rse@engelschall.com
   **      www.engelschall.com
  @@ -219,7 +214,7 @@
   };
   
       /* the cache */
  -cache *cachep;
  +static cache *cachep;
   
       /* whether proxy module is available or not */
   static int proxy_available;
  @@ -779,6 +774,10 @@
                || strcasecmp(key, "G") == 0   ) {
           cfg->flags |= RULEFLAG_GONE;
       }
  +    else if (   strcasecmp(key, "qsappend") == 0
  +             || strcasecmp(key, "QSA") == 0   ) {
  +        cfg->flags |= RULEFLAG_QSAPPEND;
  +    }
       else {
           return pstrcat(p, "RewriteRule: unknown flag '", key, "'\n", NULL);
       }
  @@ -926,8 +925,11 @@
   
               /* check if the proxy module is enabled, so
                  we can actually use it! */
  -            if (!proxy_available)
  -                return FORBIDDEN; 
  +            if (!proxy_available) {
  +		log_reason("attempt to make remote request from mod_rewrite "
  +    	    	    "without proxy enabled", r->filename, r);
  +                return FORBIDDEN;
  +    	    }
   
               /* make sure the QUERY_STRING and
                  PATH_INFO parts get incorporated */
  @@ -1110,6 +1112,7 @@
       char *prefix;
       int l;
       int n;
  +    char *ofilename;
   
       dconf = (rewrite_perdir_conf *)get_module_config(r->per_dir_config, &rewrite_module);
   
  @@ -1143,6 +1146,13 @@
       }
   
       /*
  +     *  remember the current filename before rewriting for later check
  +     *  to prevent deadlooping because of internal redirects
  +     *  on final URL/filename which can be equal to the inital one.
  +     */
  +    ofilename = r->filename;
  +
  +    /*
        *  now apply the rules ... 
        */
       if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) {
  @@ -1256,6 +1266,18 @@
               if (r->filename[0] != '/')
                   return BAD_REQUEST;
   
  +            /* Check for deadlooping:
  +             * At this point we KNOW that at least one rewriting
  +             * rule was applied, but when the resulting URL is
  +             * the same as the initial URL, we are not allowed to
  +             * use the following internal redirection stuff because
  +             * this would lead to a deadloop.
  +             */
  +            if (strcmp(r->filename, ofilename) == 0) {
  +                rewritelog(r, 1, "[per-dir %s] initial URL equal rewritten URL: %s [IGNORING REWRITE]", dconf->directory, r->filename);
  +                return OK;
  +            }
  +
               /* if there is a valid base-URL then substitute
                  the per-dir prefix with this base-URL if the
                  current filename still is inside this per-dir 
  @@ -1497,8 +1519,17 @@
               return 0; /* if any condition fails this complete rule fails */
   
           /* if this is a pure matching rule we return immediately */
  -        if (strcmp(output, "-") == 0) 
  +        if (strcmp(output, "-") == 0) {
  +            /* but before we set the env variables... */
  +            for (i = 0; p->env[i] != NULL; i++) {
  +                strncpy(env2, p->env[i], sizeof(env2)-1);
  +                EOS_PARANOIA(env2);
  +                strncpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch), sizeof(env)-1);    /* substitute in output */
  +                EOS_PARANOIA(env);
  +                add_env_variable(r, env);
  +            }
               return 2;
  +        }
   
           /* if this is a forced proxy request ... */
           if (p->flags & RULEFLAG_PROXY) {
  @@ -1531,7 +1562,7 @@
               return 1;
           }
   
  -        /* if this is a implicit redirect in a per-dir rule */
  +        /* if this is an implicit redirect in a per-dir rule */
           i = strlen(output);
           if (perdir != NULL
               && (   (i > 7 && strncmp(output, "http://", 7) == 0)
  @@ -1559,13 +1590,14 @@
               }
               rewritelog(r, 2, "[per-dir %s] redirect %s -> %s", perdir, r->filename, newuri);
               r->filename = pstrdup(r->pool, newuri);
  +            splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
  +            r->status = p->forced_responsecode;
               return 1;
           }
   
  -        /* add the previously stripped perdir prefix 
  -           if the new URI is not a new one (i.e.
  -           prefixed by a slash which means that is 
  -           no for this per-dir context) */
  +        /* add again the previously stripped perdir prefix if the new 
  +           URI is not a new one (i.e. prefixed by a slash which means 
  +           that it is not for this per-dir context)                    */
           if (prefixstrip && output[0] != '/') {
               rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", perdir, output, perdir, output);
               output = pstrcat(r->pool, perdir, output, NULL);
  @@ -1602,7 +1634,7 @@
           reduce_uri(r);
   
           /* split out on-the-fly generated QUERY_STRING '....?xxxxx&xxxx...' */
  -        splitout_queryargs(r);
  +        splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
   
           /* if a MIME-type should be later forced for this URL, then remember this */
           if (p->forced_mimetype != NULL) {
  @@ -1617,6 +1649,7 @@
              and the current URL still is not a fully qualified one we
              finally prefix it with http[s]://<ourname> explicitly */
           if (flags & RULEFLAG_FORCEREDIRECT) {
  +            r->status = p->forced_responsecode;
               if (  !(strlen(r->filename) > 7 &&
                       strncmp(r->filename, "http://", 7) == 0)
                  && !(strlen(r->filename) > 8 &&
  @@ -1652,7 +1685,6 @@
                   else
                       rewritelog(r, 2, "[per-dir %s] prepare forced redirect %s -> %s", perdir, r->filename, newuri);
                   r->filename = pstrdup(r->pool, newuri);
  -                r->status = p->forced_responsecode;
                   return 1;
               }
           }
  @@ -1763,7 +1795,9 @@
       if (p->flags & CONDFLAG_NOTMATCH) 
           rc = !rc;
   
  -    rewritelog(r, 4, "RewriteCond: input='%s' pattern='%s' => %s", input, p->pattern, rc ? "matched" : "not-matched");
  +    rewritelog(r, 4, "RewriteCond: input='%s' pattern='%s%s' => %s", 
  +               input, (p->flags & CONDFLAG_NOTMATCH ? "!" : ""), 
  +               p->pattern, rc ? "matched" : "not-matched");
   
       /* end just return the result */
       return rc;
  @@ -1788,7 +1822,7 @@
   **
   */
   
  -static void splitout_queryargs(request_rec *r)
  +static void splitout_queryargs(request_rec *r, int qsappend)
   {
       char *q;
       char *olduri;
  @@ -1797,10 +1831,19 @@
       if (q != NULL) {
           olduri = pstrdup(r->pool, r->filename);
           *q++ = '\0';
  -        r->args = pstrcat(r->pool, q, "&", r->args, NULL);
  -        if (r->args[strlen(r->args)-1] == '&')
  -            r->args[strlen(r->args)-1] = '\0';
  -        rewritelog(r, 3, "split uri=%s -> uri=%s, args=%s", olduri, r->filename, r->args);
  +        if (qsappend)
  +            r->args = pstrcat(r->pool, q, "&", r->args, NULL);
  +        else
  +            r->args = pstrdup(r->pool, q);
  +        if (strlen(r->args) == 0) {
  +            r->args = NULL;
  +            rewritelog(r, 3, "split uri=%s -> uri=%s, args=<none>", olduri, r->filename);
  +        }
  +        else {
  +            if (r->args[strlen(r->args)-1] == '&')
  +                r->args[strlen(r->args)-1] = '\0';
  +            rewritelog(r, 3, "split uri=%s -> uri=%s, args=%s", olduri, r->filename, r->args);
  +        }
       }
       return;            
   }
  @@ -2203,7 +2246,9 @@
       int i;
   
       /* lock the channel */
  +#ifdef USE_PIPE_LOCKING
       fd_lock(fpin);
  +#endif
   
       /* write out the request key */
       write(fpin, key, strlen(key));
  @@ -2219,7 +2264,9 @@
       buf[i] = '\0';
   
       /* unlock the channel */
  +#ifdef USE_PIPE_LOCKING
       fd_unlock(fpin);
  +#endif
   
       if (strcasecmp(buf, "NULL") == 0)
           return NULL;
  @@ -2244,8 +2291,8 @@
       rewrite_server_conf *conf;
       char *fname;
       FILE *fp;
  -    static int    rewritelog_flags = ( O_WRONLY|O_APPEND|O_CREAT );
  -    static mode_t rewritelog_mode  = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
  +    int    rewritelog_flags = ( O_WRONLY|O_APPEND|O_CREAT );
  +    mode_t rewritelog_mode  = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
     
       conf = get_module_config(s->module_config, &rewrite_module);
       
  @@ -2296,14 +2343,15 @@
       rewrite_server_conf *conf;
       conn_rec *connect;
       char *str1;
  -    static char str2[HUGE_STRING_LEN];
  -    static char str3[HUGE_STRING_LEN];
  -    static char type[20];
  -    static char redir[20];
  +    char str2[512];
  +    char str3[1024];
  +    char type[20];
  +    char redir[20];
       va_list ap;
       int i;
       request_rec *req;
       char *ruser;
  +    const char *rhost;
       
       va_start(ap, text);
       conf = get_module_config(r->server->module_config, &rewrite_module);
  @@ -2329,7 +2377,11 @@
           ruser = "\"\"";
       }
   
  -    str1 = pstrcat(r->pool, get_remote_host(connect, r->server->module_config, REMOTE_NAME), " ",
  +    rhost = get_remote_host(connect, r->server->module_config, REMOTE_NAME);
  +    if (rhost == NULL)
  +        rhost = "UNKNOWN-HOST";
  +
  +    str1 = pstrcat(r->pool, rhost, " ",
                               (connect->remote_logname != NULL ? connect->remote_logname : "-"), " ",
                               ruser, NULL);
       ap_vsnprintf(str2, sizeof(str2), text, ap);
  @@ -2339,8 +2391,8 @@
       else
           strcpy(type, "subreq");
   
  -    for (i = 0, req = r->prev; req != NULL; req = req->prev) 
  -        ;
  +    for (i = 0, req = r; req->prev != NULL; req = req->prev) 
  +        i++;
       if (i == 0)
           redir[0] = '\0';
       else
  @@ -3177,18 +3229,7 @@
   
   static int is_proxy_available(server_rec *s)
   {
  -    extern module *preloaded_modules[];
  -    command_rec *c;
  -    int n;
  -    
  -    for (n = 0; preloaded_modules[n] != NULL; n++) {
  -        for (c = preloaded_modules[n]->cmds; c && c->name; ++c) {
  -            if (strcmp(c->name, "ProxyRequests") == 0) {
  -                return 1;
  -            }
  -        }
  -    }
  -    return 0;
  +    return (find_linked_module("mod_proxy.c") != NULL); 
   }
   
   
  @@ -3270,7 +3311,7 @@
   **
   */
   
  -int compare_lexicography(char *cpNum1, char *cpNum2)
  +static int compare_lexicography(char *cpNum1, char *cpNum2)
   {
       int i;
       int n1, n2;
  
  
  
  1.23      +14 -10    apache-1.2/src/mod_rewrite.h
  
  Index: mod_rewrite.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_rewrite.h,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- mod_rewrite.h	1997/04/17 02:52:51	1.22
  +++ mod_rewrite.h	1998/01/30 09:14:09	1.23
  @@ -56,7 +56,6 @@
   #define _MOD_REWRITE_H 1
   
   /*
  -**  mod_rewrite.h -- Common Header File
   **                       _                            _ _ 
   **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___ 
   **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
  @@ -64,7 +63,7 @@
   **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
   **                       |_____|
   **
  -**  URL Rewriting Module, Version 3.0.5 (16-Apr-1997)
  +**  URL Rewriting Module
   **
   **  This module uses a rule-based rewriting engine (based on a
   **  regular-expression parser) to rewrite requested URLs on the fly. 
  @@ -81,12 +80,9 @@
   **  can lead to internal subprocessing, external request redirection or even
   **  to internal proxy throughput.
   **
  -**  The documentation and latest release can be found on
  -**  http://www.engelschall.com/sw/mod_rewrite/
  +**  This module was originally written in April 1996 and 
  +**  gifted exclusively to the The Apache Group in July 1997 by
   **
  -**  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
  -**
  -**  Written for The Apache Group by
   **      Ralf S. Engelschall
   **      rse@engelschall.com
   **      www.engelschall.com
  @@ -137,7 +133,14 @@
   #include <fcntl.h>
   #endif
   
  -
  +    /* The locking support for the RewriteMap programs:
  +       Locking a pipe to the child works fine under most
  +       Unix derivates, but braindead SunOS 4.1.x has 
  +       problems with this approach... */
  +#define USE_PIPE_LOCKING 1
  +#ifdef SUNOS4
  +#undef USE_PIPE_LOCKING
  +#endif
   
   
   /*
  @@ -171,6 +174,7 @@
   #define RULEFLAG_PASSTHROUGH        1<<8
   #define RULEFLAG_FORBIDDEN          1<<9
   #define RULEFLAG_GONE               1<<10
  +#define RULEFLAG_QSAPPEND           1<<11
   
   #define MAPTYPE_TXT                 1<<0
   #define MAPTYPE_DBM                 1<<1
  @@ -334,7 +338,7 @@
   static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, char *perdir); 
   
       /* URI transformation function */
  -static void  splitout_queryargs(request_rec *r);
  +static void  splitout_queryargs(request_rec *r, int qsappend);
   static void  reduce_uri(request_rec *r);
   static char *expand_tildepaths(request_rec *r, char *uri);
   static void  expand_map_lookups(request_rec *r, char *uri, int uri_len);
  @@ -389,7 +393,7 @@
   static void fd_unlock(int fd);
   
       /* Lexicographic Comparison */
  -int compare_lexicography(char *cpNum1, char *cpNum2);
  +static int compare_lexicography(char *cpNum1, char *cpNum2);
   
   #endif /* _MOD_REWRITE_H */
   
  
  
  
  1.48      +8 -1      apache-1.2/src/mod_status.c
  
  Index: mod_status.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_status.c,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- mod_status.c	1997/05/08 08:23:31	1.47
  +++ mod_status.c	1998/01/30 09:14:09	1.48
  @@ -95,6 +95,7 @@
   #include "util_script.h"
   #include <time.h>
   #include "scoreboard.h"
  +#include "http_log.h"
   
   #ifdef NEXT
   #include <machine/param.h>
  @@ -229,7 +230,13 @@
       status[SERVER_BUSY_DNS]='D';
       status[SERVER_GRACEFUL]='G';
   
  -    if (r->method_number != M_GET) return NOT_IMPLEMENTED;
  +    if (!exists_scoreboard_image()) {
  +         log_printf(r->server, "Server status unavailable in inetd mode");
  +         return HTTP_NOT_IMPLEMENTED;
  +     }
  +    r->allowed = (1 << M_GET) | (1 << M_TRACE);
  +    if (r->method_number != M_GET) return HTTP_METHOD_NOT_ALLOWED;
  +
       r->content_type = "text/html";
   
       /*
  
  
  
  1.15      +3 -1      apache-1.2/src/mod_userdir.c
  
  Index: mod_userdir.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_userdir.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- mod_userdir.c	1997/03/07 14:15:44	1.14
  +++ mod_userdir.c	1998/01/30 09:14:10	1.15
  @@ -114,6 +114,7 @@
       char *name = r->uri;
       const char *w, *dname, *redirect;
       char *x = NULL;
  +    struct stat statbuf;
   
       if (userdirs == NULL || !strcasecmp(userdirs, "disabled") ||
           (name[0] != '/') || (name[1] != '~')) {
  @@ -182,8 +183,9 @@
          in the hope that some handler might handle it. This can be used, for
          example, to run a CGI script for the user. 
          */
  -      if (filename && (!*userdirs || stat(filename, &r->finfo) != -1)) {
  +      if (filename && (!*userdirs || stat(filename, &statbuf) != -1)) {
   	r->filename = pstrcat(r->pool, filename, dname, NULL);
  +	r->finfo = statbuf;
   	return OK;
         }
       }
  
  
  
  1.11      +2 -0      apache-1.2/src/mod_usertrack.c
  
  Index: mod_usertrack.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/mod_usertrack.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- mod_usertrack.c	1997/03/07 14:15:45	1.10
  +++ mod_usertrack.c	1998/01/30 09:14:11	1.11
  @@ -97,7 +97,9 @@
   #include "httpd.h"
   #include "http_config.h"
   #include "http_core.h"
  +#ifndef MPE
   #include <sys/time.h>
  +#endif
   
   module usertrack_module;
   
  
  
  
  1.22      +1 -1      apache-1.2/src/scoreboard.h
  
  Index: scoreboard.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/scoreboard.h,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- scoreboard.h	1997/04/24 23:35:23	1.21
  +++ scoreboard.h	1998/01/30 09:14:12	1.22
  @@ -107,4 +107,4 @@
   
   extern void sync_scoreboard_image(void);
   short_score get_scoreboard_info(int x);
  -
  +int exists_scoreboard_image ();
  
  
  
  1.53      +51 -10    apache-1.2/src/util.c
  
  Index: util.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/util.c,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -r1.52 -r1.53
  --- util.c	1997/04/12 04:24:59	1.52
  +++ util.c	1998/01/30 09:14:12	1.53
  @@ -83,6 +83,7 @@
   
       /* check return code? */
       strftime(ts,MAX_STRING_LEN,fmt,tms);
  +    ts[MAX_STRING_LEN - 1] = '\0';
       return pstrdup (p, ts);
   }
   
  @@ -232,7 +233,7 @@
   	    if (c == '\\' && (*src == '$' || *src == '&'))
   		c = *src++;
   	    len++;
  -	} else if (no <= nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
  +	} else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
   	    len += pmatch[no].rm_eo - pmatch[no].rm_so;
   	}
   
  @@ -256,7 +257,7 @@
   	    if (c == '\\' && (*src == '$' || *src == '&'))
   		c = *src++;
   	    *dst++ = c;
  -	} else if (no <= nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
  +	} else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
   	    len = pmatch[no].rm_eo - pmatch[no].rm_so;
   	    strncpy(dst, source + pmatch[no].rm_so, len);
   	    dst += len;
  @@ -328,14 +329,22 @@
       }
   } 
   
  -void no2slash(char *name) {
  -    register int x,y;
  +void no2slash(char *name)
  +{
  +    char *d, *s;
   
  -    for(x=0; name[x];)
  -        if(x && (name[x-1] == '/') && (name[x] == '/'))
  -            for(y=x+1;name[y-1];y++)
  -                name[y-1] = name[y];
  -	else x++;
  +    s = d = name;
  +    while (*s) {
  +        if ((*d++ = *s) == '/') {
  +            do {
  +                ++s;
  +            } while (*s == '/');
  +        }
  +        else {
  +            ++s;
  +        }
  +    }
  +    *d = '\0';
   }
   
   char *make_dirstr(pool *p, const char *s, int n) {
  @@ -561,6 +570,11 @@
       if(c == EOF)
   	return 1;
   
  +    if(n < 2) {
  +	/* too small, assume caller is crazy */
  +	return 1;
  +    }
  +
       while(1) {
           if((c == '\t') || (c == ' ')) {
               s[i++] = ' ';
  @@ -570,7 +584,7 @@
           if(c == CR) {
               c = getc(f);
           }
  -        if(c == EOF || c == 0x4 || c == LF || i == (n-1)) {
  +        if(c == EOF || c == 0x4 || c == LF || i >= (n-2)) {
               /* blast trailing whitespace */
               while(i && (s[i-1] == ' ')) --i;
               s[i] = '\0';
  @@ -1326,3 +1340,30 @@
       return (p);
   }
   #endif
  +
  +
  +int ap_slack (int fd, int line)
  +{
  +#if !defined(F_DUPFD) || defined(NO_SLACK)
  +    return fd;
  +#else
  +    int new_fd;
  +
  +#ifdef HIGH_SLACK_LINE
  +    if (line == AP_SLACK_HIGH) {
  +	new_fd = fcntl (fd, F_DUPFD, HIGH_SLACK_LINE);
  +	if (new_fd != -1) {
  +	    close (fd);
  +	    return new_fd;
  +	}
  +    }
  +#endif
  +    /* otherwise just assume line == AP_SLACK_LOW */
  +    new_fd = fcntl (fd, F_DUPFD, LOW_SLACK_LINE);
  +    if (new_fd == -1) {
  +      return fd;
  +    }
  +    close (fd);
  +    return new_fd;
  +#endif
  +}
  
  
  
  1.59      +4 -1      apache-1.2/src/util_script.c
  
  Index: util_script.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/util_script.c,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -r1.58 -r1.59
  --- util_script.c	1997/05/11 23:13:22	1.58
  +++ util_script.c	1998/01/30 09:14:13	1.59
  @@ -502,7 +502,10 @@
           program = fopen (r->filename, "r");
           if (!program) {
               char err_string[HUGE_STRING_LEN];
  -            ap_snprintf(err_string, sizeof(err_string), "open of %s failed, errno is %d\n", r->filename, errno);
  +            ap_snprintf(err_string, sizeof(err_string), 
  +		 "open of %s failed, reason: fopen: %s (errno = %d)\n", 
  +		 r->filename, strerror(errno), errno);
  +
               /* write(2, err_string, strlen(err_string)); */
               /* exit(0); */
               log_unixerr("fopen", NULL, err_string, r->server);
  
  
  
  1.20      +12 -2     apache-1.2/src/helpers/GuessOS
  
  Index: GuessOS
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/helpers/GuessOS,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- GuessOS	1997/04/27 07:52:19	1.19
  +++ GuessOS	1998/01/30 09:14:25	1.20
  @@ -41,6 +41,8 @@
   	    4.2MP)
   		if [ "x$VERSION" = "x2.1.1" ]; then
   		    echo "${MACHINE}-whatever-unixware211"; exit 0
  +		elif [ "x$VERSION" = "x2.1.2" ]; then
  +		    echo "${MACHINE}-whatever-unixware212"; exit 0
   		else
   		    echo "${MACHINE}-whatever-unixware2"; exit 0
   		fi
  @@ -59,7 +61,7 @@
   	;;
   
       AIX:*)
  -	echo "${MACHINE}-ibm-aix"; exit 0
  +	echo "${MACHINE}-ibm-aix${VERSION}.${RELEASE}"; exit 0
   	;;
   
       dgux:*)
  @@ -190,8 +192,16 @@
   	echo "${MACHINE}-ncr-sysv4"; exit 0
   	;;
   
  -    ConvexOS:*:11.0:*)
  +    ConvexOS:*:11.*:*)
   	echo "${MACHINE}-v11-${SYSTEM}"; exit 0;
  +	;;
  +    
  +    UNIX_SV:*:*:maxion)
  +	echo "${MACHINE}-ccur-sysv4"; exit 0;
  +	;;
  +    
  +    NonStop-UX:4.[02]*:[BC]*:*)
  +	echo "${MACHINE}-tandem-sysv4"; exit 0;
   	;;
   
   esac
  
  
  
  1.12      +1 -1      apache-1.2/src/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/modules/proxy/mod_proxy.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- mod_proxy.h	1997/04/16 00:13:05	1.11
  +++ mod_proxy.h	1998/01/30 09:14:26	1.12
  @@ -225,7 +225,7 @@
   int proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
       struct cache_req **cr);
   int proxy_cache_update(struct cache_req *c, array_header *resp_hdrs,
  -    const char *protocol, int nocache);
  +    const int is_HTTP1, int nocache);
   void proxy_garbage_coll(request_rec *r);
   
   /* proxy_connect.c */
  
  
  
  1.14      +11 -10    apache-1.2/src/modules/proxy/proxy_cache.c
  
  Index: proxy_cache.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/modules/proxy/proxy_cache.c,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- proxy_cache.c	1997/05/29 15:16:01	1.13
  +++ proxy_cache.c	1998/01/30 09:14:27	1.14
  @@ -84,6 +84,7 @@
   static unsigned long int curblocks;
   static time_t now, expire;
   static char *filename;
  +static int filenamelen;
   
   static int sub_garbage_coll(request_rec *r,array_header *files,
   			    const char *cachedir,const char *cachesubdir);
  @@ -111,9 +112,10 @@
   
       block_alarms();	/* avoid SIGALRM on big cache cleanup */
   
  -    filename = palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
  -    strcpy(filename, cachedir);
  -    strcat(filename, "/.time");
  +    filenamelen = strlen(cachedir) + HASH_LEN + 2;
  +    filename = palloc(r->pool, filenamelen);
  +    ap_snprintf(filename, filenamelen, "%s/.time", cachedir);
  +
       if (stat(filename, &buf) == -1) /* does not exist */
       {
   	if (errno != ENOENT)
  @@ -161,7 +163,7 @@
       for (i=0; i < files->nelts; i++)
       {
   	fent = elts[i];
  -	sprintf(filename, "%s%s", cachedir, fent->file);
  +	ap_snprintf(filename, filenamelen, "%s%s", cachedir, fent->file);
   	Explain3("GC Unlinking %s (expiry %ld, now %ld)",filename,fent->expire,now);
   #if TESTING
   	fprintf(stderr,"Would unlink %s\n",filename);
  @@ -216,7 +218,7 @@
       while ((ent = readdir(dir)) != NULL)
       {
   	if (ent->d_name[0] == '.') continue;
  -	sprintf(filename, "%s%s", cachedir, ent->d_name);
  +	ap_snprintf(filename, filenamelen, "%s%s", cachedir, ent->d_name);
   	Explain1("GC Examining file %s",filename);
   /* is it a temporary file? */
   	if (strncmp(ent->d_name, "tmp", 3) == 0)
  @@ -315,8 +317,8 @@
   	fent = palloc(r->pool, sizeof(struct gc_ent));
   	fent->len = buf.st_size;
   	fent->expire = expire;
  -	strcpy(fent->file,cachesubdir);
  -	strcat(fent->file, ent->d_name);
  +	ap_snprintf(fent->file, sizeof(fent->file), "%s%s", cachesubdir,
  +	    ent->d_name);
   	*(struct gc_ent **)push_array(files) = fent;
   
   /* accumulate in blocks, to cope with directories > 4Gb */
  @@ -581,7 +583,7 @@
    */
   int
   proxy_cache_update(struct cache_req *c, array_header *resp_hdrs,
  -	     const char *protocol, int nocache)
  +                   const int is_HTTP1, int nocache)
   {
       request_rec *r=c->req;
       char *p;
  @@ -632,8 +634,7 @@
       if ((r->status != 200 && r->status != 301 && r->status != 304) ||
   	(expire != NULL && expc == BAD_DATE) ||
   	(r->status == 304 && c->fp == NULL) ||
  -	(r->status == 200 && lmods == NULL &&
  -	                     strncmp(protocol, "HTTP/1.", 7) == 0) ||
  +	(r->status == 200 && lmods == NULL && is_HTTP1) ||
   	r->header_only ||
   	table_get(r->headers_in, "Authorization") != NULL ||
   	nocache)
  
  
  
  1.22      +9 -8      apache-1.2/src/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- proxy_ftp.c	1997/04/22 03:29:37	1.21
  +++ proxy_ftp.c	1998/01/30 09:14:27	1.22
  @@ -286,8 +286,8 @@
   	    buf[sizeof(buf)-1] = '\0';
               n=strlen(buf);
           }
  -        else if(buf[0]=='d' || buf[0]=='-' || buf[0]=='l' || isdigit(buf[0]))
  -        {
  +        else if (strrchr(buf, ' ') && (buf[0]=='d' || buf[0]=='-' || 
  +				       buf[0]=='l' || isdigit(buf[0])) ) {
   	    if(isdigit(buf[0])) {		/* handle DOS dir */
   	        searchptr = strchr(buf, '<');
   	        if(searchptr != NULL)
  @@ -372,9 +372,10 @@
               o+=w;
           }
       }
  -    ap_snprintf(buf, sizeof(buf), "</PRE><HR><I><A HREF=\"http://www.apache.org\">%s</A></I></BODY></HTML>", SERVER_VERSION);
  -    bwrite(con->client, buf, strlen(buf));
  -    if (f2 != NULL) bwrite(f2, buf, strlen(buf));
  +    bputs("</PRE><HR></BODY></HTML>\015\012", con->client);
  +    if (f2 != NULL) {
  +	bputs("</PRE><HR></BODY></HTML>\015\012", f2);
  +    }
       total_bytes_sent+=strlen(buf);
       bflush(con->client);
       
  @@ -908,7 +909,7 @@
               nocache = 1;
       }
   
  -    i = proxy_cache_update(c, resp_hdrs, "FTP", nocache);
  +    i = proxy_cache_update(c, resp_hdrs, 0, nocache);
   
       if (i != DECLINED)
       {
  @@ -944,9 +945,9 @@
   /* send response */
   /* write status line */
       if (!r->assbackwards)
  -	rvputs(r, SERVER_PROTOCOL, " ", r->status_line, "\015\012", NULL);
  +	rvputs(r, "HTTP/1.0 ", r->status_line, "\015\012", NULL);
       if (cache != NULL)
  -	if (bvputs(cache, SERVER_PROTOCOL, " ", r->status_line, "\015\012",
  +	if (bvputs(cache, "HTTP/1.0 ", r->status_line, "\015\012",
   		   NULL) == -1)
   	    cache = proxy_cache_error(c);
   
  
  
  
  1.18      +28 -29    apache-1.2/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- proxy_http.c	1997/04/11 05:10:51	1.17
  +++ proxy_http.c	1998/01/30 09:14:28	1.18
  @@ -143,7 +143,7 @@
   {
       char *p;
       const char *err, *desthost;
  -    int i, j, sock, len;
  +    int i, j, sock, len, backasswards;
       array_header *reqhdrs_arr, *resp_hdrs;
       table_entry *reqhdrs;
       struct sockaddr_in server;
  @@ -151,11 +151,12 @@
       struct hostent server_hp;
       BUFF *f, *cache;
       struct hdr_entry *hdr;
  -    char buffer[HUGE_STRING_LEN], inprotocol[9], outprotocol[9];
  +    char buffer[HUGE_STRING_LEN];
       pool *pool=r->pool;
       const long int zero=0L;
       int destport = 0;
       char *destportstr = NULL;
  +    char *urlptr = NULL;
   
       void *sconf = r->server->module_config;
       proxy_server_conf *conf =
  @@ -169,19 +170,21 @@
   
   /* We break the URL into host, port, path-search */
   
  -    url += 7;  /* skip http:// */
  +    urlptr = strstr(url,"://");
  +    if (urlptr == NULL) return BAD_REQUEST;
  +    urlptr += 3;
       destport = DEFAULT_PORT;
  -    p = strchr(url, '/');
  +    p = strchr(urlptr, '/');
       if (p == NULL)
       {
  -        desthost = pstrdup(pool, url);
  -        url = "/";
  +        desthost = pstrdup(pool, urlptr);
  +        urlptr = "/";
       } else
       {
  -        char *q = palloc(pool, p-url+1);
  -        memcpy(q, url, p-url);
  -        q[p-url] = '\0';
  -        url = p;
  +        char *q = palloc(pool, p-urlptr+1);
  +        memcpy(q, urlptr, p-urlptr);
  +        q[p-urlptr] = '\0';
  +        urlptr = p;
           desthost = q;
       }
   
  @@ -207,7 +210,6 @@
   
       if (proxyhost != NULL)
       {
  -	url = r->uri;			/* restore original URL */
   	server.sin_port = htons(proxyport);
   	err = proxy_host2addr(proxyhost, &server_hp);
   	if (err != NULL) return DECLINED;  /* try another */
  @@ -248,7 +250,8 @@
       bpushfd(f, sock, sock);
   
       hard_timeout ("proxy send", r);
  -    bvputs(f, r->method, " ", url, " HTTP/1.0\015\012", NULL);
  +    bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0\015\012",
  +           NULL);
       bvputs(f, "Host: ", desthost, NULL);
       if (destportstr != NULL && destport != DEFAULT_PORT)
   	bvputs(f, ":", destportstr, "\015\012", NULL);
  @@ -260,7 +263,7 @@
       for (i=0; i < reqhdrs_arr->nelts; i++)
       {
   	if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
  -	  || !strcmp(reqhdrs[i].key, "Host"))	/* already sent if there */
  +	  || !strcasecmp(reqhdrs[i].key, "Host"))  /* already sent if there */
   	    continue;
   	bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, "\015\012", NULL);
       }
  @@ -286,7 +289,7 @@
   	return proxyerror(r, "Error reading from remote server");
       }
   
  -/* Is it an HTTP/1 response? */
  +/* Is it an HTTP/1 response?  This is buggy if we ever see an HTTP/1.10 */
       if (checkmask(buffer,  "HTTP/#.# ###*"))
       {
   /* If not an HTTP/1 messsage or if the status line was > 8192 bytes */
  @@ -296,12 +299,9 @@
   	    kill_timeout(r);
   	    return BAD_GATEWAY;
   	}
  +	backasswards = 0;
   	buffer[--len] = '\0';
  -	memcpy(inprotocol, buffer, 8);
  -	inprotocol[8] = '\0';
   
  -/* we use the same protocol on output as on input */
  -	strcpy(outprotocol, inprotocol);
   	buffer[12] = '\0';
   	r->status = atoi(&buffer[9]);
   	buffer[12] = ' ';
  @@ -312,11 +312,13 @@
   /* Also, take care with headers with multiple occurences. */
   
   	resp_hdrs = proxy_read_headers(pool, buffer, HUGE_STRING_LEN, f);
  -    } else
  +
  +	clear_connection((table *)resp_hdrs);  /* Strip Connection hdrs */
  +    }
  +    else
       {
   /* an http/0.9 response */
  -	strcpy(inprotocol, "HTTP/0.9");
  -	strcpy(outprotocol, "HTTP/1.0");
  +	backasswards = 1;
   	r->status = 200;
   	r->status_line = "200 OK";
   
  @@ -331,9 +333,8 @@
    * one type
    */
       
  -    len = resp_hdrs->nelts;
       hdr = (struct hdr_entry *)resp_hdrs->elts;
  -    for (i=0; i < len; i++)
  +    for (i=0; i < resp_hdrs->nelts; i++)
       {
   	if (hdr[i].value[0] == '\0') continue;
   	p = hdr[i].field;
  @@ -351,7 +352,7 @@
   	    nocache = 1; 
       }
   
  -    i = proxy_cache_update(c, resp_hdrs, inprotocol, nocache);
  +    i = proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
       if (i != DECLINED)
       {
   	pclosef(pool, sock);
  @@ -366,13 +367,11 @@
       if (!r->assbackwards)
           rvputs(r, "HTTP/1.0 ", r->status_line, "\015\012", NULL);
       if (cache != NULL)
  -	if (bvputs(cache, outprotocol, " ", r->status_line, "\015\012", NULL)
  -	    == -1)
  +	if (bvputs(cache, "HTTP/1.0 ", r->status_line, "\015\012", NULL) == -1)
   	    cache = proxy_cache_error(c);
   
   /* send headers */
  -    len = resp_hdrs->nelts;
  -    for (i=0; i < len; i++)
  +    for (i=0; i < resp_hdrs->nelts; i++)
       {
   	if (hdr[i].field == NULL || hdr[i].value == NULL ||
   	    hdr[i].value[0] == '\0') continue;
  @@ -391,7 +390,7 @@
       bsetopt(r->connection->client, BO_BYTECT, &zero);
       r->sent_bodyct = 1;
   /* Is it an HTTP/0.9 respose? If so, send the extra data */
  -    if (strcmp(inprotocol, "HTTP/0.9") == 0)
  +    if (backasswards)
       {
   	bwrite(r->connection->client, buffer, len);
   	if (cache != NULL)
  
  
  
  1.18      +5 -2      apache-1.2/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- proxy_util.c	1997/06/04 21:20:27	1.17
  +++ proxy_util.c	1998/01/30 09:14:28	1.18
  @@ -296,8 +296,11 @@
       for (mon=0; mon < 12; mon++) if (strcmp(month, months[mon]) == 0) break;
       if (mon == 12) return x;
   
  -    if (strlen(x) < 31) x = palloc(p, 31);
  -    ap_snprintf(x, strlen(x)+1, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", wday[wk], mday,
  +    if (strlen(x)+1 < 30) {
  +        x = palloc(p, 30);
  +    }
  +    /* format: "Wed, 17 Dec 1997 00:53:40 GMT" (29 chars data) */
  +    ap_snprintf(x, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", wday[wk], mday,
   	    months[mon], year, hour, min, sec);
       return x;
   }
  
  
  
  1.8       +3 -1      apache-1.2/support/logresolve.c
  
  Index: logresolve.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/support/logresolve.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- logresolve.c	1997/02/04 23:54:28	1.7
  +++ logresolve.c	1998/01/30 09:14:30	1.8
  @@ -202,7 +202,9 @@
       } else
   	cachehits++;
   
  -    strcpy(string, (*current)->hostname);
  +    /* size of string == MAXDNAME +1 */
  +    strncpy(string, (*current)->hostname, MAXDNAME);
  +    string[MAXDNAME] = '\0';
   }
   
   /*
  
  
  
  1.23      +3 -1      apache-1.2/support/suexec.c
  
  Index: suexec.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.2/support/suexec.c,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- suexec.c	1997/04/24 23:28:46	1.22
  +++ suexec.c	1998/01/30 09:14:31	1.23
  @@ -75,7 +75,7 @@
   #include <sys/types.h>
   #include <stdio.h>
   #include <stdarg.h>
  -#include <strings.h>
  +#include <string.h>
   #include <pwd.h>
   #include <grp.h>
   #include <time.h>
  @@ -138,6 +138,7 @@
   
   static void err_output(const char *fmt, va_list ap)
   {
  +#ifdef LOG_EXEC
       time_t timevar;
       struct tm *lt;
   
  @@ -157,6 +158,7 @@
       vfprintf(log, fmt, ap);
   
       fflush(log);
  +#endif /* LOG_EXEC */
       return;
   }