四川大学蓝色星空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: 蓝色☆空]
[回到开始]
[上一篇][下一篇]