Дочерний процесс не может прочитать с созданного псевдо-терминала - PullRequest
1 голос
/ 02 февраля 2010

Я пытаюсь написать приложение, которое может войти в SSH с паролем, используя псевдо-терминалы. Но если я пишу () на ведущее устройство, то данные как-то не появляются на ведомом устройстве. Вот простой тестовый пример:

#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#ifdef __linux__
    #include <pty.h>
#else
    #include <util.h>
#endif

int
main() {
    int master;
    pid_t pid = forkpty(&master, NULL, NULL, NULL);
    if (pid == 0) {
        int ch;
        read(0, &ch, 1);
        _exit(1);
    } else {
        printf("Press Enter to send a byte.\n");
        getchar();
        write(master, "1", 1);
        printf("Done. Waiting for process to exit...\n");
        waitpid(pid, NULL, 0);
        return 0;
    }
}

Приложение сначала выдаст «Нажмите Enter, чтобы отправить байт». После нажатия Enter я ожидаю, что read () дочернего процесса вернется. Но read () там, кажется, блокируется на неопределенный срок, даже если мастер master (write) успешно завершает свою работу, поэтому мастер всегда ждет waitpid (). Что происходит?

Ответы [ 2 ]

2 голосов
/ 02 февраля 2010

Проблема в том, что вы не изменили дисциплину PTY. Строковая дисциплина по умолчанию ориентирована на строки, поэтому никакие входные данные не будут отправляться подчиненному процессу до тех пор, пока не будет прочитан символ новой строки. (Это можно увидеть, отправив «\ n» на ведомое устройство вместо просто «1».) Вы можете запустить PTY в режиме RAW, вызвав в дочернем процессе вызовы tcgetattr, cfmakeraw и * 1003. *, как следует:

    if (pid == 0) {
        int ch;
        struct termios t;
        tcgetattr(0, &t);
        cfmakeraw(&t);
        tcsetattr(0, TCSANOW, &t);
        read(0, &ch, 1);
        _exit(1);
    } else {

Кажется, это работает для меня.

1 голос
/ 02 февраля 2010

Пример кода на в этом блоге , вероятно, должен помочь. У автора есть обновление к его исходной задаче (очень похожей на вашу) с доступной функцией spawn (char *argv[]);.

...