⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libhttpd.c.bak

📁 修改后的thttp
💻 BAK
📖 第 1 页 / 共 5 页
字号:
	r = vfork( );#else	r = fork( );#endif	if ( r < 0 )	    {	    syslog( LOG_ERR, "fork - %m" );	    httpd_send_err( hc, 500, err500title, err500form, hc->encodedurl );	    return -1;	    }	if ( r == 0 )	    {	    /* Child process. */#ifdef CGI_NICE	    /* Set priority. */	    (void) nice( CGI_NICE );#endif /* CGI_NICE */	    /* Open a stdio stream so that we can use fprintf, which is more	    ** efficient than a bunch of separate write()s.  We don't have	    ** to worry about double closes or file descriptor leaks cause	    ** we're in a subprocess.	    */	    fp = fdopen( hc->conn_fd, "w" );	    if ( fp == (FILE*) 0 )		{		syslog( LOG_ERR, "fdopen - %m" );		httpd_send_err(		    hc, 500, err500title, err500form, hc->encodedurl );		closedir( dirp );		return -1;		}	    (void) fprintf( fp, "\<HTML><HEAD><TITLE>Index of %.80s</TITLE></HEAD>\n\<BODY>\n\<H2>Index of %.80s</H2>\n\<PRE>\n\mode  links  bytes  last-changed  name\n\<HR>",		hc->encodedurl, hc->encodedurl );	    /* Read in names. */	    nnames = 0;	    while ( ( de = readdir( dirp ) ) != 0 )	/* dirent or direct */		{		if ( nnames >= maxnames )		    {		    if ( maxnames == 0 )			{			maxnames = 100;			names = NEW( char, maxnames * MAXPATHLEN );			nameptrs = NEW( char*, maxnames );			}		    else			{			maxnames *= 2;			names = RENEW( names, char, maxnames * MAXPATHLEN );			nameptrs = RENEW( nameptrs, char*, maxnames );			}		    if ( names == (char*) 0  || nameptrs == (char**) 0 )			{			syslog( LOG_ERR, "out of memory" );			exit( 1 );			}		    for ( i = 0; i < maxnames; ++i )			nameptrs[i] = &names[i * MAXPATHLEN];		    }		namlen = NAMLEN(de);		(void) strncpy( nameptrs[nnames], de->d_name, namlen );		nameptrs[nnames][namlen] = '\0';		++nnames;		}	    closedir( dirp );	    /* Sort the names. */	    qsort( nameptrs, nnames, sizeof(*nameptrs), name_compare );	    /* Generate output. */	    for ( i = 0; i < nnames; ++i )		{		realloc_str(		    &name, &maxname,		    strlen( hc->expnfilename ) + 1 + strlen( nameptrs[i] ) );		realloc_str(		    &rname, &maxrname,		    strlen( hc->origfilename ) + 1 + strlen( nameptrs[i] ) );		if ( hc->expnfilename[0] == '\0' ||		     strcmp( hc->expnfilename, "." ) == 0 )		    {		    (void) strcpy( name, nameptrs[i] );		    (void) strcpy( rname, nameptrs[i] );		    }		else		    {		    (void) sprintf(			name, "%s/%s", hc->expnfilename, nameptrs[i] );		    (void) sprintf(			rname, "%s%s", hc->origfilename, nameptrs[i] );		    }		if ( stat( name, &sb ) < 0 || lstat( name, &lsb ) < 0 )		    continue;		linkprefix = "";		link[0] = '\0';		/* Break down mode word.  First the file type. */		switch ( lsb.st_mode & S_IFMT )		    {		    case S_IFIFO:  modestr[0] = 'p'; break;		    case S_IFCHR:  modestr[0] = 'c'; break;		    case S_IFDIR:  modestr[0] = 'd'; break;		    case S_IFBLK:  modestr[0] = 'b'; break;		    case S_IFREG:  modestr[0] = '-'; break;		    case S_IFSOCK: modestr[0] = 's'; break;		    case S_IFLNK:  modestr[0] = 'l';		    linklen = readlink( name, link, sizeof(link) );		    if ( linklen != -1 )			{			link[linklen] = '\0';			linkprefix = " -> ";			}		    break;		    default:       modestr[0] = '?'; break;		    }		/* Now the world permissions.  Owner and group permissions		** are not of interest to web clients.		*/		modestr[1] = ( lsb.st_mode & S_IROTH ) ? 'r' : '-';		modestr[2] = ( lsb.st_mode & S_IWOTH ) ? 'w' : '-';		modestr[3] = ( lsb.st_mode & S_IXOTH ) ? 'x' : '-';		modestr[4] = '\0';		/* We also leave out the owner and group name, they are		** also not of interest to web clients.  Plus if we're		** running under chroot(), they would require a copy		** of /etc/passwd and /etc/group, which we want to avoid.		*/		/* Get time string. */		now = time( (time_t*) 0 );		timestr = ctime( &lsb.st_mtime );		timestr[ 0] = timestr[ 4];		timestr[ 1] = timestr[ 5];		timestr[ 2] = timestr[ 6];		timestr[ 3] = ' ';		timestr[ 4] = timestr[ 8];		timestr[ 5] = timestr[ 9];		timestr[ 6] = ' ';		if ( now - lsb.st_mtime > 60*60*24*182 )	/* 1/2 year */		    {		    timestr[ 7] = ' ';		    timestr[ 8] = timestr[20];		    timestr[ 9] = timestr[21];		    timestr[10] = timestr[22];		    timestr[11] = timestr[23];		    }		else		    {		    timestr[ 7] = timestr[11];		    timestr[ 8] = timestr[12];		    timestr[ 9] = ':';		    timestr[10] = timestr[14];		    timestr[11] = timestr[15];		    }		timestr[12] = '\0';		/* The ls -F file class. */		switch ( sb.st_mode & S_IFMT )		    {		    case S_IFDIR:  fileclass = "/"; break;		    case S_IFSOCK: fileclass = "="; break;		    case S_IFLNK:  fileclass = "@"; break;		    default:		    fileclass = ( sb.st_mode & S_IXOTH ) ? "*" : "";		    break;		    }		/* And print. */		(void)  fprintf( fp,		   "%s %3ld  %8ld  %s  <A HREF=\"/%.500s%s\">%.80s</A>%s%s%s\n",		    modestr, (long) lsb.st_nlink, (long) lsb.st_size, timestr,		    rname, S_ISDIR(sb.st_mode) ? "/" : "", nameptrs[i],		    linkprefix, link, fileclass );		}	    (void) fprintf( fp, "</PRE></BODY></HTML>\n" );	    (void) fclose( fp );	    exit( 0 );	    }	/* Parent process. */	closedir( dirp );#ifdef CGI_TIMELIMIT	/* Schedule a kill for the child process, in case it runs too long */	client_data.i = r;	(void) tmr_create(	    (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L,	    0 );#endif /* CGI_TIMELIMIT */	hc->status = 200;	hc->bytes = CGI_BYTECOUNT;	}    else	{	httpd_send_err(	    hc, 501, err501title, err501form, httpd_method_str( hc->method ) );	return -1;	}    return 0;    }#endif /* GENERATE_INDEXES */static char*build_env( char* fmt, char* arg )    {    char* cp;    int size;    static char* buf;    static int maxbuf = 0;    size = strlen( fmt ) + strlen( arg );    if ( size > maxbuf )        realloc_str( &buf, &maxbuf, size );    (void) sprintf( buf, fmt, arg );    cp = strdup( buf );    if ( cp == (char*) 0 )        {        syslog( LOG_ERR, "out of memory" );        exit( 1 );        }    return cp;    }#ifdef SERVER_NAME_LISTstatic char*hostname_map( char* hostname )    {    int len, n;    static char* list[] = { SERVER_NAME_LIST };    len = strlen( hostname );    for ( n = sizeof(list) / sizeof(*list) - 1; n >= 0; --n )	if ( strncasecmp( hostname, list[n], len ) == 0 )	    if ( list[n][len] == '/' )	/* check in case of a substring match */		return &list[n][len + 1];    return (char*) 0;    }#endif /* SERVER_NAME_LIST *//* Set up environment variables. Be real careful here to avoid** letting malicious clients overrun a buffer.  We don't have** to worry about freeing stuff since we're a sub-process.*/static char**make_envp( httpd_conn* hc )    {    static char* envp[50];    int envn;    char* cp;    char buf[256];    envn = 0;    envp[envn++] = build_env( "PATH=%s", CGI_PATH );    envp[envn++] = build_env( "SERVER_SOFTWARE=%s", SERVER_SOFTWARE );    cp = hc->hs->hostname;#ifdef SERVER_NAME_LIST    if ( cp == (char*) 0 && gethostname( buf, sizeof(buf) ) >= 0 )	cp = hostname_map( buf );#endif /* SERVER_NAME_LIST */    if ( cp == (char*) 0 )	{#ifdef SERVER_NAME	cp = SERVER_NAME;#else /* SERVER_NAME */	if ( gethostname( buf, sizeof(buf) ) >= 0 )	    cp = buf;#endif /* SERVER_NAME */	}    if ( cp != (char*) 0 )	envp[envn++] = build_env( "SERVER_NAME=%s", cp );    envp[envn++] = "GATEWAY_INTERFACE=CGI/1.1";    envp[envn++] = build_env("SERVER_PROTOCOL=%s", hc->protocol);    (void) sprintf( buf, "%d", hc->hs->port );    envp[envn++] = build_env( "SERVER_PORT=%s", buf );    envp[envn++] = build_env(	"REQUEST_METHOD=%s", httpd_method_str( hc->method ) );    if ( hc->pathinfo[0] != '\0' )	{	char* cp2;	envp[envn++] = build_env( "PATH_INFO=/%s", hc->pathinfo );	cp2 = NEW( char, strlen( hc->hs->cwd ) + strlen( hc->pathinfo ) );	if ( cp2 != (char*) 0 )	    {	    (void) sprintf( cp2, "%s%s", hc->hs->cwd, hc->pathinfo );	    envp[envn++] = build_env( "PATH_TRANSLATED=%s", cp2 );	    }	}    envp[envn++] = build_env( "SCRIPT_NAME=/%s", hc->origfilename );    if ( hc->query[0] != '\0')	envp[envn++] = build_env( "QUERY_STRING=%s", hc->query );    envp[envn++] = build_env( "REMOTE_ADDR=%s", inet_ntoa( hc->client_addr ) );    if ( hc->referer[0] != '\0' )	envp[envn++] = build_env( "HTTP_REFERER=%s", hc->referer );    if ( hc->useragent[0] != '\0' )	envp[envn++] = build_env( "HTTP_USER_AGENT=%s", hc->useragent );    if ( hc->accept[0] != '\0' )	envp[envn++] = build_env( "HTTP_ACCEPT=%s", hc->accept );    if ( hc->accepte[0] != '\0' )	envp[envn++] = build_env( "HTTP_ACCEPT_ENCODING=%s", hc->accepte );    if ( hc->cookie[0] != '\0' )	envp[envn++] = build_env( "HTTP_COOKIE=%s", hc->cookie );    if ( hc->contenttype[0] != '\0' )	envp[envn++] = build_env( "CONTENT_TYPE=%s", hc->contenttype );    if ( hc->contentlength != -1 )	{	(void) sprintf( buf, "%ld", (long) hc->contentlength );	envp[envn++] = build_env( "CONTENT_LENGTH=%s", buf );	}    if ( hc->remoteuser[0] != '\0' )	envp[envn++] = build_env( "REMOTE_USER=%s", hc->remoteuser );    if ( getenv( "TZ" ) != (char*) 0 )	envp[envn++] = build_env( "TZ=%s", getenv( "TZ" ) );    envp[envn] = (char*) 0;    return envp;    }/* Set up argument vector.  Again, we don't have to worry about freeing stuff** since we're a sub-process.  This gets done after make_envp() because we** scribble on hc->query.*/static char**make_argp( httpd_conn* hc )    {    char** argp;    int argn;    char* cp1;    char* cp2;    /* By allocating an arg slot for every character in the query, plus    ** one for the filename and one for the NULL, we are guaranteed to    ** have enough.  We could actually use strlen/2.    */    argp = NEW( char*, strlen( hc->query ) + 2 );    if ( argp == (char**) 0 )	return (char**) 0;    argp[0] = strrchr( hc->expnfilename, '/' );    if ( argp[0] != (char*) 0 )	++argp[0];    else	argp[0] = hc->expnfilename;    argn = 1;    /* According to the CGI spec at http://hoohoo.ncsa.uiuc.edu/cgi/cl.html,    ** "The server should search the query information for a non-encoded =    ** character to determine if the command line is to be used, if it finds    ** one, the command line is not to be used."    */    if ( strchr( hc->query, '=' ) == (char*) 0 )	{	for ( cp1 = cp2 = hc->query; *cp2 != '\0'; ++cp2 )	    {	    if ( *cp2 == '+' )		{		*cp2 = '\0';		strdecode( cp1, cp1 );		argp[argn++] = cp1;		cp1 = cp2 + 1;		}	    }	if ( cp2 != cp1 )	    {	    strdecode( cp1, cp1 );	    argp[argn++] = cp1;	    }	}    argp[argn] = (char*) 0;    return argp;    }/* This routine is used only for POST requests.  It reads the data** from the request and sends it to the child process.  The only reason** we need to do it this way instead of just letting the child read** directly is that we have already read part of the data into our** buffer.*/static voidcgi_interpose( httpd_conn* hc, int wfd )    {    int c, r;    char buf[1024]; printf("CGI interpose\n");     c = hc->read_idx - hc->checked_idx;    if ( c > 0 )	{	if ( write( wfd, &(hc->read_buf[hc->checked_idx]), c ) < 0 )	    exit( -1 );	}    while ( c < hc->contentlength )	{	r = read( hc->conn_fd, buf, MIN( sizeof(buf), hc->contentlength - c ) );	if ( r == 0 )	    sleep( 1 );	else if ( r < 0 )	    {	    if ( errno == EAGAIN )		sleep( 1 );	    else		exit( -1 );	    }	else	    {	    if ( write( wfd, buf, r ) < 0 )		exit( -1 );	    c += r;	    }	}    exit( 0 );    }/* CGI child process. */static voidcgi_child( httpd_conn* hc )    {    int r;    char** argp;    char** envp;    char http_head[] = "HTTP/1.0 200 OK\n";    char* binary;    char* directory;    /* Set up stdin.  For POSTs we may have to set up a pipe from an    ** interposer process, depending on if we've read some of the data    ** into our buffer.    */printf("CGI child\n");    if ( hc->method == METHOD_POST && hc->read_idx > hc->checked_idx )	{	int p[2];	if ( pipe( p ) < 0 )	    {	    syslog( LOG_ERR, "pipe - %m" );	    httpd_send_err( hc, 500, err500title, err500form, hc->encodedurl );	    exit( 1 );	    }#ifdef EMBED	r = vfork( );#else	r = fork( );#endif	if ( r < 0 )	    {	    syslog( LOG_ERR, "fork - %m" );	    httpd_send_err( hc, 500, err500title, err500form, hc->encodedurl );	    exit( 1 );	    }	if ( r == 0 )	    {	    /* Interposer process. */	    (void) close( p[0] );	    cgi_interpose( hc, p[1] );	    }	(void) close( p[1] );	(void) dup2( p[0], STDIN_FILENO );	}    else	{	/* Otherwise, the request socket is stdin. */	(void) dup2( hc->conn_fd, STDIN_FILENO );	}    /* Unset close-on-exec flag for this socket.  This actually shouldn't    ** be necessary, according to POSIX a dup()'d file descriptor does    ** *not* inherit the close-on-exec flag, its flag is always clear.    ** However, Linux messes this up and does copy the flag to the    ** dup()'d descrip

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -