You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Randy Terbush <ra...@zyzzyva.com> on 1997/07/06 07:43:44 UTC

Re: cvs commit: apache/src CHANGES alloc.c alloc.h http_protocol.c http_protocol.h mod_cgi.c util_script.c util_script.h

Uh, I would like to see some comments regarding this before it is 
commited. Granted I did not veto it, but without some explanation, 
I will. For one thing, it commits code that is commented out with 
#if 0.

I raised several questions for which I saw no answer.

I would like to see us go back to the voting system for 1.3.


> sameer      97/07/05 22:37:24
> 
>   Modified:    src       CHANGES alloc.c alloc.h http_protocol.c
>                         http_protocol.h  mod_cgi.c util_script.c
>                         util_script.h
>   Log:
>   Make cgi unbuffered so that nph is only a header thing
>   
>   Revision  Changes    Path
>   1.323     +2 -0      apache/src/CHANGES
>   
>   Index: CHANGES
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/CHANGES,v
>   retrieving revision 1.322
>   retrieving revision 1.323
>   diff -c -C3 -r1.322 -r1.323
>   *** CHANGES	1997/07/05 22:12:24	1.322
>   --- CHANGES	1997/07/06 05:37:18	1.323
>   ***************
>   *** 1,4 ****
>   --- 1,6 ----
>     Changes with Apache 1.3
>   +   *) CGI: Add a select() loop so that CGI scripts don't have to be
>   +      nph in order to be "unbuffered". [Sameer Parekh]
>     
>       *) Makefile.nt added - to build all the bits from the command line:
>             nmake -f Makefile.nt
>   
>   
>   
>   1.36      +192 -0    apache/src/alloc.c
>   
>   Index: alloc.c
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/alloc.c,v
>   retrieving revision 1.35
>   retrieving revision 1.36
>   diff -c -C3 -r1.35 -r1.36
>   *** alloc.c	1997/06/29 19:19:34	1.35
>   --- alloc.c	1997/07/06 05:37:18	1.36
>   ***************
>   *** 1025,1030 ****
>   --- 1025,1222 ----
>     #define enc_pipe(fds) pipe(fds)
>     #endif /* WIN32 */
>     
>   + 
>   + int spawn_child_err_buff (pool *p, int (*func)(void *), void *data,
>   + 			  enum kill_conditions kill_how,
>   + 			  BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err)
>   + {
>   +   int pid;
>   +   int in_fds[2];
>   +   int out_fds[2];
>   +   int err_fds[2];
>   +   int save_errno;
>   + 
>   +   block_alarms();
>   +   
>   +   if (pipe_in && enc_pipe (in_fds) < 0)
>   +   {
>   +       save_errno = errno;
>   +       unblock_alarms();
>   +       errno = save_errno;
>   +       return 0;
>   +   }
>   +   
>   +   if (pipe_out && enc_pipe (out_fds) < 0) {
>   +     save_errno = errno;
>   +     if (pipe_in) {
>   +       close (in_fds[0]); close (in_fds[1]);
>   +     }
>   +     unblock_alarms();
>   +     errno = save_errno;
>   +     return 0;
>   +   }
>   + 
>   +   if (pipe_err && enc_pipe (err_fds) < 0) {
>   +     save_errno = errno;
>   +     if (pipe_in) {
>   +       close (in_fds[0]); close (in_fds[1]);
>   +     }
>   +     if (pipe_out) {
>   +       close (out_fds[0]); close (out_fds[1]);
>   +     }
>   +     unblock_alarms();
>   +     errno = save_errno;
>   +     return 0;
>   +   }
>   + 
>   + #ifdef WIN32
>   + 
>   +   {
>   +       HANDLE thread_handle;
>   +       int hStdIn, hStdOut, hStdErr;
>   +       int old_priority;
>   +       
>   +       (void)acquire_mutex(spawn_mutex);
>   +       thread_handle = GetCurrentThread(); /* doesn't need to be closed */
>   +       old_priority = GetThreadPriority(thread_handle);
>   +       SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST);
>   +       /* Now do the right thing with your pipes */
>   +       if(pipe_in)
>   +       {
>   +           hStdIn = dup(fileno(stdin));
>   +           dup2(in_fds[0], fileno(stdin));
>   +           close(in_fds[0]);
>   +       }
>   +       if(pipe_out)
>   +       {
>   +           hStdOut = dup(fileno(stdout));
>   +           dup2(out_fds[1], fileno(stdout));
>   +           close(out_fds[1]);
>   +       }
>   +       if(pipe_err)
>   +       {
>   +           hStdErr = dup(fileno(stderr));
>   +           dup2(err_fds[1], fileno(stderr));
>   +           close(err_fds[1]);
>   +       }
>   + 
>   +       pid = (*func)(data);
>   +       if(!pid)
>   +       {
>   +           save_errno = errno;
>   +           close(in_fds[1]);
>   +           close(out_fds[0]);
>   +           close(err_fds[0]);
>   +       }
>   + 
>   +       /* restore the original stdin, stdout and stderr */
>   +       if(pipe_in)
>   +           dup2(hStdIn, fileno(stdin));
>   +       if(pipe_out)
>   +           dup2(hStdOut, fileno(stdout));
>   +       if(pipe_err)
>   +           dup2(hStdErr, fileno(stderr));
>   + 
>   +       if(pid)
>   +       {
>   +           note_subprocess(p, pid, kill_how);
>   +           if(pipe_in)
>   +           {
>   +               *pipe_in = bcreate(p, B_WR);
>   + 	      bpushfd(*pipe_in, in_fds[1], in_fds[1]);
>   +           }
>   +           if(pipe_out)
>   +           {
>   +               *pipe_out = bcreate(p, B_RD);
>   + 	      bpushfd(*pipe_out, out_fds[0], out_fds[0]);
>   +           }
>   +           if(pipe_err)
>   +           {
>   +               *pipe_err = bcreate(p, B_RD);
>   + 	      bpushfd(*pipe_err, err_fds[0], err_fds[0]);
>   +           }
>   +       }
>   +       SetThreadPriority(thread_handle, old_priority);
>   +       (void)release_mutex(spawn_mutex);
>   +       /*
>   +        * go on to the end of the function, where you can
>   +        * unblock alarms and return the pid
>   +        */
>   + 
>   +   }
>   + #else
>   + 
>   +   if ((pid = fork()) < 0) {
>   +     save_errno = errno;
>   +     if (pipe_in) {
>   +       close (in_fds[0]); close (in_fds[1]);
>   +     }
>   +     if (pipe_out) {
>   +       close (out_fds[0]); close (out_fds[1]);
>   +     }
>   +     if (pipe_err) {
>   +       close (err_fds[0]); close (err_fds[1]);
>   +     }
>   +     unblock_alarms();
>   +     errno = save_errno;
>   +     return 0;
>   +   }
>   + 
>   +   if (!pid) {
>   +     /* Child process */
>   +     
>   +     if (pipe_out) {
>   +       close (out_fds[0]);
>   +       dup2 (out_fds[1], STDOUT_FILENO);
>   +       close (out_fds[1]);
>   +     }
>   + 
>   +     if (pipe_in) {
>   +       close (in_fds[1]);
>   +       dup2 (in_fds[0], STDIN_FILENO);
>   +       close (in_fds[0]);
>   +     }
>   + 
>   +     if (pipe_err) {
>   +       close (err_fds[0]);
>   +       dup2 (err_fds[1], STDERR_FILENO);
>   +       close (err_fds[1]);
>   +     }
>   + 
>   +     /* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
>   +     signal (SIGCHLD, SIG_DFL);	/* Was that it? */
>   +     
>   +     func (data);
>   +     exit (1);		/* Should only get here if the exec in func() failed */
>   +   }
>   + 
>   +   /* Parent process */
>   + 
>   +   note_subprocess (p, pid, kill_how);
>   +   
>   +   if (pipe_out) {
>   +     close (out_fds[1]);
>   +     *pipe_out = bcreate(p, B_RD);
>   +     bpushfd(*pipe_out, out_fds[0], out_fds[0]);
>   +   }
>   + 
>   +   if (pipe_in) {
>   +     close (in_fds[0]);
>   +     *pipe_in = bcreate(p, B_WR);
>   +     bpushfd(*pipe_in, in_fds[1], in_fds[1]);
>   +   }
>   + 
>   +   if (pipe_err) {
>   +     close (err_fds[1]);
>   +     *pipe_err = bcreate(p, B_RD);
>   +     bpushfd(*pipe_err, err_fds[0], err_fds[0]);
>   +   }
>   + #endif /* WIN32 */
>   + 
>   +   unblock_alarms();
>   +   return pid;
>   + }
>   + 
>     int spawn_child_err (pool *p, int (*func)(void *), void *data,
>     		     enum kill_conditions kill_how,
>     		     FILE **pipe_in, FILE **pipe_out, FILE **pipe_err)
>   
>   
>   
>   1.24      +5 -0      apache/src/alloc.h
>   
>   Index: alloc.h
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/alloc.h,v
>   retrieving revision 1.23
>   retrieving revision 1.24
>   diff -c -C3 -r1.23 -r1.24
>   *** alloc.h	1997/06/28 20:24:27	1.23
>   --- alloc.h	1997/07/06 05:37:19	1.24
>   ***************
>   *** 243,248 ****
>   --- 243,253 ----
>     int spawn_child_err (pool *, int (*)(void *), void *,
>     		 enum kill_conditions, FILE **pipe_in, FILE **pipe_out,
>                      FILE **pipe_err);
>   + #if 0
>   + int spawn_child_err_buff (pool *, int (*)(void *), void *,
>   +            	  enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out,
>   +                   BUFF **pipe_err);
>   + #endif
>     #define spawn_child(p,f,v,k,in,out) spawn_child_err(p,f,v,k,in,out,NULL)
>     
>     /* magic numbers --- min free bytes to consider a free pool block useable,
>   
>   
>   
>   1.133     +76 -0     apache/src/http_protocol.c
>   
>   Index: http_protocol.c
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/http_protocol.c,v
>   retrieving revision 1.132
>   retrieving revision 1.133
>   diff -c -C3 -r1.132 -r1.133
>   *** http_protocol.c	1997/07/05 14:53:57	1.132
>   --- http_protocol.c	1997/07/06 05:37:19	1.133
>   ***************
>   *** 1516,1521 ****
>   --- 1516,1597 ----
>     
>         return (chunk_start + len_read);
>     }
>   + long send_fb_length(BUFF *fb, request_rec *r, long length)
>   + {
>   +     char buf[IOBUFSIZE];
>   +     long total_bytes_sent;
>   +     register int n, w, o;
>   +     conn_rec *c = r->connection;
>   +     
>   +     if (length == 0) return 0;
>   + 
>   +     total_bytes_sent = 0;
>   + 
>   +     /* Clear out the buffer */
>   +     if(fb->incnt != 0)
>   +       {
>   + 	int o;
>   + 	o = bwrite(c->client, fb->inptr, fb->incnt);
>   + 	fb->incnt -= o;
>   + 	fb->inptr += o;
>   + 	total_bytes_sent += o;
>   +       }
>   + 
>   +     /* Make unbuffered */
>   +     fb->flags &= ~B_RD;
>   + 
>   +     while(1)
>   +       {
>   + 	fd_set fds;
>   + 
>   + 	bflush(c->client);
>   + 
>   + 	FD_ZERO(&fds);
>   + 	FD_SET(fb->fd_in, &fds);
>   + 
>   + 	select(FD_SETSIZE, &fds, NULL, NULL, NULL);
>   + 
>   + 	while((n = bread(fb, buf, IOBUFSIZE)) < 1
>   + 	      && fb->flags & B_ERROR && errno == EINTR)
>   + 	  continue;
>   + 	
>   + 	if (n < 1) {
>   +             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 */
>   +                 n-=w;
>   +                 o+=w;
>   +             }
>   +             else if (w < 0) {
>   +                 if (r->connection->aborted)
>   +                     break;
>   +                 else if (errno == EAGAIN)
>   +                     continue;
>   +                 else {
>   +                     log_unixerr("send body lost connection to",
>   +                                 get_remote_host(r->connection,
>   +                                     r->per_dir_config, REMOTE_NAME),
>   +                                 NULL, r->server);
>   +                     bsetflag(r->connection->client, B_EOUT, 1);
>   +                     r->connection->aborted = 1;
>   +                     break;
>   +                 }
>   +             }
>   +         }
>   +     }
>   + 
>   +     kill_timeout(r);
>   +     SET_BYTES_SENT(r);
>   +     return total_bytes_sent;
>   + }
>   + 
>   + long send_fb(BUFF *fb, request_rec *r) { return send_fb_length(fb, r, -1); }
>     
>     long send_fd(FILE *f, request_rec *r) { return send_fd_length(f, r, -1); }
>     
>   
>   
>   
>   1.20      +3 -0      apache/src/http_protocol.h
>   
>   Index: http_protocol.h
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/http_protocol.h,v
>   retrieving revision 1.19
>   retrieving revision 1.20
>   diff -c -C3 -r1.19 -r1.20
>   *** http_protocol.h	1997/04/07 10:58:38	1.19
>   --- http_protocol.h	1997/07/06 05:37:20	1.20
>   ***************
>   *** 110,115 ****
>   --- 110,118 ----
>     
>     long send_fd(FILE *f, request_rec *r);
>     long send_fd_length(FILE *f, request_rec *r, long length);
>   + 
>   + long send_fb(BUFF *f, request_rec *r);
>   + long send_fb_length(BUFF *f, request_rec *r, long length);
>          
>     /* Hmmm... could macrofy these for now, and maybe forever, though the
>      * definitions of the macros would get a whole lot hairier.
>   
>   
>   
>   1.43      +31 -47    apache/src/mod_cgi.c
>   
>   Index: mod_cgi.c
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
>   retrieving revision 1.42
>   retrieving revision 1.43
>   diff -c -C3 -r1.42 -r1.43
>   *** mod_cgi.c	1997/06/29 17:39:50	1.42
>   --- mod_cgi.c	1997/07/06 05:37:20	1.43
>   ***************
>   *** 183,189 ****
>     }
>     
>     static int log_script(request_rec *r, cgi_server_conf *conf, int ret,
>   ! 	       char *dbuf, char *sbuf, FILE *script_in, FILE *script_err)
>     {
>         table *hdrs_arr = r->headers_in;
>         table_entry *hdrs = (table_entry *)hdrs_arr->elts;
>   --- 183,189 ----
>     }
>     
>     static int log_script(request_rec *r, cgi_server_conf *conf, int ret,
>   ! 		    char *dbuf, char *sbuf, BUFF *script_in, BUFF *script_err)
>     {
>         table *hdrs_arr = r->headers_in;
>         table_entry *hdrs = (table_entry *)hdrs_arr->elts;
>   ***************
>   *** 197,205 ****
>     	((f = pfopen(r->pool, server_root_relative(r->pool, conf->logname),
>     		     "a")) == NULL)) {
>           /* Soak up script output */
>   !       while (fgets(argsbuffer, MAX_STRING_LEN-1, script_in) != NULL)
>     	continue;
>   !       while (fgets(argsbuffer, MAX_STRING_LEN-1, script_err) != NULL)
>     	continue;
>           return ret;
>         }
>   --- 197,205 ----
>     	((f = pfopen(r->pool, server_root_relative(r->pool, conf->logname),
>     		     "a")) == NULL)) {
>           /* Soak up script output */
>   !       while (bgets(argsbuffer, MAX_STRING_LEN-1, script_in))
>     	continue;
>   !       while (bgets(argsbuffer, MAX_STRING_LEN-1, script_err))
>     	continue;
>           return ret;
>         }
>   ***************
>   *** 207,213 ****
>         /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
>         fprintf(f, "%%%% [%s] %s %s%s%s %s\n", get_time(), r->method, r->uri,
>     	    r->args ? "?" : "", r->args ? r->args : "", r->protocol);
>   !     /* "%% 500 /usr/local/etc/httpd/cgi-bin */
>         fprintf(f, "%%%% %d %s\n", ret, r->filename);
>     
>         fputs("%request\n", f);
>   --- 207,213 ----
>         /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
>         fprintf(f, "%%%% [%s] %s %s%s%s %s\n", get_time(), r->method, r->uri,
>     	    r->args ? "?" : "", r->args ? r->args : "", r->protocol);
>   !     /* "%% 500 /usr/local/etc/httpd/cgi-bin" */
>         fprintf(f, "%%%% %d %s\n", ret, r->filename);
>     
>         fputs("%request\n", f);
>   ***************
>   *** 216,222 ****
>           fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
>         }
>         if ((r->method_number == M_POST || r->method_number == M_PUT)
>   ! 	&& dbuf && *dbuf) {
>           fprintf(f, "\n%s\n", dbuf);
>         }
>     
>   --- 216,222 ----
>           fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
>         }
>         if ((r->method_number == M_POST || r->method_number == M_PUT)
>   ! 	&& *dbuf) {
>           fprintf(f, "\n%s\n", dbuf);
>         }
>     
>   ***************
>   *** 233,259 ****
>           fprintf(f, "%s\n", sbuf);
>     
>         *argsbuffer = '\0';
>   !     fgets(argsbuffer, HUGE_STRING_LEN-1, script_in);
>         if (*argsbuffer) {
>           fputs("%stdout\n", f);
>           fputs(argsbuffer, f);
>   !       while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in) != NULL)
>     	fputs(argsbuffer, f);
>           fputs("\n", f);
>         }
>     
>         *argsbuffer = '\0';
>   !     fgets(argsbuffer, HUGE_STRING_LEN-1, script_err);
>         if (*argsbuffer) {
>           fputs("%stderr\n", f);
>           fputs(argsbuffer, f);
>   !       while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err) != NULL)
>     	fputs(argsbuffer, f);
>           fputs("\n", f);
>         }
>     
>   !     pfclose(r->main ? r->main->pool : r->pool, script_in);
>   !     pfclose(r->main ? r->main->pool : r->pool, script_err);
>     
>         pfclose(r->pool, f);
>         return ret;
>   --- 233,259 ----
>           fprintf(f, "%s\n", sbuf);
>     
>         *argsbuffer = '\0';
>   !     bgets(argsbuffer, HUGE_STRING_LEN-1, script_in);
>         if (*argsbuffer) {
>           fputs("%stdout\n", f);
>           fputs(argsbuffer, f);
>   !       while (bgets(argsbuffer, HUGE_STRING_LEN-1, script_in))
>     	fputs(argsbuffer, f);
>           fputs("\n", f);
>         }
>     
>         *argsbuffer = '\0';
>   !     bgets(argsbuffer, HUGE_STRING_LEN-1, script_err);
>         if (*argsbuffer) {
>           fputs("%stderr\n", f);
>           fputs(argsbuffer, f);
>   !       while (bgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
>     	fputs(argsbuffer, f);
>           fputs("\n", f);
>         }
>     
>   !     bclose(script_in);
>   !     bclose(script_err);
>     
>         pfclose(r->pool, f);
>         return ret;
>   ***************
>   *** 277,283 ****
>         struct cgi_child_stuff *cld = (struct cgi_child_stuff *)child_stuff;
>         request_rec *r = cld->r;
>         char *argv0 = cld->argv0;
>   -     int nph = cld->nph;
>         int child_pid;
>     
>     #ifdef DEBUG_CGI    
>   --- 277,282 ----
>   ***************
>   *** 312,321 ****
>         if (!cld->debug)
>           error_log2stderr (r->server);
>     
>   - #if !defined(__EMX__) && !defined(WIN32)
>   -     if (nph) client_to_stdout (r->connection);
>   - #endif    
>   - 
>         /* Transumute outselves into the script.
>          * NB only ISINDEX scripts get decoded arguments.
>          */
>   --- 311,316 ----
>   ***************
>   *** 352,358 ****
>     {
>         int retval, nph, dbpos = 0;
>         char *argv0, *dbuf = NULL;
>   !     FILE *script_out, *script_in, *script_err;
>         char argsbuffer[HUGE_STRING_LEN];
>         int is_included = !strcmp (r->protocol, "INCLUDED");
>         void *sconf = r->server->module_config;
>   --- 347,353 ----
>     {
>         int retval, nph, dbpos = 0;
>         char *argv0, *dbuf = NULL;
>   !     BUFF *script_out, *script_in, *script_err;
>         char argsbuffer[HUGE_STRING_LEN];
>         int is_included = !strcmp (r->protocol, "INCLUDED");
>         void *sconf = r->server->module_config;
>   ***************
>   *** 421,435 ****
>     	   * waiting for free_proc_chain to cleanup in the middle of an
>     	   * SSI request -djg
>     	   */
>   ! 	  spawn_child_err (r->main ? r->main->pool : r->pool, cgi_child,
>   ! 			    (void *)&cld,
>   ! 			   nph ? just_wait : kill_after_timeout,
>   ! #if defined(__EMX__) || defined(WIN32)
>   ! 			   &script_out, &script_in, &script_err))) {
>   ! #else
>   ! 			   &script_out, nph ? NULL : &script_in,
>   ! 	    		   &script_err))) {
>   ! #endif
>             log_reason ("couldn't spawn child process", r->filename, r);
>             return SERVER_ERROR;
>         }
>   --- 416,425 ----
>     	   * waiting for free_proc_chain to cleanup in the middle of an
>     	   * SSI request -djg
>     	   */
>   ! 	  spawn_child_err_buff (r->main ? r->main->pool : r->pool, cgi_child,
>   ! 				(void *)&cld,
>   ! 				kill_after_timeout,
>   ! 				&script_out, &script_in, &script_err))) {
>             log_reason ("couldn't spawn child process", r->filename, r);
>             return SERVER_ERROR;
>         }
>   ***************
>   *** 471,477 ****
>     		dbpos += dbsize;
>     	    }
>     	    reset_timeout(r);
>   ! 	    if (fwrite(argsbuffer, sizeof(char), len_read, script_out)
>     	            < (size_t)len_read) {
>     	        /* silly script stopped reading, soak up remaining message */
>     	        while (get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
>   --- 461,467 ----
>     		dbpos += dbsize;
>     	    }
>     	    reset_timeout(r);
>   ! 	    if (bwrite(script_out, argsbuffer, len_read)
>     	            < (size_t)len_read) {
>     	        /* silly script stopped reading, soak up remaining message */
>     	        while (get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
>   ***************
>   *** 480,499 ****
>     	    }
>     	}
>     
>   ! 	fflush (script_out);
>     	signal (SIGPIPE, handler);
>     	
>     	kill_timeout (r);
>         }
>         
>   !     pfclose (r->main ? r->main->pool : r->pool, script_out);
>         
>         /* Handle script return... */
>         if (script_in && !nph) {
>             char *location, sbuf[MAX_STRING_LEN];
>     	int ret;
>           
>   !         if ((ret = scan_script_header_err(r, script_in, sbuf)))
>     	    return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
>     	
>     	location = table_get (r->headers_out, "Location");
>   --- 470,489 ----
>     	    }
>     	}
>     
>   ! 	bflush (script_out);
>     	signal (SIGPIPE, handler);
>     	
>     	kill_timeout (r);
>         }
>         
>   !     bclose(script_out);
>         
>         /* Handle script return... */
>         if (script_in && !nph) {
>             char *location, sbuf[MAX_STRING_LEN];
>     	int ret;
>           
>   !         if ((ret = scan_script_header_err_buff(r, script_in, sbuf)))
>     	    return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
>     	
>     	location = table_get (r->headers_out, "Location");
>   ***************
>   *** 502,512 ****
>     	  
>     	    /* Soak up all the script output */
>     	    hard_timeout ("read from script", r);
>   ! 	    while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_in)
>   ! 	           > 0)
>     	        continue;
>   ! 	    while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err)
>   ! 	           > 0)
>     	        continue;
>     	    kill_timeout (r);
>     
>   --- 492,500 ----
>     	  
>     	    /* Soak up all the script output */
>     	    hard_timeout ("read from script", r);
>   ! 	    while (bgets(argsbuffer, HUGE_STRING_LEN-1, script_in))
>     	        continue;
>   ! 	    while (bgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
>     	        continue;
>     	    kill_timeout (r);
>     
>   ***************
>   *** 535,558 ****
>     	
>     	send_http_header(r);
>     	if (!r->header_only)
>   ! 	    send_fd(script_in, r);
>   ! 	pfclose (r->main ? r->main->pool : r->pool, script_in);
>     
>   - 	/* Soak up stderr */
>     	soft_timeout("soaking script stderr", r);
>   ! 	while (!r->connection->aborted &&
>   ! 	  (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err) > 0))
>   ! 	    continue;
>     	kill_timeout(r);
>   ! 	pfclose (r->main ? r->main->pool : r->pool, script_err);
>         }
>     
>   !     if (nph) {
>   ! #if defined(__EMX__) || defined(WIN32)
>   !         while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in) != NULL) {
>   !             bputs(argsbuffer, r->connection->client);
>   !         }
>   ! #else
>     	waitpid(child_pid, (int*)0, 0);
>     #endif
>         }    
>   --- 523,542 ----
>     	
>     	send_http_header(r);
>     	if (!r->header_only)
>   ! 	    send_fb(script_in, r);
>     
>     	soft_timeout("soaking script stderr", r);
>   ! 	while(bgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
>   ! 	      continue;
>     	kill_timeout(r);
>   ! 	     
>   ! 	bclose(script_in);
>   ! 	bclose(script_out);
>         }
>     
>   !     if (script_in && nph) {
>   !       send_fb(script_in, r);
>   ! #if !defined(__EMX__) && !defined(WIN32)
>     	waitpid(child_pid, (int*)0, 0);
>     #endif
>         }    
>   
>   
>   
>   1.63      +89 -0     apache/src/util_script.c
>   
>   Index: util_script.c
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/util_script.c,v
>   retrieving revision 1.62
>   retrieving revision 1.63
>   diff -c -C3 -r1.62 -r1.63
>   *** util_script.c	1997/06/29 19:19:37	1.62
>   --- util_script.c	1997/07/06 05:37:20	1.63
>   ***************
>   *** 312,317 ****
>   --- 312,406 ----
>         }
>     }
>     
>   + int scan_script_header_err_buff(request_rec *r, BUFF *fb, char *buffer)
>   + {
>   +     char x[MAX_STRING_LEN];
>   +     char *w, *l;
>   +     int p;
>   + 
>   +     if (buffer) *buffer = '\0';
>   +     w = buffer ? buffer : x;
>   + 
>   +     hard_timeout ("read script header", r);
>   +     
>   +     while(1) {
>   + 
>   + 	if (bgets(w, MAX_STRING_LEN-1, fb) <= 0) {
>   + 	    log_reason ("Premature end of script headers", r->filename, r);
>   + 	    return SERVER_ERROR;
>   +         }
>   + 
>   + 	/* Delete terminal (CR?)LF */
>   + 	
>   + 	p = strlen(w);
>   + 	if (p > 0 && w[p-1] == '\n')
>   + 	{
>   + 	    if (p > 1 && w[p-2] == '\015') w[p-2] = '\0';
>   + 	    else w[p-1] = '\0';
>   + 	}
>   + 
>   +         if(w[0] == '\0') {
>   + 	    kill_timeout (r);
>   + 	    return OK;
>   + 	}
>   +                                    
>   + 	/* if we see a bogus header don't ignore it. Shout and scream */
>   + 	
>   +         if(!(l = strchr(w,':'))) {
>   + 	    char malformed[(sizeof MALFORMED_MESSAGE)+1+MALFORMED_HEADER_LENGTH_TO_SHOW];
>   +             strcpy(malformed, MALFORMED_MESSAGE);
>   +             strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW);
>   + 
>   + 	    if (!buffer)
>   + 	      /* Soak up all the script output --- may save an outright kill */
>   + 	      while (bgets(w, MAX_STRING_LEN-1, fb) <= 0)
>   + 		continue;
>   + 	    
>   + 	    kill_timeout (r);
>   + 	    log_reason (malformed, r->filename, r);
>   + 	    return SERVER_ERROR;
>   +         }
>   + 
>   +         *l++ = '\0';
>   + 	while (*l && isspace (*l)) ++l;
>   + 	
>   +         if(!strcasecmp(w,"Content-type")) {
>   + 
>   + 	    /* Nuke trailing whitespace */
>   + 	    
>   + 	    char *endp = l + strlen(l) - 1;
>   + 	    while (endp > l && isspace(*endp)) *endp-- = '\0';
>   + 	    
>   + 	    r->content_type = pstrdup (r->pool, l);
>   + 	}
>   +         else if(!strcasecmp(w,"Status")) {
>   +             sscanf(l, "%d", &r->status);
>   +             r->status_line = pstrdup(r->pool, l);
>   +         }
>   +         else if(!strcasecmp(w,"Location")) {
>   + 	    table_set (r->headers_out, w, l);
>   +         }   
>   +         else if(!strcasecmp(w,"Content-Length")) {
>   + 	    table_set (r->headers_out, w, l);
>   +         }   
>   +         else if(!strcasecmp(w,"Transfer-Encoding")) {
>   + 	    table_set (r->headers_out, w, l);
>   +         }   
>   + 
>   + /* The HTTP specification says that it is legal to merge duplicate
>   +  * headers into one.  Some browsers that support Cookies don't like
>   +  * merged headers and prefer that each Set-Cookie header is sent
>   +  * separately.  Lets humour those browsers.
>   +  */
>   + 	else if(!strcasecmp(w, "Set-Cookie")) {
>   + 	    table_add(r->err_headers_out, w, l);
>   + 	}
>   +         else {
>   + 	    table_merge (r->err_headers_out, w, l);
>   +         }
>   +     }
>   + }
>   + 
>     int scan_script_header_err(request_rec *r, FILE *f, char *buffer)
>     {
>         char x[MAX_STRING_LEN];
>   
>   
>   
>   1.18      +1 -0      apache/src/util_script.h
>   
>   Index: util_script.h
>   ===================================================================
>   RCS file: /export/home/cvs/apache/src/util_script.h,v
>   retrieving revision 1.17
>   retrieving revision 1.18
>   diff -c -C3 -r1.17 -r1.18
>   *** util_script.h	1997/06/15 19:22:35	1.17
>   --- util_script.h	1997/07/06 05:37:20	1.18
>   ***************
>   *** 64,69 ****
>   --- 64,70 ----
>     void add_common_vars(request_rec *r);
>     #define scan_script_header(a1,a2) scan_script_header_err(a1,a2,NULL)
>     int scan_script_header_err(request_rec *r, FILE *f, char *buffer);
>   + int scan_script_header_err_buff(request_rec *r, BUFF *f, char *buffer);
>     void send_size(size_t size, request_rec *r);
>     int call_exec (request_rec *r, char *argv0, char **env, int shellcmd);
>     
>   
>   
>