Index: cgi.c
===================================================================
RCS file: /cvs/roxen_src/extern/cgi.c,v
retrieving revision 1.16
diff -C3 -r1.16 cgi.c
*** cgi.c	1997/10/06 18:06:52	1.16
--- cgi.c	1998/05/08 17:29:12
***************
*** 1,9 ****
  #include <string.h>
  #include <sys/types.h>
  #include <stdio.h>
  #include <sys/signal.h>
  #include <sys/time.h>
- #include "../pike/src/machine.h" /* for MAX_OPEN_FILEDESCRIPTORS */
  
  #ifdef HAVE_CONFIG_H
  #include "config.h"
--- 1,29 ----
+ /*
+  * $Id: cgi.c,v 1.28 1998/05/08 14:29:31 grubba Exp $
+  *
+  * CGI-wrapper for Roxen.
+  *
+  * David Hedbor
+  * Per Hedbor
+  * Henrik Grubbström
+  * and others.
+  */
+ 
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+ #endif /* HAVE_CONFIG_H */
+ 
  #include <string.h>
+ #ifdef HAVE_STRINGS_H
+ #include <strings.h>
+ #endif /* HAVE_STRINGS_H */
  #include <sys/types.h>
  #include <stdio.h>
+ #ifdef HAVE_SIGNAL_H
+ #include <signal.h>
+ #endif /* HAVE_SIGNAL_H */
  #include <sys/signal.h>
  #include <sys/time.h>
  
  #ifdef HAVE_CONFIG_H
  #include "config.h"
***************
*** 42,49 ****
  #ifndef MAXPATHLEN 
  # define MAXPATHLEN  2048
  #endif
  
! #undef DEBUG
  
  #include <errno.h>
  
--- 62,76 ----
  #ifndef MAXPATHLEN 
  # define MAXPATHLEN  2048
  #endif
+ 
+ #ifndef MAXHEADERLEN
+ /* maximum size of the header before sending and error message and
+  * killing the script.
+  */
+ # define MAXHEADERLEN 32769
+ #endif
  
! #define DEBUG
  
  #include <errno.h>
  
***************
*** 70,76 ****
--- 97,114 ----
  fd_set writefd[1];
  #endif
  
+ #define LONGHEADER "HTTP/1.0 500 Buggy CGI Script\r\n\
+ Content-Type: text/html\r\n\r\n\
+ <title>CGI-script error</title> \n\
+ <h1>CGI-script error</h1> \n\
+ The CGI script you accessed is not working correctly. It tried \n\
+ to send too much header data (probably due to incorrect separation between \n\
+ the headers and the body. Please notify the author of the script of this\n\
+ problem.\n"
  
+ 
+ 
+ 
  /* This is stdout from the CGI script */
  int script;
  
***************
*** 236,260 ****
  }
  #endif
  
- int is_end_of_headers(char *s, int len)
- {
-   if(!headers) 
-   {
-     hsize = (len/1024+1)*1024;
-     headers = malloc(hsize);
-     hpointer = 0;
-   } else if(hsize <= hpointer+len) {
-     headers = my_realloc(headers, hsize*2, hsize);
-     hsize *= 2;
-   }
- 
-   movemem(headers+hpointer, s, len);
-   hpointer += len;
-   headers[hpointer] = 0;
- 
-   return (strstr(headers, "\n\n")||strstr(headers, "\r\n\r\n")||strstr(headers, "\n\r\n\r"));
- }
- 
  void reaper(int i)
  {
    int status;
--- 274,279 ----
***************
*** 283,295 ****
    close(script);
    signal(SIGCHLD, reaper);
    kill(pid, 1);		/* HUP */
!   sleep(10);
    kill(pid, 13);	/* PIPE */
!   sleep(10);
    kill(pid, 2);		/* INT */
!   sleep(10);
    kill(pid, 15);	/* TERM */
!   sleep(10);
    kill(pid, 9);		/* KILL */
    exit(0);
  }
--- 302,314 ----
    close(script);
    signal(SIGCHLD, reaper);
    kill(pid, 1);		/* HUP */
!   sleep(3);
    kill(pid, 13);	/* PIPE */
!   sleep(3);
    kill(pid, 2);		/* INT */
!   sleep(3);
    kill(pid, 15);	/* TERM */
!   sleep(3);
    kill(pid, 9);		/* KILL */
    exit(0);
  }
***************
*** 320,329 ****
      }
    } while(re);
  }
  
