6

新しいソケット接続でプログラムを実行する必要がある単純な「telnet/server」デーモンを開発しようとしています。この部分は正常に動作しています。

しかし、新しいプロセスを pty に関連付ける必要があります。これは、このプロセスにはいくつかの端末機能 (readline など) があるためです。

私が開発したコードは次のとおりです (socketfd は、新しい入力接続の新しいソケット ファイル記述子です)。

int masterfd, pid;
const char *prgName = "...";
char *arguments[10] = ....;

if ((pid = forkpty(&masterfd, NULL, NULL, NULL)) < 0)
    perror("FORK");
else if (pid)
    return pid;
else
{
    close(STDOUT_FILENO);
    dup2(socketfd, STDOUT_FILENO);

    close(STDIN_FILENO);
    dup2(socketfd, STDIN_FILENO);

    close(STDERR_FILENO);
    dup2(socketfd, STDERR_FILENO);

    if (execvp(prgName, arguments) < 0)
    {
        perror("execvp");
        exit(2);
    }
}

そのコードでは、「prgName」の stdin / stdout / stderr ファイル記述子がソケットに関連付けられているため (ls -la /proc/PID/fd で検索した場合)、このプロセスの端末機能は機能しません。 .

リモート デバイスで ssh/sshd を介して接続し、「localy」(ssh 接続で) prgName を実行するテストでは、このプロセス「prgName」の stdin/stdout/stderr fd が pty に関連付けられていることが示されます (したがって、このプロセスの端末機能は正常に動作しています)。

私が間違っていることは何ですか?自分の socketfd を pty (forkpty で作成) に関連付けるには?

感謝

アレックス

4

1 に答える 1

5

ソケットからマスター pty に、またはその逆にデータを転送するには、いくつかのコードを記述する必要があります。通常は親プロセスの仕事です。データ転送は双方向でなければならないことに注意してください。多くのオプションがあります: masterfd と socketfd の両方を追跡する select() 駆動のサイクル

(ヒントとして、非常に悪いコードであり、本番用ではありません!!!エラーとeofチェックがありません!!!)

for (;;) {
  FD_ZERO(&set);
  FD_SET(masterfd,&set);
  FD_SET(socketfd,&set);
  select(...,&set,...);
  if (FD_ISSET(masterfd,&set)) {
       read(masterfd,&c,1);
       write(socketfd,&c,1);
  }
  if (FD_ISSET(sockerfd,&set)) {
       read(sochetfd,&c,1);
       write(masterfd,&c,1);
  }

または、socketfd->masterfd 転送用と masterfd->sockefd 転送用のスレッドのペア。

(ヒントとして、非常に悪いコードであり、本番用ではありません!!!)

/*thread 1 */
      while (read(masterfd,&c,1) > 0)
           write(socketfd,&c,1);


/*thread 2 */
      while (read(socketfd,&c,1) > 0)
           write(masterfdfd,&c,1);

とにかく、ブランチの親側にコードを追加する必要があります。

よろしく

---編集--- もちろん、fd 0、1、2 を子プロセスの socketfd にリダイレクトしてはいけません。

于 2010-03-23T15:40:15.897 に答える