cvs commit: apache-2.0/src/main http_protocol.c http_request.c

2000-01-12 Thread rbb
rbb 00/01/12 10:20:45

  Modified:src/main http_protocol.c http_request.c
  Log:
  Fix some remaining problems with SSI's and Windows.  Basically, the
  sendfile stuff doesn't work properly with chuncked data.
  Submitted by: Allan Edwards
  Reviewed by:  Ryan Bloom
  
  Revision  ChangesPath
  1.47  +14 -9 apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- http_protocol.c   2000/01/09 05:18:23 1.46
  +++ http_protocol.c   2000/01/12 18:20:43 1.47
  @@ -2016,16 +2016,21 @@
   {
   long len;
   #ifdef HAVE_SENDFILE
  -ap_bflush(r->connection->client);
  -if (ap_get_filesize(&len, fd) != APR_SUCCESS) {
  -ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -  "ap_send_fd: ap_get_filesize failed.");
  -return 0;
  +if (!r->chunked) {
  +ap_bflush(r->connection->client);
  +if (ap_get_filesize(&len, fd) != APR_SUCCESS) {
  +ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +  "ap_send_fd: ap_get_filesize failed.");
  +return 0;
  +}
  +if (iol_sendfile(r->connection->client->iol, fd, len,
  + NULL, 0, 0) != APR_SUCCESS) {
  +ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +  "ap_send_fd: iol_sendfile failed.");
  +}
   }
  -if (iol_sendfile(r->connection->client->iol, fd, len,
  - NULL, 0, 0) != APR_SUCCESS) {
  -ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -  "ap_send_fd: iol_sendfile failed.");
  +else {
  +len = ap_send_fd_length(fd, r, -1);
   }
   #else
   len = ap_send_fd_length(fd, r, -1);
  
  
  
  1.16  +1 -0  apache-2.0/src/main/http_request.c
  
  Index: http_request.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_request.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- http_request.c2000/01/10 15:35:49 1.15
  +++ http_request.c2000/01/12 18:20:43 1.16
  @@ -845,6 +845,7 @@
   rnew->server = r->server;
   rnew->request_config = ap_create_request_config(rnew->pool);
   rnew->htaccess   = r->htaccess;
  +rnew->chunked= r->chunked;
   
   ap_set_sub_req_protocol(rnew, r);
   fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-12-21 Thread rbb
