Linux伪终端 telnet源码


pty_fun.cpp 

  1. #include "pty_fun.h"   
  2.   
  3. int ptym_open(char *pts_name, int pts_namesz)  
  4. {  
  5.     char *ptr;  
  6.     char fdm;  
  7.     /* 
  8.      *return the name of the master device so that on failure 
  9.      *the caller can print an error message. Null terminate to 
  10.      *handle case where string lenth > pts_namesz 
  11.      * */  
  12.   
  13.     strncpy(pts_name, "/dev/ptmx", pts_namesz);  
  14.     pts_name[pts_namesz - 1] = '\0';  
  15.   
  16.     fdm = posix_openpt(O_RDWR);  
  17.     if (fdm < 0)  
  18.         return OPEN_PTY_ERR;  
  19.     if (grantpt(fdm) < 0)  
  20.     {  
  21.         close(fdm);  
  22.         return GRANT_PTY_ERR;  
  23.     }  
  24.     if (unlockpt(fdm) < 0)  
  25.     {  
  26.         close(fdm);  
  27.         return UNLOCK_PTY_ERR;  
  28.     }  
  29.     if ((ptr = ptsname(fdm)) == NULL)  
  30.     {  
  31.         close(fdm);  
  32.         return GET_PTYS_NAME_ERR;  
  33.     }  
  34.     strncpy(pts_name, ptr, pts_namesz);  
  35.     pts_name[pts_namesz - 1] = '\0';  
  36.   
  37.     return fdm;  
  38.   
  39. }  
  40.   
  41. int ptys_open(char *pts_name)  
  42. {  
  43.     int fds;  
  44.     if ((fds = open(pts_name, O_RDWR)) < 0)  
  45.         return OPEN_PTYS_ERR;  
  46.     return fds;  
  47. }  
  48.   
  49. int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,  
  50.         const struct termios *slave_termiors,  
  51.         const struct winsize *slave_winsize, pid_t *ppid)  
  52. {  
  53.     int fdm, fds;  
  54.     pid_t pid;  
  55.     char pts_name[20];  
  56.   
  57.     if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0)  
  58.     {  
  59.         return fdm;  
  60.     }  
  61.   
  62.     if (slave_name != NULL)  
  63.     {  
  64.         strncpy(slave_name, pts_name, slave_namesz);  
  65.         slave_name[slave_namesz - 1] = '\0';  
  66.     }  
  67.   
  68.     if ((pid = fork()) < 0)  
  69.     {  
  70.         return FORK_ERR;  
  71.     }  
  72.     else if (pid == 0)  
  73.     {  
  74.         if (setsid() < 0)  
  75.         {  
  76.             return SETSID_ERR;  
  77.         }  
  78.         if ((fds = ptys_open(pts_name)) < 0)  
  79.         {  
  80.             close(fdm);  
  81.             return OPEN_PTYS_ERR;  
  82.         }  
  83. #ifdef TIOCSCTTY   
  84.         if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0)  
  85.             return TIOCSCTTY_ERR;  
  86. #endif   
  87. //      if (slave_termiors != NULL)   
  88. //      {   
  89. //          if (tcsetattr(fds, TCSANOW, slave_termiors) < 0)   
  90. //              return INIT_ATTR_ERR;   
  91. //      }   
  92. //      if (slave_winsize != NULL)   
  93. //      {   
  94. //          if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)   
  95. //              return INIT_ATTR_ERR;   
  96. //      }   
  97.   
  98.         if (dup2(fds, STDIN_FILENO) != STDIN_FILENO)  
  99.             return DUP_STDIN_ERR;  
  100.         if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)  
  101.             return DUP_STDOUT_ERR;  
  102.         if (dup2(fds, STDERR_FILENO) != STDERR_FILENO)  
  103.             return DUP_STDERR_ERR;  
  104.         if (fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO)  
  105.         {  
  106.             close(fds);  
  107.         }  
  108.         *ppid = 0;  
  109.         return 0;  
  110.   
  111.     }  
  112.     else  
  113.     {  
  114.         *ptrfdm =fdm;  
  115.         *ppid = pid;  
  116.         return 0;  
  117.     }  
  118. }  

