http

来源:互联网 发布:openwrt 安装软件 编辑:程序博客网 时间:2024/05/21 12:08
#include <stdarg.h>#include <errno.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <errno.h>#include <netinet/in.h>#include <sys/socket.h>#include <resolv.h>#include <arpa/inet.h>#include <stdlib.h>#include <signal.h>#include <getopt.h>#define DEFAULTIP "127.0.0.1"#define DEFAULTPORT "80"#define DEFAULTBACK "10"#define DEFAULTDIR "/home"#define DEFAULTLOG "/tmp/das-server.log"void prterrmsg(char *msg);#define prterrmsg(msg)        { perror(msg); abort(); }void wrterrmsg(char *msg);#define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }void prtinfomsg(char *msg);#define prtinfomsg(msg)        { fputs(msg, stdout);  }void wrtinfomsg(char *msg);#define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}#define MAXBUF        1024char buffer[MAXBUF + 1];char *host = 0;char *port = 0;char *back = 0;char *dirroot = 0;char *logdir = 0;unsigned char daemon_y_n = 0;FILE *logfp;#define MAXPATH        150/*---------------------------------------- *--- dir_up - 查找dirpath所指目录的上一级目录*----------------------------------------*/char *dir_up(char *dirpath){    static char Path[MAXPATH];    int len;    strcpy(Path, dirpath);    len = strlen(Path);    if (len > 1 && Path[len - 1] == '/')        len--;    while (Path[len - 1] != '/' && len > 1)        len--;    Path[len] = 0;    return Path;}/*------------------------------------------------------ *--- AllocateMemory - 分配空间并把d所指的内容复制*------------------------------------------------------*/void AllocateMemory(char **s, int l, char *d){    *s = malloc(l + 1);    bzero(*s, l + 1);    memcpy(*s, d, l);}/************关于本文档*********************************************filename: das-server.c*purpose: 这是在Linux下用C语言写的目录访问服务器,支持目录浏览和文件下载*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言*date time:2007-01-26 19:32*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途* 但请遵循GPL*Thanks to: Google.com*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!*********************************************************************//*------------------------------------------------------*--- GiveResponse - 把Path所指的内容发送到client_sock去*-------------------如果Path是一个目录,则列出目录内容*-------------------如果Path是一个文件,则下载文件*------------------------------------------------------*/void GiveResponse(FILE * client_sock, char *Path){    struct dirent *dirent;    struct stat info;    char Filename[MAXPATH];    DIR *dir;    int fd, len, ret;    char *p, *realPath, *realFilename, *nport;    /* 获得实际工作目录或文件 */    len = strlen(dirroot) + strlen(Path) + 1;    realPath = malloc(len + 1);    bzero(realPath, len + 1);    sprintf(realPath, "%s/%s", dirroot, Path);    /* 获得实际工作端口 */    len = strlen(port) + 1;    nport = malloc(len + 1);    bzero(nport, len + 1);    sprintf(nport, ":%s", port);    /* 获得实际工作目录或文件的信息以判断是文件还是目录 */    if (stat(realPath, &info)) {        fprintf(client_sock,                "HTTP/1.1 200 OK\r\nServer: DAS by ZhouLifa\r\nConnection: close\r\n\r\n<html><head><title>%d - %s</title></head>"                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"                "<table border cols=3 width=\"100%%\">", errno,                strerror(errno));        fprintf(client_sock,                "</table><font color=\"CC0000\" size=+2>请向管理员咨询为何出现如下错误提示:\n%s %s</font></body></html>",                Path, strerror(errno));        goto out;    }    /* 处理浏览文件请求,即下载文件 */    if (S_ISREG(info.st_mode)) {        fd = open(realPath, O_RDONLY);        len = lseek(fd, 0, SEEK_END);        p = (char *) malloc(len + 1);        bzero(p, len + 1);        lseek(fd, 0, SEEK_SET);        ret = read(fd, p, len);        close(fd);        fprintf(client_sock,                "HTTP/1.1 200 OK\r\nServer: DAS by ZhouLifa\r\nConnection: keep-alive\r\nContent-type: application/*\r\nContent-Length:%d\r\n\r\n",                len);        fwrite(p, len, 1, client_sock);        free(p);    } else if (S_ISDIR(info.st_mode)) {        /* 处理浏览目录请求 */        dir = opendir(realPath);        fprintf(client_sock,                "HTTP/1.1 200 OK\r\nServer: DAS by ZhouLifa\r\nConnection: close\r\n\r\n<html><head><title>%s</title></head>"                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"                "<table border cols=3 width=\"100%%\">", Path);        fprintf(client_sock,                "<caption><font size=+3>目录 %s</font></caption>\n",                Path);        fprintf(client_sock,                "<tr><td>名称</td><td>大小</td><td>修改时间</td></tr>\n");        if (dir == 0) {            fprintf(client_sock,                    "</table><font color=\"CC0000\" size=+2>%s</font></body></html>",                    strerror(errno));            return;        }        /* 读取目录里的所有内容 */        while ((dirent = readdir(dir)) != 0) {            if (strcmp(Path, "/") == 0)                sprintf(Filename, "/%s", dirent->d_name);            else                sprintf(Filename, "%s/%s", Path, dirent->d_name);            fprintf(client_sock, "<tr>");            len = strlen(dirroot) + strlen(Filename) + 1;            realFilename = malloc(len + 1);            bzero(realFilename, len + 1);            sprintf(realFilename, "%s/%s", dirroot, Filename);            if (stat(realFilename, &info) == 0) {                if (strcmp(dirent->d_name, "..") == 0)                    fprintf(client_sock,                            "<td><a href=\"http://%s%s%s\">(parent)</a></td>",                            host, atoi(port) == 80 ? "" : nport,                            dir_up(Path));                else                    fprintf(client_sock,                            "<td><a href=\"http://%s%s%s\">%s</a></td>",                            host, atoi(port) == 80 ? "" : nport, Filename,                            dirent->d_name);                if (S_ISDIR(info.st_mode))                    fprintf(client_sock, "<td>目录</td>");                else if (S_ISREG(info.st_mode))                    fprintf(client_sock, "<td>%d</td>", info.st_size);                else if (S_ISLNK(info.st_mode))                    fprintf(client_sock, "<td>链接</td>");                else if (S_ISCHR(info.st_mode))                    fprintf(client_sock, "<td>字符设备</td>");                else if (S_ISBLK(info.st_mode))                    fprintf(client_sock, "<td>块设备</td>");                else if (S_ISFIFO(info.st_mode))                    fprintf(client_sock, "<td>FIFO</td>");                else if (S_ISSOCK(info.st_mode))                    fprintf(client_sock, "<td>Socket</td>");                else                    fprintf(client_sock, "<td>(未知)</td>");                fprintf(client_sock, "<td>%s</td>", ctime(&info.st_ctime));            }            fprintf(client_sock, "</tr>\n");            free(realFilename);        }        fprintf(client_sock, "</table></center></body></html>");    } else {        /* 既非常规文件又非目录,禁止访问 */        fprintf(client_sock,                "HTTP/1.1 200 OK\r\nServer: DAS by ZhouLifa\r\nConnection: close\r\n\r\n<html><head><title>permission denied</title></head>"                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=\"100%%\"><br><center>"                "<table border cols=3 width=\"100%%\">");        fprintf(client_sock,                "</table><font color=\"CC0000\" size=+2>你访问的资源'%s'被禁止访问,请联系管理员解决!</font></body></html>",                Path);    }  out:    free(realPath);    free(nport);}/*------------------------------------------------------ *--- getoption - 分析取出程序的参数*------------------------------------------------------*/void getoption(int argc, char **argv){    int c, len;    char *p = 0;    opterr = 0;    while (1) {        int option_index = 0;        static struct option long_options[] = {            {"host", 1, 0, 0},            {"port", 1, 0, 0},            {"back", 1, 0, 0},            {"dir", 1, 0, 0},            {"log", 1, 0, 0},            {"daemon", 0, 0, 0},            {0, 0, 0, 0}        };        /* 本程序支持如一些参数:         * --host IP地址 或者 -H IP地址         * --port 端口 或者 -P 端口         * --back 监听数量 或者 -B 监听数量         * --dir 网站根目录 或者 -D 网站根目录         * --log 日志存放路径 或者 -L 日志存放路径         * --daemon 使程序进入后台运行模式         */        c = getopt_long(argc, argv, "H:P:B:D:L",                        long_options, &option_index);        if (c == -1 || c == '?')            break;        if(optarg)        len = strlen(optarg);        else        len = 0;        if ((!c && !(strcasecmp(long_options[option_index].name, "host")))            || c == 'H')            p = host = malloc(len + 1);        else if ((!c                  &&                  !(strcasecmp(long_options[option_index].name, "port")))                 || c == 'P')            p = port = malloc(len + 1);        else if ((!c                  &&                  !(strcasecmp(long_options[option_index].name, "back")))                 || c == 'B')            p = back = malloc(len + 1);        else if ((!c                  && !(strcasecmp(long_options[option_index].name, "dir")))                 || c == 'D')            p = dirroot = malloc(len + 1);        else if ((!c                  && !(strcasecmp(long_options[option_index].name, "log")))                 || c == 'L')            p = logdir = malloc(len + 1);        else if ((!c                  &&                  !(strcasecmp                    (long_options[option_index].name, "daemon")))) {            daemon_y_n = 1;            continue;        }        else            break;        bzero(p, len + 1);        memcpy(p, optarg, len);    }}int main(int argc, char **argv){    struct sockaddr_in addr;    int sock_fd, addrlen;    /* 获得程序工作的参数,如 IP 、端口、监听数、网页根目录、目录存放位置等 */    getoption(argc, argv);    if (!host) {        addrlen = strlen(DEFAULTIP);        AllocateMemory(&host, addrlen, DEFAULTIP);    }    if (!port) {        addrlen = strlen(DEFAULTPORT);        AllocateMemory(&port, addrlen, DEFAULTPORT);    }    if (!back) {        addrlen = strlen(DEFAULTBACK);        AllocateMemory(&back, addrlen, DEFAULTBACK);    }    if (!dirroot) {        addrlen = strlen(DEFAULTDIR);        AllocateMemory(&dirroot, addrlen, DEFAULTDIR);    }    if (!logdir) {        addrlen = strlen(DEFAULTLOG);        AllocateMemory(&logdir, addrlen, DEFAULTLOG);    }    printf        ("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后台工作模式(进程ID:%d)\n",         host, port, back, dirroot, logdir, daemon_y_n?"":"不", getpid());    /* fork() 两次处于后台工作模式下 */    if (daemon_y_n) {        if (fork())            exit(0);        if (fork())            exit(0);        close(0), close(1), close(2);        logfp = fopen(logdir, "a+");        if (!logfp)            exit(0);    }    /* 处理子进程退出以免产生僵尸进程 */    signal(SIGCHLD, SIG_IGN);    /* 创建 socket */    if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {        if (!daemon_y_n) {            prterrmsg("socket()");        } else {            wrterrmsg("socket()");        }    }    /* 设置端口快速重用 */    addrlen = 1;    setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,               sizeof(addrlen));    addr.sin_family = AF_INET;    addr.sin_port = htons(atoi(port));    addr.sin_addr.s_addr = inet_addr(host);    addrlen = sizeof(struct sockaddr_in);    /* 绑定地址、端口等信息 */    if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0) {        if (!daemon_y_n) {            prterrmsg("bind()");        } else {            wrterrmsg("bind()");        }    }    /* 开启临听 */    if (listen(sock_fd, atoi(back)) < 0) {        if (!daemon_y_n) {            prterrmsg("listen()");        } else {            wrterrmsg("listen()");        }    }    while (1) {        int len;        int new_fd;        addrlen = sizeof(struct sockaddr_in);        /* 接受新连接请求 */        new_fd = accept(sock_fd, (struct sockaddr *) &addr, &addrlen);        if (new_fd < 0) {            if (!daemon_y_n) {                prterrmsg("accept()");            } else {                wrterrmsg("accept()");            }            break;        }        bzero(buffer, MAXBUF + 1);        sprintf(buffer, "连接来自于: %s:%d\n",                inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));        if (!daemon_y_n) {            prtinfomsg(buffer);        } else {            wrtinfomsg(buffer);        }        /* 产生一个子进程去处理请求,当前进程继续等待新的连接到来 */        if (!fork()) {            bzero(buffer, MAXBUF + 1);            if ((len = recv(new_fd, buffer, MAXBUF, 0)) > 0) {                FILE *ClientFP = fdopen(new_fd, "w");                if (ClientFP == NULL) {                    if (!daemon_y_n) {                        prterrmsg("fdopen()");                    } else {                        prterrmsg("fdopen()");                    }                } else {                    char Req[MAXPATH + 1] = "";                    sscanf(buffer, "GET %s HTTP", Req);                    bzero(buffer, MAXBUF + 1);                    sprintf(buffer, "请求取文件: \"%s\"\n", Req);                    if (!daemon_y_n) {                        prtinfomsg(buffer);                    } else {                        wrtinfomsg(buffer);                    }                    /* 处理用户请求 */                    GiveResponse(ClientFP, Req);                    fclose(ClientFP);                }            }            exit(0);        }        close(new_fd);    }    close(sock_fd);    return 0;}

原创粉丝点击