Linux伪终端 telnet源码
Linux伪终端 telnet源码
pty_fun.cpp
- #include "pty_fun.h"
- int ptym_open(char *pts_name, int pts_namesz)
- {
- char *ptr;
- char fdm;
- /*
- *return the name of the master device so that on failure
- *the caller can print an error message. Null terminate to
- *handle case where string lenth > pts_namesz
- * */
- strncpy(pts_name, "/dev/ptmx", pts_namesz);
- pts_name[pts_namesz - 1] = '\0';
- fdm = posix_openpt(O_RDWR);
- if (fdm < 0)
- return OPEN_PTY_ERR;
- if (grantpt(fdm) < 0)
- {
- close(fdm);
- return GRANT_PTY_ERR;
- }
- if (unlockpt(fdm) < 0)
- {
- close(fdm);
- return UNLOCK_PTY_ERR;
- }
- if ((ptr = ptsname(fdm)) == NULL)
- {
- close(fdm);
- return GET_PTYS_NAME_ERR;
- }
- strncpy(pts_name, ptr, pts_namesz);
- pts_name[pts_namesz - 1] = '\0';
- return fdm;
- }
- int ptys_open(char *pts_name)
- {
- int fds;
- if ((fds = open(pts_name, O_RDWR)) < 0)
- return OPEN_PTYS_ERR;
- return fds;
- }
- int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,
- const struct termios *slave_termiors,
- const struct winsize *slave_winsize, pid_t *ppid)
- {
- int fdm, fds;
- pid_t pid;
- char pts_name[20];
- if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0)
- {
- return fdm;
- }
- if (slave_name != NULL)
- {
- strncpy(slave_name, pts_name, slave_namesz);
- slave_name[slave_namesz - 1] = '\0';
- }
- if ((pid = fork()) < 0)
- {
- return FORK_ERR;
- }
- else if (pid == 0)
- {
- if (setsid() < 0)
- {
- return SETSID_ERR;
- }
- if ((fds = ptys_open(pts_name)) < 0)
- {
- close(fdm);
- return OPEN_PTYS_ERR;
- }
- #ifdef TIOCSCTTY
- if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0)
- return TIOCSCTTY_ERR;
- #endif
- // if (slave_termiors != NULL)
- // {
- // if (tcsetattr(fds, TCSANOW, slave_termiors) < 0)
- // return INIT_ATTR_ERR;
- // }
- // if (slave_winsize != NULL)
- // {
- // if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
- // return INIT_ATTR_ERR;
- // }
- if (dup2(fds, STDIN_FILENO) != STDIN_FILENO)
- return DUP_STDIN_ERR;
- if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)
- return DUP_STDOUT_ERR;
- if (dup2(fds, STDERR_FILENO) != STDERR_FILENO)
- return DUP_STDERR_ERR;
- if (fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO)
- {
- close(fds);
- }
- *ppid = 0;
- return 0;
- }
- else
- {
- *ptrfdm =fdm;
- *ppid = pid;
- return 0;
- }
- }
pty_fun.h
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <linux/limits.h>
- #include <features.h>
- #include <termios.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- //master pty
- #ifndef OPEN_PTY_ERR
- #define OPEN_PTY_ERR -1
- #endif
- #ifndef GRANT_PTY_ERR
- #define GRANT_PTY_ERR -2
- #endif
- #ifndef UNLOCK_PTY_ERR
- #define UNLOCK_PTY_ERR -3
- #endif
- #ifndef GET_PTYS_NAME_ERR
- #define GET_PTYS_NAME_ERR -4
- #endif
- //pty slave
- #ifndef OPEN_PTYS_ERR
- #define OPEN_PTYS_ERR -5
- #endif
- #ifndef FORK_ERR
- #define FORK_ERR -6
- #endif
- #ifndef SETSID_ERR
- #define SETSID_ERR -7
- #endif
- #ifndef TIOCSCTTY_ERR
- #define TIOCSCTTY_ERR -8
- #endif
- #ifndef INIT_ATTR_ERR
- #define INIT_ATTR_ERR -9
- #endif
- #ifndef DUP_STDIN_ERR
- #define DUP_STDIN_ERR -10
- #endif
- #ifndef DUP_STDOUT_ERR
- #define DUP_STDOUT_ERR -11
- #endif
- #ifndef DUP_STDERR_ERR
- #define DUP_STDERR_ERR -12
- #endif
- int ptym_open(char *pts_name, int pts_namesz);
- int ptys_open(char *pts_name);
- int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz,
- const struct termios *slave_termiors,
- const struct winsize *slave_winsize, pid_t *ppid);
telnetserver.cpp
- #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;
- }
评论暂时关闭