Чтение из pty

Я хотел бы получать (и позже обрабатывать) сообщения write(1) и wall(1), используя псевдотерминал (в стиле Unix 98) в Linux. У меня уже есть следующая минимальная реализация:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <utempter.h>

#define BUF_LENGTH 1024

int
main (void)
{
    FILE *lf;
    int masterfd, slavefd;
    char *slave_name = NULL;
    char buf[BUF_LENGTH];
    size_t nbytes = sizeof(buf);
    ssize_t bytes_read;
    int exit_code = EXIT_SUCESS;

    if ((masterfd = posix_openpt (O_RDWR | O_NOCTTY)) == -1 
            || grantpt (masterfd) == -1
            || unlockpt (masterfd) == -1
            || (slave_name = ptsname (masterfd)) == NULL)
        exit (EXIT_FAILURE);

    if (!(lf = fopen("term.log","w")))
        exit (EXIT_FAILURE);

    addToUtmp (slave_name, NULL, masterfd);

    for (;;)
    {
        bytes_read = read(masterfd, buf, nbytes);
        if (bytes_read <= 0)
            break
        fwrite (buf, 1, bytes_read, lf);
    }

    if (bytes_read < 0)
    {
        fprintf (stderr, "error reading from master pty: %s\n", strerror (errno));
        exit_code = EXIT_FAILURE;
    }

    fclose (lf);
    if (slavefd >= 0)
        close (slavefd);
    if (masterfd >= 0)
    {
        removeLineFromUtmp (slave_name, masterfd);
        close (masterfd);
    }
    exit (exit_code);
}

Проблема в том, что теперь он работает только для чтения первого сообщения, а затем чтение дает мне ошибку EIO. Это почему?


c pty
person gber    schedule 04.06.2010    source источник


Ответы (1)


Похоже, это происходит просто при закрытии последнего дескриптора подчиненного файла. Учитывая, что write(1) и wall(1) будут иметь единственный файловый дескриптор подчиненного устройства, вы получите EIO, как только они закончат запись.

Самый простой способ предотвратить это — сохранить файловый дескриптор. Сразу после вашего ptsname звонка сделайте open(slave_name, O_RDRW).

(Любопытно, что у вас уже есть переменная slavefd и код для ее очистки. Вы нас тестируете? :p)

person Stéphan Kochen    schedule 04.06.2010
comment
D'oh, я, должно быть, случайно удалил строку open во время эксперимента (как вы заметили, переменная fd и cleanup уже там). Большое спасибо, еще одна пара глаз иногда может быть очень полезной :) - person gber; 04.06.2010