! int parse_and_send_headers(void)
  {
!   char *error, *pointer;
    if(headers)
    {
      if(((error=strstr(headers, "status:")) || 
--- 339,390 ----
      }
    } while(re);
  }
+ 
+ 
+ char *is_end_of_headers(char *s, int len)
+ {
+   char *end_of_header;
+ 
+   if(!headers) 
+   {
+     hpointer = 0;
+     hsize = (len/1024+1)*1024;
+     headers = malloc(hsize);
+     if ((s[0] == '\r') || (s[0] == '\n')) {
+       /* No headers. */
+       movemem(headers, s, len);
+       hpointer = len;
+       headers[hpointer] = 0;
+       return(headers);
+     }
+   } else if(hsize <= hpointer+len) {
+     headers = my_realloc(headers, (hpointer+len)*2+1, hsize);
+     hsize = (hpointer+len)*2;
+   }
+   if(hsize > MAXHEADERLEN) {
+     send_data(LONGHEADER, strlen(LONGHEADER));
+     kill_kill_kill();
+   }
+     
+   
+   movemem(headers + hpointer, s, len);
+   hpointer += len;
+   headers[hpointer] = 0;
+ 
+   end_of_header = strstr(headers, "\r\n\r\n");
+   if (!end_of_header) {
+     end_of_header = strstr(headers, "\n\n");
+   }
+   if (!end_of_header) {
+     end_of_header = strstr(headers, "\n\r\n\r");
+   }
+   return(end_of_header);
+ }
  
! 
! void parse_and_send_headers(char *header_end)
  {
!   char *error, *pointer = NULL;
    if(headers)
    {
      if(((error=strstr(headers, "status:")) || 
***************
*** 331,355 ****
         && error==headers)
      {
        char *tmp;
        pointer = error;
!       while(*error!=' ') error++;
!       while(*error==' ') error++;
        tmp=error;
!       while(*tmp!='\n') tmp++;
        
        send_data("HTTP/1.0 ", 9);
!       send_data(error, tmp-error+1);
!       /*  send_data(headers, pointer-headers);*/
!       send_data(tmp+1, hpointer-(tmp-headers));
        free(headers);
!       return 1;
      }
!     if(strstr(headers, "Location:") || strstr(headers, "location:"))
!       error = "HTTP/1.0 302 Document Found\n";
!     else
!       error = "HTTP/1.0 200 Ok\n";
    } else
!     error = "HTTP/1.0 200 Ok\n";
    
    send_data(error, strlen(error));
    if(headers)
--- 392,432 ----
         && error==headers)
      {
        char *tmp;
+       int skip;
        pointer = error;
!       while(*error!=' ' && *error != ':') error++;
!       while(*error==' ' || *error == ':') error++;
        tmp=error;
!       while(*tmp!='\n' && *tmp!='\r') tmp++;
!       if ((*tmp == '\n' && tmp[1] == '\r') ||
! 	  (*tmp == '\r' && tmp[1] == '\n'))
! 	skip = 2;
!       else
! 	skip = 1;
        
        send_data("HTTP/1.0 ", 9);
!       send_data(error, tmp - error);
!       send_data("\r\n", 2);
!       /*  send_data(headers, hpointer-headers);*/
!       send_data(tmp+skip, hpointer-(tmp+skip-headers));
        free(headers);
!       return;
      }
!     if(((pointer = strstr(headers, "Location:")) &&
! 	(!header_end || (pointer < header_end))) ||
!        ((pointer = strstr(headers, "location:")) &&
! 	(!header_end || (pointer < header_end)))) {
! #ifdef DEBUG
!       fprintf(stderr, "Redirect: pointer:%p, header_end:%p, headers:%p\n",
! 	      pointer, header_end, headers);
! #endif /* DEBUG */
! 	      
!       error = "HTTP/1.0 302 Redirect\r\n";
!     } else {
!       error = "HTTP/1.0 200 Ok\r\n";
!     }
    } else
!     error = "HTTP/1.0 200 Ok\r\n";
    
    send_data(error, strlen(error));
    if(headers)
***************
*** 358,364 ****
      free(headers);
    }
  /*  send_data("\n", 1);*/
!   return 1;
  }
  
  
--- 435,441 ----
      free(headers);
    }
  /*  send_data("\n", 1);*/
!   return;
  }
  
  
***************
*** 377,383 ****
    return !(strncmp(foo+len, "nph", 3));
  }
  
! void main(int argc, char **argv)
  {
    int i;
    /* Insure that all filedecriptors except stdin, stdout and stderr are closed
--- 454,460 ----
    return !(strncmp(foo+len, "nph", 3));
  }
  
! int main(int argc, char **argv)
  {
    int i;
    /* Insure that all filedecriptors except stdin, stdout and stderr are closed
***************
*** 401,407 ****
    if(!getuid()) {
      int euid = geteuid();
      int egid = getegid();
! #ifdef HAVE_SETRESUID
      setresgid(egid, egid, -1);
      setresuid(euid, euid, -1);
  #else
--- 478,484 ----
    if(!getuid()) {
      int euid = geteuid();
      int egid = getegid();
! #if defined(HAVE_SETRESUID) && !defined(HAVE_SETEUID)
      setresgid(egid, egid, -1);
      setresuid(euid, euid, -1);
  #else
***************
*** 442,468 ****
      char foo[2049], *bar;
      
      re = read(script, foo, 2048);
- #ifdef DEBUG
-     foo[re]=0;
-     fprintf(stderr, "read %s\n", foo);
- #endif
      if(re <= 0)
      {
  #ifdef DEBUG
        perror("read failed");
  #endif
!       if(!raw) parse_and_send_headers();
        kill(pid, 9);
        close(0); close(1); close(2);
        exit(0);
      }
  
      bar=foo;
      
      if(!raw)
      {
!       if(is_end_of_headers(foo, re)) 
! 	raw = parse_and_send_headers();
      } else 
        send_data(bar, re);
    }
--- 519,548 ----
      char foo[2049], *bar;
      
      re = read(script, foo, 2048);
      if(re <= 0)
      {
  #ifdef DEBUG
        perror("read failed");
  #endif
!       if(!raw) parse_and_send_headers(NULL);
        kill(pid, 9);
        close(0); close(1); close(2);
        exit(0);
      }
+     foo[re]=0;
+ #ifdef DEBUG
+     fprintf(stderr, "read %s\n", foo);
+ #endif
  
      bar=foo;
      
      if(!raw)
      {
!       char *header_end;
!       if((header_end = is_end_of_headers(foo, re))) {
! 	parse_and_send_headers(header_end);
! 	raw = 1;
!       }
      } else 
        send_data(bar, re);
    }
