四川大学蓝色星空BBS论坛

四川大学bbs,蓝色星空,四川大学吧,四川大学蓝色星空,蓝色星空bbs,川大蓝色星空bbs,四川大学蓝色星空站,蓝色星空四川大学,川大bbs

[回到开始] [上一篇][下一篇]


发信人: seawolf (暗黑), 信区: SCU_CS
标  题: 最小化web server代码
发信站: BBS 蓝色星空站 (Mon Dec 18 13:35:55 2006), 站内

代码很少, 但是足以演示web服务器的实现

webserv.c

/*******************/

/* webserv.c - a minimal web server (version 0.2)
 *      usage: ws portnumber
 *   features: supports the GET command only
 *             runs in the current directory
 *             forks a new child to handle each request
 *             has MAJOR security holes, for demo purposes only
 *             has many other weaknesses, but is a good start
 *      build: cc webserv.c socklib.c -o webserv
 */
#include    <stdio.h>
#include    <sys/types.h>
#include    <sys/stat.h>
#include    <string.h>

main(int ac, char *av[])
{
    int     sock, fd;
    FILE    *fpin;
    char    request[BUFSIZ];

    if ( ac == 1 ){
        fprintf(stderr,"usage: ws portnum\n");
        exit(1);
    }
    sock = make_server_socket( atoi(av[1]) );
    if ( sock == -1 ) exit(2);

    /* main loop here */

    while(1){
        /* take a call and buffer it */
        fd = accept( sock, NULL, NULL );
        fpin = fdopen(fd, "r" );

        /* read request */
        fgets(request,BUFSIZ,fpin);
        printf("got a call: request = %s", request);
        read_til_crnl(fpin);

        /* do what client asks */
        process_rq(request, fd);

        fclose(fpin);
    }
}

/* ------------------------------------------------------ *
   read_til_crnl(FILE *)
   skip over all request info until a CRNL is seen
   ------------------------------------------------------ */

read_til_crnl(FILE *fp)
{
    char    buf[BUFSIZ];
    while( fgets(buf,BUFSIZ,fp) != NULL && strcmp(buf,"\r\n") != 0 )
        ;
}

/* ------------------------------------------------------ *
   process_rq( char *rq, int fd )
   do what the request asks for and write reply to fd
   handles request in a new process
   rq is HTTP command:  GET /foo/bar.html HTTP/1.0
   ------------------------------------------------------ */

process_rq( char *rq, int fd )
{
    char    cmd[BUFSIZ], arg[BUFSIZ];

    /* create a new process and return if not the child */
    if ( fork() != 0 )
        return;

    strcpy(arg, "./");        /* precede args with ./ */
    if ( sscanf(rq, "%s%s", cmd, arg+2) != 2 )
        return;

    if ( strcmp(cmd,"GET") != 0 )
        cannot_do(fd);
    else if ( not_exist( arg ) )
        do_404(arg, fd );
    else if ( isadir( arg ) )
        do_ls( arg, fd );
    else if ( ends_in_cgi( arg ) )
        do_exec( arg, fd );
    else
        do_cat( arg, fd );
}

/* ------------------------------------------------------ *
   the reply header thing: all functions need one
   if content_type is NULL then don't send content type
   ------------------------------------------------------ */

header( FILE *fp, char *content_type )
{
    fprintf(fp, "HTTP/1.0 200 OK\r\n");
    if ( content_type )
        fprintf(fp, "Content-type: %s\r\n", content_type );
}

/* ------------------------------------------------------ *
   simple functions first:
        cannot_do(fd)       unimplemented HTTP command
    and do_404(item,fd)     no such object
   ------------------------------------------------------ */

cannot_do(int fd)
{
    FILE    *fp = fdopen(fd,"w");

    fprintf(fp, "HTTP/1.0 501 Not Implemented\r\n");
    fprintf(fp, "Content-type: text/plain\r\n");
    fprintf(fp, "\r\n");

    fprintf(fp, "That command is not yet implemented\r\n");
    fclose(fp);
}

