[comp.sources.misc] v02i062: New Version of the UnixPC pty driver

eric@e.ms.uky.edu (Eric Herrin) (02/29/88)

Comp.sources.misc: Volume 2, Issue 62

Submitted-By: Eric Herrin <eric@e.ms.uky.edu>

Archive-Name: 3b1-ptys-v2


Comp.sources.misc: Volume 2, Issue 62
Submitted-By: Eric Herrin <eric@e.ms.uky.edu>
Archive-Name: 3b1-ptys-v2

Here's the latest version of the pty driver for the UnixPC, with all the
known bugs/problems fixed.  If anyone has any problems, let me know,
I have been pretty careful to make sure this one works without any
hitches.  Hope everyone enjoys it as much as I do.

			eric


|  Eric Herrin II: {cbosgd!ukma!eric, eric@UKMA.BITNET, eric@ms.uky.edu}      |
|  "But I soon noticed that while I thus wished to                            |
|   think everything false, it was necessarily true                           |
|   that I who thought so was something"   - Rene Descartes                   |
-------------------------  cut here -------------------------------------------
#! /bin/sh
: This is a shell archive, meaning:
: 1. Remove everything above the '#! /bin/sh' line.
: 2. Save the resulting text in a file.
: 3. Execute the file with /bin/sh '(not csh)' to create the files:
:	'Files'
:	'Install'
:	'MKflop'
:	'Makefile'
:	'Name'
:	'README.3b1'
:	'READ_ME'
:	'Remove'
:	'Remove.orig'
:	'Size'
:	'Version'
:	'number-ptys.h'
:	'pty.c'
:	'pty.h'
: This archive created: 'Sun Feb 28 13:52:08 1988
'
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Files'" '(118 characters)'
if test -f 'Files'
then
	echo shar: will not over-write existing file "'Files'"
else
sed 's/^X//'  >'Files' <<'SHAR_EOF'
XSize
XName
XRemove
XInstall
XFiles
XMKflop
XMakefile
Xpty.o
XREADME.3b1
XREAD_ME
XRemove.orig
XVersion
Xnumber-ptys.h
Xpty.c
Xpty.h
SHAR_EOF
if test 118 -ne "`wc -c < 'Files'`"
then
	echo shar: error transmitting "'Files'" '(should have been 118 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Install'" '(1929 characters)'
if test -f 'Install'
then
	echo shar: will not over-write existing file "'Install'"
else
sed 's/^X//'  >'Install' <<'SHAR_EOF'
X# Eric H. Herrin II
X# University of Kentucky Mathematical Sciences
X# eric@ms.uky.edu, !cbosgd!ukma!eric
X#
X# Install script for System V Pty driver
XMODULE=pty
X# put the module in the appropriate place
Xcp ${MODULE}.o /etc/lddrv/${MODULE}.o
X# add the entry to the /etc/master file
X/etc/masterupd -a char open release close read write ioctl ${MODULE}
X# get the assigned device number
XMODULEDEVNO=`/etc/masterupd -c ${MODULE}`
Xif [  ! ${MODULEDEVNO} ]
Xthen 
X	echo "${MODULEDEVNO} cannot be added to the /etc/master file"
X	exit 1
Xfi
X# NOTE!!!!!!!!!!!!!!
X# To change the number of ptys, change the value in number-ptys.h.
X# VVVVVVV
XPTYCNT=`grep NUMBER_OF_PTYS number-ptys.h | \
Xsed -e "s/#define//" -e "s/NUMBER_OF_PTYS//" -e "s/ //g"`
Xecho "PTYCNT=$PTYCNT" > Remove
Xcat Remove.orig >> Remove
X# make the pty device files
Xecho "Making pty pseudo device files"
Xcnt=0
Xfor x in p q r s t u v w x y z
Xdo
X	for y in 0 1 2 3 4 5 6 7 8 9 a b c d e f
X	do
X		i=$x$y
X		if [ $cnt -ge ${PTYCNT} ] 
X		then 
X			break
X		fi
X		/etc/mknod /dev/pty$i c ${MODULEDEVNO}\
X `expr $cnt + $PTYCNT`
X		/etc/mknod /dev/tty$i c ${MODULEDEVNO} $cnt
X		chown root /dev/tty$i /dev/pty$i
X		chgrp root /dev/tty$i /dev/pty$i
X		chmod 0666 /dev/tty$i /dev/pty$i
X		cnt=`expr $cnt + 1`
X	done
Xdone
X
Xecho "Putting entry into InstDrv"
X# put an entry in /etc/lddrv/InstDrv for ${MODULE}
XV=`cat Version`
Xecho "Name=${MODULE} driver: Version ${V}" 	>> /etc/lddrv/InstDrv
Xecho "File=${MODULE}"     			>> /etc/lddrv/InstDrv
Xecho "Comment=Pseudo tty driver (ptys!!)" 	>> /etc/lddrv/InstDrv
Xcd /etc/lddrv
X# allocate and load the module
Xecho "Allocating pty module with lddrv"
X./lddrv -av -o ${MODULE}.o ${MODULE} > /dev/null 2>&1
Xif [ $? -eq 0 ]
Xthen
X	echo "Driver ${MODULE} successfully loaded"
Xelse
X	echo "Error: Driver ${MODULE} failed loading stage"
X	exit 1
Xfi
X
X# load the ${MODULE} at boot time
Xecho ${MODULE} >> /etc/lddrv/drivers
X
Xecho "Pseudo tty drivers are now installed"
Xexit 0
SHAR_EOF
if test 1929 -ne "`wc -c < 'Install'`"
then
	echo shar: error transmitting "'Install'" '(should have been 1929 characters)'
