--- mini_httpd.c.acmeorig	Wed Dec  3 19:27:22 2003
+++ mini_httpd.c	Sun Jul 18 19:05:46 2004
@@ -171,9 +171,12 @@
 static char* argv0;
 static int debug;
 static unsigned short port;
+static int maxproc;
+static int currproc;
 static char* dir;
 static char* data_dir;
 static int do_chroot;
+static int captivemode;
 static int vhost;
 static char* user;
 static char* cgi_pattern;
@@ -209,6 +212,7 @@
 static size_t request_size, request_len, request_idx;
 static int method;
 static char* path;
+static char* captive_reqpath;
 static char* file;
 static char* pathinfo;
 struct stat sb;
@@ -236,7 +240,7 @@
 static void value_required( char* name, char* value );
 static void no_value_required( char* name, char* value );
 static int initialize_listen_socket( usockaddr* usaP );
-static void handle_request( void );
+static void handle_request( int http_error );
 static void de_dotdot( char* file );
 static int get_pathinfo( void );
 static void do_file( void );
@@ -322,9 +326,13 @@
     argv0 = argv[0];
     debug = 0;
     port = 0;
+	maxproc = 16 ;
+	currproc = 0 ;
     dir = (char*) 0;
     data_dir = (char*) 0;
     do_chroot = 0;
+    captivemode = 0;
+    captive_reqpath = NULL;
     vhost = 0;
     cgi_pattern = (char*) 0;
     url_pattern = (char*) 0;
@@ -377,6 +385,11 @@
 	    ++argn;
 	    port = (unsigned short) atoi( argv[argn] );
 	    }
+	else if ( strcmp( argv[argn], "-maxproc" ) == 0 && argn + 1 < argc )
+	    {
+	    ++argn;
+	    maxproc = (unsigned short) atoi( argv[argn] );
+	    }
 	else if ( strcmp( argv[argn], "-d" ) == 0 && argn + 1 < argc )
 	    {
 	    ++argn;
@@ -431,6 +444,8 @@
 	    ++argn;
 	    max_age = atoi( argv[argn] );
 	    }
+	else if ( strcmp( argv[argn], "-a" ) == 0 )
+	    captivemode = 1;
 	else
 	    usage();
 	++argn;
@@ -722,6 +737,7 @@
 	    exit( 1 );
 	    }
 	/* Check for unnecessary security exposure. */
+	/*
 	if ( ! do_chroot )
 	    {
 	    syslog( LOG_WARNING,
@@ -729,6 +745,7 @@
 	    (void) fprintf( stderr,
 		"%s: started as root without requesting chroot(), warning only\n", argv0 );
 	    }
+	*/
 	}
 
     /* Catch various signals. */
@@ -751,6 +768,7 @@
 
     init_mime();
 
+	/*
     if ( hostname == (char*) 0 )
 	syslog(
 	    LOG_NOTICE, "%.80s starting on port %d", SERVER_SOFTWARE,
@@ -759,7 +777,8 @@
 	syslog(
 	    LOG_NOTICE, "%.80s starting on %.80s, port %d", SERVER_SOFTWARE,
 	    hostname, (int) port );
-
+	*/
+	
     /* Main loop. */
     for (;;)
 	{
@@ -816,7 +835,7 @@
 	    }
 	if ( conn_fd < 0 )
 	    {
-	    if ( errno == EINTR || errno == EAGAIN )
+	    if ( errno == EINTR || errno == EAGAIN || errno == ECONNABORTED )
 		continue;	/* try again */
 #ifdef EPROTO
 	    if ( errno == EPROTO )
@@ -827,8 +846,16 @@
 	    exit( 1 );
 	    }
 
+	/* If we've reach max child procs, then send back server busy error */
+	if (currproc >= maxproc) {
+		handle_request(503) ;
+		close(conn_fd) ;
+		continue ;
+	}
+
 	/* Fork a sub-process to handle the connection. */
 	r = fork();
+
 	if ( r < 0 )
 	    {
 	    syslog( LOG_CRIT, "fork - %m" );
@@ -843,9 +870,10 @@
 		(void) close( listen4_fd );
 	    if ( listen6_fd != -1 )
 		(void) close( listen6_fd );
-	    handle_request();
+	    handle_request(0);
 	    exit( 0 );
 	    }
+	currproc++;
 	(void) close( conn_fd );
 	}
     }
