--- thttpd/libhttpd.c 2001/06/29 13:17:52 1.1.4.3 +++ thttpd/libhttpd.c 2001/07/08 08:21:57 1.4 @@ -157,8 +157,8 @@ static void cgi_interpose_input( httpd_conn* hc, int wfd ); static void post_post_garbage_hack( httpd_conn* hc ); static void cgi_interpose_output( httpd_conn* hc, int rfd ); -static void cgi_child( httpd_conn* hc ); -static off_t cgi( httpd_conn* hc ); +static void cgi_child( httpd_conn* hc, char* exefilename ); +static off_t cgi( httpd_conn* hc, char* exefilename ); static int really_start_request( httpd_conn* hc, struct timeval* nowP ); static void make_log_entry( httpd_conn* hc, struct timeval* nowP ); static int check_referer( httpd_conn* hc ); @@ -240,6 +240,8 @@ free( (void*) hs->binding_hostname ); if ( hs->cwd != (char*) 0 ) free( (void*) hs->cwd ); + if ( hs->autoindex_prog != (char*) 0 ) + free( (void*) hs->autoindex_prog ); if ( hs->cgi_pattern != (char*) 0 ) free( (void*) hs->cgi_pattern ); if ( hs->charset != (char*) 0 ) @@ -257,7 +259,8 @@ char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, int no_symlink, int vhost, int global_passwd, char* url_pattern, - char* local_pattern, int no_empty_referers ) + char* local_pattern, int no_empty_referers, + char* autoindex_prog) { httpd_server* hs; static char ghnbuf[256]; @@ -329,6 +332,7 @@ while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) (void) strcpy( cp + 1, cp + 2 ); } + hs->autoindex_prog = autoindex_prog ? strdup( autoindex_prog ) : 0; hs->charset = strdup( charset ); hs->cwd = strdup( cwd ); if ( hs->cwd == (char*) 0 ) @@ -825,10 +829,15 @@ void httpd_send_err_blocked( httpd_conn* hc ) { -#ifdef ERR_DIR + char *protocol = hc->protocol; +#ifdef ERR_DIR char filename[1000]; +#endif + hc->protocol = "HTTP/1.0"; + +#ifdef ERR_DIR /* Try virtual host error page. */ if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) { @@ -852,6 +861,7 @@ send_response( hc, 403, err403title, "", err403form, "" ); #endif /* ERR_DIR */ + hc->protocol = protocol; } #ifdef ERR_DIR @@ -1467,8 +1477,6 @@ restlen = strlen( path ); httpd_realloc_str( &rest, &maxrest, restlen ); (void) strcpy( rest, path ); - if ( rest[restlen - 1] == '/' ) - rest[--restlen] = '\0'; /* trim trailing slash */ if ( ! tildemapped ) /* Remove any leading slashes. */ while ( rest[0] == '/' ) @@ -1734,6 +1742,10 @@ hc->keep_alive = 0; hc->should_linger = 0; hc->file_address = (char*) 0; +#ifdef MMAP_MAX + hc->file_fd = -1; + hc->write_buf = (char*) 0; +#endif return GC_OK; } @@ -2384,6 +2396,18 @@ { make_log_entry( hc, nowP ); +#ifdef MMAP_MAX + if ( hc->file_fd >= 0) + { + (void) close( hc->file_fd ); + hc->file_fd = -1; + } + if ( hc->write_buf ) + { + (void) free (hc->write_buf); + hc->write_buf = 0; + } +#endif if ( hc->file_address != (char*) 0 ) { mmc_unmap( hc->file_address, &(hc->sb), nowP ); @@ -2792,7 +2816,7 @@ /* Parent process. */ closedir( dirp ); - syslog( LOG_INFO, "spawned indexing process %d for directory '%.200s'", r, hc->expnfilename ); + /*syslog( LOG_INFO, "spawned indexing process %d for directory '%.200s'", r, hc->expnfilename );*/ #ifdef CGI_TIMELIMIT /* Schedule a kill for the child process, in case it runs too long */ client_data.i = r; @@ -3158,7 +3182,7 @@ /* CGI child process. */ static void -cgi_child( httpd_conn* hc ) +cgi_child( httpd_conn* hc, char* exefilename ) { int r; char** argp; @@ -3310,20 +3334,25 @@ ** to the program's own directory. This isn't in the CGI 1.1 ** spec, but it's what other HTTP servers do. */ - directory = strdup( hc->expnfilename ); - if ( directory == (char*) 0 ) - binary = hc->expnfilename; /* ignore errors */ + if (exefilename) + binary = exefilename; else - { - binary = strrchr( directory, '/' ); - if ( binary == (char*) 0 ) - binary = hc->expnfilename; - else - { - *binary++ = '\0'; - (void) chdir( directory ); /* ignore errors */ - } - } + { + directory = strdup( exefilename ? exefilename : hc->expnfilename ); + if ( directory == (char*) 0 ) + binary = exefilename; /* ignore errors */ + else + { + binary = strrchr( directory, '/' ); + if ( binary == (char*) 0 ) + binary = exefilename; + else + { + *binary++ = '\0'; + (void) chdir( directory ); /* ignore errors */ + } + } + } /* Default behavior for SIGPIPE. */ (void) signal( SIGPIPE, SIG_DFL ); @@ -3339,7 +3368,7 @@ static off_t -cgi( httpd_conn* hc ) +cgi( httpd_conn* hc, char* exefilename ) { int r; ClientData client_data; @@ -3357,11 +3386,11 @@ if ( r == 0 ) { unlisten( hc->hs ); - cgi_child( hc ); + cgi_child( hc, exefilename ); } /* Parent process. */ - syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); + /*syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename );*/ #ifdef CGI_TIMELIMIT /* Schedule a kill for the child process, in case it runs too long */ client_data.i = r; @@ -3497,7 +3526,7 @@ if ( ! check_referer( hc ) ) return -1; /* Ok, generate an index. */ - return ls( hc ); + return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc ); #else /* GENERATE_INDEXES */ syslog( LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", @@ -3590,7 +3619,7 @@ if ( hc->hs->cgi_pattern != (char*) 0 && ( hc->sb.st_mode & S_IXOTH ) && match( hc->hs->cgi_pattern, hc->expnfilename ) ) - return cgi( hc ); + return cgi( hc, 0 ); /* It's not CGI. If it's executable or there's pathinfo, someone's ** trying to either serve or run a non-CGI file as CGI. Either case @@ -3642,11 +3671,22 @@ } else { - hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); +#ifdef MMAP_MAX + if ( hc->sb.st_size < MMAP_MAX) +#endif + hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); if ( hc->file_address == (char*) 0 ) { - httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); - return -1; +#ifdef MMAP_MAX + hc->file_fd = open ( hc->expnfilename, O_RDONLY); + hc->write_buf = malloc (WRITE_BUFFER); + hc->write_ofs = WRITE_BUFFER; + if ( hc->file_fd < 0 || !hc->write_buf ) +#endif + { + httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); + return -1; + } } send_mime( hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, @@ -3681,7 +3721,7 @@ return; /* don't log UNKNOWN protocol requests (blocks etc..) */ - if ( !strcmp (hc->protocol, "UNKNOWN") ) + if ( hc->method == METHOD_UNKNOWN ) return; /* This is straight CERN Combined Log Format - the only tweak