You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Dean Gaudet <dg...@hyperreal.org> on 1997/07/24 06:24:08 UTC
cvs commit: apache/src CHANGES alloc.c buff.c buff.h http_protocol.c http_protocol.h mod_cgi.c util_script.c util_script.h
dgaudet 97/07/23 21:24:07
Modified: src CHANGES alloc.c buff.c buff.h http_protocol.c
http_protocol.h mod_cgi.c util_script.c
util_script.h
Log:
cgi unbuffering. Includes various BUFF * routines for script/cgi that
suplement the FILE * routines. BUFF's now nicely handle switching from
buffered reading to unbuffered reading.
Submitted by: Dean Gaudet, Sameer Parekh, Roy Fielding
Reviewed by: Brian Behlendorf
Revision Changes Path
1.361 +20 -0 apache/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache/src/CHANGES,v
retrieving revision 1.360
retrieving revision 1.361
diff -u -r1.360 -r1.361
--- CHANGES 1997/07/23 00:06:05 1.360
+++ CHANGES 1997/07/24 04:23:55 1.361
@@ -1,3 +1,23 @@
+Changes with Apache 1.3a2
+
+ *) "nph-" CGIs were not compatible with HTTP/1.1 or SSL support because
+ they were passed a socket that connected directly to the client.
+ As such they would have to implement the transport level details
+ such as encryption or chunking in order to work properly.
+ This isn't part of the CGI spec so CGIs generally don't do this.
+ The most common use of nph- CGIs is when the programmer wants an
+ unbuffered connection to the client; regular CGIs have always been
+ fully buffered. Apache now provides an unbuffered connection to
+ all CGIs. Given that most CGIs are written in a language that by
+ default does buffering (i.e. perl) this shouldn't have a detrimental
+ effect on performance. The programmer can still use nph- CGIs,
+ and they're still responsible for sending valid HTTP/1.1 responses.
+ [Dean Gaudet, Sameer Parekh, Roy Fielding]
+
+ *) If a BUFF is switched from buffered to unbuffered reading the first
+ bread() will return whatever remained in the buffer prior to the
+ switch. [Dean Gaudet]
+
Changes with Apache 1.3a1
*) Added another Configure helper script: TestLib. It determines
1.43 +104 -52 apache/src/alloc.c
Index: alloc.c
===================================================================
RCS file: /export/home/cvs/apache/src/alloc.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- alloc.c 1997/07/24 04:14:24 1.42
+++ alloc.c 1997/07/24 04:23:56 1.43
@@ -1067,9 +1067,16 @@
#define enc_pipe(fds) pipe(fds)
#endif /* WIN32 */
-API_EXPORT(int) spawn_child_err (pool *p, int (*func)(void *), void *data,
+/* for fdopen, to get binary mode */
+#if defined (__EMX__) || defined (WIN32)
+#define BINMODE "b"
+#else
+#define BINMODE
+#endif
+
+static int spawn_child_err_core (pool *p, int (*func)(void *), void *data,
enum kill_conditions kill_how,
- FILE **pipe_in, FILE **pipe_out, FILE **pipe_err)
+ int *pipe_in, int *pipe_out, int *pipe_err)
{
int pid;
int in_fds[2];
@@ -1077,13 +1084,7 @@
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;
+ if (pipe_in && enc_pipe (in_fds) < 0) {
return 0;
}
@@ -1092,7 +1093,6 @@
if (pipe_in) {
close (in_fds[0]); close (in_fds[1]);
}
- unblock_alarms();
errno = save_errno;
return 0;
}
@@ -1105,7 +1105,6 @@
if (pipe_out) {
close (out_fds[0]); close (out_fds[1]);
}
- unblock_alarms();
errno = save_errno;
return 0;
}
@@ -1161,23 +1160,14 @@
if(pid)
{
note_subprocess(p, pid, kill_how);
- if(pipe_in)
- {
- *pipe_in = fdopen(in_fds[1], "wb");
- if(*pipe_in)
- note_cleanups_for_file(p, *pipe_in);
+ if(pipe_in) {
+ *pipe_in = in_fds[1];
}
- if(pipe_out)
- {
- *pipe_out = fdopen(out_fds[0], "rb");
- if(*pipe_out)
- note_cleanups_for_file(p, *pipe_out);
+ if(pipe_out) {
+ *pipe_out = out_fds[0];
}
- if(pipe_err)
- {
- *pipe_err = fdopen(err_fds[0], "rb");
- if(*pipe_err)
- note_cleanups_for_file(p, *pipe_err);
+ if(pipe_err) {
+ *pipe_err = err_fds[0];
}
}
SetThreadPriority(thread_handle, old_priority);
@@ -1201,7 +1191,6 @@
if (pipe_err) {
close (err_fds[0]); close (err_fds[1]);
}
- unblock_alarms();
errno = save_errno;
return 0;
}
@@ -1240,43 +1229,106 @@
if (pipe_out) {
close (out_fds[1]);
-#ifdef __EMX__
- /* Need binary mode set for OS/2. */
- *pipe_out = fdopen (out_fds[0], "rb");
-#else
- *pipe_out = fdopen (out_fds[0], "r");
-#endif
-
- if (*pipe_out) note_cleanups_for_file (p, *pipe_out);
+ *pipe_out = out_fds[0];
}
if (pipe_in) {
close (in_fds[0]);
-#ifdef __EMX__
- /* Need binary mode set for OS/2 */
- *pipe_in = fdopen (in_fds[1], "wb");
-#else
- *pipe_in = fdopen (in_fds[1], "w");
-#endif
-
- if (*pipe_in) note_cleanups_for_file (p, *pipe_in);
+ *pipe_in = in_fds[1];
}
if (pipe_err) {
close (err_fds[1]);
-#ifdef __EMX__
- /* Need binary mode set for OS/2. */
- *pipe_err = fdopen (err_fds[0], "rb");
-#else
- *pipe_err = fdopen (err_fds[0], "r");
-#endif
-
- if (*pipe_err) note_cleanups_for_file (p, *pipe_err);
+ *pipe_err = err_fds[0];
}
#endif /* WIN32 */
- unblock_alarms();
return pid;
+}
+
+
+API_EXPORT(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)
+{
+ int fd_in, fd_out, fd_err;
+ int pid, save_errno;
+
+ block_alarms();
+
+ pid = spawn_child_err_core (p, func, data, kill_how,
+ pipe_in ? &fd_in : NULL,
+ pipe_out ? &fd_out : NULL,
+ pipe_err ? &fd_err : NULL );
+
+ if (pid == 0) {
+ save_errno = errno;
+ unblock_alarms();
+ errno = save_errno;
+ return 0;
+ }
+
+ if (pipe_out) {
+ *pipe_out = fdopen (fd_out, "r" BINMODE);
+ if (*pipe_out) note_cleanups_for_file (p, *pipe_out);
+ else close (fd_out);
+ }
+
+ if (pipe_in) {
+ *pipe_in = fdopen (fd_in, "w" BINMODE);
+ if (*pipe_in) note_cleanups_for_file (p, *pipe_in);
+ else close (fd_in);
+ }
+
+ if (pipe_err) {
+ *pipe_err = fdopen (fd_err, "r" BINMODE);
+ if (*pipe_err) note_cleanups_for_file (p, *pipe_err);
+ else close (fd_err);
+ }
+
+ unblock_alarms();
+ return pid;
+}
+
+
+API_EXPORT(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 fd_in, fd_out, fd_err;
+ int pid, save_errno;
+
+ block_alarms();
+
+ pid = spawn_child_err_core (p, func, data, kill_how,
+ pipe_in ? &fd_in : NULL,
+ pipe_out ? &fd_out : NULL,
+ pipe_err ? &fd_err : NULL );
+
+ if (pid == 0) {
+ save_errno = errno;
+ unblock_alarms();
+ errno = save_errno;
+ return 0;
+ }
+
+ if (pipe_out) {
+ *pipe_out = bcreate(p, B_RD);
+ bpushfd(*pipe_out, fd_out, fd_out);
+ }
+
+ if (pipe_in) {
+ *pipe_in = bcreate(p, B_WR);
+ bpushfd(*pipe_in, fd_in, fd_in);
+ }
+
+ if (pipe_err) {
+ *pipe_err = bcreate(p, B_RD);
+ bpushfd(*pipe_err, fd_err, fd_err);
+ }
+
+ unblock_alarms();
+ return pid;
}
static void free_proc_chain (struct process_chain *procs)
1.38 +33 -5 apache/src/buff.c
Index: buff.c
===================================================================
RCS file: /export/home/cvs/apache/src/buff.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- buff.c 1997/07/15 21:39:50 1.37
+++ buff.c 1997/07/24 04:23:57 1.38
@@ -415,18 +415,38 @@
{
if (value) {
fb->flags |= flag;
- if( flag & B_CHUNK ) {
+ if (flag & B_CHUNK) {
start_chunk(fb);
}
} else {
fb->flags &= ~flag;
- if( flag & B_CHUNK ) {
+ if (flag & B_CHUNK) {
end_chunk(fb);
}
}
return value;
}
+
+API_EXPORT(int) bnonblock(BUFF *fb, int direction)
+{
+ int fd;
+
+ fd = ( direction == B_RD ) ? fb->fd_in : fb->fd;
+#if defined(O_NONBLOCK)
+ return fcntl (fd, F_SETFL, O_NONBLOCK);
+#elif defined(F_NDELAY)
+ return fcntl (fd, F_SETFL, F_NDELAY);
+#else
+ return 0;
+#endif
+}
+
+API_EXPORT(int) bfileno(BUFF *fb, int direction)
+{
+ return (direction == B_RD) ? fb->fd_in : fb->fd;
+}
+
/*
* This is called instead of read() everywhere in here. It implements
* the B_SAFEREAD functionality -- which is to force a flush() if a read()
@@ -521,10 +541,18 @@
if (fb->flags & B_RDERR) return -1;
if (nbyte == 0) return 0;
- if (!(fb->flags & B_RD))
- {
-/* Unbuffered reading */
+ if (!(fb->flags & B_RD)) {
+ /* Unbuffered reading. First check if there was something in the
+ * buffer from before we went unbuffered. */
+ if (fb->incnt) {
+ i = (fb->incnt > nbyte) ? nbyte : fb->incnt;
+ memcpy (buf, fb->inptr, i);
+ fb->incnt -= i;
+ fb->inptr += i;
+ return i;
+ }
i = saferead( fb, buf, nbyte );
+ if (i == 0) fb->flags |= B_EOF;
if (i == -1 && errno != EAGAIN) doerror(fb, B_RD);
return i;
}
1.22 +9 -0 apache/src/buff.h
Index: buff.h
===================================================================
RCS file: /export/home/cvs/apache/src/buff.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- buff.h 1997/07/19 22:34:05 1.21
+++ buff.h 1997/07/24 04:23:57 1.22
@@ -158,3 +158,12 @@
#define bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \
(fb)->outcnt == (fb)->bufsiz) ? bflsbuf(c, (fb)) : \
((fb)->outbase[(fb)->outcnt++] = (c), 0))
+
+API_EXPORT(int) spawn_child_err_buff (pool *, int (*)(void *), void *,
+ enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out,
+ BUFF **pipe_err);
+
+/* enable non-blocking operations */
+API_EXPORT(int) bnonblock(BUFF *fb, int direction);
+/* and get an fd to select() on */
+API_EXPORT(int) bfileno(BUFF *fb, int direction);
1.145 +79 -0 apache/src/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.144
retrieving revision 1.145
diff -u -r1.144 -r1.145
--- http_protocol.c 1997/07/20 18:52:40 1.144
+++ http_protocol.c 1997/07/24 04:23:58 1.145
@@ -1629,6 +1629,85 @@
return total_bytes_sent;
}
+/*
+ * Send the body of a response to the client.
+ */
+API_EXPORT(long) send_fb(BUFF *fb, request_rec *r) {
+ return send_fb_length(fb, r, -1);
+}
+
+API_EXPORT(long) send_fb_length(BUFF *fb, request_rec *r, long length)
+{
+ char buf[IOBUFSIZE];
+ long total_bytes_sent = 0;
+ register int n, w, o, len, fd;
+ fd_set fds;
+
+ if (length == 0) return 0;
+
+ /* Make fb unbuffered and non-blocking */
+ bsetflag (fb, B_RD, 0);
+ bnonblock (fb, B_RD);
+ fd = bfileno (fb, B_RD);
+
+ soft_timeout("send body", r);
+
+ while (!r->connection->aborted) {
+ if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
+ len = length - total_bytes_sent;
+ else len = IOBUFSIZE;
+
+ do {
+ n = bread (fb, buf, len);
+ if (n >= 0) break;
+ if (n < 0 && errno != EAGAIN) break;
+ /* we need to block, so flush the output first */
+ bflush (r->connection->client);
+ FD_ZERO (&fds);
+ FD_SET (fd, &fds);
+ /* we don't care what select says, we might as well loop back
+ * around and try another read
+ */
+ ap_select (fd+1, &fds, NULL, NULL, NULL);
+ } while (!r->connection->aborted);
+
+ if (n < 1 || r->connection->aborted) {
+ 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;
+}
+
API_EXPORT(int) rputc (int c, request_rec *r)
{
if (r->connection->aborted) return EOF;
1.25 +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.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- http_protocol.h 1997/07/19 20:27:52 1.24
+++ http_protocol.h 1997/07/24 04:23:59 1.25
@@ -110,6 +110,9 @@
API_EXPORT(long) send_fd(FILE *f, request_rec *r);
API_EXPORT(long) send_fd_length(FILE *f, request_rec *r, long length);
+
+API_EXPORT(long) send_fb(BUFF *f, request_rec *r);
+API_EXPORT(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.50 +35 -56 apache/src/mod_cgi.c
Index: mod_cgi.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- mod_cgi.c 1997/07/17 22:27:34 1.49
+++ mod_cgi.c 1997/07/24 04:23:59 1.50
@@ -183,7 +183,7 @@
}
static int log_script(request_rec *r, cgi_server_conf *conf, int ret,
- char *dbuf, char *sbuf, FILE *script_in, FILE *script_err)
+ 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,9 +197,9 @@
((f = pfopen(r->pool, server_root_relative(r->pool, conf->logname),
"a")) == NULL)) {
/* Soak up script output */
- while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in))
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
continue;
- while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
continue;
return ret;
}
@@ -207,7 +207,7 @@
/* "%% [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 */
+ /* "%% 500 /usr/local/etc/httpd/cgi-bin" */
fprintf(f, "%%%% %d %s\n", ret, r->filename);
fputs("%request\n", f);
@@ -216,7 +216,7 @@
fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
}
if ((r->method_number == M_POST || r->method_number == M_PUT)
- && dbuf && *dbuf) {
+ && *dbuf) {
fprintf(f, "\n%s\n", dbuf);
}
@@ -232,28 +232,24 @@
if (sbuf && *sbuf)
fprintf(f, "%s\n", sbuf);
- *argsbuffer = '\0';
- fgets(argsbuffer, HUGE_STRING_LEN-1, script_in);
- if (*argsbuffer) {
+ if (bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
fputs("%stdout\n", f);
fputs(argsbuffer, f);
- while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in))
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
fputs(argsbuffer, f);
fputs("\n", f);
}
- *argsbuffer = '\0';
- fgets(argsbuffer, HUGE_STRING_LEN-1, script_err);
- if (*argsbuffer) {
+ if (bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
fputs("%stderr\n", f);
fputs(argsbuffer, f);
- while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
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);
+ bclose(script_in);
+ bclose(script_err);
pfclose(r->pool, f);
return ret;
@@ -277,7 +273,6 @@
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
@@ -312,10 +307,6 @@
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.
*/
@@ -352,7 +343,7 @@
{
int retval, nph, dbpos = 0;
char *argv0, *dbuf = NULL;
- FILE *script_out, *script_in, *script_err;
+ 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;
@@ -415,21 +406,16 @@
cld.argv0 = argv0; cld.r = r; cld.nph = nph;
cld.debug = conf->logname ? 1 : 0;
+ /*
+ * we spawn out of r->main if it's there so that we can avoid
+ * waiting for free_proc_chain to cleanup in the middle of an
+ * SSI request -djg
+ */
if (!(child_pid =
- /*
- * we spawn out of r->main if it's there so that we can avoid
- * 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
+ 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,7 +457,7 @@
dbpos += dbsize;
}
reset_timeout(r);
- if (fwrite(argsbuffer, sizeof(char), len_read, script_out)
+ 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,20 +466,20 @@
}
}
- fflush (script_out);
+ bflush (script_out);
signal (SIGPIPE, handler);
kill_timeout (r);
}
- pfclose (r->main ? r->main->pool : r->pool, script_out);
+ bclose(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)))
+ 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,11 +488,9 @@
/* Soak up all the script output */
hard_timeout ("read from script", r);
- while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_in)
- > 0)
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
continue;
- while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err)
- > 0)
+ while (bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
continue;
kill_timeout (r);
@@ -535,24 +519,19 @@
send_http_header(r);
if (!r->header_only)
- send_fd(script_in, r);
- pfclose (r->main ? r->main->pool : r->pool, script_in);
+ send_fb(script_in, r);
+ bclose(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;
+ while(bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+ continue;
kill_timeout(r);
- pfclose (r->main ? r->main->pool : r->pool, script_err);
+ bclose(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
+ if (script_in && nph) {
+ send_fb(script_in, r);
+#if !defined(__EMX__) && !defined(WIN32)
waitpid(child_pid, (int*)0, 0);
#endif
}
1.67 +27 -3 apache/src/util_script.c
Index: util_script.c
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -r1.66 -r1.67
--- util_script.c 1997/07/15 21:39:59 1.66
+++ util_script.c 1997/07/24 04:24:00 1.67
@@ -312,7 +312,9 @@
}
}
-API_EXPORT(int) scan_script_header_err(request_rec *r, FILE *f, char *buffer)
+
+static int scan_script_header_err_core (request_rec *r, char *buffer,
+ int (*getsfunc)(char *, int, void *), void *getsfunc_data)
{
char x[MAX_STRING_LEN];
char *w, *l;
@@ -325,7 +327,7 @@
while(1) {
- if (fgets(w, MAX_STRING_LEN-1, f) == NULL) {
+ if ((*getsfunc)(w, MAX_STRING_LEN-1, getsfunc_data) == 0) {
kill_timeout (r);
log_reason ("Premature end of script headers", r->filename, r);
return SERVER_ERROR;
@@ -354,7 +356,7 @@
if (!buffer)
/* Soak up all the script output --- may save an outright kill */
- while (fgets(w, MAX_STRING_LEN-1, f) != NULL)
+ while ((*getsfunc)(w, MAX_STRING_LEN-1, getsfunc_data))
continue;
kill_timeout (r);
@@ -401,6 +403,28 @@
}
}
}
+
+static int getsfunc_FILE (char *buf, int len, void *f)
+{
+ return fgets (buf, len, (FILE *)f) != NULL;
+}
+
+API_EXPORT(int) scan_script_header_err(request_rec *r, FILE *f, char *buffer)
+{
+ return scan_script_header_err_core (r, buffer, getsfunc_FILE, f);
+}
+
+static int getsfunc_BUFF (char *w, int len, void *fb)
+{
+ return bgets (w, len, (BUFF *)fb) > 0;
+}
+
+API_EXPORT(int) scan_script_header_err_buff(request_rec *r, BUFF *fb,
+ char *buffer)
+{
+ return scan_script_header_err_core (r, buffer, getsfunc_BUFF, fb);
+}
+
API_EXPORT(void) send_size(size_t size, request_rec *r) {
char ss[20];
1.22 +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.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- util_script.h 1997/07/15 21:40:00 1.21
+++ util_script.h 1997/07/24 04:24:00 1.22
@@ -64,6 +64,7 @@
API_EXPORT(void) add_common_vars(request_rec *r);
#define scan_script_header(a1,a2) scan_script_header_err(a1,a2,NULL)
API_EXPORT(int) scan_script_header_err(request_rec *r, FILE *f, char *buffer);
+API_EXPORT(int) scan_script_header_err_buff(request_rec *r, BUFF *f, char *buffer);
API_EXPORT(void) send_size(size_t size, request_rec *r);
API_EXPORT(int) call_exec (request_rec *r, char *argv0, char **env, int shellcmd);