@@ -855,9 +883,9 @@
 usage( void )
     {
 #ifdef USE_SSL
-    (void) fprintf( stderr, "usage:  %s [-C configfile] [-D] [-S] [-E certfile] [-Y cipher] [-p port] [-d dir] [-dd data_dir] [-c cgipat] [-u user] [-h hostname] [-r] [-v] [-l logfile] [-i pidfile] [-T charset] [-P P3P] [-M maxage]\n", argv0 );
+    (void) fprintf( stderr, "usage:  %s [-C configfile] [-D] [-S] [-E certfile] [-Y cipher] [-p port] [-d dir] [-dd data_dir] [-c cgipat] [-u user] [-h hostname] [-r] [-v] [-l logfile] [-i pidfile] [-T charset] [-P P3P] [-M maxage] [-maxproc max_concurrent_procs]\n", argv0 );
 #else /* USE_SSL */
-    (void) fprintf( stderr, "usage:  %s [-C configfile] [-D] [-p port] [-d dir] [-dd data_dir] [-c cgipat] [-u user] [-h hostname] [-r] [-v] [-l logfile] [-i pidfile] [-T charset] [-P P3P] [-M maxage]\n", argv0 );
+    (void) fprintf( stderr, "usage:  %s [-C configfile] [-D] [-p port] [-d dir] [-dd data_dir] [-c cgipat] [-u user] [-h hostname] [-r] [-v] [-l logfile] [-i pidfile] [-T charset] [-P P3P] [-M maxage] [-maxproc max_concurrent_procs]\n", argv0 );
 #endif /* USE_SSL */
     exit( 1 );
     }
@@ -1121,14 +1149,14 @@
 ** not needed.
 */
 static void
-handle_request( void )
+handle_request( int http_error )
     {
     char* method_str;
     char* line;
     char* cp;
     int r, file_len, i;
     const char* index_names[] = {
-	"index.html", "index.htm", "index.xhtml", "index.xht", "Default.htm",
+	"index.php", "index.html", "index.htm", "index.xhtml", "index.xht", "Default.htm",
 	"index.cgi" };
 
     /* Set up the timeout for reading. */
@@ -1166,9 +1194,11 @@
     ** solution is writev() (as used in thttpd), or send the headers with
     ** send(MSG_MORE) (only available in Linux so far).
     */
+	/*
     r = 1;
     (void) setsockopt(
 	conn_fd, IPPROTO_TCP, TCP_NOPUSH, (void*) &r, sizeof(r) );
+	*/
 #endif /* TCP_NOPUSH */
 
 #ifdef USE_SSL
@@ -1215,11 +1245,13 @@
 	send_error( 400, "Bad Request", "", "Can't parse request." );
     *protocol++ = '\0';
     protocol += strspn( protocol, " \t\012\015" );
-    query = strchr( path, '?' );
-    if ( query == (char*) 0 )
-	query = "";
-    else
-	*query++ = '\0';
+    if (!captivemode) {
+	    query = strchr( path, '?' );
+	    if ( query == (char*) 0 )
+			query = "";
+	    else
+			*query++ = '\0';
+	}
 
     /* Parse the rest of the request headers. */
     while ( ( line = get_request_line() ) != (char*) 0 )
@@ -1286,6 +1318,38 @@
 	method = METHOD_POST;
     else
 	send_error( 501, "Not Implemented", "", "That method is not implemented." );
+	
+	if(http_error == 503) {
+		add_headers(
+		503, "Server temporarily overloaded", "", "", "text/html; charset=%s", (off_t) -1, (time_t) -1 );
+
+		send_error_body( 503, "Server temporarily overloaded", "The server cannot process the request due to a high load" );
+
+		send_response();
+
+		#ifdef USE_SSL
+			SSL_free( ssl );
+		#endif /* USE_SSL */
+		alarm(0) ;
+		return ;
+	}	
+
+	if (captivemode) {
+		/* only accept GET in captive portal mode */
+		captive_reqpath = path;		
+		path = "/index.php";
+		file = "index.php";
+		
+    	/* Set up the timeout for writing. */
+#ifdef HAVE_SIGSET
+		(void) sigset( SIGALRM, handle_write_timeout );
+#else /* HAVE_SIGSET */
+		(void) signal( SIGALRM, handle_write_timeout );
+#endif /* HAVE_SIGSET */
+		(void) alarm( WRITE_TIMEOUT );
+		
+		do_cgi();
+	} else {
 
     strdecode( path, path );
     if ( path[0] != '/' )
@@ -1360,7 +1424,7 @@
 
 	got_one: ;
 	}
-
+	}
 #ifdef USE_SSL
     SSL_free( ssl );
 #endif /* USE_SSL */