fi
chmod +x 'Install'
fi # end of overwriting check
echo shar: extracting "'MKflop'" '(120 characters)'
if test -f 'MKflop'
then
	echo shar: will not over-write existing file "'MKflop'"
else
sed 's/^X//'  >'MKflop' <<'SHAR_EOF'
Xecho "Insert floppy disk and press return"
Xread junk
X/usr/bin/fdfmt.nl
Xfind `cat Files` -print | cpio -oBc > /dev/fp021
SHAR_EOF
if test 120 -ne "`wc -c < 'MKflop'`"
then
	echo shar: error transmitting "'MKflop'" '(should have been 120 characters)'
fi
chmod +x 'MKflop'
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(403 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//'  >'Makefile' <<'SHAR_EOF'
X#       Eric H. Herrin II
X#	University of Kentucky Mathematical Sciences Laboratories
X# 	915 Patterson Office Tower
X#	University of Kentucky
X#	Lexington, KY 40506
X#	eric@ms.uky.edu, ..!cbosgd!ukma!eric 
XDEFS=   -UDEBUG
XCFLAGS= -O -c ${DEFS}
XSHELL= /bin/sh
X
X.c.o:
X	${CC} ${CFLAGS} $<
X
Xall: pty.o
X
Xinstall: all
X	${SHELL} ./Install
X
Xclean: 
X	rm -f pty.o
X
Xclobber: clean
X	${SHELL} ./Remove
X
Xremove: clobber
SHAR_EOF
if test 403 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 403 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Name'" '(24 characters)'
if test -f 'Name'
then
	echo shar: will not over-write existing file "'Name'"
else
sed 's/^X//'  >'Name' <<'SHAR_EOF'
XPty Driver Version 2.1 
SHAR_EOF
if test 24 -ne "`wc -c < 'Name'`"
then
	echo shar: error transmitting "'Name'" '(should have been 24 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README.3b1'" '(5891 characters)'
if test -f 'README.3b1'
then
	echo shar: will not over-write existing file "'README.3b1'"
else
sed 's/^X//'  >'README.3b1' <<'SHAR_EOF'
XREADME: Eric H. Herrin II
X	University of Kentucky Mathematical Sciences Laboratories
X 	915 Patterson Office Tower
X	University of Kentucky
X	Lexington, KY 40506
X	eric@ms.uky.edu, ..!cbosgd!ukma!eric 
X
XVersion 2.1
X
XThanks to 
X1.  Mike "Ford" Ditto
X    kenobi!ford@crash.CTS.COM, ...!crash!kenobi!ford
X    for his bug fix in the ptyrelease routine.
X2.  Michael Bloom 
X    mb@ttidca.tti.com
X    for his bug fix to the master read routine in the original driver.
X    I incorporated this fix and it seems to work fine.
X
XThis directory contains the PD pty driver for System V, modified for
Xuse with the AT&T UnixPC or Convergent Technologies Safari 4 computers,
Xrunning Version 3.51 of the UNIX System V OS (it may also work on
Xearlier versions, but I have no way of verifying this).  Anyone using
Xthis driver should have no problems, but I will provide little support.
XQuestions should be sent to the above address, either with ground mail
Xor real (e-)mail.
X
X
XThis README is intended to mark the changes made to the PD pty driver to
Xsatisfy the author's request.  It was not easy or feasible to clearly mark
Xevery change in the code, thus it was decided that an explanation of the
Xprocedure would probably be enough.  A brief introduction to UnixPC 
Xdevice drivers is followed by the list of changes made.  A couple of
Xhacks will also be explained.
X
XNOTE: The #ifdef DEBUG statements use eprintf() instead of printf().
X      This puts any messages into the error icon's queue of system 
X      errors (the icon is the !! icon at the top of the console).
X
X
XUnixPC device drivers:
X
X	The UnixPC has a different kind of device driver from other 
XSystem V machines.  They can be loaded while the machine is running or
Xat boot time, but are always linked into the OS while the kernel is
Xactive.  However nice this may be, there ARE some problems.  
X
X	1.  Loadable device drivers CANNOT communicate with one another.
X	    That is, one driver cannot use a data structure defined in 
X	    another driver (IE. they are not in the same identifier
X	    name space).  
X	2.  Conf.c doesn't exist, it is redone by the /etc/lddrv -av 
X	    program and relinked into the kernel.  Thus, one can't
X	    declare common structures this way.
X	
X
XChanges to the PD pty driver:
X
X	The following changes (hacks?) were made to the PD pty driver for
Xthe purpose of making it usable on the UnixPC.
X
X	   Problem 1 & 2 influenced me to try to make a single driver
X	   (there were two, ptm and pts).  How could one do this?
X	   My solution (and I would be very interested if you can
X	   think of a better one) was to create the slave devices
X	   /dev/tty[p-z][0-f] with minor numbers 0-(PTYCNT/2-1) and
X	   master devices /dev/pty[p-z][0-f] with minor numbers 
X	   (PTYCNT/2)-(PTYCNT-1).  Major numbers of both types of devices
X	   are the same. I can then simply define a macro to determine 
X	   whether the dev_t passed to the driver was a slave or master 
X	   pty.  Once determined, I can perform the appropriate duties.  
X	   Also, it was more readable to merge the ptm and pts modules 
X	   into a single set of pty[open, close, ioctl, read, write]
X	   routines.  I added a release routine so that the kernel will
X	   know the device has properly released if one deallocates
X	   the driver. 
X	   Another modification was the addition of ptystate[], which
X	   holds the MRWAIT, MWWAIT, MOPEN flags.  This was necessary
X	   because the original author insisted upon using 3 UNUSED
X	   bits in the t_state field of the tty.  The UnixPC does not
X	   have any free bits here.
X	   A check for TTIOW was added due to the fix by Michael
X	   Bloom in the master section of the ptyread() routine.  Note 
X	   his original fixes were for the original pty driver and
X	   most of the changes were already incorporated into this driver.
X
XMaking alterations to the number of ptys, etc.
X	   The number of ptys is defined in the file number-ptys.h.  This 
X	   number should not exceed the maximum minor device number divided by
X	   two.  Ie. a maximum minor device number of 128 would allow
X	   a maximum of 64 ptys.  It is currently defined at only 32, but
X	   I believe this is quite liberal, especially for a machine as
X	   small as a 3b1.  One could load the driver multiple times by
X	   calling it a different name in the /etc/master file.  One could
X	   have the first 64 ptys with major number 10, the next 64 with
X	   major number 11, etc.  I think 64 should do fine for any reasonable
X	   UNIX PC user (good grief, how would one use 64 ptys on a max
X   	   5 user machine?  Better yet, how would one get 5 users on the
X  	   thing?  Yuch!).  At any rate, we don't use that many ptys on
X	   a large system with lots of users.... so I really don't see this
X	   as a problem.
X	   
X
XPty driver generation and installation procedure.
X	   Put the number of ptys you want in the file number-ptys.h.
X	   Type "make"
X	   Type "/bin/sh MKflop"
X	   Insert a floppy diskette.
X	   Use the UA to install the diskette.
X	   (you can skip the floppy part and simply run the Install script 
X	   in the same directory the pty.o object is located.  But you
X	   won't be able to uninstall it from the UA.  There is a
X	   Remove script to do this which you will have to run manually.)
X
XAcknowledgement:  I realize the usage of a single major device number is
Xa supreme hack, and I welcome any improvements/solutions.  I do not assume
Xany responsibility for the changes I have made, nor do I imply any 
Xliability on the part of the original author.  I include a complete set
Xof {Install, Remove, etc, etc} scripts so that binary floppies may be
Xmade to be installed by the UnixPC user agent.  I do not assume any
Xresponsibility for these either.  I don't assume any responsibility for
Xanything even remotely related to this stuff.
X
X
X	    Eric H. Herrin II
X	    University of Kentucky Mathematical Sciences Laboratories
X	    eric@ms.uky.edu, !cbosgd!ukma!eric
X
SHAR_EOF
if test 5891 -ne "`wc -c < 'README.3b1'`"
then
	echo shar: error transmitting "'README.3b1'" '(should have been 5891 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'READ_ME'" '(1624 characters)'
if test -f 'READ_ME'
then
	echo shar: will not over-write existing file "'READ_ME'"
else
sed 's/^X//'  >'READ_ME' <<'SHAR_EOF'
XThis is a pseudo tty driver for system V machines. It works very
Xsimilar to ptys on BSD, for instance emacs works fine. To install this
Xdriver you will need to modify your `master' and `dfile' file which
Xcontains your driver specifications. As these vary from machine to machine,
Xyou will have to look up in your manual how to do that. Here is an example
Xfor a sperry s5050 alias ncr tower 32 :
X
XAdd the following two lines to the driver description section in master:
Xpts	0	237	244	pts	0	0	28	32	0	tty
Xptm	0	37	344	ptm	0	0	29	0	0
X
XThis says there are max 32 pts devices at major number 28 having associated
Xtty structures and 0 ptm devices having major number 29 with no associated
Xdata. The number of ptm devices is not configurable, as this depends on the
Xnumber of pts's.
X
XThe following two lines go in the dfile:
Xpts	0	0	0
Xptm	0	0	0
X
XProbably you will also want to increase the NCLIST parameter.
X
XIf your configuration procedure is different, you must change the shell
Xscript mkpty, which is used to create the device nodes in /dev.
X
XThe ptm devices (/dev/pty[p-z][0-9a-f]) are the controlling ones, everything
Xwritten there will show up at the associated pts device
X(/dev/tty[p-z][0-9a-f]), as well as erverything which is written on the pts
Xdevice will show up on the ptm device. The pts side will accept the usual
Xtermio ioctl calls. The master side is a bit different, as ioctl calls which
Xnormally wait for output to drain flush output. The reason for this funny
Xbehaviour is that otherwise the master side will hang. Also the master side
Xmay be opened only once, further open calls will result in an EBUSY error.
SHAR_EOF
if test 1624 -ne "`wc -c < 'READ_ME'`"
then
	echo shar: error transmitting "'READ_ME'" '(should have been 1624 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Remove'" '(1065 characters)'
if test -f 'Remove'
then
	echo shar: will not over-write existing file "'Remove'"
else
sed 's/^X//'  >'Remove' <<'SHAR_EOF'
XPTYCNT=32
X# Eric H. Herrin II
X# University of Kentucky Mathematical Sciences
X# eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
X#
X# Remove script for pty driver.
XMODULE=pty
Xecho "Removing /etc/lddrv entries and /etc/master entries"
X/etc/lddrv/lddrv -d ${MODULE}
X/etc/masterupd -d ${MODULE}
X# remove the pty device files
Xcnt=0
Xecho "Removing the pty device files"
Xfor x in p q r s t u v w x y z
Xdo
X	for y in 0 1 2 3 4 5 6 7 8 9 a b c d e f
X	do
X		i=$x$y
X		if [ ${cnt} -ge ${PTYCNT} ] 
X		then 
X			break
X		fi
X		/bin/rm -f /dev/pty$i
X		/bin/rm -f /dev/tty$i
X		cnt=`expr ${cnt} + 1`
X	done
Xdone
X# get rid of stuff in /etc/lddrv
Xecho "removing InstDrv entries, etc."
X/bin/rm -f /etc/lddrv/${MODULE}.o /etc/lddrv/${MODULE} \
X	/etc/lddrv/ifile.${MODULE}
Xgrep -v "^${MODULE}" /etc/lddrv/drivers > /tmp/XXX$$
Xmv /tmp/XXX$$ /etc/lddrv/drivers
Xgrep -v "${MODULE}" /etc/lddrv/InstDrv > /tmp/XXX$$
Xmv /tmp/XXX$$ /etc/lddrv/InstDrv
Xchmod +r /etc/lddrv/drivers /etc/lddrv/InstDrv
Xchmod go-w /etc/lddrv/drivers /etc/lddrv/InstDrv
Xchown root /etc/lddrv/drivers /etc/lddrv/InstDrv
SHAR_EOF
if test 1065 -ne "`wc -c < 'Remove'`"
then
	echo shar: error transmitting "'Remove'" '(should have been 1065 characters)'
fi
chmod +x 'Remove'
fi # end of overwriting check
echo shar: extracting "'Remove.orig'" '(1055 characters)'
if test -f 'Remove.orig'
then
	echo shar: will not over-write existing file "'Remove.orig'"
else
sed 's/^X//'  >'Remove.orig' <<'SHAR_EOF'
X# Eric H. Herrin II
X# University of Kentucky Mathematical Sciences
X# eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
X#
X# Remove script for pty driver.
XMODULE=pty
Xecho "Removing /etc/lddrv entries and /etc/master entries"
X/etc/lddrv/lddrv -d ${MODULE}
X/etc/masterupd -d ${MODULE}
X# remove the pty device files
Xcnt=0
Xecho "Removing the pty device files"
Xfor x in p q r s t u v w x y z
Xdo
X	for y in 0 1 2 3 4 5 6 7 8 9 a b c d e f
X	do
X		i=$x$y
X		if [ ${cnt} -ge ${PTYCNT} ] 
X		then 
X			break
X		fi
X		/bin/rm -f /dev/pty$i
X		/bin/rm -f /dev/tty$i
X		cnt=`expr ${cnt} + 1`
X	done
Xdone
X# get rid of stuff in /etc/lddrv
Xecho "removing InstDrv entries, etc."
X/bin/rm -f /etc/lddrv/${MODULE}.o /etc/lddrv/${MODULE} \
X	/etc/lddrv/ifile.${MODULE}
Xgrep -v "^${MODULE}" /etc/lddrv/drivers > /tmp/XXX$$
Xmv /tmp/XXX$$ /etc/lddrv/drivers
Xgrep -v "${MODULE}" /etc/lddrv/InstDrv > /tmp/XXX$$
Xmv /tmp/XXX$$ /etc/lddrv/InstDrv
Xchmod +r /etc/lddrv/drivers /etc/lddrv/InstDrv
Xchmod go-w /etc/lddrv/drivers /etc/lddrv/InstDrv
Xchown root /etc/lddrv/drivers /etc/lddrv/InstDrv
SHAR_EOF
if test 1055 -ne "`wc -c < 'Remove.orig'`"
then
	echo shar: error transmitting "'Remove.orig'" '(should have been 1055 characters)'
fi
chmod +x 'Remove.orig'
fi # end of overwriting check
echo shar: extracting "'Size'" '(3 characters)'
if test -f 'Size'
then
	echo shar: will not over-write existing file "'Size'"
else
sed 's/^X//'  >'Size' <<'SHAR_EOF'
X61
SHAR_EOF
if test 3 -ne "`wc -c < 'Size'`"
then
	echo shar: error transmitting "'Size'" '(should have been 3 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Version'" '(4 characters)'
if test -f 'Version'
then
	echo shar: will not over-write existing file "'Version'"
else
sed 's/^X//'  >'Version' <<'SHAR_EOF'
X2.1
SHAR_EOF
if test 4 -ne "`wc -c < 'Version'`"
then
	echo shar: error transmitting "'Version'" '(should have been 4 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'number-ptys.h'" '(176 characters)'
if test -f 'number-ptys.h'
then
	echo shar: will not over-write existing file "'number-ptys.h'"
else
sed 's/^X//'  >'number-ptys.h' <<'SHAR_EOF'
X/* number-ptys.h - Eric H. Herrin II
X *
X * define the number of ptys here so the actual number only has to be in
X * one place.
X * 
X * Version 2.1
X */
X#define NUMBER_OF_PTYS 32
SHAR_EOF
if test 176 -ne "`wc -c < 'number-ptys.h'`"
then
	echo shar: error transmitting "'number-ptys.h'" '(should have been 176 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pty.c'" '(9946 characters)'
if test -f 'pty.c'
then
	echo shar: will not over-write existing file "'pty.c'"
else
sed 's/^X//'  >'pty.c' <<'SHAR_EOF'
X/*
X * pty.c - Berkeley style pseudo tty driver for system V
X *
X * Copyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH
X * Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X */
X
X/*
X * Modified for use on the UnixPC by:
X * Eric H. Herrin II
X * University of Kentucky Mathematical Sciences Laboratories
X * eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
X *
X * See README.3b1 for details of port and installation.
X * Version 2.1
X */
X
X/*
X * the following are arbitrary 3 unused bits from t_state
X * in sys/tty.h
X */
X/* The UnixPC does not have any extra bits in t_state, thus
X * one must provide other means of storing the state.
X */
X#define MRWAIT	01	/* master waiting in read */
X#define t_rloc	t_cc[0]		/* wchannel */
X#define MWWAIT	02	/* master waiting in write */
X#define t_wloc	t_cc[1]		/* wchannel */
X#define MOPEN	04	/* master is open */
X
X#include "pty.h"
X#include "sys/param.h"
X#include "sys/types.h"
X#include "sys/sysmacros.h"
X#include "sys/systm.h"
X#include "sys/file.h"
X#include "sys/conf.h"
X#include "sys/proc.h"
X#include "sys/dir.h"
X#include "sys/tty.h"
X#include "sys/signal.h"
X#include "sys/user.h"
X#include "sys/errno.h"
X#include "sys/termio.h"
X#include "sys/ttold.h"
X
X/* The tty structures must be local to this driver.  One doesn't have
X * conf.c
X */
Xstruct tty pts_tty[PTYCNT];
Xint pts_cnt = PTYCNT;
Xint ptystate[PTYCNT];
X
Xptyopen(dev, flag)
X	register dev_t		dev;
X	register int		flag;
X{
X	register struct tty *tp;
X
X	dev = minor(dev);
X	if (Master(dev) == True) {
X#		ifdef DEBUG
X		eprintf("open(master): \n");
X#		endif
X		dev -= PTYCNT; 
X		tp = &pts_tty[dev];
X		if (dev >= pts_cnt) {
X			u.u_error = ENXIO;
X			return;
X		}
X		/*
X	 	* allow only one controlling process
X	 	*/
X		if (ptystate[dev] & MOPEN) {
X			u.u_error = EBUSY;
X			return;
X		}
X		if (tp->t_state & WOPEN)
X			wakeup((caddr_t)&tp->t_canq);
X		tp->t_state |= CARR_ON;
X		ptystate[dev] |= MOPEN;
X	} else {
X#		ifdef DEBUG
X		eprintf("open(slave): \n");
X#		endif
X		tp = &pts_tty[dev];
X		if (dev >= pts_cnt) {
X			u.u_error = ENXIO;
X			return;
X		}
X		if ((tp->t_state & (ISOPEN|WOPEN)) == 0) {
X			ttinit(tp);
X			tp->t_proc = ptsproc;
X		}
X		/*
X	  	 * if master is still open, don't wait for carrier
X	 	 */
X		if (ptystate[dev] & MOPEN)
X			tp->t_state |= CARR_ON;
X		if (!(flag & FNDELAY)) {
X			while ((tp->t_state & CARR_ON) == 0) {
X				tp->t_state |= WOPEN;
X				sleep((caddr_t)&tp->t_canq, TTIPRI);
X			}
X		}
X		(*linesw[tp->t_line].l_open)(tp);
X	}
X}
X
Xptyclose(dev, flag)
X	register dev_t		dev;
X	register int		flag;
X{
X        register struct tty     *tp;
X
X	dev = minor(dev);
X	if (Master(dev) == True) {
X#		ifdef DEBUG
X		eprintf("close(master): \n");
X#		endif
X		dev -= PTYCNT;
X		tp = &pts_tty[dev];
X		if (tp->t_state & ISOPEN) {
X			signal(tp->t_pgrp, SIGHUP);
X			ttyflush(tp, FREAD|FWRITE);
X		}
X		/*
X	 	 * virtual carrier gone
X	 	 */
X		tp->t_state &= ~(CARR_ON);
X		ptystate[dev] &= ~MOPEN;
X	} else {
X#		ifdef DEBUG
X		eprintf("close(slave): \n");
X#		endif
X		tp = &pts_tty[dev];
X		(*linesw[tp->t_line].l_close)(tp);
X		tp->t_state &= ~CARR_ON;
X	}
X}
X
Xptyread(dev)
X        register dev_t		dev;
X{
X	register struct tty     *tp;
X	register                n;
X
X	dev = minor(dev);
X	if (Master(dev) == True) {
X#		ifdef DEBUG
X		eprintf("read(master): \n");
X#		endif
X		dev -= PTYCNT;		
X                tp = &pts_tty[dev];
X
X		/* added fix for hanging master side when the slave hangs
X		 * up too early.  Fix by Michael Bloom (mb@ttidca.tti.com).
X		 */
X		if ((tp->t_state & (ISOPEN|TTIOW)) == 0) {
X			u.u_error = EIO;
X			return;
X		}
X		while (u.u_count > 0) {
X			ptsproc(tp, T_OUTPUT);
X			if ((tp->t_state & (TTSTOP|TIMEOUT))
X			    || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) {
X				if (u.u_fmode & FNDELAY)
X					break;
X#				ifdef DEBUG
X				eprintf("read(master): master going to sleep\n");
X#				endif
X				ptystate[dev] |= MRWAIT;
X				sleep((caddr_t)&tp->t_rloc, TTIPRI);
X#				ifdef DEBUG
X				eprintf("read(master): master woke up\n");
X#				endif
X
X				continue;
X			}
X			n = min(u.u_count, tp->t_tbuf.c_count);
X			if (n) {
X#				ifdef DEBUG
X				eprintf("read(master): got some stuff\n");
X#				endif
X				if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) {
X					u.u_error = EFAULT;
X					break;
X				}
X				tp->t_tbuf.c_count -= n;
X				tp->t_tbuf.c_ptr += n;
X				u.u_base += n;
X				u.u_count -= n;
X			}
X		}
X	} else {
X#		ifdef DEBUG
X		eprintf("read(slave): \n");
X#		endif
X		tp = &pts_tty[dev];
X#		ifdef DEBUG
X		eprintf("read(slave): got some stuff\n");
X#		endif
X		(*linesw[tp->t_line].l_read)(tp);
X	}
X}
X	
Xptywrite(dev)
X	register dev_t		dev;
X{
X	register struct tty     *tp;
X	register                n;
X
X	dev = minor(dev);
X	if (Master(dev) == True) {
X#		ifdef DEBUG
X		eprintf("write(master): \n");
X#		endif
X		dev -= PTYCNT;
X		tp = &pts_tty[dev];
X		
X		if ((tp->t_state & ISOPEN) == 0) {
X			u.u_error = EIO;
X			return;
X		}
X		while (u.u_count > 0) {
X			if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
X				if (u.u_fmode & FNDELAY)
X					break;
X				ptystate[dev] |= MWWAIT;
X#				ifdef DEBUG
X				eprintf("write(master): going to sleep\n");
X#				endif
X
X				sleep((caddr_t)&tp->t_wloc, TTOPRI);
X
X#				ifdef DEBUG
X				eprintf("write: waking up\n");
X#				endif
X
X				continue;
X			}
X			n = min(u.u_count, tp->t_rbuf.c_count);
X			if (n) {
X#				ifdef DEBUG
X				eprintf("write(master): sending some stuff\n");
X#				endif
X				if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) {
X					u.u_error = EFAULT;
X					break;
X				}
X				tp->t_rbuf.c_count -= n;
X				u.u_base += n;
X				u.u_count -= n;
X			}
X			(*linesw[tp->t_line].l_input)(tp);
X		}
X	} else {
X#		ifdef DEBUG
X		eprintf("write(slave): \n");
X#		endif
X		tp = &pts_tty[dev];
X#		ifdef DEBUG
X		eprintf("write(slave): sending some stuff\n");
X#		endif
X		(*linesw[tp->t_line].l_write)(tp);
X	}
X}
X
Xptyioctl(dev, cmd, arg, mode)
X	dev_t		dev;
X	int		cmd, arg, mode;
X{
X	register struct tty *tp;
X
X	dev = minor(dev);
X	if (Master(dev) == True) {
X#		ifdef DEBUG
X		eprintf("ioctl(master): \n");
X#		endif
X		dev -= PTYCNT;
X		tp = &pts_tty[dev];
X		/*
X	 	 * sorry, but we can't fiddle with the tty struct without
X	 	 * having done LDOPEN
X	 	 */
X		if (tp->t_state & ISOPEN) {
X			if (cmd == TCSBRK && arg ==  NULL) {
X				signal(tp->t_pgrp, SIGINT);
X				if ((tp->t_iflag & NOFLSH) == 0)
X					ttyflush(tp, FREAD|FWRITE);
X			} else {
X				/*
X			 	 * we must flush output to avoid hang in ttywait
X			 	 */
X				if (cmd == TCSETAW || cmd == TCSETAF || 
X				   cmd == TCSBRK || cmd == TIOCSETP)
X					ttyflush(tp, FWRITE);
X				ttiocom(tp, cmd, arg, mode);
X			}
X		}
X	} else {
X#		ifdef DEBUG
X		eprintf("ioctl(slave): \n");
X#		endif
X		tp = &pts_tty[dev];
X		ttiocom(tp, cmd, arg, mode);
X	}
X}
X
Xptsproc(tp, cmd)
Xregister struct tty *tp;
X{
X	register struct ccblock *tbuf;
X	extern ttrstrt();
X
X	switch (cmd) {
X	case T_TIME:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_TIME:\n");
X#		endif
X		tp->t_state &= ~TIMEOUT;
X		goto start;
X	case T_WFLUSH:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_WFLUSH:\n");
X#		endif
X		tp->t_tbuf.c_size  -= tp->t_tbuf.c_count;
X		tp->t_tbuf.c_count = 0;
X		/* fall through */
X	case T_RESUME:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_RESUME:\n");
X#		endif
X		tp->t_state &= ~TTSTOP;
X		/* fall through */
X	case T_OUTPUT:
Xstart:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_OUTPUT:\n");
X#		endif
X		if (tp->t_state & (TTSTOP|TIMEOUT))
X			break;
X#		ifdef DEBUG
X		eprintf("ptsproc: T_OUTPUT: past(TTSTOP|TIMEOUT)");
X#		endif
X		tbuf = &tp->t_tbuf;
X		if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
X#		ifdef DEBUG
X		eprintf("ptsproc: T_OUTPUT: tbuf empty, may break\n");
X#		endif
X			if (tbuf->c_ptr)
X				tbuf->c_ptr -= tbuf->c_size;
X			if (!(CPRES & (*linesw[tp->t_line].l_output)(tp)))
X				break;
X		}
X		if (tbuf->c_count && (ptystate[tp-pts_tty] & MRWAIT)) {
X#		ifdef DEBUG
X		eprintf("ptsproc: T_OUTPUT: waking up master\n");
X#		endif
X			ptystate[tp-pts_tty] &= ~MRWAIT;
X			wakeup((caddr_t)&tp->t_rloc);
X		}
X#		ifdef DEBUG
X		eprintf("ptsproc: T_OUTPUT: leaving end\n");
X#		endif
X		break;
X	case T_SUSPEND:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_SUSPEND:\n");
X#		endif
X		tp->t_state |= TTSTOP;
X		break;
X	case T_BLOCK:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_BLOCK:\n");
X#		endif
X		/*
X		 * the check for ICANON appears to be neccessary
X		 * to avoid a hang when overflowing input
X		 */
X		if ((tp->t_iflag & ICANON) == 0)
X			tp->t_state |= TBLOCK;
X		break;
X	case T_BREAK:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_BREAK:\n");
X#		endif
X		tp->t_state |= TIMEOUT;
X		timeout(ttrstrt, tp, HZ/4);
X		break;
X#ifdef T_LOG_FLUSH
X	case T_LOG_FLUSH:
X#endif
X	case T_RFLUSH:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_RFLUSH:\n");
X#		endif
X		if (!(tp->t_state & TBLOCK))
X			break;
X		/* fall through */
X	case T_UNBLOCK:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_UNBLOCK:\n");
X#		endif
X		tp->t_state &= ~(TTXOFF|TBLOCK);
X		/* fall through */
X	case T_INPUT:
X#		ifdef DEBUG
X		eprintf("ptsproc: T_INPUT:\n");
X#		endif
X		if (ptystate[tp-pts_tty] & MWWAIT) {
X			ptystate[tp-pts_tty] &= ~MWWAIT;
X#			ifdef DEBUG
X			eprintf("ptsproc: T_INPUT: waking up master\n");
X#			endif
X			wakeup((caddr_t)&tp->t_wloc);
X		}
X		break;
X	default:
X#		ifdef DEBUG
X		eprintf("ptsproc: default:\n");
X#		else
X		;
X#		endif
X	}
X}
X	
X/* This routine used to be a stub, however, an industrious soul found
X * the release routine caused a panic whenever the driver is released
X * and some ptys are still open.  The simple 'for' loop fixes this 
X * problem.
X *
X * Credit should be given to:
X * Mike "Ford" Ditto
X * kenobi!ford@crash.CTS.COM, ...!crash!kenobi!ford
X * for finding the bug and writing the for loop.
X *
X * [Eric H. Herrin II, 10-7-87]
X */
Xptyrelease()
X{
X	register int 	i;
X
X#	ifdef DEBUG
X	eprintf("ptyrelease:\n");
X#	endif
X	for (i=0; i<PTYCNT; i++)
X		if ((ptystate[i] & (ISOPEN|MOPEN)) || 
X                   (pts_tty[i].t_state & WOPEN)) {
X			u.u_error = EBUSY;
X			return;
X		}
X	return;
X}
SHAR_EOF
if test 9946 -ne "`wc -c < 'pty.c'`"
then
	echo shar: error transmitting "'pty.c'" '(should have been 9946 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pty.h'" '(854 characters)'
