Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.1 (Tek) 9/26/83; site azure.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!mhuxj!ihnp4!zehntel!tektronix!teklds!azure!keithp
From: keithp@azure.UUCP (Keith Packard)
Newsgroups: net.bugs.4bsd
Subject: bug in 4.2 ptys stuff.  Weird results when programs are swapped.
Message-ID: <91@azure.UUCP>
Date: Thu, 18-Oct-84 16:35:31 EDT
Article-I.D.: azure.91
Posted: Thu Oct 18 16:35:31 1984
Date-Received: Sun, 21-Oct-84 11:12:33 EDT
Organization: Tektronix, Beaverton OR
Lines: 102

I found an interesting bug in the pty controller driver.  A program
hanging on a read from the controlling side of a pty gets swapped out.
When this program is swapped back in, it continues the wait *but* when
it successfully reads from the pty, processes the data and reads
again, read returns -1 instead of hanging on the read.  Note that
the data is being fed to this program from a sequence of other
programs which write out a small amount of text to the other end
of the pty and close the pty.  (Actually my cd is aliased to:
'cd \!*; echo $cwd > /dev/ttypf'  but the problem even occurs if
the process writing to the device exits as in cp)

Here is the source text for the faulty program:

/*
 *	pty.c  read from pty, write to stdout.
 *	good for fixed pipes.  writes name of
 *	pty to file specified by first argument, stdin default.
 */

# include	
# include	
# include	

char	buffer[4096];
int	named = 2;
int	off = 0;
char	pname[] = "/dev/ptypf";
char	tname[] = "/dev/ttypf\n";
char	devName[] = "0123456789abcdef";

main (argc, argv)
char **argv;
{
	register int	fd, len, count;
	char		nbuf[15];

	if (argc == 2) {
		named = open (argv[1], O_WRONLY|O_TRUNC|O_CREAT, 0600);
		if (named == -1) {
			write (2, "could not access file\n", 22);
			_exit (1);
		}
	} else {
		write (2, "usage: pty file\n");
		_exit (2);
	}
	fd = openPty();
	if (fd < 0)
		_exit (1);
	if (fork())
		_exit (0);
	ioctl (fd, FIONBIO, &off);
	close (named);
	close (0);
	close (2);
	for (;;) {
		len = read (fd, buffer, 4096);
		if (len > 0) {
			if (buffer[0] == '#')
				_exit();
			if (write (1, buffer, len) == -1)
				_exit();
		} else {
			extern int	errno;
			printf ("len was: %d\n", len);
			printf ("error was: %d\n", errno);
			perror ("error name on write");
			exit (1);
		}
	}
}

# define	DEVINDEX	9

openPty ()
{
	register int	fd;
	register int	dev;

	dev = 16;
	do {
		if (dev == 0)
			return -1;
		pname [DEVINDEX] = devName [--dev];
	} while ((fd = open (pname, 2)) == -1);
	tname [DEVINDEX] = devName [dev];
	write (named, tname, sizeof (tname) - 1);
	return fd;
}

To repeat:

cc -o pty pty.c
pty foo > outputfile
set pty=`cat foo`
cp /etc/motd $pty

wait until pty is swapped

cp /etc/motd $pty

and cat the outputfile.