httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Randy Terbush <ra...@zyzzyva.com>
Subject Re: [PATCH] CGI unbuffering for 1.3
Date Sat, 05 Jul 1997 15:40:10 GMT
> 	Whee, I made my cgi unbuffering work with 1.3 What this does:
> createas a select() loops between the cgi and the client, so that if
> the cgi pauses its output, the client sees a puase. If nph- is on,
> then the only difference is that the select() loops starts as soon as
> the cgi starts, instead of waiting until
> scan_script_headers/send_http_hedares happens.
> 
> 	I am guessing that this patch will work as-is on NT except for
> my send_fb function, which is the select() loop. It's been tested so
> far on freebsd.
> 
> 	I coudln't figure out how to prototype spawn_child_err_buff()
> in alloc.c because in alloc.h buff.h isn't included yet.
> 
> 	Comments? Should I stick this in? This CGI code has been in
> Stronghold since just after 1.2 went into feature freeze. SO it's
> pretty stable on UNIX, in its stronghold incarnation. I may have messed
> up and created some instability when I modified the stuff for 1.3,
> though.

I'm not clear on why we need to create parallel functions rather 
than change the existing ones. Note that I'm not saying we don't, 
but am not clear on why we can't change the existing functions.

Also, I question why send_fb_length() returns a long. It appears to 
promote the return of bwrite() from an int to a long. bwrite should 
probably be returning a size_t as I look at this.

Also, as Roy oft points out, single character variable names are 
kind of a pain to follow. Especially the use of 'o'.

Lastly (a nit) there are comments that reference directories that 
don't necessarily exist. /usr/local/etc/httpd. There has been some 
discussion of this lately. I would like to see us lose this legacy 
in the source reorganization that Paul has been working on. This is 
an incredibily stupid place to install the web server IMO.


> Index: alloc.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/alloc.c,v
> retrieving revision 1.35
> diff -c -r1.35 alloc.c
> *** alloc.c	1997/06/29 19:19:34	1.35
> --- alloc.c	1997/07/04 05:37:28
> ***************
> *** 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)
> Index: alloc.h
> ===================================================================
> RCS file: /export/home/cvs/apache/src/alloc.h,v
> retrieving revision 1.23
> diff -c -r1.23 alloc.h
> *** alloc.h	1997/06/28 20:24:27	1.23
> --- alloc.h	1997/07/04 05:37:31
> ***************
> *** 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,
> Index: http_protocol.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_protocol.c,v
> retrieving revision 1.131
> diff -c -r1.131 http_protocol.c
> *** http_protocol.c	1997/07/01 06:46:02	1.131
> --- http_protocol.c	1997/07/04 05:38:01
> ***************
> *** 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); }
>   
> Index: http_protocol.h
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_protocol.h,v
> retrieving revision 1.19
> diff -c -r1.19 http_protocol.h
> *** http_protocol.h	1997/04/07 10:58:38	1.19
> --- http_protocol.h	1997/07/04 05:38:06
> ***************
> *** 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.
> Index: mod_cgi.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
> retrieving revision 1.42
> diff -c -r1.42 mod_cgi.c
> *** mod_cgi.c	1997/06/29 17:39:50	1.42
> --- mod_cgi.c	1997/07/04 05:38:40
> ***************
> *** 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
>       }    
> Index: util_script.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/util_script.c,v
> retrieving revision 1.62
> diff -c -r1.62 util_script.c
> *** util_script.c	1997/06/29 19:19:37	1.62
> --- util_script.c	1997/07/04 05:38:56
> ***************
> *** 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];
> Index: util_script.h
> ===================================================================
> RCS file: /export/home/cvs/apache/src/util_script.h,v
> retrieving revision 1.17
> diff -c -r1.17 util_script.h
> *** util_script.h	1997/06/15 19:22:35	1.17
> --- util_script.h	1997/07/04 05:38:59
> ***************
> *** 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);
>   
> 
> 
> -- 
> Sameer Parekh					Voice:   510-986-8770
> President					FAX:     510-986-8777
> C2Net
> http://www.c2.net/				sameer@c2.net




Mime
View raw message