ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/thttpd/libhttpd.c
(Generate patch)

Comparing thttpd/libhttpd.c (file contents):
Revision 1.1.4.5 by root, Mon Jul 2 18:52:37 2001 UTC vs.
Revision 1.2 by root, Mon Jun 25 02:35:16 2001 UTC

155static char** make_envp( httpd_conn* hc ); 155static char** make_envp( httpd_conn* hc );
156static char** make_argp( httpd_conn* hc ); 156static char** make_argp( httpd_conn* hc );
157static void cgi_interpose_input( httpd_conn* hc, int wfd ); 157static void cgi_interpose_input( httpd_conn* hc, int wfd );
158static void post_post_garbage_hack( httpd_conn* hc ); 158static void post_post_garbage_hack( httpd_conn* hc );
159static void cgi_interpose_output( httpd_conn* hc, int rfd ); 159static void cgi_interpose_output( httpd_conn* hc, int rfd );
160static void cgi_child( httpd_conn* hc ); 160static void cgi_child( httpd_conn* hc, char* exefilename );
161static off_t cgi( httpd_conn* hc ); 161static off_t cgi( httpd_conn* hc, char* exefilename );
162static int really_start_request( httpd_conn* hc, struct timeval* nowP ); 162static int really_start_request( httpd_conn* hc, struct timeval* nowP );
163static void make_log_entry( httpd_conn* hc, struct timeval* nowP ); 163static void make_log_entry( httpd_conn* hc, struct timeval* nowP );
164static int check_referer( httpd_conn* hc ); 164static int check_referer( httpd_conn* hc );
165static int really_check_referer( httpd_conn* hc ); 165static int really_check_referer( httpd_conn* hc );
166static int sockaddr_check( httpd_sockaddr* saP ); 166static int sockaddr_check( httpd_sockaddr* saP );
238 { 238 {
239 if ( hs->binding_hostname != (char*) 0 ) 239 if ( hs->binding_hostname != (char*) 0 )
240 free( (void*) hs->binding_hostname ); 240 free( (void*) hs->binding_hostname );
241 if ( hs->cwd != (char*) 0 ) 241 if ( hs->cwd != (char*) 0 )
242 free( (void*) hs->cwd ); 242 free( (void*) hs->cwd );
243 if ( hs->autoindex_prog != (char*) 0 )
244 free( (void*) hs->autoindex_prog );
243 if ( hs->cgi_pattern != (char*) 0 ) 245 if ( hs->cgi_pattern != (char*) 0 )
244 free( (void*) hs->cgi_pattern ); 246 free( (void*) hs->cgi_pattern );
245 if ( hs->charset != (char*) 0 ) 247 if ( hs->charset != (char*) 0 )
246 free( (void*) hs->charset ); 248 free( (void*) hs->charset );
247 if ( hs->url_pattern != (char*) 0 ) 249 if ( hs->url_pattern != (char*) 0 )
255httpd_server* 257httpd_server*
256httpd_initialize( 258httpd_initialize(
257 char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, 259 char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port,
258 char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, 260 char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp,
259 int no_symlink, int vhost, int global_passwd, char* url_pattern, 261 int no_symlink, int vhost, int global_passwd, char* url_pattern,
260 char* local_pattern, int no_empty_referers ) 262 char* local_pattern, int no_empty_referers,
263 char* autoindex_prog)
261 { 264 {
262 httpd_server* hs; 265 httpd_server* hs;
263 static char ghnbuf[256]; 266 static char ghnbuf[256];
264 char* cp; 267 char* cp;
265 268
327 } 330 }
328 /* Nuke any leading slashes in the cgi pattern. */ 331 /* Nuke any leading slashes in the cgi pattern. */
329 while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) 332 while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 )
330 (void) strcpy( cp + 1, cp + 2 ); 333 (void) strcpy( cp + 1, cp + 2 );
331 } 334 }
335 hs->autoindex_prog = autoindex_prog ? strdup( autoindex_prog ) : 0;
332 hs->charset = strdup( charset ); 336 hs->charset = strdup( charset );
333 hs->cwd = strdup( cwd ); 337 hs->cwd = strdup( cwd );
334 if ( hs->cwd == (char*) 0 ) 338 if ( hs->cwd == (char*) 0 )
335 { 339 {
336 syslog( LOG_CRIT, "out of memory copying cwd" ); 340 syslog( LOG_CRIT, "out of memory copying cwd" );
823 } 827 }
824 828
825void 829void
826httpd_send_err_blocked( httpd_conn* hc ) 830httpd_send_err_blocked( httpd_conn* hc )
827 { 831 {
828 char *protocol = hc->protocol;
829
830#ifdef ERR_DIR 832#ifdef ERR_DIR
833
831 char filename[1000]; 834 char filename[1000];
832#endif
833 835
834 hc->protocol = "HTTP/1.0";
835
836#ifdef ERR_DIR
837 /* Try virtual host error page. */ 836 /* Try virtual host error page. */
838 if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) 837 if ( hc->hs->vhost && hc->hostdir[0] != '\0' )
839 { 838 {
840 (void) my_snprintf( filename, sizeof(filename), 839 (void) my_snprintf( filename, sizeof(filename),
841 "%s/%s/err403blocked.html", hc->hostdir, ERR_DIR ); 840 "%s/%s/err403blocked.html", hc->hostdir, ERR_DIR );
843 return; 842 return;
844 } 843 }
845 844
846 /* Try server-wide error page. */ 845 /* Try server-wide error page. */
847 (void) my_snprintf( filename, sizeof(filename), 846 (void) my_snprintf( filename, sizeof(filename),
848 "%s/err403blocked.html", ERR_DIR ); 847 "%s/errerr403blocked.html", ERR_DIR );
849 if ( send_err_file( hc, 403, err403title, "", filename ) ) 848 if ( send_err_file( hc, 403, err403title, "", filename ) )
850 return; 849 return;
851 850
852 /* Fall back on built-in error page. */ 851 /* Fall back on built-in error page. */
853 send_response( hc, 403, err403title, "", err403form, "" ); 852 send_response( hc, 403, err403title, "", err403form, "" );
855#else /* ERR_DIR */ 854#else /* ERR_DIR */
856 855
857 send_response( hc, 403, err403title, "", err403form, "" ); 856 send_response( hc, 403, err403title, "", err403form, "" );
858 857
859#endif /* ERR_DIR */ 858#endif /* ERR_DIR */
860 hc->protocol = protocol;
861 } 859 }
862 860
863#ifdef ERR_DIR 861#ifdef ERR_DIR
864static int 862static int
865send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename ) 863send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename )
1471 checked[0] = '\0'; 1469 checked[0] = '\0';
1472 checkedlen = 0; 1470 checkedlen = 0;
1473 restlen = strlen( path ); 1471 restlen = strlen( path );
1474 httpd_realloc_str( &rest, &maxrest, restlen ); 1472 httpd_realloc_str( &rest, &maxrest, restlen );
1475 (void) strcpy( rest, path ); 1473 (void) strcpy( rest, path );
1476 if ( rest[restlen - 1] == '/' )
1477 rest[--restlen] = '\0'; /* trim trailing slash */
1478 if ( ! tildemapped ) 1474 if ( ! tildemapped )
1479 /* Remove any leading slashes. */ 1475 /* Remove any leading slashes. */
1480 while ( rest[0] == '/' ) 1476 while ( rest[0] == '/' )
1481 { 1477 {
1482 (void) strcpy( rest, &(rest[1]) ); 1478 (void) strcpy( rest, &(rest[1]) );
1738 hc->init_byte_loc = 0; 1734 hc->init_byte_loc = 0;
1739 hc->end_byte_loc = -1; 1735 hc->end_byte_loc = -1;
1740 hc->keep_alive = 0; 1736 hc->keep_alive = 0;
1741 hc->should_linger = 0; 1737 hc->should_linger = 0;
1742 hc->file_address = (char*) 0; 1738 hc->file_address = (char*) 0;
1739#ifdef MMAP_MAX
1740 hc->file_fd = -1;
1741 hc->write_buf = (char*) 0;
1742#endif
1743 return GC_OK; 1743 return GC_OK;
1744 } 1744 }
1745 1745
1746 1746
1747/* Checks hc->read_buf to see whether a complete request has been read so far; 1747/* Checks hc->read_buf to see whether a complete request has been read so far;
2388void 2388void
2389httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) 2389httpd_close_conn( httpd_conn* hc, struct timeval* nowP )
2390 { 2390 {
2391 make_log_entry( hc, nowP ); 2391 make_log_entry( hc, nowP );
2392 2392
2393#ifdef MMAP_MAX
2394 if ( hc->file_fd >= 0)
2395 {
2396 (void) close( hc->file_fd );
2397 hc->file_fd = -1;
2398 }
2399 if ( hc->write_buf )
2400 (void) free (hc->write_buf);
2401#endif
2393 if ( hc->file_address != (char*) 0 ) 2402 if ( hc->file_address != (char*) 0 )
2394 { 2403 {
2395 mmc_unmap( hc->file_address, &(hc->sb), nowP ); 2404 mmc_unmap( hc->file_address, &(hc->sb), nowP );
2396 hc->file_address = (char*) 0; 2405 hc->file_address = (char*) 0;
2397 } 2406 }
3162 } 3171 }
3163 3172
3164 3173
3165/* CGI child process. */ 3174/* CGI child process. */
3166static void 3175static void
3167cgi_child( httpd_conn* hc ) 3176cgi_child( httpd_conn* hc, char* exefilename )
3168 { 3177 {
3169 int r; 3178 int r;
3170 char** argp; 3179 char** argp;
3171 char** envp; 3180 char** envp;
3172 char* binary; 3181 char* binary;
3314 3323
3315 /* Split the program into directory and binary, so we can chdir() 3324 /* Split the program into directory and binary, so we can chdir()
3316 ** to the program's own directory. This isn't in the CGI 1.1 3325 ** to the program's own directory. This isn't in the CGI 1.1
3317 ** spec, but it's what other HTTP servers do. 3326 ** spec, but it's what other HTTP servers do.
3318 */ 3327 */
3319 directory = strdup( hc->expnfilename ); 3328 if (exefilename)
3320 if ( directory == (char*) 0 ) 3329 binary = exefilename;
3321 binary = hc->expnfilename; /* ignore errors */
3322 else 3330 else
3323 { 3331 {
3332 directory = strdup( exefilename ? exefilename : hc->expnfilename );
3333 if ( directory == (char*) 0 )
3334 binary = exefilename; /* ignore errors */
3335 else
3336 {
3324 binary = strrchr( directory, '/' ); 3337 binary = strrchr( directory, '/' );
3325 if ( binary == (char*) 0 ) 3338 if ( binary == (char*) 0 )
3326 binary = hc->expnfilename; 3339 binary = exefilename;
3327 else 3340 else
3328 { 3341 {
3329 *binary++ = '\0'; 3342 *binary++ = '\0';
3330 (void) chdir( directory ); /* ignore errors */ 3343 (void) chdir( directory ); /* ignore errors */
3344 }
3345 }
3331 } 3346 }
3332 }
3333 3347
3334 /* Default behavior for SIGPIPE. */ 3348 /* Default behavior for SIGPIPE. */
3335 (void) signal( SIGPIPE, SIG_DFL ); 3349 (void) signal( SIGPIPE, SIG_DFL );
3336 3350
3337 /* Run the program. */ 3351 /* Run the program. */
3343 exit( 1 ); 3357 exit( 1 );
3344 } 3358 }
3345 3359
3346 3360
3347static off_t 3361static off_t
3348cgi( httpd_conn* hc ) 3362cgi( httpd_conn* hc, char* exefilename )
3349 { 3363 {
3350 int r; 3364 int r;
3351 ClientData client_data; 3365 ClientData client_data;
3352 3366
3353 if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) 3367 if ( hc->method == METHOD_GET || hc->method == METHOD_POST )
3361 return -1; 3375 return -1;
3362 } 3376 }
3363 if ( r == 0 ) 3377 if ( r == 0 )
3364 { 3378 {
3365 unlisten( hc->hs ); 3379 unlisten( hc->hs );
3366 cgi_child( hc ); 3380 cgi_child( hc, exefilename );
3367 } 3381 }
3368 3382
3369 /* Parent process. */ 3383 /* Parent process. */
3370 syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); 3384 syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename );
3371#ifdef CGI_TIMELIMIT 3385#ifdef CGI_TIMELIMIT
3501#endif /* AUTH_FILE */ 3515#endif /* AUTH_FILE */
3502 /* Referer check. */ 3516 /* Referer check. */
3503 if ( ! check_referer( hc ) ) 3517 if ( ! check_referer( hc ) )
3504 return -1; 3518 return -1;
3505 /* Ok, generate an index. */ 3519 /* Ok, generate an index. */
3506 return ls( hc ); 3520 return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc );
3507#else /* GENERATE_INDEXES */ 3521#else /* GENERATE_INDEXES */
3508 syslog( 3522 syslog(
3509 LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", 3523 LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory",
3510 httpd_ntoa( &hc->client_addr ), hc->encodedurl ); 3524 httpd_ntoa( &hc->client_addr ), hc->encodedurl );
3511 httpd_send_err( 3525 httpd_send_err(
3594 3608
3595 /* Is it world-executable and in the CGI area? */ 3609 /* Is it world-executable and in the CGI area? */
3596 if ( hc->hs->cgi_pattern != (char*) 0 && 3610 if ( hc->hs->cgi_pattern != (char*) 0 &&
3597 ( hc->sb.st_mode & S_IXOTH ) && 3611 ( hc->sb.st_mode & S_IXOTH ) &&
3598 match( hc->hs->cgi_pattern, hc->expnfilename ) ) 3612 match( hc->hs->cgi_pattern, hc->expnfilename ) )
3599 return cgi( hc ); 3613 return cgi( hc, 0 );
3600 3614
3601 /* It's not CGI. If it's executable or there's pathinfo, someone's 3615 /* It's not CGI. If it's executable or there's pathinfo, someone's
3602 ** trying to either serve or run a non-CGI file as CGI. Either case 3616 ** trying to either serve or run a non-CGI file as CGI. Either case
3603 ** is prohibited. 3617 ** is prohibited.
3604 */ 3618 */
3646 hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, 3660 hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size,
3647 hc->sb.st_mtime ); 3661 hc->sb.st_mtime );
3648 } 3662 }
3649 else 3663 else
3650 { 3664 {
3665#ifdef MMAP_MAX
3666 if ( hc->sb.st_size < MMAP_MAX)
3667#endif
3651 hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); 3668 hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP );
3652 if ( hc->file_address == (char*) 0 ) 3669 if ( hc->file_address == (char*) 0 )
3653 { 3670 {
3671#ifdef MMAP_MAX
3672 hc->file_fd = open ( hc->expnfilename, O_RDONLY);
3673 hc->write_buf = malloc (WRITE_BUFFER);
3674 hc->write_ofs = WRITE_BUFFER;
3675 if ( hc->file_fd < 0 || !hc->write_buf )
3676#endif
3677 {
3654 httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); 3678 httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
3655 return -1; 3679 return -1;
3680 }
3656 } 3681 }
3657 send_mime( 3682 send_mime(
3658 hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, 3683 hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size,
3659 hc->sb.st_mtime ); 3684 hc->sb.st_mtime );
3660 } 3685 }
3683 char url[305]; 3708 char url[305];
3684 char bytes[40]; 3709 char bytes[40];
3685 3710
3686 if ( hc->hs->no_log ) 3711 if ( hc->hs->no_log )
3687 return; 3712 return;
3688
3689 /* don't log UNKNOWN protocol requests (blocks etc..) */
3690 if ( !strcmp (hc->protocol, "UNKNOWN") )
3691 return;
3692 3713
3693 /* This is straight CERN Combined Log Format - the only tweak 3714 /* This is straight CERN Combined Log Format - the only tweak
3694 ** being that if we're using syslog() we leave out the date, because 3715 ** being that if we're using syslog() we leave out the date, because
3695 ** syslogd puts it in. The included syslogtocern script turns the 3716 ** syslogd puts it in. The included syslogtocern script turns the
3696 ** results into true CERN format. 3717 ** results into true CERN format.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines