вилка - розетка - PullRequest
       19

вилка - розетка

4 голосов
/ 23 марта 2010

Я пытаюсь разработать простой демон "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);
    }
}

С этим кодом дескриптор файла stdin / stdout / stderr моего "prgName" связан с сокетом (при просмотре с помощью ls -la / proc / PID / fd), и, следовательно, возможности терминала этого процесса не не работает.

Тест с подключением через ssh / sshd на удаленном устройстве и выполнением «localy» (при подключении ssh) prgName, показывает, что stdin / stdout / stderr fd этого процесса «prgName» связаны с pty (и поэтому терминальные возможности этого процесса работают нормально).

Что я делаю не так? Как связать мой socketfd с pty (созданным forkpty)?

Спасибо

Alex

1 Ответ

4 голосов
/ 23 марта 2010

Вы должны написать некоторый код для передачи данных из сокета в главный pty и наоборот. Обычно это работа родительского процесса. Обратите внимание, что передача данных должна быть двунаправленной. Есть много опций: цикл select (), управляемый для отслеживания как masterfd, так и socketfd

(просто подсказка, очень плохой код, не для производства !!! Отсутствует проверка ошибок и 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);

В любом случае вы должны добавить некоторый код в родительскую часть ветви.

Привет

--- EDIT --- Конечно, вы не должны перенаправлять fd 0,1 и 2 в socketfd в дочернем процессе.

...