Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading from a pty

Tags:

c

pty

I'd like to receive (and later process) write(1) and wall(1) messages using a (Unix 98-style) pseudo tty on Linux. I already have the following minimal implementation:

#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);
}

The problem is now that it only works for reading the first message, then read gives me a EIO error. Why is that?

like image 478
gber Avatar asked Nov 05 '22 12:11

gber


1 Answers

It looks like this happens simply when the last slave file descriptor is closed. Considering write(1) and wall(1) will have the only file descriptor to the slave, you get EIO as soon as those finish writing.

The easiest way to keep this from happening is by keeping a file descriptor around. Right after your ptsname call, do an open(slave_name, O_RDRW).

(Curiously, you already have a slavefd variable, and the code to clean it up. Are you testing us? :p)

like image 177
Stéphan Kochen Avatar answered Nov 12 '22 16:11

Stéphan Kochen