@@ -2117,6 +2181,7 @@
     int envn;
     char* cp;
     char buf[256];
+    char rp[MAXPATHLEN];
 
     envn = 0;
     envp[envn++] = build_env( "PATH=%s", CGI_PATH );
@@ -2135,6 +2200,7 @@
     envp[envn++] = build_env(
 	"REQUEST_METHOD=%s", get_method_str( method ) );
     envp[envn++] = build_env( "SCRIPT_NAME=%s", path );
+    envp[envn++] = build_env( "SCRIPT_FILENAME=%s", realpath(file, rp) );
     if ( pathinfo != (char*) 0 )
 	{
 	envp[envn++] = build_env( "PATH_INFO=/%s", pathinfo );
@@ -2166,6 +2232,9 @@
 	envp[envn++] = build_env( "AUTH_TYPE=%s", "Basic" );
     if ( getenv( "TZ" ) != (char*) 0 )
 	envp[envn++] = build_env( "TZ=%s", getenv( "TZ" ) );
+	
+	if (captive_reqpath != NULL)
+		envp[envn++] = build_env("CAPTIVE_REQPATH=%s", captive_reqpath);
 
     envp[envn] = (char*) 0;
     return envp;
@@ -2341,8 +2410,6 @@
 
     send_error_body( s, title, text );
 
-    send_error_tail();
-
     send_response();
 
 #ifdef USE_SSL
@@ -2378,14 +2445,15 @@
     /* Send built-in error page. */
     buflen = snprintf(
 	buf, sizeof(buf), "\
-<HTML>\n\
-<HEAD><TITLE>%d %s</TITLE></HEAD>\n\
-<BODY BGCOLOR=\"#cc9999\" TEXT=\"#000000\" LINK=\"#2020ff\" VLINK=\"#4040cc\">\n\
-<H4>%d %s</H4>\n",
+<html>\n\
+<head><title>%d %s</title></head>\n\
+<body>\n\
+<h3>%d %s</h3>\n",
 	s, title, s, title );
     add_to_response( buf, buflen );
     buflen = snprintf( buf, sizeof(buf), "%s\n", text );
     add_to_response( buf, buflen );
+    send_error_tail();
     }
 
 
@@ -2416,7 +2484,7 @@
     {
     char buf[500];
     int buflen;
-
+/*
     if ( match( "**MSIE**", useragent ) )
 	{
 	int n;
@@ -2430,13 +2498,10 @@
 	buflen = snprintf( buf, sizeof(buf), "-->\n" );
 	add_to_response( buf, buflen );
 	}
-
+*/
     buflen = snprintf( buf, sizeof(buf), "\
-<HR>\n\
-<ADDRESS><A HREF=\"%s\">%s</A></ADDRESS>\n\
-</BODY>\n\
-</HTML>\n",
-	SERVER_URL, SERVER_SOFTWARE );
+</body>\n\
+</html>\n");
     add_to_response( buf, buflen );
     }
 
@@ -2457,8 +2522,10 @@
     start_response();
     buflen = snprintf( buf, sizeof(buf), "%s %d %s\015\012", protocol, status, title );
     add_to_response( buf, buflen );
+/*
     buflen = snprintf( buf, sizeof(buf), "Server: %s\015\012", SERVER_SOFTWARE );
     add_to_response( buf, buflen );
+*/
     now = time( (time_t*) 0 );
     (void) strftime( timebuf, sizeof(timebuf), rfc1123_fmt, gmtime( &now ) );
     buflen = snprintf( buf, sizeof(buf), "Date: %s\015\012", timebuf );
@@ -3034,8 +3101,10 @@
     {
     /* Don't need to set up the handler again, since it's a one-shot. */
 
+	/*
     syslog( LOG_NOTICE, "exiting due to signal %d", sig );
     (void) fprintf( stderr, "%s: exiting due to signal %d\n", argv0, sig );
+	*/
     closelog();
     exit( 1 );
     }
@@ -3096,6 +3165,7 @@
 		}
 	    break;
 	    }
+	currproc-- ;
 	}
 
     /* Restore previous errno. */
@@ -3128,7 +3198,9 @@
 static void
 handle_read_timeout( int sig )
     {
+	/*
     syslog( LOG_INFO, "%.80s connection timed out reading", ntoa( &client_addr ) );
+	*/
     send_error(
 	408, "Request Timeout", "",
 	"No request appeared within a reasonable time period." );
