2

私は Linux デーモンを作成しており、telnet 経由でそのパラメーターを構成する機能を実装したいと考えています。履歴とコンプリーターを備えた gnu readline ライブラリを使用して記述された cli インターフェイス コードがあり、そのインターフェイス コードをデーモンに使用したいと考えています。

stdin/stdout をソケットにリダイレクトし、rl_instream/rl_outstream をソケットにリダイレクトし、マスター/スレーブ pty に読み書きしようとしましたが、成功しませんでした。

同様の質問が回答なしでここで尋ねられました。

this questionも読んでください。ただし、子プロセスはありません。

私の質問は次のとおりです。

  1. 単一プロセス内で pty 機能を使用するにはどうすればよいですか?
  2. プロセスが 1 つしかない場合、マスターとスレーブの 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 プロトコルは基本的に回線ベースのプロトコルであるため、1 回のキー操作や特殊なコードを簡単に処理することはできません。接続された telnet クライアントに、行の代わりにすべてのキーを送信するように依頼できます。これは、telnet ネゴシエーションと呼ばれるものによって行われます。

これについて詳しく知るには、telnet の RFC を読む必要があります。最も重要なのはRFC 854RFC 855です。クライアント側の編集を無効にするために、RFC 1116も読む必要があります。また、ウィキペディアのページをチェックして、すべての telnet 関連の RFC のリストを確認してください。

要するに、一連のコマンドをクライアントに送信して、ラインモード処理を停止するように依頼し、クライアントがそれを停止するという応答を返すことを期待する必要があります。これは単純なことではなく、実際にはまったく逆です。ただし、完全な telnet ステートマシンを実装することは可能です。それでも、キーストロークが適切な上下キーとして認識されない可能性があり、何らかの変換を行う必要があるため、readline ライブラリを適切に使用できない可能性があります。readline のような外部ライブラリの機能を使用するか、内部ライブラリを使用して、履歴を追跡しながら、通常の stdin/stdout 処理と PTY 処理もスキップし、クライアントに編集を処理させることをお勧めします。履歴キュー。

于 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 は、PTY を介して readline をテストするテスト ファイル rlPtyTest.c を提供します。ソケットを実装するためのテンプレートとして使用できます。https://github.com/alexmac/alcextra/blob/master/readline-6.2/examples/rlptytest.c

于 2014-01-30T02:07:52.703 に答える