rbb 99/12/21 08:21:44

  Modified:src/lib/apr/include apr_time.h
   src/lib/apr/time/unix timestr.c
   src/main http_protocol.c
  Log:
  Change ap_gm_timestr_822 to ap_timestr.  Now, one function can be used to get
  a timestr for GMT and Localtimes.
  
  Revision  ChangesPath
  1.5   +1 -1  apache-2.0/src/lib/apr/include/apr_time.h
  
  Index: apr_time.h
  ===
  RCS file: /home/cvs/apache-2.0/src/lib/apr/include/apr_time.h,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- apr_time.h1999/12/20 16:10:11 1.4
  +++ apr_time.h1999/12/21 16:21:41 1.5
  @@ -76,7 +76,7 @@
   ap_status_t ap_explode_time(ap_time_t *, ap_timetype_e);
   ap_status_t ap_implode_time(ap_time_t *);
   
  -ap_status_t ap_gm_timestr_822(char **date_str, struct atime_t *t, 
ap_context_t *p);
  +ap_status_t ap_timestr(char **date_str, struct atime_t *t, ap_timetype_e 
type, ap_context_t *p);
   ap_status_t ap_strftime(char *s, ap_size_t max, const char *format, 
ap_time_t *tm);
   
   /* accessor functions */
  
  
  
  1.2   +8 -8  apache-2.0/src/lib/apr/time/unix/timestr.c
  
  Index: timestr.c
  ===
  RCS file: /home/cvs/apache-2.0/src/lib/apr/time/unix/timestr.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- timestr.c 1999/12/20 16:10:16 1.1
  +++ timestr.c 1999/12/21 16:21:43 1.2
  @@ -65,7 +65,7 @@
   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
   };
   
  -ap_status_t ap_gm_timestr_822(char **date_str, struct atime_t *t, 
ap_context_t *p)
  +ap_status_t ap_timestr(char **date_str, struct atime_t *t, ap_timetype_e 
type, ap_context_t *p)
   {
   struct tm *tms;
   char *date_str_ptr;
  @@ -74,9 +74,7 @@
   (*date_str) = ap_palloc(p, 48 * sizeof(char));
   date_str_ptr = (*date_str);
   
  -if (t->time_ex == 0) {
  -ap_explode_time(t, APR_UTCTIME);
  -}
  +ap_explode_time(t, type);
   
   /* Assumption: this is always 3 */
   /* i = strlen(ap_day_snames[tms->tm_wday]); */
  @@ -107,10 +105,12 @@
   *date_str_ptr++ = ':';
   *date_str_ptr++ = t->explodedtime->tm_sec / 10 + '0';
   *date_str_ptr++ = t->explodedtime->tm_sec % 10 + '0';
  -*date_str_ptr++ = ' ';
  -*date_str_ptr++ = 'G';
  -*date_str_ptr++ = 'M';
  -*date_str_ptr++ = 'T';
  +if (type == APR_UTCTIME) {
  +*date_str_ptr++ = ' ';
  +*date_str_ptr++ = 'G';
  +*date_str_ptr++ = 'M';
  +*date_str_ptr++ = 'T';
  +}
   *date_str_ptr = '\0';

   return APR_SUCCESS;
   /* RFC date format; as strftime '%a, %d %b %Y %T GMT' */
  
  
  
  1.44  +3 -3  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- http_protocol.c   1999/12/21 11:33:22 1.43
  +++ http_protocol.c   1999/12/21 16:21:44 1.44
  @@ -605,7 +605,7 @@
   {
   ap_time_t *mod_time = ap_rationalize_mtime(r, r->mtime);
   char *datestr;
  -ap_gm_timestr_822(&datestr, mod_time, r->pool);
  +ap_timestr(&datestr, mod_time, APR_UTCTIME, r->pool);
   ap_table_setn(r->headers_out, "Last-Modified", datestr);
   }
   
  @@ -1362,7 +1362,7 @@
   
   ap_rvputs(r, protocol, " ", r->status_line, "\015\012", NULL);
   
  -ap_gm_timestr_822(&date, r->request_time, r->pool);
  +ap_timestr(&date, r->request_time, APR_UTCTIME, r->pool);
   ap_send_header_field(r, "Date", date);
   ap_send_header_field(r, "Server", ap_get_server_version());
   
  @@ -1645,7 +1645,7 @@
* some other part of the server configuration.
*/
   if (r->no_cache && !ap_table_get(r->headers_out, "Expires")) {
  -ap_gm_timestr_822(&date, r->request_time, r->pool);
  +ap_timestr(&date, r->request_time, APR_UTCTIME, r->pool);
   ap_table_addn(r->headers_out, "Expires", date);
   }
   
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c http_vhost.c

1999-12-21 Thread fanf
fanf99/12/21 03:33:23

  Modified:src  CHANGES
   src/main http_protocol.c http_vhost.c
  Log:
  Fix the mass vhosting security problem spotted by Lars, as in 1.3
  Submitted by: Ben Hyde
  Reviewed by:  Tony Finch
  
  Revision  ChangesPath
  1.19  +5 -0  apache-2.0/src/CHANGES
  
  Index: CHANGES
  ===
  RCS file: /home/cvs/apache-2.0/src/CHANGES,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- CHANGES   1999/12/21 07:54:07 1.18
  +++ CHANGES   1999/12/21 11:33:21 1.19
  @@ -1,4 +1,9 @@
   Changes with Apache 2.0-dev
  +
  +  *) More rigorous checking of Host: headers to fix security problems
  + with mass name-based virtual hosting (whether using mod_rewrite
  + or mod_vhost_alias).
  + [Ben Hyde, Tony Finch]
 
 *) Add back support for UseCanonicalName in  containers.
