How to use /dev/ptmx multiplexor pipes/ptys

Piercarlo Grandi pcg at aber-cs.UUCP
Fri Feb 2 05:41:33 AEST 1990


I have received some request some time ago for an idea of how
to use the /dev/ptmx device.

/dev/ptmx is a multiplexor named pipe device; you configure a
number of ptm devices, each of which has two ends, to which two
programs can be attached. When you open /dev/ptmx (a clone
device) you get a fd to one of them; another program can then
communicate with you by opening the other side. You can either
have a single program that opens /dev/ptmx and serves any
program that opens one of the other sides (/dev/ptsXXX), or
viceversa, the server opens all the /dev/ptsXXX sides and
whenever a client wants to communicate it opens /dev/ptmx and
gets a master side.

Applications are named pipes, and pseudo ttys; the latter happen
when you push the line discipline module "ldterm" onto the slave
side.

There is a virtually undocumented library, /usr/lib/libpt.a,
that deals with such entities. I believe that it is essentially
the code below.

As usual, this example is provided as is, with no warranties,
etc..., and is no way related to any activity of my employer,
that I thank for the permission to use News. This snippet of
code is also not copyrighted at all. Too small for it to make
sense.

------8<-------------------------8<-------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/stream.h>
#include <sys/ptms.h>

int			main()
{
    int			    ptm,pts;
    struct stat		    st;
    int			    u;
    char		    buf[128];

    /*
	/dev/ptmx is a clone device that will select a free /dev/ptmXXX device
	and return a file descriptor to it (note that /dev/ptmXXX files do
	not actually exist, even if they could well be created).
    */

    if ((ptm = open("/dev/ptmx",O_RDWR|O_NDELAY)) == 0)
    {
	perror("opening /dev/ptmx");
	return 1;
    }

    /*
	Now ptm contains a file descriptor to the master side of a
	/dev/ptmXXX /dev/ptsXXX pair.
    */

    if (fstat(ptm,&st) < 0)
    {
	perror("stat'ing /dev/ptmx");
	return 1;
    }

    printf("ptm major %u, minor %u\n",st.st_rdev>>8,st.st_rdev&0xff);

    /*
	We unlock the slave side, otherwise only us or our children
	will be able to open it.
    */

    if (ioctl(ptm,UNLKPT,buf) < 0)
    {
	perror("unlocking ptm");
	close(ptm);
	return 1;
    }

    /*
	We open the /dev/ptsXXX device with the same XXX as the /dev/ptmXXX
	device we got from cloning /dev/ptmx
    */

    sprintf(buf,"/dev/pts%03u",st.st_rdev&0xff);
    if ((pts = open(buf,O_RDWR|O_NDELAY)) == 0)
    {
	perror("opening pts");
	return 1;
    }

    if (fstat(ptm,&st) < 0)
    {
	perror("stat'ing pts");
	return 1;
    }

    printf("pts major %u, minor %u\n",st.st_rdev>>8,st.st_rdev&0xff);

    /*
	Here we have a child write a test string into the /dev/ptsXXX stream;
	we will read it from the /dev/ptmXXX master and print it.
    */

    if (fork())
	close(pts);
    else
    {
	close(ptm);

	strcpy(buf,"PTS side working!!!!\n");
	write(pts,buf,strlen(buf));

	close(pts);
    }

    while ((u = read(ptm,buf,sizeof buf)) != -3)
	if (u <= 0)
	    sleep(1);
	else
	    write(1,buf,u);

    close(ptm);

    return 0;
}
------8<-------------------------8<-------------------------------------------

-- 
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk at nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg at cs.aber.ac.uk



More information about the Comp.unix.i386 mailing list