linux中的伪终端编程,Linux伪终端 telnet源码

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#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

typedefstructthread_arg

{

intpty;

intsockfd;

} thread_arg;

voidprterrmsg(char*msg);

#define prterrmsg(msg)        { perror(msg); abort(); }

voidwrterrmsg(char*msg);

#define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }

voidprtinfomsg(char*msg);

#define prtinfomsg(msg)        { fputs(msg, stdout);  }

voidwrtinfomsg(char*msg);

#define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}

#define MAXBUF        1024

charbuffer[MAXBUF + 1];

char*host = 0;

char*port = 0;

char*back = 0;

char*dirroot = 0;

char*logdir = 0;

unsignedchardaemon_y_n = 0;

FILE*logfp;

#define MAXPATH        150

/*------------------------------------------------------

*--- AllocateMemory - 分配空间并把d所指的内容复制

*------------------------------------------------------

*/

voidAllocateMemory(char**s,intl,char*d)

{

*s = malloc(l + 1);

bzero(*s, l + 1);

memcpy(*s, d, l);

}

/*------------------------------------------------------

*--- getoption - 分析取出程序的参数

*------------------------------------------------------

*/

voidgetoption(intargc,char**argv)

{

intc, len;

char*p = 0;

opterr = 0;

while(1)

{

intoption_index = 0;

staticstructoption 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);

elseif((!c && !(strcasecmp(long_options[option_index].name,"port")))

|| c =='P')

p = port = malloc(len + 1);

elseif((!c && !(strcasecmp(long_options[option_index].name,"back")))

|| c =='B')

p = back = malloc(len + 1);

elseif((!c && !(strcasecmp(long_options[option_index].name,"dir")))

|| c =='D')

p = dirroot = malloc(len + 1);

elseif((!c && !(strcasecmp(long_options[option_index].name,"log")))

|| c =='L')

p = logdir = malloc(len + 1);

elseif((!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)

{

intret, sockfd, pty;

charbuffer[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 

{

continue;

}

printf("%s", buffer);

write(pty, buffer, strlen(buffer));

}

}

voidread_write_pty(intpty,intsockfd)

{

charbuffer[MAX_BUFSIZE];

intret;

//  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()) 

{

perror("");

exit(1);

}

elseif(pid == 0)

{

while(1)

{

memset(buffer, 0, MAX_BUFSIZE);

ret = recv(sockfd, buffer, MAX_BUFSIZE - 1, 0);

if(ret 

{

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;

}

intmain(intargc,char**argv)

{

structsockaddr_in addr;

intsock_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)) 

{

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(structsockaddr_in);

setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,sizeof(addrlen));

/* 绑定地址、端口等信息 */

if(bind(sock_fd, (structsockaddr *) &addr, addrlen) 

{

if(!daemon_y_n)

{

prterrmsg("bind()");

}

else

{

wrterrmsg("bind()");

}

}

/* 开启临听 */

if(listen(sock_fd, atoi(back)) 

{

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)

{

intnew_fd;

addrlen =sizeof(structsockaddr_in);

/* 接受新连接请求 */

new_fd = accept(sock_fd, (structsockaddr *) &addr, &addrlen);

if(new_fd 

{

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())

{

intret, ptrfdm;

charslave_name[PTY_NAME_SIZE];

structtermios slave_termiors;

structwinsize 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 

{

printf("pty_fork err ! ret = %d", ret);

return-1;

}

if(ppid 

{

printf("pty_fork err !");

return-1;

}

elseif(ppid == 0)

{

execl("/bin/bash","bash", NULL);

}

else

{

read_write_pty(ptrfdm, new_fd);

}

}

close(new_fd);

}

close(sock_fd);

return0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值