2

我正在编写 linux 守护程序,我想实现通过 telnet 配置其参数的能力。我有一个 cli 接口代码,使用带有历史和完成程序的 gnu readline 库编写,我想将该接口代码用于守护进程。

我尝试将标准输入/标准输出重定向到套接字,将 rl_instream/rl_outstream 重定向到套接字,读/写到主/从 pty,但没有成功。

类似的问题在这里问没有任何答案。

还阅读了这个问题,但我没有子进程。

我的问题是:

  1. 如何在单个进程中使用 pty 功能?
  2. 如果我只有单个进程,是否需要使用 master 和 slave pty?

代码示例(在 pty 设备上没有操作),预期结果 - readline 正常工作

char* readline_buff;

int main(void){
int mSock = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
int socketfd, n, flag = 1;

int addrlen;
daemon(1,1);
setsockopt(mSock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(5000);
addr.sin_addr.s_addr = INADDR_ANY;
bind(mSock, (const sockaddr*)&addr, sizeof(addr));
listen(mSock,SOMAXCONN);
addrlen = sizeof(addrlen);
bzero(&addr, sizeof(addr));

int m_pty = posix_openpt(O_RDWR);
grantpt(m_pty);
unlockpt(m_pty);
string m_ptsname = ptsname(m_pty);
int slave = open(m_ptsname.c_str(), O_RDWR);
//
socketfd = accept(mSock, (struct sockaddr *) &addr, (socklen_t*)&addrlen);
//
close(STDOUT_FILENO);
dup2(socketfd, STDOUT_FILENO);
close(STDIN_FILENO);
dup2(socketfd, STDIN_FILENO);
close(STDERR_FILENO);
dup2(socketfd, STDERR_FILENO);
//
 while(true){   
  readline_buff = readline("ME: ");
  add_history(readline_buff);
  free(readline_buff);
}
return 0;
}

非常感谢。

4

3 回答 3

1

telnet 协议基本上是一个基于行的协议,因此它不能轻易处理单个按键或特殊代码。您可以要求连接的 telnet 客户端发送每个密钥而不是线路,这是通过称为 telnet 协商的方式完成的。

要了解更多信息,您应该阅读 telnet RFC,最重要的是RFC 854RFC 855。要禁用客户端编辑,您还应该阅读RFC 1116。另请查看Wikipedia 页面以查看所有与 telnet 相关的 RFC 的列表。

简而言之,您必须向客户端发送一系列命令,要求它停止进行线路模式处理,并希望客户端回复它会停止执行此操作。这不是简单的事情,实际上恰恰相反。不过,要实现一个完整的 telnet 状态机是可以的。即使这样,您也可能无法正确使用 readline 库,因为击键可能不会被识别为正确的向上/向下键,并且您可能仍需要进行一些翻译。我实际上建议您也跳过正常的 stdin/stdout 处理和 PTY 处理,让客户端处理编辑,同时您可以通过使用 readline 等外部库的功能或使用内部库来跟踪历史记录历史队列。

于 2012-08-19T16:16:38.067 回答
0

不需要 Pty。您需要readline通过将以下行添加到/etc/inputrc~/.inputrc文件来配置新的历史记录键:

"\e[A":history-search-backward
"\e[B":history-search-forward

原因:

通常,当用户按下向上或向下箭头键时,终端程序(阅读:telnet 客户端)会发送转义码。

转义码是:

\33[A   - up arrow 
\33[B   - down arrow

因为您的程序打印: ^[[A^[[A^[[A^[[A,所以它不会重新设置转义序列。所以你需要将这些转义序列告诉readline.

查看更多信息

于 2012-08-21T13:03:30.673 回答
0

Readline 提供了一个测试文件 rlPtyTest.c,它通过 PTY 测试 readline。您可以将其用作实现套接字的模板。https://github.com/alexmac/alcextra/blob/master/readline-6.2/examples/rlptytest.c

于 2014-01-30T02:07:52.703 回答