v08i027: Microport System V/286 pty driver

Brandon S. Allbery - comp.sources.misc allbery at uunet.UU.NET
Thu Sep 7 12:01:03 AEST 1989


Posting-number: Volume 8, Issue 27
Submitted-by: jay at splut.conmicro.com (Jay "you ignorant splut!" Maynard)
Archive-name: pty_uport

I've had sporadic requests for this one.
It's a gross, unsubtle hack based on Jens-Uwe Mager's original, with
Michael Bloom's mode incorporated as well (he did the hard work).

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  READ_ME READ_ME.orig pty.c mkpty
# Wrapped by jay at splut on Sat Sep  2 17:44:40 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f READ_ME -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"READ_ME\"
else
echo shar: Extracting \"READ_ME\" \(1487 characters\)
sed "s/^X//" >READ_ME <<'END_OF_READ_ME'
XThis version of the pty driver has been hacked upon until it worked under
XMicroport System V/AT. It's probably full of system no-nos, as I am no
Xkernel hacker. In particular, the declaration of pty_tty[] and pty_stat[] is
Xhorribly wrong; if you know the right way to do that, PLEASE let me
Xknow. I have tested it under System V/AT versions 2.3 and 2.4, and it
Xappears to work. This version does NOT work as-is under System V/386.
X
XThe required lines for the master file are:
X
Xpts	0	ocrwi	ct	pts	0	14	32
Xptm	0	ocrwi	c	ptm	0	15	32
X                                                ^^---major device number;
X                                                change these if you have
X                                                conflicts with other
X                                                device drivers
X
Xand for the dfile:
X
Xpts	0	32
Xptm	0	32
X
XThis can be installed using the usual driver installation:
X1) Put pty.c in /usr/linkkit/io.
X2) cd to /usr/linkkit/io, then:
X	cc -c -Ml -O pty.c
X	ar r ../lib2 pty.o
X                   ^--------if your lib2 fills up, create a new one (I
X                            used lib5; it must be lib[0-9])
X3) Become superuser, and then:
X	cd /usr/linkkit/cf
X	[edit master, dfile.wini if you haven't]
X	make wini
X4) The file /usr/linkkit/system5 can be installed as your kernel and
Xbooted.
X5) The mkpty shell script will automagically build 32 master and slave
Xdevice files. It will figure out which major device numbers you assigned.
X
XGood luck...Jay
X
END_OF_READ_ME
if test 1487 -ne `wc -c <READ_ME`; then
    echo shar: \"READ_ME\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f READ_ME.orig -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"READ_ME.orig\"
else
echo shar: Extracting \"READ_ME.orig\" \(1624 characters\)
sed "s/^X//" >READ_ME.orig <<'END_OF_READ_ME.orig'
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.
END_OF_READ_ME.orig
if test 1624 -ne `wc -c <READ_ME.orig`; then
    echo shar: \"READ_ME.orig\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f pty.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"pty.c\"
