/* wwwserv.c */ /* WWW server program for UNIX, with original expantions */ /* This source is to be compiled by gcc. */ /* John Kohji Suguiyama 杉山 光児 mailto:johnkoji@ylw.mmtr.or.jp http://www.ylw.mmtr.or.jp/~johnkoji/ */ #include #include #include #include #include #include #include #include #include #include #include #include #include void ErrExit( char *x ) { fputs("server- ", stderr ) ; perror( x ) ; exit(1) ; } void Err( char *x ) { fputs("server- ", stderr ) ; perror( x ) ; } /* You need to change these directory names to existing ones. */ #define SERV_DIR "/home/user/www/server" #define CGI_DIR "/home/user/www/cgi" #define WWW_DIR "/home/user/www/html" #define DIR_COUNT "/home/user/www/counter" #define C_BUF_SIZE 1024 #define L_BUF_SIZE 128 #define MSG_BUF_SIZE 4096 #define POST_BUFS 1024 /* Max POST size = C_BUF_SIZE * POST_BUFS */ #define MIME_FILE "mimetype.txt" #define MIME_DEFAULT "Content-type: text/plain\n" #define MIME_HTML "Content-type: text/html\n" int mimetype( char *type, char *ext ) { char buf[L_BUF_SIZE] ; char *tp, *ep ; FILE *fp ; if( ext == NULL || ext-1 == NULL ) { strcpy( type, MIME_DEFAULT ) ; return 0 ; } sprintf( buf,"%s/%s", SERV_DIR, MIME_FILE ) ; if( (fp = fopen( buf,"rt"))== NULL ) { type[0] = '\0' ; return -1 ; } while( fgets( buf, L_BUF_SIZE, fp )!= NULL ) { tp = strtok( buf," \n\t\r") ; while( (ep = strtok( NULL," \n\t\r"))!= NULL ) if( strcmp( ep, ext )== 0 ) { sprintf( type,"Content-type: %s\n", tp ) ; fclose( fp ) ; return 1 ; } } fclose( fp ) ; strcpy( type, MIME_DEFAULT ) ; return 0 ; } /* From the IP address like "130.54.54.213" in 4-byte chars 'sin_addr', get domain name string like "www.kyoto-u.ac.jp", by 'nslookup' command */ #define STR_HOST "host name = " #define SOCKET_DNS "dnscache.soc" int nslookup( char *host, u_char *ip ) { int j, soc_id ; struct sockaddr socket_name ; char line_buf[128], tmp_fn[24], tmp_in[24], *cp ; FILE *fp ; if( (soc_id = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { Err("socket"); goto nocache ; } bzero( (char *)&socket_name, sizeof( struct sockaddr ) ) ; socket_name.sa_family = PF_INET ; strcpy( socket_name.sa_data, SOCKET_DNS ) ; if( connect( soc_id, &socket_name, sizeof( struct sockaddr ) )!= 0 ) { Err("connect") ; close( soc_id ) ; goto nocache ; } if( write( soc_id, ip, 4 )== 4 && read( soc_id, host, 48 ) > 0 ) j = 0 ; else j = -1 ; close( soc_id ) ; return j ; nocache: host[0] = '\0' ; /* Default: No domain name */ sprintf( tmp_in,"nslookup%04x.tmp", getpid() ) ; if( (fp = fopen( tmp_in,"wt"))== NULL ) return -2 ; fprintf( fp,"set q=PTR\n%u.%u.%u.%u.in-addr.arpa\nexit\n", ip[3], ip[2], ip[1], ip[0] ) ; fclose( fp ) ; sprintf( tmp_fn,"dnscache%04x.tmp", getpid() ) ; sprintf( line_buf,"nslookup < %s > %s", tmp_in, tmp_fn ) ; system( line_buf ) ; remove( tmp_in ) ; if( (fp = fopen( tmp_fn,"rt"))== NULL ) return -2 ; while( fgets( line_buf, 128, fp )!= NULL ) { if( (cp = strstr( line_buf, STR_HOST ))!= NULL && sscanf( cp + strlen(STR_HOST),"%s", host )==1 ) { fclose( fp ) ; remove( tmp_fn ) ; return 0 ; /* OK */ } } fclose( fp ) ; remove( tmp_fn ) ; return -1 ; /* can't find domain name */ } /* stdin format realname=&e_mail=&url=http%3A%2F%2F&comment=This+is+Japan. */ void decode( char *str ) { int i, j, c ; char buf[MSG_BUF_SIZE], code_buf[6] ; for( i=0, j=0 ; str[i]!='\0' && iWWW Server Test\n\n" #define DEFAULT_MSG "

WWW Server Test

\n\n" #define DEFAULT_FILE "default.html" #define ROBOTS_FILE "robots.txt" #define DEFAULT_ROBOTS "\nUser-Agent: *\nDisallow: /~bbs/\nDisallow: /~cgi/\nDisallow: /~info/\nDisallow: /~www/buttons/\n\n" #define LOG_FILE "wwwserv.log" /* Data file name to record access number */ #define FILE_COUNT "count.dat" #define SOCKET_COUNT "countsrv.soc" /* Max file size = 4KB, max records = 128 */ #define DATA_BUF_SIZE 32 #define DATA_NUM 128 #define MAX_WORD_LEN 15 /* Find "keyword" from data file, return the number, and add 1 */ /* If "keyword" doesn't exist, return 0 and record "1" */ unsigned long guest_count( char *keyword ) { unsigned long count = 0L, l ; int i = 0, j, wl ; char buf[DATA_NUM][DATA_BUF_SIZE], word[MAX_WORD_LEN+1],data_row[DATA_BUF_SIZE] ; FILE *f ; /* "keyword" length <= MAX_WORD_LEN */ strncpy( word, keyword, MAX_WORD_LEN ) ; word[MAX_WORD_LEN] = '\0'; wl = strlen( word ) ; /* Open data file and find "keyword", read the record */ if( (f = fopen( FILE_COUNT,"rt")) != NULL ) { while( i= 1048576 ) { l = guest_count("logfile") ; sprintf( tmp_fn,"wwws%04lu.log", l ) ; rename( LOG_FILE, tmp_fn ) ; } } exit(0) ; } void www_err( int soc_id, char *errmsg ) { char c_buf[C_BUF_SIZE] ; int fd, bytes = 0 ; chdir( SERV_DIR ) ; if( errmsg != NULL ) bytes = strlen( errmsg ) ; write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, MIME_HTML, strlen(MIME_HTML) ) ; if( (fd = open( DEFAULT_FILE, O_RDONLY )) >= 0 ) header_stat( soc_id, fd, strlen(DEFAULT_TITLE)+bytes ) ; write( soc_id, DEFAULT_TITLE, strlen(DEFAULT_TITLE) ) ; if( errmsg != NULL ) write( soc_id, errmsg, bytes ) ; if( fd < 0 ) write( soc_id, DEFAULT_MSG, strlen(DEFAULT_MSG) ) ; else { while( (bytes = read( fd, c_buf, C_BUF_SIZE )) > 0 ) write( soc_id, c_buf, bytes ) ; close( fd ) ; } } void wwwserv( int soc_id, u_char *ip ) { char c_buf[C_BUF_SIZE], req[C_BUF_SIZE], fn_buf[C_BUF_SIZE] ; char req_b[C_BUF_SIZE], ref[C_BUF_SIZE], agent[C_BUF_SIZE], z[C_BUF_SIZE] ; char *env_agent, *env_ref, *env_addr, *env_req ; char tmp_fn[24], tmp_po[24], time_str[20], host[80], com[C_BUF_SIZE] ; char *rp, *fnp, *ext, *cp ; int i, n, fd = -1, bytes, pid ; u_long l ; FILE *fp, *tmpf ; time_t timer ; struct tm *t_unit ; struct stat stat_file ; fd_set bmask ; struct timeval { long tv_sec; long tv_usec; } tv ; timer = time( NULL ) ; pid = getpid() ; if( (fp = fdopen( soc_id,"rt"))== NULL ) { close( soc_id ) ; exit(2) ; } FD_ZERO( &bmask ) ; FD_SET( soc_id, &bmask ) ; tv.tv_sec = 600 ; tv.tv_usec = 0 ; /* 10 min. */ if( select( soc_id+1, &bmask, NULL, NULL, &tv )<= 0 ) /* Time out */ { fclose( fp ) ; exit(3) ; } if( fgets( req, C_BUF_SIZE, fp )== NULL ) /* Request */ { fclose( fp ) ; exit(2) ; } strcpy( req_b, req ) ; rp = strtok( req," ") ; fnp = strtok( NULL," \n\r") ; decode( fnp ) ; ref[0] = agent[0] = '-' ; ref[1] = agent[1] = '\0' ; strcpy( z,"\n") ; while( fgets( c_buf, C_BUF_SIZE, fp )!= NULL && strlen( c_buf ) > 2 ){ #ifdef REQ_HEADER fputs( c_buf, stdout ) ; #endif ext = strtok( c_buf," \n\r") ; if( strcmp(ext,"User-Agent:")==0 && (ext=strtok(NULL,"\n\r"))!=NULL ) { strcpy( agent, ext ) ; sprintf( fn_buf, "HTTP_USER_AGENT=%s", ext ) ; if( (env_agent = strdup( fn_buf ))!= NULL ) putenv( env_agent ) ; } else if( strcmp(ext,"Referer:")==0 && (ext=strtok(NULL,"\n\r"))!=NULL ) { strcpy( ref, ext ) ; sprintf( fn_buf, "HTTP_REFERER=%s", ext ) ; if( (env_ref = strdup( fn_buf ))!= NULL ) putenv( env_ref ) ; } else if( strcmp(ext,"Host:")==0 && (ext=strtok(NULL,"\n\r"))!=NULL ) strcpy( host, ext ) ; #ifdef CONTENT_LENGTH else if( strcmp(ext,"Content-length:")==0 && (ext=strtok(NULL,"\n\r"))!=NULL ) sscanf( ext,"%d", &cont_len ) ; #endif } sprintf( fn_buf, "REMOTE_ADDR=%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3] ) ; if( (env_addr = strdup( fn_buf ))!= NULL ) putenv( env_addr ) ; sprintf( fn_buf, "REQUEST_METHOD=%s", rp ) ; if( (env_req = strdup( fn_buf ))!= NULL ) putenv( env_req ) ; /* Branches for each function */ if( strncmp( fnp, "/~www/", 6 )== 0 ) /* Send WWW file */ { if( strcmp( rp,"GET")== 0 || strcmp( rp,"HEAD")== 0 ) { fnp += 5 ; sprintf( fn_buf,"%s%s", WWW_DIR, fnp ) ; if( fn_buf[strlen(fn_buf)-1] == '/') /* Directory */ { strcat( fn_buf,"index.html") ; if( (fd = open( fn_buf, O_RDONLY )) < 0 ) { ext = strrchr( fn_buf,'/') ; /* Not exist index.html */ *ext = '\0' ; sprintf( tmp_fn,"WWW_ls%04x.tmp", pid ) ; sprintf( com,"ls -lF %s > %s", fn_buf, tmp_fn ) ; /* Debug */ sprintf( z,"Dir: %s\n", com ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; system( com ) ; if( (tmpf = fopen( tmp_fn,"rt"))== NULL || fgets( c_buf, C_BUF_SIZE, tmpf )== NULL || strstr( c_buf,"not found")!= NULL ) { sprintf( c_buf,"Directory Error: %s
\n", fnp ) ; www_err( soc_id, c_buf ) ; remove( tmp_fn ) ; goto end ; } /* Output directory list as HTML */ write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, MIME_HTML, strlen( MIME_HTML ) ) ; write( soc_id,"\n", strlen("\n") ) ; if( strcmp( rp,"HEAD")== 0 ) { remove( tmp_fn ) ; goto end ; } sprintf( fn_buf,"Index of %s\n", fnp ) ; write( soc_id, fn_buf, strlen( fn_buf ) ) ; sprintf( fn_buf,"

Index of %s

\n",fnp );
					write( soc_id, fn_buf, strlen( fn_buf ) ) ;
					strcpy( fn_buf,"Parent directory\n") ;
					write( soc_id, fn_buf, strlen( fn_buf ) ) ;
					while( fgets( c_buf, C_BUF_SIZE, tmpf )!= NULL )
					{	if( (ext = strrchr( c_buf,'\n')) != NULL )
							*ext = '\0' ;
						ext = strrchr( c_buf,' ') ;
						*ext = '\0' ;
						ext ++ ;
						bytes = strlen( ext ) - 1 ;
						if( ext[bytes] == '*')
							ext[bytes] = '\0' ;
						sprintf( fn_buf,"%s %s\n", c_buf, ext, ext ) ;
						write( soc_id, fn_buf, strlen( fn_buf ) ) ;
					}
					strcpy( c_buf,"
\n") ; write( soc_id, c_buf, strlen( c_buf ) ) ; fclose( tmpf ) ; remove( tmp_fn ) ; goto end ; } /* End of directory */ /* else : "index.html" is open as 'fd' */ } else /* Not Directory : Open file normally */ { if( (fd = open( fn_buf, O_RDONLY )) < 0 ) { sprintf( z,"File Not Found: %s\n", fnp ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; sprintf( c_buf,"Not Found: %s
\n", fnp ) ; www_err( soc_id, c_buf ) ; goto end ; } } if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; ext = strrchr( fn_buf,'.') ; if( mimetype( c_buf, ext+1 ) < 0 ) { close( fd ) ; www_err( soc_id, "Server MIME type Error
\n" ) ; goto end ; } /* Output file */ write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; header_stat( soc_id, fd, 0 ) ; write( soc_id,"\n", strlen("\n") ) ; if( strcmp( rp,"GET")== 0 ) while( (bytes = read( fd, c_buf, C_BUF_SIZE )) > 0 ) write( soc_id, c_buf, bytes ) ; close( fd ) ; } /* End of "GET /~www/" */ else /* /~www/", not GET: Request method error */ { strcpy( z,"WWW: Request Method Error!\n") ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; www_err( soc_id, NULL ) ; } } /* End of "/~www/" function */ else if( strncmp( fnp,"/~cgi/", 6 )== 0 ) /* CGI program */ { if( chdir( CGI_DIR ) != 0 ) /* CGI directory */ { sprintf( z,"CGI - Can\'t chdir: %s\n", CGI_DIR ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; sprintf( c_buf,"CGI - Can\'t chdir: %s
\n", CGI_DIR ) ; www_err( soc_id, c_buf ) ; goto end ; } cp = fnp + 6 ; if( (ext = strchr( cp,'?'))!= NULL ) { *ext = '\0' ; ext ++ ; /* Command argument */ } else ext = "" ; if( (fnp = strrchr( cp,'/'))== NULL ) /* CGI directory */ fnp = cp ; else { *fnp = '\0'; fnp ++ ; } sprintf( fn_buf,"%s/%s", CGI_DIR, fnp ) ; if( (fd = open( fn_buf, O_RDONLY )) < 0 ) /* CGI file exist? */ { sprintf( z,"CGI - Not found: %s\n", fnp ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; sprintf( c_buf,"CGI - Not found: %s
\n", fnp ) ; www_err( soc_id, c_buf ) ; goto end ; } else close( fd ) ; if( fnp != cp ) /* Send header first */ { if( mimetype( c_buf, cp ) < 0 ) { close( fd ) ; sprintf( z,"MIME Type Error: %s\n", cp ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; sprintf( c_buf,"Server MIME type Error: %s
\n", cp ) ; www_err( soc_id, c_buf ) ; goto end ; } write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; write( soc_id,"\n", strlen("\n") ) ; } sprintf( tmp_fn,"WWW_cgi%04x.tmp", pid ) ; /* GET CGI */ if( strcmp( rp,"GET")== 0 ) { sprintf( com,"%s \"%s\" > %s", fnp, ext, tmp_fn ) ; sprintf( z,"CGI: %s\n", com ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; system( com ) ; } /* End of "GET /~cgi/" */ /* POST CGI */ else if( strcmp( rp,"POST")== 0 ) { sprintf( tmp_po,"WWW_post%04x.tmp", pid ) ; /* POST > temporary file */ if( (tmpf = fopen( tmp_po,"wt"))== NULL ) { sprintf( z,"CGI - POST buffer error: %s\n", tmp_po ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; sprintf(c_buf,"CGI - POST buffer error: %s %s
\n",fnp,ext); www_err( soc_id, c_buf ) ; goto end ; } for( bytes=0 ; bytes out */ sprintf( com,"%s \"%s\" < %s > %s", fnp, ext, tmp_po, tmp_fn ) ; sprintf( z,"CGI: %s\n", com ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; system( com ) ; remove( tmp_po ) ; } /* End of "POST /~cgi/" */ else /* /~cgi/ type: not GET or POST */ { strcpy( z,"CGI: Request Method Error!\n") ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; www_err( soc_id, NULL ) ; } if( ( n = fork() )== 0 ) { sleep( 3600 ) ; remove( tmp_fn ) ; exit(0) ; } /* temporary file > client */ if( (fd = open( tmp_fn, O_RDONLY )) < 0 ) { sprintf( c_buf,"CGI - execution error: %s %s
\n",fnp,ext ); www_err( soc_id, c_buf ) ; goto end ; } if( fnp == cp ) /* Send header after execution */ { write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; header_stat( soc_id, fd, -strlen( MIME_HTML ) ) ; } while( (bytes = read( fd, c_buf, C_BUF_SIZE )) > 0 ) write( soc_id, c_buf, bytes ) ; close( fd ) ; remove( tmp_fn ) ; sprintf( com,"kill %d", n ) ; system( com ) ; } /* End of "/~cgi/" function */ else if( strncmp( fnp,"/~info/", 6 )== 0 ) /* Information */ { strcpy( z,"Info: \n") ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; if( nslookup( fn_buf, ip )!= 0 ) strcpy( fn_buf,"-") ; t_unit = localtime( &timer ) ; strftime( time_str, 20,"%D-%T", t_unit ) ; write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, MIME_HTML, strlen( MIME_HTML ) ) ; write( soc_id,"\n", strlen("\n") ) ; strcpy( c_buf,"Information about your WWW client(browser)\n

Information about your WWW client(browser)

\n
") ; write( soc_id, c_buf, strlen( c_buf ) ) ; sprintf( c_buf,"
Client Address\n
%s [%u.%u.%u.%u]\n", fn_buf, ip[0], ip[1], ip[2], ip[3] ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; sprintf( c_buf,"
Access time (at Japanese standard time)\n
%s\n", time_str ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; sprintf( c_buf,"
Type of your browser\n
%s\n", agent ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; sprintf( c_buf,"
URL Address of this page\n
http://%s%s\n", host, fnp ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; sprintf( c_buf,"
Refered from\n
%s\n", ref ) ; write( soc_id, c_buf, strlen( c_buf ) ) ; strcpy( c_buf,"
\n Back to server root \n\n") ; write( soc_id, c_buf, strlen( c_buf ) ) ; } /* End of "/~info/" function */ else if( strncmp( fnp,"/robots", 7 )== 0 ) /* robots.txt */ { sprintf( z,"File: %s\n", ROBOTS_FILE ) ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; write( soc_id, DEFAULT_HEADER, strlen(DEFAULT_HEADER) ) ; write( soc_id, MIME_DEFAULT, strlen( MIME_DEFAULT ) ) ; if( (fd = open( ROBOTS_FILE, O_RDONLY )) < 0 ) { write( soc_id, DEFAULT_ROBOTS, strlen(DEFAULT_ROBOTS) ) ; goto end ; } header_stat( soc_id, fd, 0 ) ; write( soc_id,"\n", strlen("\n") ) ; while( (bytes = read( fd, c_buf, C_BUF_SIZE )) > 0 ) write( soc_id, c_buf, bytes ) ; close( fd ) ; } /* End of "/~robots/" function */ else /* Function: Unknown, not www or cgi */ { strcpy( z,"Error: Default HTML\n") ; if( fork()== 0 ) write_log( ip, pid, timer, req_b, ref, agent, z ) ; www_err( soc_id, NULL ) ; } end: fclose( fp ) ; exit( 0 ) ; } #define TMP_FILE_KILL "WWW_kill.tmp" #define LOG_FILE_KILL "kill_www.log" void kill_ghost( time_t t ) { int i, n, n_pid, n_start, log=0 ; char l_buf[L_BUF_SIZE], command[L_BUF_SIZE], time_str[20] ; char *cp, *pid, *t_start ; FILE *f, *f_log ; struct tm *t_unit ; sleep( 60 ) ; sprintf( command,"ps ux > %s", TMP_FILE_KILL ) ; system( command ) ; if( (f = fopen( TMP_FILE_KILL,"rt"))== NULL ) return ; if( (f_log = fopen( LOG_FILE_KILL,"at"))!= NULL ) { log = 1 ; t_unit = localtime( &t ) ; strftime( time_str, 20,"%D-%T\n", t_unit ) ; fputs( time_str, f_log ) ; } if( fgets( l_buf, L_BUF_SIZE, f )== NULL ) { fclose( f ) ; remove( TMP_FILE_KILL ) ; return ; } for( i=0 ; (cp = strtok( i==0 ? l_buf : NULL," \t\n\r"))!= NULL ; i++ ) { if( strncmp("PID", cp, 3 )== 0 ) n_pid = i ; else if( strncmp("START", cp, 5 )== 0 ) n_start = i ; } n = i ; while( fgets( l_buf, L_BUF_SIZE, f )!= NULL ) { if( strstr( l_buf,"wwwserv")== NULL ) continue ; pid = "" ; t_start = "00:00" ; for( i=0 ; i 1 && sscanf( argv[1],"%d", &i )== 1 ) port = i ; else port = WWW_PORT ; if( chdir( SERV_DIR )!= 0 ) { fprintf( stderr,"Can\'t chdir \'%s\'.\n", SERV_DIR ) ; return -1 ; } if( (soc_id = socket( PF_INET, SOCK_STREAM, 0 )) < 0 ) { Err("socket") ; return -1 ; } if( gethostname( hname, sizeof(hname) ) < 0 ) { Err("gethostname") ; return -1 ; } if( (shost = gethostbyname( hname ))== NULL ) { Err("gethostbyname") ; return -1 ; } bzero( (char *)&sv_addr, sizeof(sv_addr) ) ; sv_addr.sin_family = PF_INET ; sv_addr.sin_port = htons( port ) ; memcpy((char *)&sv_addr.sin_addr, (char *)shost->h_addr, shost->h_length ); if( bind( soc_id, &sv_addr, sizeof(sv_addr) ) < 0 ) { Err("bind") ; return -1 ; } if( listen( soc_id, 5 ) < 0 ) { Err("listen") ; return -1 ; } time_prev = time( NULL ) ; while( 1 ) { j = sizeof(cl_addr) ; if( (soc_ac = accept( soc_id, &cl_addr, &j )) < 0 ) { Err("accept") ; return -1 ; } if( fork() != 0 ) { close( soc_id ) ; cl_ip = (u_char *)&cl_addr.sin_addr ; /* Client IP address */ wwwserv( soc_ac, cl_ip ) ; exit(0) ; } close( soc_ac ) ; time_now = time( NULL ) ; if( time_now - time_prev > KILL_TIME ) { if( fork() != 0 ) { kill_ghost( time_now ) ; exit(0) ; } else time_prev = time_now ; } } return 0 ; }