[Manoj Kasichainula]
  
  
  
  1.43  +3 -1  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- http_protocol.c   1999/12/20 16:38:34 1.42
  +++ http_protocol.c   1999/12/21 11:33:22 1.43
  @@ -1033,7 +1033,7 @@
   r->status = HTTP_OK; /* Until further notice. */
   
   /* update what we think the virtual host is based on the headers we've
  - * now read
  + * now read. may update status.
*/
   ap_update_vhost_from_headers(r);
   
  @@ -1056,6 +1056,8 @@
   ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
 "client sent HTTP/1.1 request without hostname "
 "(see RFC2068 section 9, and 14.23): %s", r->uri);
  +}
  +if (r->status != HTTP_OK) {
   ap_send_error_response(r, 0);
   ap_run_log_transaction(r);
   return r;
  
  
  
  1.10  +41 -10apache-2.0/src/main/http_vhost.c
  
  Index: http_vhost.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_vhost.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- http_vhost.c  1999/12/15 00:59:56 1.9
  +++ http_vhost.c  1999/12/21 11:33:23 1.10
  @@ -658,22 +658,51 @@
* run-time vhost matching functions
*/
   
  -/* Remove :port and optionally a single trailing . from the hostname, this
  - * canonicalizes it somewhat.
  +/* Lowercase and remove any trailing dot and/or :port from the hostname,
  + * and check that it is sane.
*/
   static void fix_hostname(request_rec *r)
   {
  -const char *hostname = r->hostname;
  -char *host = ap_getword(r->pool, &hostname, ':');/* get rid of 
port */
  -size_t l;
  -
  -/* trim a trailing . */
  -l = strlen(host);
  -if (l > 0 && host[l-1] == '.') {
  -host[l-1] = '\0';
  +char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
  +const char *src;
  +char *dst;
  +
  +/* check and copy the host part */
  +src = r->hostname;
  +dst = host;
  +while (*src) {
  + if (!isalnum(*src) && *src != '.' && *src != '-') {
  + if (*src == ':')
  + break;
  + else
  + goto bad;
  + } else {
  + *dst++ = *src++;
  + }
  +}
  +/* check the port part */
  +if (*src++ == ':') {
  + while (*src) {
  + if (!isdigit(*src++)) {
  + goto bad;
  + }
  + }
  +}
  +/* strip trailing gubbins */
  +if (dst > host && dst[-1] == '.') {
  + dst[-1] = '\0';
  +} else {
  + dst[0] = '\0';
   }
   
   r->hostname = host;
  +return;
  +
  +bad:
  +r->status = HTTP_BAD_REQUEST;
  +ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  +   "Client sent malformed Host header");
  +return;
   }
   
   
  @@ -876,6 +905,8 @@
   /* must set this for HTTP/1.1 support */
   if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) {
fix_hostname(r);
  + if (r->status != HTTP_OK)
  + return;
   }
   /* check if we tucked away a name_chain */
   if (r->connection->vhost_lookup_data) {
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-12-09 Thread stoddard
stoddard99/12/09 13:47:50

  Modified:src/main http_protocol.c
  Log:
  Fix Windows build break
  
  Revision  ChangesPath
  1.40  +3 -0  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- http_protocol.c   1999/11/30 03:36:33 1.39
  +++ http_protocol.c   1999/12/09 21:47:45 1.40
  @@ -2155,6 +2155,8 @@
   return total_bytes_sent;
   }
   
  +#ifdef USE_MMAP_FILES
  +
   /* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to 
Apache's
* timeout model, which is a timeout per-write rather than a time for the
* entire transaction to complete.  Essentially this should be small enough
  @@ -2218,6 +2220,7 @@
   SET_BYTES_SENT(r);
   return total_bytes_sent;
   }
  +#endif /* USE_MMAP_FILES */
   
   API_EXPORT(int) ap_rputc(int c, request_rec *r)
   {
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-11-30 Thread manoj
manoj   99/11/29 19:36:35

  Modified:src/main http_protocol.c
  Log:
  The extra (n < 1) check is redundant, leftover from pre-APR code.
  
  Revision  ChangesPath
  1.39  +1 -2  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -d -u -r1.38 -r1.39
  --- http_protocol.c   1999/11/20 11:56:13 1.38
  +++ http_protocol.c   1999/11/30 03:36:33 1.39
  @@ -2045,8 +2045,7 @@
   n = o;
   do {
   rv = ap_read(fd, buf, &n);
  -} while (rv == APR_EINTR && !ap_is_aborted(r->connection) &&
  - (n < 1));
  +} while (rv == APR_EINTR && !ap_is_aborted(r->connection));
   
   if (n < 1) {
   break;
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-11-03 Thread bjh
bjh 99/11/03 04:47:24

  Modified:src/lib/apr/file_io/os2 readwrite.c
   src/main http_protocol.c
  Log:
  OS/2: Don't return APR_EOF from ap_read(). EOF is indicated by a APR_SUCCESS
  status with nbytes set to 0.
  
  Revision  ChangesPath
  1.6   +10 -15apache-2.0/src/lib/apr/file_io/os2/readwrite.c
  
  Index: readwrite.c
  ===
  RCS file: /home/cvs/apache-2.0/src/lib/apr/file_io/os2/readwrite.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- readwrite.c   1999/10/19 15:24:19 1.5
  +++ readwrite.c   1999/11/03 12:47:22 1.6
  @@ -85,8 +85,11 @@
   while (rc == 0 && size > 0) {
   if (thefile->bufpos >= thefile->dataRead) {
   rc = DosRead(thefile->filedes, thefile->buffer, 
APR_FILE_BUFSIZE, &thefile->dataRead );
  -if (thefile->dataRead == 0)
  +if (thefile->dataRead == 0) {
  +if (rc == 0)
  +thefile->eof_hit = TRUE;
   break;
  +}
   thefile->filePtr += thefile->dataRead;
   thefile->bufpos = 0;
   }
  @@ -99,15 +102,6 @@
   }
   
   *nbytes = rc == 0 ? pos - (char *)buf : 0;
  -
  -// if an error occurred report it
  -// if we read some data but hit EOF before reading 'size' bytes, 
return Ok (0)
  -// if we hit EOF with no data read, return -1
  -if (size && rc == 0 && pos == (char *)buf) {
  -thefile->eof_hit = TRUE;
  -*_errno() = APR_EOF;
  -return APR_EOF;
  -}
   return os2errno(rc);
   } else {
   rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
  @@ -307,15 +301,16 @@
   ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
   {
   ssize_t readlen;
  -ap_status_t rv;
  +ap_status_t rv = APR_SUCCESS;
   int i;
   
   for (i = 0; i < len-1; i++) {
   readlen = 1;
   rv = ap_read(thefile, str+i, &readlen);
  -
  -if (rv != APR_SUCCESS) {
  -return rv;
  +
  +if (readlen != 1) {
  +rv = APR_EOF;
  +break;
   }
   
   if (str[i] == '\r')
  @@ -324,7 +319,7 @@
   break;
   }
   str[i] = 0;
  -return APR_SUCCESS; 
  +return rv;
   }
   
   
  
  
  
  1.35  +1 -1  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- http_protocol.c   1999/11/02 14:34:32 1.34
  +++ http_protocol.c   1999/11/03 12:47:23 1.35
  @@ -2111,7 +2111,7 @@
   while (!ap_is_aborted(r->connection)) {
   rv = ap_bread(fb, buf, sizeof(buf), &n);
   if (n == 0) {
  -if (rv == APR_SUCCESS || rv == APR_EOF) {/* eof */
  +if (rv == APR_SUCCESS) {/* eof */
   (void) ap_rflush(r);
   break;
   }
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-11-02 Thread stoddard
stoddard99/11/02 06:34:36

  Modified:src/main http_protocol.c
  Log:
  Delete useless code...
  
  Revision  ChangesPath
  1.34  +1 -1  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- http_protocol.c   1999/11/02 14:30:19 1.33
  +++ http_protocol.c   1999/11/02 14:34:32 1.34
  @@ -2008,7 +2008,7 @@
*/
   API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
   {
  -ap_ssize_t len =  r->finfo.st_size;
  +long len;
   #ifdef HAVE_SENDFILE
   ap_bflush(r->connection->client);
   if (ap_get_filesize(&len, fd) != APR_SUCCESS) {
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-11-01 Thread bjh
bjh 99/11/01 02:50:48

  Modified:src/main http_protocol.c
  Log:
  In ap_send_fb_length() don't treat APR_EOF as a fatal error.
  
  Revision  ChangesPath
  1.32  +1 -1  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- http_protocol.c   1999/10/31 09:13:22 1.31
  +++ http_protocol.c   1999/11/01 10:50:47 1.32
  @@ -2095,7 +2095,7 @@
   while (!ap_is_aborted(r->connection)) {
   rv = ap_bread(fb, buf, sizeof(buf), &n);
   if (n == 0) {
  -if (rv == APR_SUCCESS) {/* eof */
  +if (rv == APR_SUCCESS || rv == APR_EOF) {/* eof */
   (void) ap_rflush(r);
   break;
   }
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-10-26 Thread manoj
manoj   99/10/26 15:15:20

  Modified:src/main http_protocol.c
  Log:
  One ap_bflush to the client wasn't checked. Now fixed.
  
  Revision  ChangesPath
  1.25  +4 -2  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -d -u -r1.24 -r1.25
  --- http_protocol.c   1999/10/24 19:23:58 1.24
  +++ http_protocol.c   1999/10/26 22:15:16 1.25
  @@ -2072,7 +2072,7 @@
   char buf[IOBUFSIZE];
   long total_bytes_sent = 0;
   long zero_timeout = 0;
  -int n, w, rc, o;
  +int n, w, o;
   
   if (length == 0) {
   return 0;
  @@ -2096,7 +2096,9 @@
   break;
   }
   /* next read will block, so flush the client now */
  -rc = ap_bflush(r->connection->client);
  +if (ap_rflush(r) == EOF) {
  +break;
  +}
   
   ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout);
   n = ap_bread(fb, buf, sizeof(buf));
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-10-12 Thread manoj
manoj   99/10/12 13:39:03

  Modified:src/main http_protocol.c
  Log:
  Eliminate a warning.
  
  Revision  ChangesPath
  1.21  +1 -1  apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -d -u -r1.20 -r1.21
  --- http_protocol.c   1999/10/12 20:36:56 1.20
  +++ http_protocol.c   1999/10/12 20:38:58 1.21
  @@ -2008,7 +2008,7 @@
   {
   char buf[IOBUFSIZE];
   long total_bytes_sent = 0;
  -register w, o;
  +register int w, o;
   int n;
   ap_status_t status;
   
  
  
  


cvs commit: apache-2.0/src/main http_protocol.c

1999-10-12 Thread manoj
manoj   99/10/12 13:37:05

  Modified:src/main http_protocol.c
  Log:
  Attempt to make ap_send_fb work again. This is untested, but it works
  better than the old version because it compiles.
  
  Revision  ChangesPath
  1.20  +28 -71apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -d -u -r1.19 -r1.20
  --- http_protocol.c   1999/10/11 22:07:25 1.19
  +++ http_protocol.c   1999/10/12 20:36:56 1.20
  @@ -2056,9 +2056,6 @@
   return total_bytes_sent;
   }
   
  -
  -/* TODO: reimplement ap_send_fb */
  -#if 0
   /*
* Send the body of a response to the client.
*/
  @@ -2071,82 +2068,46 @@
   {
   char buf[IOBUFSIZE];
   long total_bytes_sent = 0;
  -register int n, w, o, len, fd;
  -struct pollfd fds;
  +long zero_timeout = 0;
  +int n, w, rc, o;
   
  -if (length == 0)
  +if (length == 0) {
   return 0;
  -
  -/* Make fb unbuffered and non-blocking */
  -ap_bsetflag(fb, B_RD, 0);
  -fd = ap_bfileno(fb, B_RD);
  -ap_bnonblock(fd);
  -#ifdef CHECK_FD_SETSIZE
  -if (fd >= FD_SETSIZE) {
  - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
  - "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
  - "found, you probably need to rebuild Apache with a "
  - "larger FD_SETSIZE", fd, FD_SETSIZE);
  - return 0;
   }
  -#endif
   
  -fds.fd = fd;
  -fds.events = POLLIN;
  +/* This function tries to as much as possible through non-blocking
  + * reads so that it can do writes while waiting for the CGI to
  + * produce more data. This way, the CGI's output gets to the client
  + * as soon as possible */
   
  +ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout);
   while (!ap_is_aborted(r->connection)) {
  -#ifdef NDELAY_PIPE_RETURNS_ZERO
  - /* Contributed by [EMAIL PROTECTED] for UTS 2.1.2, where the fcntl */
  - /*   O_NDELAY flag causes read to return 0 when there's nothing */
  - /*   available when reading from a pipe.  That makes it tricky */
  - /*   to detect end-of-file :-(.  This stupid bug is even documented */
  - /*   in the read(2) man page where it says that everything but */
  - /*   pipes return -1 and EAGAIN.  That makes it a feature, right? */
  - int afterselect = 0;
  -#endif
  -if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
  -len = length - total_bytes_sent;
  -else
  -len = IOBUFSIZE;
  -
  -do {
  -n = ap_bread(fb, buf, len);
  -#ifdef NDELAY_PIPE_RETURNS_ZERO
  - if ((n > 0) || (n == 0 && afterselect))
  - break;
  -#else
  -if (n >= 0)
  -break;
  -#endif
  -if (ap_is_aborted(r->connection))
  +n = ap_bread(fb, buf, sizeof(buf));
  +if (n <= 0) {
  +if (n == 0) {
  +(void) ap_rflush(r);
   break;
  -if (n < 0 && errno != EAGAIN /* ZZZ rethink for threaded impl */)
  +}
  +if (n == -1 && errno != EAGAIN) {
  +r->connection->aborted = 1;
   break;
  +}
  +/* next read will block, so flush the client now */
  +rc = ap_bflush(r->connection->client);
   
  -/* we need to block, so flush the output first */
  -if (ap_bflush(r->connection->client) < 0) {
  -ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
  -"client stopped connection before send body completed");
  -ap_bsetflag(r->connection->client, B_EOUT, 1);
  +ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout);
  +n = ap_bread(fb, buf, sizeof(buf));
  +if (n <= 0) {
  +if (n == 0) {
  +(void) ap_rflush(r);
  +}
   r->connection->aborted = 1;
   break;
   }
  -/*
  - * we don't care what poll says, we might as well loop back
  - * around and try another read
  - */
  - /* use AP funcs */
  -poll(&fds, 1, -1);
  -#ifdef NDELAY_PIPE_RETURNS_ZERO
  - afterselect = 1;
  -#endif
  -} while (!ap_is_aborted(r->connection));
  -
  -if (n < 1 || ap_is_aborted(r->connection)) {
  -break;
  +ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout);
   }
  +
   o = 0;
  -
   while (n && !ap_is_aborted(r->connection)) {
   w = ap_bwrite(r->connection->client, &buf[o], n);
   if (w > 0) {
  @@ -2157,7 +2118,7 @@
   else if (w < 0) {
   if (!ap_is_aborted(r->connection)) {