if test -f 'pty.h'
then
	echo shar: will not over-write existing file "'pty.h'"
else
sed 's/^X//'  >'pty.h' <<'SHAR_EOF'
X/* pty.h - Eric H. Herrin II (eric@ms.uky.edu)
X * 
X * some elementary definitions for the pty driver (UnixPC version)
X *
X * Version 2.1
X */
X
Xint ptsproc();
X
X#define True  (1 == 1)
X#define False (0 == 1)
X
X/*  This is the total number of ptys.  Note the maximum number here is
X *  currently 64 for the UnixPC (128 minor devices/2 minor devices per pty
X *  yields 64 total ptys).  I really don't see the need for more than 32
X *  on the 3B1, however, if someone does, then (s)he can change it.
X */
X#include "number-ptys.h"
X#define PTYCNT (dev_t)NUMBER_OF_PTYS
X
X/* some definitions to include kernel info from system header files.
X */
X#define KERNEL 1
X#define defined_io 1
X#define NOSTREAMS 1
X
X#define UNIXPC 1
X
X/* This macro returns True if the parameter is a master minor device number,
X * False otherwise.
X */
X#define Master( dev )	(minor(dev) >= PTYCNT)
SHAR_EOF
if test 854 -ne "`wc -c < 'pty.h'`"
then
	echo shar: error transmitting "'pty.h'" '(should have been 854 characters)'
fi
fi # end of overwriting check
:	End of shell archive
exit 0
-- 
|  Eric Herrin II: {cbosgd!ukma!eric, eric@UKMA.BITNET, eric@ms.uky.edu}      |
|  "But I soon noticed that while I thus wished to                            |
|   think everything false, it was necessarily true                           |
|   that I who thought so was something"   - Rene Descartes                   |