else
echo shar: Extracting \"pty.c\" \(8704 characters\)
sed "s/^X//" >pty.c <<'END_OF_pty.c'
X/*
X * pty.c - Berkeley style pseudo tty driver for system V
X *
X * Additions marked:
X * TTI - for the changes made by Michael Bloom at Citicorp/TTI to make
X *       it not Sperry 5000-series dependent. He did all the hard work.
X *       The original code used some unused bits in the tty structure;
X *       they turned out to be only unused in the Sperry/NCR Tower version.
X *       He added the code to move the status bits out. He also added the
X *       DEBUG code, which helped me to understand a little better how
X *       the bytes flowed.
X * JRM - my unsubtle hacks to make it work with Microport.
X *
X * Other portions:
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#define MAXPTYS 32
X
X/* TTI: */
X#define MRWAIT	01		/* master waiting in read */
X#define t_rloc	t_cc[0]		/* rchannel */
X
X#define MWWAIT	02		/* master waiting in write */
X#define t_wloc	t_cc[1]		/* wchannel */
X
X#define MOPEN	04		/* master is open */
X/* end TTI */
X
X#include "sys/param.h"
X#include "sys/types.h"
X#include "sys/sysmacros.h"
X#include "sys/seg.h"
X#include "sys/systm.h"
X#include "sys/file.h"
X#include "sys/conf.h"
X
X/* JRM: following removed
X#include "sys/page.h"
X#include "sys/immu.h"
X#include "sys/region.h"
X*/
X
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/* JRM:
X * note: this is not subtle...if you know of a slick way to get this from
X *       config, please tell me about it! */
Xextern int pts_cnt;
Xstruct tty pts_tty[MAXPTYS];
Xint pts_state[MAXPTYS];
X
X/*
X * slave side is a fairly standard system V tty driver
X */
Xptsopen(fdev, flag) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X	extern int ptsproc();
X
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 (pts_state[dev] & MOPEN) /* TTI */
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
Xptswrite(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
X#ifdef DEBUG
X		printf("T_TIME\n"); /* TTI */
X#endif DEBUG
X	(*linesw[tp->t_line].l_write)(tp);
X}
X
Xptsread(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
X	(*linesw[tp->t_line].l_read)(tp);
X}
X
Xptsclose(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X	
X	(*linesw[tp->t_line].l_close)(tp);
X	tp->t_state &= ~CARR_ON;
X}
X
Xptsioctl(fdev, cmd, arg, mode)
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
X	ttiocom(tp, cmd, arg, mode);
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		printf("T_TIME\n"); /* TTI */
X#endif
X		tp->t_state &= ~TIMEOUT;
X		goto start;
X	case T_WFLUSH:
X#ifdef DEBUG
X		printf("T_WFLUSH\n"); /* TTI */
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		printf("T_RESUME\n"); /* TTI */
X#endif
X		tp->t_state &= ~TTSTOP;
X		/* fall through */
X	case T_OUTPUT:
X#ifdef DEBUG
X		printf("T_OUTPUT\n"); /* TTI */
X#endif
Xstart:
X		if (tp->t_state & (TTSTOP|TIMEOUT))
X			break;
X		tbuf = &tp->t_tbuf;
X		if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
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 && (pts_state[tp-pts_tty] & MRWAIT)) {
X			pts_state[tp-pts_tty] &= ~MRWAIT; /* TTI */
X			wakeup((caddr_t)&tp->t_rloc);
X		}
X		break;
X	case T_SUSPEND:
X#ifdef DEBUG
X		printf("T_SUSPEND\n"); /* TTI */
X#endif
X		tp->t_state |= TTSTOP;
X		break;
X	case T_BLOCK:
X#ifdef DEBUG
X		printf("T_BLOCK\n"); /* TTI */
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		printf("T_BREAK\n"); /* TTI */
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#ifdef DEBUG
X		printf("T_LOG_FLUSH\n"); /* TTI */
X#endif
X#endif
X	case T_RFLUSH:
X#ifdef DEBUG
X		printf("T_RFLUSH\n"); /* TTI */
X#endif
X		if (!(tp->t_state & TBLOCK))
X			break;
X		/* fall through */
X	case T_UNBLOCK:
X#ifdef DEBUG
X		printf("T_UNBLOCK\n"); /* TTI */
X#endif
X		tp->t_state &= ~(TTXOFF|TBLOCK);
X		/* fall through */
X	case T_INPUT:
X#ifdef DEBUG
X		printf("T_INPUT\n"); /* TTI */
X#endif
X		if (pts_state[tp-pts_tty] & MWWAIT) {
X			pts_state[tp-pts_tty] &= ~MWWAIT; /* TTI */
X			wakeup((caddr_t)&tp->t_wloc);
X		}
X		break;
X#ifdef DEBUG
X	default: /* TTI */
X		printf("ptsproc: cmd %d\n",cmd);
X#endif
X	}
X}
X
X/*
X * master part - not actually like a tty
X */
X
Xptmopen(fdev, flag) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
X#ifdef DEBUG
X	printf("ptmopen(%d)\n",dev); /* TTI */
X#endif
X	if (dev >= pts_cnt) {
X		u.u_error = ENXIO;
X		return;
X	}
X	/*
X	 * allow only one controlling process
X	 */
X	if (pts_state[dev] & MOPEN) { /* TTI */
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; /* TTI */
X	pts_state[dev] |= MOPEN;
X}
X
Xptmread(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X	register n;
X
X	if ((tp->t_state & (ISOPEN|TTIOW)) == 0) { /* TTI */
X#ifdef DEBUG
X	printf("ptmread(%d) EIO\n",dev); /* TTI */
X#endif
X		u.u_error = EIO;
X		return;
X	}
X#ifdef DEBUG
X	printf("ptmread(%d)\n",dev); /* TTI */
X#endif
X	while (u.u_count>0) { /* TTI */
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			pts_state[dev] |= MRWAIT; /* TTI */
X			sleep((caddr_t)&tp->t_rloc, TTIPRI);
X			continue;
X		}
X		n = min(u.u_count, tp->t_tbuf.c_count);
X		if (n) {
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			break; /* JRM: added - without this, the flow from
X			               slave to master is buffered */
X		}
X	}
X}
X
Xptmwrite(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X	register n;
X
X	if ((tp->t_state & ISOPEN) == 0) {
X		u.u_error = EIO;
X		return;
X	}
X#ifdef DEBUG
X	printf("ptmwrite(%d)\n",dev); /* TTI */
X#endif
X	while (u.u_count>0) { /* TTI */
X		if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
X			if (u.u_fmode & FNDELAY)
X				break;
X			pts_state[dev] |= MWWAIT; /* TTI */
X			sleep((caddr_t)&tp->t_wloc, TTOPRI);
X			continue;
X		}
X		n = min(u.u_count, tp->t_rbuf.c_count);
X		if (n) {
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#ifdef vax || m68k /* TTI */
X		/*
X		 * somebody told me this is necessary on the vax
X		 */
X		(*linesw[tp->t_line].l_input)(tp, L_BUF);
X#else
X		(*linesw[tp->t_line].l_input)(tp);
X#endif
X	}
X}
X
Xptmclose(fdev) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
X#ifdef DEBUG
X	printf("ptmclose(%d)\n",dev); /* TTI */
X#endif
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; /* TTI */
X	pts_state[dev] &= ~MOPEN;
X}
X
Xptmioctl(fdev, cmd, arg, mode) /* TTI */
X{
X	register dev = minor(fdev); /* TTI */
X	register struct tty *tp = &pts_tty[dev];
X
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 || cmd == TCSBRK
X			    || cmd == TIOCSETP)
X				ttyflush(FWRITE);
X			ttiocom(tp, cmd, arg, mode);
X		}
X	}
X}
END_OF_pty.c
if test 8704 -ne `wc -c <pty.c`; then
    echo shar: \"pty.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mkpty -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mkpty\"