pty_fun.h

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <string.h>   
  4. #include <unistd.h>   
  5. #include <sys/types.h>   
  6. #include <linux/limits.h>   
  7. #include <features.h>   
  8. #include <termios.h>   
  9. #include <sys/ioctl.h>   
  10. #include <fcntl.h>   
  11.   
  12. //master pty   
  13. #ifndef OPEN_PTY_ERR   
  14. #define OPEN_PTY_ERR -1   
  15. #endif   
  16.   
  17. #ifndef GRANT_PTY_ERR   
  18. #define GRANT_PTY_ERR -2   
  19. #endif   
  20.   
  21. #ifndef UNLOCK_PTY_ERR   
  22. #define UNLOCK_PTY_ERR -3   
  23. #endif   
  24.   
  25. #ifndef GET_PTYS_NAME_ERR   
  26. #define GET_PTYS_NAME_ERR -4   
  27. #endif   
  28.   
  29. //pty slave   
  30. #ifndef OPEN_PTYS_ERR   
  31. #define OPEN_PTYS_ERR -5   
  32. #endif   
  33.   
  34. #ifndef FORK_ERR   
  35. #define FORK_ERR -6   
  36. #endif   
  37.   
  38. #ifndef SETSID_ERR   
  39. #define SETSID_ERR -7   
  40. #endif   
  41.   
  42. #ifndef TIOCSCTTY_ERR   
  43. #define TIOCSCTTY_ERR -8   
  44. #endif   
  45.   
  46. #ifndef INIT_ATTR_ERR   
  47. #define INIT_ATTR_ERR -9   
  48. #endif   
  49.   
  50. #ifndef DUP_STDIN_ERR   
  51. #define DUP_STDIN_ERR -10   
  52. #endif   
  53.   
  54. #ifndef DUP_STDOUT_ERR   
  55. #define DUP_STDOUT_ERR -11   
  56. #endif   
  57.   
  58. #ifndef DUP_STDERR_ERR   
  59. #define DUP_STDERR_ERR -12   
  60. #endif   
  61.   
  62.   
  63.   
  64.   
  65. int ptym_open(char *pts_name, int pts_namesz);  
  66.   
  67. int ptys_open(char *pts_name);  
  68.   
  69. int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,  
  70.         const struct termios *slave_termiors,  
  71.         const struct winsize *slave_winsize, pid_t *ppid);  