do_404(char *item, int fd)
{
    FILE    *fp = fdopen(fd,"w");

    fprintf(fp, "HTTP/1.0 404 Not Found\r\n");
    fprintf(fp, "Content-type: text/plain\r\n");
    fprintf(fp, "\r\n");

    fprintf(fp, "The item you requested: %s\r\nis not found\r\n",
            item);
    fclose(fp);
}

/* ------------------------------------------------------ *
   the directory listing section
   isadir() uses stat, not_exist() uses stat
   do_ls runs ls. It should not
   ------------------------------------------------------ */

isadir(char *f)
{
    struct stat info;
    return ( stat(f, &info) != -1 && S_ISDIR(info.st_mode) );
}

not_exist(char *f)
{
    struct stat info;
    return( stat(f,&info) == -1 );
}

do_ls(char *dir, int fd)
{
    FILE    *fp ;

    fp = fdopen(fd,"w");
    header(fp, "text/plain");
    fprintf(fp,"\r\n");
    fflush(fp);

    dup2(fd,1);
    dup2(fd,2);
    close(fd);
    execlp("ls","ls","-l",dir,NULL);
    perror(dir);
    exit(1);
}

/* ------------------------------------------------------ *
   the cgi stuff.  function to check extension and
   one to run the program.
   ------------------------------------------------------ */

char * file_type(char *f)
/* returns 'extension' of file */
{
    char    *cp;
    if ( (cp = strrchr(f, '.' )) != NULL )
        return cp+1;
    return "";
}

ends_in_cgi(char *f)
{
    return ( strcmp( file_type(f), "cgi" ) == 0 );
}

do_exec( char *prog, int fd )
{
    FILE    *fp ;

    fp = fdopen(fd,"w");
    header(fp, NULL);
    fflush(fp);
    dup2(fd, 1);
    dup2(fd, 2);
    close(fd);
    execl(prog,prog,NULL);
    perror(prog);
}
/* ------------------------------------------------------ *
   do_cat(filename,fd)
   sends back contents after a header
   ------------------------------------------------------ */

do_cat(char *f, int fd)
{
    char    *extension = file_type(f);
    char    *content = "text/plain";
    FILE    *fpsock, *fpfile;
    int    c;

    if ( strcmp(extension,"html") == 0 )
        content = "text/html";
    else if ( strcmp(extension, "gif") == 0 )
        content = "image/gif";
    else if ( strcmp(extension, "jpg") == 0 )
        content = "image/jpeg";
    else if ( strcmp(extension, "jpeg") == 0 )
        content = "image/jpeg";

    fpsock = fdopen(fd, "w");
    fpfile = fopen( f , "r");
    if ( fpsock != NULL && fpfile != NULL )
    {
        header( fpsock, content );
        fprintf(fpsock, "\r\n");
        while( (c = getc(fpfile) ) != EOF )
            putc(c, fpsock);
        fclose(fpfile);
        fclose(fpsock);
    }
    exit(0);
}

--

此ID仅用于 蓝色星空 BBS 灌水!

                           星空灌水猪


※ 来源:·四川大学蓝色星空站 http://lsxk.org·[FROM: 蓝色☆空]


[回到开始] [上一篇][下一篇]

szuonline.cn 今天是 2024/04/20
深大在线 荔园在线 荔园晨风 荔园晨风BBS 荔园晨风bbs站 深大bbs 深圳大学bbs 深圳大学论坛 深圳大学内部网 szu bbs 荔园晨风地址 荔园晨风校外地址 荔园晨风登陆地址 荔园晨风登录地址 荔园晨风怎么登录 荔园晨风怎么登陆 深圳大学荔园晨风 荔园晨风登录不了吗 深大荔园晨风关了吗 荔园晨风官网 荔园晨风无法校外登陆 荔园晨风bbs登录不了 梨园晨风
Life doesn't just happen to you; you receive everything in your life based on what you've given.