www.pudn.com > telnet.rar > telnetserver.c, change:2013-01-28,size:10787b


#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>    
#include <pthread.h>    
   
#include "pty_fun.h"    
   
#define DEFAULTIP         "127.0.0.1"    
#define DEFAULTPORT       "20013"    
#define DEFAULTBACK       "10"    
#define DEFAULTDIR        "/root"    
#define DEFAULTLOG        "/tmp/telnet-server.log"    
#define PTY_NAME_SIZE     20    
#define MAX_BUFSIZE       512    
   
typedef struct _thread_arg 
{ 
	int pty; 
	int sockfd; 
}thread_arg; 
 
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        1024    
  
char 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    
   
/*------------------------------------------------------  
 *--- AllocateMemory - 分配空间并把d所指的内容复制  
 *------------------------------------------------------  
 */   
void AllocateMemory(char **s, int l, char *d)   
{   
    *s = malloc(l + 1);   
    bzero(*s, l + 1);   
    memcpy(*s, d, l);   
}   
   
/*------------------------------------------------------  
 *--- 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);   
    }   
}   
   
void *thread_recv_add_write_pyt(void *arg)   
{   
    int ret, sockfd, pty;   
    char buffer[MAX_BUFSIZE];   
    thread_arg *arg1 = (thread_arg*) arg;   
   
    sockfd = arg1->sockfd;   
    pty = arg1->pty;   
   
    while (1)   
    {   
        memset(buffer, 0, MAX_BUFSIZE);   
        ret = recv(sockfd, buffer, MAX_BUFSIZE, 0);   
        if (ret < 0)   
        {   
           continue;   
        }   
        printf("%s", buffer);   
        write(pty, buffer, strlen(buffer));   
    }   
}   
   
void read_write_pty(int pty, int sockfd)   
{   
    char buffer[MAX_BUFSIZE];   
    int ret;   
    //  pthread_t thread_t;    
    //  pthread_attr_t attr;    
    //  thread_arg arg;    
    //  arg.pty = pty;    
    //  arg.sockfd = sockfd;    
    //    
    //  if ((ret = pthread_create(&thread_t, &attr, thread_recv_add_write_pyt,    
    //          (void*) &arg)))    
    //  {    
    //      perror("thread create recieve message and write to pty err:\n");    
    //  }    
   
    pid_t pid;   
    if ((pid = fork()) < 0)   
    {   
        perror("");   
        exit(1);   
    }   
    else if (pid == 0)   
    {   
        while (1)   
        {   
            memset(buffer, 0, MAX_BUFSIZE);   
            ret = recv(sockfd, buffer, MAX_BUFSIZE - 1, 0);   
            if (ret < 0)   
            {   
                continue;   
            }   
            //printf("%s", buffer);    
            write(pty, buffer, strlen(buffer));   
        }   
    }   
   
    memset(buffer, 0, MAX_BUFSIZE);   
   
    while (ret = read(pty, buffer, MAX_BUFSIZE - 1))   
	    {   
        buffer[ret - 1] = 0; //read是读不到字符串结束符的,需要自己添加,否则printf会出错    
        if (ret <= 0)   
        {   
            break;   
        }   
        fflush(stdout);//这步很重要,std中经常有数据滞留在存储区中需要此函数刷新    
        printf("%s", buffer);//打印出结果    
        send(sockfd, buffer, strlen(buffer), 0);   
        memset(buffer, 0, MAX_BUFSIZE);   
    }   
   return;   
}   
   
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);   
    }   
   
    /* 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;   
   
    addr.sin_family = AF_INET;   
    addr.sin_port = htons(atoi(port));   
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   
    addrlen = sizeof(struct sockaddr_in);   
   
    setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen, sizeof(addrlen));   
    /* 绑定地址、端口等信息 */   
    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()");   
        }   
    }   
   
    printf("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后台工作模式(进程ID:%d)\n",   
            host, port, back, dirroot, logdir, daemon_y_n ? "" : "不", getpid());   
   
    while (1)   
    {   
        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())   
        {   
            int ret, ptrfdm;   
            char slave_name[PTY_NAME_SIZE];   
            struct termios slave_termiors;   
            struct winsize slave_winsize;   
            pid_t ppid;   
   
            ret = -1;   
            ptrfdm = -1;   
            memset(slave_name, 0, PTY_NAME_SIZE);   
            ppid = -1;   
  
           ret = pty_fork(&ptrfdm, slave_name, PTY_NAME_SIZE, &slave_termiors,   
                    &slave_winsize, &ppid);   
   
            if (ret < 0)   
            {   
                printf("pty_fork err ! ret = %d", ret);   
                return -1;   
            }   
   
            if (ppid < 0)   
            {   
                printf("pty_fork err !");   
                return -1;   
            }   
            else if (ppid == 0)   
            {   
                execl("/bin/bash", "bash", NULL);   
            }   
            else   
            {   
                read_write_pty(ptrfdm, new_fd);   
   
            }   
        }   
        close(new_fd);   
    }   
    close(sock_fd);   
    return 0;   
}