/** sol12.4.c
** ------------------------------------------------------------
A version of webserv that logs all requests and the
status of their replies is
sol12.4.c.
This program accepts the name of the logfile on the command line
(with the -l filename option) and uses O_APPEND so
it can write to the log safely. The program uses the fact
that accept() records the address of the client.
** ------------------------------------------------------------
**
**
* webserv with new feature: logs requests and outcome of each request
*
* details of log function
* a) Log is opened at start in O_APPEND mode to ensure that
* multiple children will not lose data to race conditions
* b) Each accept will record the ip address of the caller
* That address will be passed to the child.
* c) Each time a header is printed out, the webserver will
* add to the log the time, the caller's ip number,
* the request, and the first line of the header
* (note: this requires passing the callers ipaddr down to
* the request processing code)
*
* The method is to create a serverlog() object that stores
* data in static variables and then can be told to write out
* the information.
*
* webserv.c - a minimal web server (version 0.3)
* usage: ws portnumber [ -l logfile ]
* 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 sol12.4.c socklib.c -o sol12.4
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>
#include <ctype.h>
#include "socklib.h"
#define oops(s) { perror(s); exit(1);}
int server_log(int, void *);
int setup(int , char **);
void read_til_crnl(FILE *);
void process_rq( char *, int , struct in_addr );
void header( FILE *, char *);
void cannot_do(int );
void do_404(char *, int );
int isadir(char *);
int not_exist(char *);
void do_ls(char *, int );
char * file_type(char *);
int ends_in_cgi(char *);
void do_exec( char *, int);
void do_cat(char *, int );
int server_log(int , void *);
int logwrite(int , struct in_addr , char *, char *);
void safecpy(char *, char *, int );
/* -----------------------------------------------------
* logfile header material. Should be in serverlog.h
*/
#define LOGMODE 0600
#define SL_OPEN 0
#define SL_ADDR 1
#define SL_REQ 2
#define SL_REPLY 3
#define REPLY_MAX 10
#define REQUEST_MAX 2048 /* longest request allowed */
/* --- end of serverlog.h ------------ */
int main(int ac, char *av[])
{
int sock, fd;
FILE *fpin;
char request[BUFSIZ];
struct sockaddr_in clnt_addr;
int len;
sock = setup(ac, av);
/*
* setup - process command line arguments
*
* returns a socket for the server
* handles -l logfile opt
*
*/
/* main loop here */
while(1){
/* wait for a call */
len = sizeof(struct sockaddr);
fd = accept( sock, (struct sockaddr *) &clnt_addr, &len);
/*
* skip the EINTR returns from accept
*/
if ( fd == -1 && errno == EINTR )
continue;
if ( fd == -1 )
oops("accept");
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, clnt_addr.sin_addr);
fclose(fpin);
}
return 0;
}
int setup(int ac, char *av[])
{
int portnum = -1;
char *logfile = NULL;
int pos;
int sock;
/* parse */
for(pos=1; pos<ac; pos++)
{
if ( isdigit(av[pos][0]) )
portnum = atoi(av[pos]);
else if ( strcmp(av[pos], "-l") == 0 ){
if ( ++pos < ac )
logfile = av[pos];
else {
fprintf(stderr,"missing logfilename\n");
exit(1);
}
}
}
/* act: make socket, make log object */
if ( portnum == -1 ){
fprintf(stderr,"usage: ws portnum\n");
exit(1);
}
sock = make_server_socket( portnum );
if ( sock == -1 ) {
perror("socket");
exit(2);
}
if ( logfile )
server_log(SL_OPEN, logfile);
return sock;
}
/* ------------------------------------------------------ *
read_til_crnl(FILE *)
skip over all request info until a CRNL is seen
------------------------------------------------------ */
void 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, struct in_addr caller )
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
------------------------------------------------------ */
void process_rq( char *rq, int fd , struct in_addr caller)
{
char cmd[BUFSIZ], arg[BUFSIZ];
/* create a new process and return if not the child */
if ( fork() != 0 )
return;
/* add more data to the log entry */
server_log(SL_REQ, rq);
server_log(SL_ADDR, &caller);
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
------------------------------------------------------ */
void 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 );
server_log(SL_REPLY, "200");
}
/* ------------------------------------------------------ *
simple functions first:
cannot_do(fd) unimplemented HTTP command
and do_404(item,fd) no such object
------------------------------------------------------ */
void 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);
server_log(SL_REPLY, "501");
}
void 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);
server_log(SL_REPLY, "404");
}
/* ------------------------------------------------------ *
the directory listing section
isadir() uses stat, not_exist() uses stat
do_ls runs ls. It should not
------------------------------------------------------ */
int isadir(char *f)
{
struct stat info;
return ( stat(f, &info) != -1 && S_ISDIR(info.st_mode) );
}
int not_exist(char *f)
{
struct stat info;
return( stat(f,&info) == -1 );
}
void 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.
------------------------------------------------------ */
/* returns 'extension' of file */
char * file_type(char *f)
{
char *cp;
if ( (cp = strrchr(f, '.' )) != NULL )
return cp+1;
return "";
}
int ends_in_cgi(char *f)
{
return ( strcmp( file_type(f), "cgi" ) == 0 );
}
void do_exec( char *prog, int fd )
{
FILE *fp ;
fp = fdopen(fd,"w");
header(fp, NULL);
fflush(fp);
没有合适的资源?快使用搜索试试~ 我知道了~
unix-linux编程实践教程习题解答及代码.rar
共355个文件
c:273个
html:29个
h:23个
5星 · 超过95%的资源 需积分: 42 697 下载量 41 浏览量
2012-05-06
22:07:40
上传
评论 13
收藏 449KB RAR 举报
温馨提示
unix-linux编程实践教程习题解答及代码.rar 全书的源码及配套的习题详细解答。经典资料!
资源推荐
资源详情
资源评论
收起资源包目录
unix-linux编程实践教程习题解答及代码.rar (355个子文件)
sol12.4.c 11KB
sol12.5.c 9KB
dumpe2fs.c 9KB
sol14.11.c 9KB
sol12.8.c 8KB
sol12.7.c 8KB
sol13.17.c 8KB
sol11.17.c 7KB
sol11.16.c 7KB
sol13.14b.c 7KB
sol12.6.c 6KB
twebserv.c 6KB
sol09.13.c 6KB
sol15.9serv.c 6KB
lserv_funcs2.c 6KB
sol03.18.c 5KB
sol13.22s.c 5KB
sol14.18c.c 5KB
sol13.13.c 5KB
sol14.15.c 5KB
webserv.c 5KB
sol11.12.c 5KB
sol11.10.c 5KB
sol09.8b.c 5KB
sol03.19.c 5KB
lclnt_funcs2.c 5KB
lclnt_funcs2.c 5KB
sol03.14.c 5KB
sol15.10serv.c 5KB
sol14.16.c 5KB
sol14.14.c 5KB
varlib.c 5KB
varlib.c 5KB
varlib.c 5KB
sol05.22.c 5KB
sol14.9.c 4KB
sol11.6.c 4KB
sol08.12.c 4KB
sol03.12.c 4KB
sol02.13b.c 4KB
sol11.11.c 4KB
sol14.18s.c 4KB
lclnt_funcs1.c 4KB
sol03.15.c 4KB
sol11.8.c 4KB
sol11.13.c 4KB
sol11.14.c 4KB
lserv_funcs1.c 4KB
sol14.10.c 4KB
sol03.11.c 4KB
sol09.4.c 4KB
sol11.9.c 4KB
sol04.20.c 4KB
sol03.22.c 4KB
sol06.4b.c 4KB
sol06.11.c 4KB
sol03.10.c 4KB
sol15.9clnt.c 4KB
sol06.4a.c 3KB
sol06.6.c 3KB
ls2.c 3KB
sol09.7.c 3KB
sol02.10a.c 3KB
sol04.16.c 3KB
splitline.c 3KB
splitline.c 3KB
splitline.c 3KB
sol09.6.c 3KB
play_again4.c 3KB
tinybc.c 3KB
sol14.12.c 3KB
sol02.12.c 3KB
tanimate.c 3KB
sol05.25.c 3KB
sol09.5.c 3KB
rlsd.c 3KB
sol13.22c.c 3KB
sol03.13.c 3KB
shm_ts2.c 3KB
sol15.10clnt.c 3KB
sol07.13.c 3KB
sol10.15.c 3KB
sol07.9.c 3KB
play_again3.c 3KB
bounce_aio.c 3KB
sol07.15.c 3KB
sol15.11serv.c 3KB
socklib.c 3KB
sol08.10.c 3KB
sol06.3.c 3KB
sol13.20.c 3KB
sol11.18s.c 3KB
socklib.c 3KB
socklib.c 3KB
socklib.c 3KB
socklib.c 3KB
sol14.18disp.c 3KB
sol07.10.c 3KB
sol03.21.c 3KB
sol06.12.c 3KB
共 355 条
- 1
- 2
- 3
- 4
smallbear_2008
- 粉丝: 28
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页