telnetserver.cpp

  1. #include <stdarg.h>   
  2. #include <errno.h>   
  3. #include <stdio.h>   
  4. #include <fcntl.h>   
  5. #include <unistd.h>   
  6. #include <string.h>   
  7. #include <time.h>   
  8. #include <sys/types.h>   
  9. #include <sys/stat.h>   
  10. #include <dirent.h>   
  11. #include <errno.h>   
  12. #include <netinet/in.h>   
  13. #include <sys/socket.h>   
  14. #include <resolv.h>   
  15. #include <arpa/inet.h>   
  16. #include <stdlib.h>   
  17. #include <signal.h>   
  18. #include <getopt.h>   
  19. #include <pthread.h>   
  20.   
  21. #include "pty_fun.h"   
  22.   
  23. #define DEFAULTIP         "127.0.0.1"   
  24. #define DEFAULTPORT       "20013"   
  25. #define DEFAULTBACK       "10"   
  26. #define DEFAULTDIR        "/root"   
  27. #define DEFAULTLOG        "/tmp/telnet-server.log"   
  28. #define PTY_NAME_SIZE     20   
  29. #define MAX_BUFSIZE       512   
  30.   
  31. typedef struct thread_arg  
  32. {  
  33.     int pty;  
  34.     int sockfd;  
  35. } thread_arg;  
  36.   
  37. void prterrmsg(char *msg);  
  38. #define prterrmsg(msg)        { perror(msg); abort(); }   
  39. void wrterrmsg(char *msg);  
  40. #define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }   
  41.   
  42. void prtinfomsg(char *msg);  
  43. #define prtinfomsg(msg)        { fputs(msg, stdout);  }   
  44. void wrtinfomsg(char *msg);  
  45. #define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}   
  46.   
  47. #define MAXBUF        1024   
  48.   
  49. char buffer[MAXBUF + 1];  
  50. char *host = 0;  
  51. char *port = 0;  
  52. char *back = 0;  
  53. char *dirroot = 0;  
  54. char *logdir = 0;  
  55. unsigned char daemon_y_n = 0;  
  56. FILE *logfp;  
  57.   
  58. #define MAXPATH        150   
  59.   
  60. /*------------------------------------------------------ 
  61.  *--- AllocateMemory - 分配空间并把d所指的内容复制 
  62.  *------------------------------------------------------ 
  63.  */  
  64. void AllocateMemory(char **s, int l, char *d)  
  65. {  
  66.     *s = malloc(l + 1);  
  67.     bzero(*s, l + 1);  
  68.     memcpy(*s, d, l);  
  69. }  
  70.   
  71. /*------------------------------------------------------ 
  72.  *--- getoption - 分析取出程序的参数 
  73.  *------------------------------------------------------ 
  74.  */  
  75. void getoption(int argc, char **argv)  
  76. {  
  77.     int c, len;  
  78.     char *p = 0;  
  79.   
  80.     opterr = 0;  
  81.     while (1)  
  82.     {  
  83.         int option_index = 0;  
  84.         static struct option long_options[] =  
  85.         {  
  86.         { "host", 1, 0, 0 },  
  87.         { "port", 1, 0, 0 },  
  88.         { "back", 1, 0, 0 },  
  89.         { "dir", 1, 0, 0 },  
  90.         { "log", 1, 0, 0 },  
  91.         { "daemon", 0, 0, 0 },  
  92.         { 0, 0, 0, 0 } };  
  93.         /* 本程序支持如一些参数: 
  94.          * --host IP地址 或者 -H IP地址 
  95.          * --port 端口 或者 -P 端口 
  96.          * --back 监听数量 或者 -B 监听数量 
  97.          * --dir 服务默认目录 或者 -D 服务默认目录 
  98.          * --log 日志存放路径 或者 -L 日志存放路径 
  99.          * --daemon 使程序进入后台运行模式 
  100.          */  
  101.         c = getopt_long(argc, argv, "H:P:B:D:L", long_options, &option_index);  
  102.         if (c == -1 || c == '?')  
  103.             break;  
  104.   
  105.         if (optarg)  
  106.             len = strlen(optarg);  
  107.         else  
  108.             len = 0;  
  109.   
  110.         if ((!c && !(strcasecmp(long_options[option_index].name, "host"))) || c  
  111.                 == 'H')  
  112.             p = host = malloc(len + 1);  
  113.         else if ((!c && !(strcasecmp(long_options[option_index].name, "port")))  
  114.                 || c == 'P')  
  115.             p = port = malloc(len + 1);  
  116.         else if ((!c && !(strcasecmp(long_options[option_index].name, "back")))  
  117.                 || c == 'B')  
  118.             p = back = malloc(len + 1);  
  119.         else if ((!c && !(strcasecmp(long_options[option_index].name, "dir")))  
  120.                 || c == 'D')  
  121.             p = dirroot = malloc(len + 1);  
  122.         else if ((!c && !(strcasecmp(long_options[option_index].name, "log")))  
  123.                 || c == 'L')  
  124.             p = logdir = malloc(len + 1);  
  125.         else if ((!c  
  126.                 && !(strcasecmp(long_options[option_index].name, "daemon"))))  
  127.         {  
  128.             daemon_y_n = 1;  
  129.             continue;  
  130.         }  
  131.         else  
  132.             break;  
  133.         bzero(p, len + 1);  
  134.         memcpy(p, optarg, len);  
  135.     }  
  136. }  
  137.   
  138. void *thread_recv_add_write_pyt(void *arg)  
  139. {  
  140.     int ret, sockfd, pty;  
  141.     char buffer[MAX_BUFSIZE];  
  142.     thread_arg *arg1 = (thread_arg*) arg;  
  143.   
  144.     sockfd = arg1->sockfd;  
  145.     pty = arg1->pty;  
  146.   
  147.     while (1)  
  148.     {  
  149.         memset(buffer, 0, MAX_BUFSIZE);  
  150.         ret = recv(sockfd, buffer, MAX_BUFSIZE, 0);  
  151.         if (ret < 0)  
  152.         {  
  153.             continue;  
  154.         }  
  155.         printf("%s", buffer);  
  156.         write(pty, buffer, strlen(buffer));  
  157.     }  
  158. }  
  159.   
  160. void read_write_pty(int pty, int sockfd)  
  161. {  
  162.     char buffer[MAX_BUFSIZE];  
  163.     int ret;  
  164.     //  pthread_t thread_t;   
  165.     //  pthread_attr_t attr;   
  166.     //  thread_arg arg;   
  167.     //  arg.pty = pty;   
  168.     //  arg.sockfd = sockfd;   
  169.     //   
  170.     //  if ((ret = pthread_create(&thread_t, &attr, thread_recv_add_write_pyt,   
  171.     //          (void*) &arg)))   
  172.     //  {   
  173.     //      perror("thread create recieve message and write to pty err:\n");   
  174.     //  }   
  175.   
  176.     pid_t pid;  
  177.     if ((pid = fork()) < 0)  
  178.     {  
  179.         perror("");  
  180.         exit(1);  
  181.     }  
  182.     else if (pid == 0)  
  183.     {  
  184.         while (1)  
  185.         {  
  186.             memset(buffer, 0, MAX_BUFSIZE);  
  187.             ret = recv(sockfd, buffer, MAX_BUFSIZE - 1, 0);  
  188.             if (ret < 0)  
  189.             {  
  190.                 continue;  
  191.             }  
  192.             //printf("%s", buffer);   
  193.             write(pty, buffer, strlen(buffer));  
  194.         }  
  195.     }  
  196.   
  197.     memset(buffer, 0, MAX_BUFSIZE);  
  198.   
  199.     while (ret = read(pty, buffer, MAX_BUFSIZE - 1))  
  200.     {  
  201.         buffer[ret - 1] = 0; //read是读不到字符串结束符的,需要自己添加,否则printf会出错   
  202.         if (ret <= 0)  
  203.         {  
  204.             break;  
  205.         }  
  206.         fflush(stdout);//这步很重要,std中经常有数据滞留在存储区中需要此函数刷新   
  207.         printf("%s", buffer);//打印出结果   
  208.         send(sockfd, buffer, strlen(buffer), 0);  
  209.         memset(buffer, 0, MAX_BUFSIZE);  
  210.     }  
  211.     return;  
  212. }  
  213.   
  214. int main(int argc, char **argv)  
  215. {  
  216.     struct sockaddr_in addr;  
  217.     int sock_fd, addrlen;  
  218.   
  219.     /* 获得程序工作的参数,如 IP 、端口、监听数、网页根目录、目录存放位置等 */  
  220.     getoption(argc, argv);  
  221.   
  222.     if (!host)  
  223.     {  
  224.         addrlen = strlen(DEFAULTIP);  
  225.         AllocateMemory(&host, addrlen, DEFAULTIP);  
  226.     }  
  227.     if (!port)  
  228.     {  
  229.         addrlen = strlen(DEFAULTPORT);  
  230.         AllocateMemory(&port, addrlen, DEFAULTPORT);  
  231.     }  
  232.     if (!back)  
  233.     {  
  234.         addrlen = strlen(DEFAULTBACK);  
  235.         AllocateMemory(&back, addrlen, DEFAULTBACK);  
  236.     }  
  237.     if (!dirroot)  
  238.     {  
  239.         addrlen = strlen(DEFAULTDIR);  
  240.         AllocateMemory(&dirroot, addrlen, DEFAULTDIR);  
  241.     }  
  242.     if (!logdir)  
  243.     {  
  244.         addrlen = strlen(DEFAULTLOG);  
  245.         AllocateMemory(&logdir, addrlen, DEFAULTLOG);  
  246.     }  
  247.   
  248.     /* fork() 两次处于后台工作模式下 */  
  249.     if (daemon_y_n)  
  250.     {  
  251.         if (fork())  
  252.             exit(0);  
  253.         if (fork())  
  254.             exit(0);  
  255.         close(0), close(1), close(2);  
  256.         logfp = fopen(logdir, "a+");  
  257.         if (!logfp)  
  258.             exit(0);  
  259.     }  
  260.   
  261.     /* 处理子进程退出以免产生僵尸进程 */  
  262.     signal(SIGCHLD, SIG_IGN);  
  263.   
  264.     /* 创建 socket */  
  265.     if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)  
  266.     {  
  267.         if (!daemon_y_n)  
  268.         {  
  269.             prterrmsg("socket()");  
  270.         }  
  271.         else  
  272.         {  
  273.             wrterrmsg("socket()");  
  274.         }  
  275.     }  
  276.   
  277.     /* 设置端口快速重用 */  
  278.     addrlen = 1;  
  279.   
  280.     addr.sin_family = AF_INET;  
  281.     addr.sin_port = htons(atoi(port));  
  282.     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  283.     addrlen = sizeof(struct sockaddr_in);  
  284.   
  285.     setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen, sizeof(addrlen));  
  286.     /* 绑定地址、端口等信息 */  
  287.     if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0)  
  288.     {  
  289.         if (!daemon_y_n)  
  290.         {  
  291.             prterrmsg("bind()");  
  292.         }  
  293.         else  
  294.         {  
  295.             wrterrmsg("bind()");  
  296.         }  
  297.     }  
  298.   
  299.     /* 开启临听 */  
  300.     if (listen(sock_fd, atoi(back)) < 0)  
  301.     {  
  302.         if (!daemon_y_n)  
  303.         {  
  304.             prterrmsg("listen()");  
  305.         }  
  306.         else  
  307.         {  
  308.             wrterrmsg("listen()");  
  309.         }  
  310.     }  
  311.   
  312.     printf("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后台工作模式(进程ID:%d)\n",  
  313.             host, port, back, dirroot, logdir, daemon_y_n ? "" : "不", getpid());  
  314.   
  315.     while (1)  
  316.     {  
  317.         int new_fd;  
  318.         addrlen = sizeof(struct sockaddr_in);  
  319.         /* 接受新连接请求 */  
  320.         new_fd = accept(sock_fd, (struct sockaddr *) &addr, &addrlen);  
  321.         if (new_fd < 0)  
  322.         {  
  323.             if (!daemon_y_n)  
  324.             {  
  325.                 prterrmsg("accept()");  
  326.             }  
  327.             else  
  328.             {  
  329.                 wrterrmsg("accept()");  
  330.             }  
  331.             break;  
  332.         }  
  333.         bzero(buffer, MAXBUF + 1);  
  334.         sprintf(buffer, "连接来自于: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(  
  335.                 addr.sin_port));  
  336.         if (!daemon_y_n)  
  337.         {  
  338.             prtinfomsg(buffer);  
  339.         }  
  340.         else  
  341.         {  
  342.             wrtinfomsg(buffer);  
  343.         }  
  344.         /* 产生一个子进程去处理请求,当前进程继续等待新的连接到来 */  
  345.         if (!fork())  
  346.         {  
  347.             int ret, ptrfdm;  
  348.             char slave_name[PTY_NAME_SIZE];  
  349.             struct termios slave_termiors;  
  350.             struct winsize slave_winsize;  
  351.             pid_t ppid;  
  352.   
  353.             ret = -1;  
  354.             ptrfdm = -1;  
  355.             memset(slave_name, 0, PTY_NAME_SIZE);  
  356.             ppid = -1;  
  357.   
  358.             ret = pty_fork(&ptrfdm, slave_name, PTY_NAME_SIZE, &slave_termiors,  
  359.                     &slave_winsize, &ppid);  
  360.   
  361.             if (ret < 0)  
  362.             {  
  363.                 printf("pty_fork err ! ret = %d", ret);  
  364.                 return -1;  
  365.             }  
  366.   
  367.             if (ppid < 0)  
  368.             {  
  369.                 printf("pty_fork err !");  
  370.                 return -1;  
  371.             }  
  372.             else if (ppid == 0)  
  373.             {  
  374.                 execl("/bin/bash""bash", NULL);  
  375.             }  
  376.             else  
  377.             {  
  378.                 read_write_pty(ptrfdm, new_fd);  
  379.   
  380.             }  
  381.         }  
  382.         close(new_fd);  
  383.     }  
  384.     close(sock_fd);  
  385.     return 0;  
  386. }  

相关内容