else
echo shar: Extracting \"mkpty\" \(451 characters\)
sed "s/^X//" >mkpty <<'END_OF_mkpty'
X:
X#!/bin/sh
Xsmajor=`grep pts /usr/linkkit/cf/master|cut -f7`
Xmmajor=`grep ptm /usr/linkkit/cf/master|cut -f7`
Xndevs=`grep pts_cnt /usr/linkkit/cf/conf.c|sed 's/int	pts_cnt = \([0-9]*\);/\1/'`
Xminor=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 [ $minor -ge $ndevs ]; then break; fi
X		/etc/mknod /dev/pty$i c $mmajor $minor
X		/etc/mknod /dev/tty$i c $smajor $minor
X		minor=`expr $minor + 1`
X	done
Xdone
END_OF_mkpty
if test 451 -ne `wc -c <mkpty`; then
    echo shar: \"mkpty\" unpacked with wrong size!
fi
chmod +x mkpty
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0

-- 
Jay Maynard, EMT-P, K5ZC, PP-ASEL   | Never ascribe to malice that which can
jay at splut.conmicro.com       (eieio)| adequately be explained by stupidity.
{attctc,bellcore}!texbell!splut!jay +----------------------------------------
"Rabid rerouters *love* to route mail to devnull at hell.org" - Brandon Allbery



More information about the Comp.sources.misc mailing list