httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject [PATCH] nph killer, cgi buffering
Date Sun, 20 Jul 1997 01:03:07 GMT
This patch:

- provides BUFF * interfaces to the various things cgi needs, in a way
  that avoids mucho code duplication

- adds bnonblock() to set a BUFF to non-blocking mode, and bfileno() to
  get an fd for calling select() on.

- provides send_fb/send_fb_length which do non-blocking reads, and
  whenever a read would block they bflush the client before blocking.

- eliminates the special case "nph-" for CGIs.  (nph doesn't work with
  HTTP/1.1 or SSL)

- works on simple .cgis, needs testing via mod_include, needs more eyes
  to look at it.  Needs testing on NT (needs porting??).

Dean

Index: alloc.c
===================================================================
RCS file: /export/home/cvs/apache/src/alloc.c,v
retrieving revision 1.40
diff -u -r1.40 alloc.c
--- alloc.c	1997/07/15 21:39:50	1.40
+++ alloc.c	1997/07/20 00:56:14
@@ -1064,9 +1064,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];
@@ -1074,13 +1081,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;
   }
   
@@ -1089,7 +1090,6 @@
     if (pipe_in) {
       close (in_fds[0]); close (in_fds[1]);
     }
-    unblock_alarms();
     errno = save_errno;
     return 0;
   }
@@ -1102,7 +1102,6 @@
     if (pipe_out) {
       close (out_fds[0]); close (out_fds[1]);
     }
-    unblock_alarms();
     errno = save_errno;
     return 0;
   }
@@ -1158,23 +1157,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);
@@ -1198,7 +1188,6 @@
     if (pipe_err) {
       close (err_fds[0]); close (err_fds[1]);
     }
-    unblock_alarms();
     errno = save_errno;
     return 0;
   }
@@ -1237,43 +1226,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)
Index: buff.c
===================================================================
RCS file: /export/home/cvs/apache/src/buff.c,v
retrieving revision 1.37
diff -u -r1.37 buff.c
--- buff.c	1997/07/15 21:39:50	1.37
+++ buff.c	1997/07/20 00:56:16
@@ -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;
     }
Index: buff.h
===================================================================
RCS file: /export/home/cvs/apache/src/buff.h,v
retrieving revision 1.21
diff -u -r1.21 buff.h
--- buff.h	1997/07/19 22:34:05	1.21
+++ buff.h	1997/07/20 00:56:17
@@ -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);
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.143
diff -u -r1.143 http_protocol.c
--- http_protocol.c	1997/07/19 20:27:52	1.143
+++ http_protocol.c	1997/07/20 00:56:22
@@ -1626,6 +1626,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;
Index: http_protocol.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.h,v
retrieving revision 1.24
diff -u -r1.24 http_protocol.h
--- http_protocol.h	1997/07/19 20:27:52	1.24
+++ http_protocol.h	1997/07/20 00:56:23
@@ -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.
Index: mod_cgi.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
retrieving revision 1.49
diff -u -r1.49 mod_cgi.c
--- mod_cgi.c	1997/07/17 22:27:34	1.49
+++ mod_cgi.c	1997/07/20 00:56:24
@@ -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))
 	continue;
-      while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
+      while (bgets(argsbuffer, HUGE_STRING_LEN, script_err))
 	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);
     }
 
@@ -233,27 +233,27 @@
       fprintf(f, "%s\n", sbuf);
 
     *argsbuffer = '\0';
-    fgets(argsbuffer, HUGE_STRING_LEN-1, script_in);
+    bgets(argsbuffer, HUGE_STRING_LEN, script_in);
     if (*argsbuffer) {
       fputs("%stdout\n", f);
       fputs(argsbuffer, f);
-      while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in))
+      while (bgets(argsbuffer, HUGE_STRING_LEN, script_in))
 	fputs(argsbuffer, f);
       fputs("\n", f);
     }
 
     *argsbuffer = '\0';
-    fgets(argsbuffer, HUGE_STRING_LEN-1, script_err);
+    bgets(argsbuffer, HUGE_STRING_LEN, script_err);
     if (*argsbuffer) {
       fputs("%stderr\n", f);
       fputs(argsbuffer, f);
-      while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err))
+      while (bgets(argsbuffer, HUGE_STRING_LEN, script_err))
 	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 +277,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 +311,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 +347,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;
@@ -421,15 +416,10 @@
 	   * 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 +461,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 +470,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 +492,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))
 	        continue;
-	    while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err)
-	           > 0)
+	    while (bgets(argsbuffer, HUGE_STRING_LEN, script_err))
 	        continue;
 	    kill_timeout (r);
 
@@ -535,24 +523,20 @@
 	
 	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);
 
-	/* 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))
+	      continue;
 	kill_timeout(r);
-	pfclose (r->main ? r->main->pool : r->pool, script_err);
+	     
+	bclose(script_in);
+	bclose(script_out);
     }
 
-    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
     }    
Index: util_script.c
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.c,v
retrieving revision 1.66
diff -u -r1.66 util_script.c
--- util_script.c	1997/07/15 21:39:59	1.66
+++ util_script.c	1997/07/20 00:56:26
@@ -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];
Index: util_script.h
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.h,v
retrieving revision 1.21
diff -u -r1.21 util_script.h
--- util_script.h	1997/07/15 21:40:00	1.21
+++ util_script.h	1997/07/20 00:56:27
@@ -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);
 



Mime
View raw message