allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/05/89)
Posting-number: Volume 6, Issue 48 Submitted-by: chip@ateng.ateng.com (Chip Salzenberg) Archive-name: ptys.sco This driver adds Berkeley-style ptys (pseudo-ttys) to SCO Xenix/286 and Xenix/386. It has a long history. It is derived from a System V version, but is now specific to SCO Xenix. Note that although Xenix/386 2.3 includes ptys, they are *broken*. They are incapable of non-blocking reads on the master side. This bug hangs Emacs. All Xenix users would be well advised to avoid SCO's pty driver and use this. -- Chip Salzenberg <chip@ateng.com> or <uunet!ateng!chip> A T Engineering "Designed with your mind in mind." -- #! /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: Makefile INSTALL MKDEVS Makefile PTYCNT README.SCO pty.c # Wrapped by chip@ateng on Mon Feb 13 17:51:07 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(357 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Uncomment the definition of FOR286 if you are compling for Xenix/286. X# X#FOR286 = -LARGE -M2em XCFLAGS = ${FOR286} -O -K -DM_KERNEL ${DEFS} X Xall: pty.o Xinstall: pty.o X ./INSTALL Xclean: X rm pty.o Xclobber: clean Xshar: pty.sh X Xpty.o: pty.c PTYCNT X $(CC) $(CFLAGS) -c pty.c X Xpty.sh: X shar Makefile INSTALL MKDEVS Makefile PTYCNT README.SCO pty.c >$@ END_OF_FILE if test 357 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'INSTALL'\" else echo shar: Extracting \"'INSTALL'\" \(1896 characters\) sed "s/^X//" >'INSTALL' <<'END_OF_FILE' X: INSTALL X# Xenix pty installation. X Xif [ ! -f /etc/systemid ] Xthen X echo "This is not a Xenix system" 1>&2 X exit 1 Xfi X Xif [ ! -f pty.o ] Xthen X echo "you must make pty.o before running INSTALL" 1>&2 X exit 1 Xfi X XPATH=/usr/sys/conf:$PATH; export PATH X Xcp pty.o /usr/sys/conf X X# NOTE!!!!!!!!!!!!!! X# To change the number of ptys, change the value in PTYCNT X XPTYCNT=`sed -n 's/.*PTYCNT//p' PTYCNT` XMASTERMINOR=`sed -n 's/.*MASTERMINOR//p' PTYCNT` X Xcd /usr/sys/conf X X# get the first available major number. X XPTYMAJOR=0 X Xfor i in `majorsinuse` Xdo X [ $i != $PTYMAJOR ] && break X PTYMAJOR=`expr $i + 1` Xdone X Xconfigure -a ptyopen ptyclose ptyread ptywrite ptyioctl -m $PTYMAJOR -c X Xif [ $? -ne 0 ] Xthen X echo "pty cannot be added to the master file" 1>&2 X exit 1 Xfi X Xif [ $? -ne 0 ] Xthen X echo "support files not updated" 1>&2 X exit 1 Xfi X X# make the pty device files in /dev X XLETTER=p X Xcnt=0 Xwhile [ $cnt -lt $PTYCNT ] 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=$LETTER$y X if [ $cnt -ge ${PTYCNT} ] X then X break X fi X X [ -c /dev/pty$i ] && rm -f /dev/pty$i X [ -c /dev/tty$i ] && rm -f /dev/tty$i X X /etc/mknod /dev/pty$i c ${PTYMAJOR} \ X `expr $cnt + $MASTERMINOR` && X /etc/mknod /dev/tty$i c ${PTYMAJOR} $cnt || X exit 1 X chmod 666 /dev/pty$i /dev/tty$i X chown root /dev/pty$i /dev/tty$i X chgrp root /dev/pty$i /dev/tty$i X X cnt=`expr $cnt + 1` X done X LETTER=`echo $LETTER | tr '[a-z][A-Y]' '[b-z][A-Z]'` Xdone X X# add pty.o to the link_xenix script X Xif fgrep pty.o link_xenix >/dev/null Xthen X : fine Xelse X ed - link_xenix <<'-EOF' X /kid\.o/s//kid.o pty.o/ X w X EOF Xfi X X# relink the kernel X Xsh -v link_xenix || exit 1 X X# tell the user what to do next X Xecho "" Xecho "The new kernel with ptys has been linked as /usr/sys/conf/xenix." Xecho "To make this kernel the default, type the following commands:" Xecho " mv /xenix /xenix.prev" Xecho " ln /usr/sys/conf/xenix /" Xecho "" END_OF_FILE if test 1896 -ne `wc -c <'INSTALL'`; then echo shar: \"'INSTALL'\" unpacked with wrong size! fi chmod +x 'INSTALL' # end of 'INSTALL' fi if test -f 'MKDEVS' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MKDEVS'\" else echo shar: Extracting \"'MKDEVS'\" \(697 characters\) sed "s/^X//" >'MKDEVS' <<'END_OF_FILE' X# make the pty device files in /dev X XPTYCNT=`sed -n 's/.*PTYCNT//p' PTYCNT` XMASTERMINOR=`sed -n 's/.*MASTERMINOR//p' PTYCNT` X XPTYMAJOR=10 XLETTER=p X Xcnt=0 Xwhile [ $cnt -lt $PTYCNT ] 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=$LETTER$y X if [ $cnt -ge ${PTYCNT} ] X then X break X fi X X [ -c /dev/pty$i ] && rm -f /dev/pty$i X [ -c /dev/tty$i ] && rm -f /dev/tty$i X X /etc/mknod /dev/pty$i c ${PTYMAJOR} \ X `expr $cnt + $MASTERMINOR` && X /etc/mknod /dev/tty$i c ${PTYMAJOR} $cnt || X exit 1 X chmod 666 /dev/pty$i /dev/tty$i X chown root /dev/pty$i /dev/tty$i X chgrp root /dev/pty$i /dev/tty$i X X cnt=`expr $cnt + 1` X done X LETTER=`echo $LETTER | tr '[a-z][A-Y]' '[b-z][A-Z]'` Xdone END_OF_FILE if test 697 -ne `wc -c <'MKDEVS'`; then echo shar: \"'MKDEVS'\" unpacked with wrong size! fi chmod +x 'MKDEVS' # end of 'MKDEVS' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(357 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Uncomment the definition of FOR286 if you are compling for Xenix/286. X# X#FOR286 = -LARGE -M2em XCFLAGS = ${FOR286} -O -K -DM_KERNEL ${DEFS} X Xall: pty.o Xinstall: pty.o X ./INSTALL Xclean: X rm pty.o Xclobber: clean Xshar: pty.sh X Xpty.o: pty.c PTYCNT X $(CC) $(CFLAGS) -c pty.c X Xpty.sh: X shar Makefile INSTALL MKDEVS Makefile PTYCNT README.SCO pty.c >$@ END_OF_FILE if test 357 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'PTYCNT' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'PTYCNT'\" else echo shar: Extracting \"'PTYCNT'\" \(131 characters\) sed "s/^X//" >'PTYCNT' <<'END_OF_FILE' X/* be careful; this file is read and used by the INSTALL script */ X#define PTYCNT 32 X#define MASTERMINOR 128 X#define MASTERBIT 128 END_OF_FILE if test 131 -ne `wc -c <'PTYCNT'`; then echo shar: \"'PTYCNT'\" unpacked with wrong size! fi # end of 'PTYCNT' fi if test -f 'README.SCO' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README.SCO'\" else echo shar: Extracting \"'README.SCO'\" \(1521 characters\) sed "s/^X//" >'README.SCO' <<'END_OF_FILE' XPublic domain pty driver originally written by: X XCopyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH X XMods (for 3b1) by: X 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, eric@ms.uky.csnet, !cbosgd!ukma!eric X X Also modified by: X Mike "Ford" Ditto X Chief Executive Hacker, Omnicron Data Systems X P.O. Box 1721 X Bonita, CA 92002 X (619) 421-1055 X kenobi!ford@crash.CTS.COM, ...!crash!kenobi!ford X X Modifications for SCO XENIX {2,3}86 by: X Keith Gabryelski X UUCP: {cbosgd, hplabs!hp-sdd, sdcsvax, nosc}!crash!portnoy!ag X INET: ag@portnoy.cts.com X ARPA: crash!portnoy!ag@nosc.mil X X Further modifications to Xenix installation by: X Chip Salzenberg X A T Engineering X <chip@ateng.com> or <uunet!ateng!chip> X X XPick a directory for this software to reside. Mine was /usr/sys/conf/pty. Xuntar and uncompress (if need be) and look at the Makefile. Uncomment Xthe definition of FOR286 if you are using a 286 machine. X X make X XIf that worked, try: X X make install X XThen, if that worked, follow the displayed directions. When you reboot your Xmachine, you should have pty's. X XTo test: X compile emacs with: X X #define FIRST_PTY_LETTER 'p' X #define HAVE_PTYS X #define subprocesses X X and try: X M-x shell X X When you get a shell prompt try: X tty (and) X stty -a X X You should be on a tty named "ttyp0" or something real similar. X XOr: X cat /dev/ttyp0 & X date > /dev/ptyp0 X X (This should print the date) X XPax, Keith END_OF_FILE if test 1521 -ne `wc -c <'README.SCO'`; then echo shar: \"'README.SCO'\" unpacked with wrong size! fi # end of 'README.SCO' fi if test -f 'pty.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pty.c'\" else echo shar: Extracting \"'pty.c'\" \(12061 characters\) sed "s/^X//" >'pty.c' <<'END_OF_FILE' X X 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 * Further modified and improved by: X * Mike "Ford" Ditto X * Chief Executive Hacker, Omnicron Data Systems X * kenobi!ford@crash.CTS.COM, ...!crash!kenobi!ford X * X * See README.3b1 for details of port and installation. X */ X X/* X * Yet more geefing done by: X * Keith M. Gabryelski X * Random X * ...crash!portnoy!ag, ag@portnoy.cts.com X * X * See README.SCO for detials of port and installation. X */ X /* XON, XOFF control flow added by Bob Best (bob@dhw68k.cts.com) X 6/13/88 X*/ X X/* The UnixPC does not have any extra bits in t_state, thus X * we provide other means of storing the state. X */ X#define MRWAIT 0x01 /* master waiting in read */ X#define t_rloc t_cc[0] /* wchannel for MRWAIT */ X#define MWWAIT 0x02 /* master waiting in write */ X#define t_wloc t_cc[1] /* wchannel for MWWAIT */ X#define MOPEN 0x04 /* master is open */ X#define SOPEN 0x08 /* slave is open */ X X#define KERNEL 1 X#define defined_io 1 X 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/page.h" /* structure defs --kmg */ X#include "sys/dir.h" /* structure defs --kmg */ X#include "sys/seg.h" /* structure defs --kmg */ X#include "sys/proc.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" /* included in sys/tty.h --kmg */ X#include "sys/ttold.h" X X#define eprintf printf /* So what do ya want, whicker? */ X X#include "PTYCNT" /* find out about PTYCNT and MASTERMINOR */ X X/* PTYCNT is the maximum number of master/slave pairs that will work */ X#ifndef PTYCNT X#define PTYCNT 32 X#endif X X/* MASTERMINOR is the lowest minor device number for master devices */ X#ifndef MASTERMINOR X#define MASTERMINOR ((minor(0xFFFF)+1)/2) X#endif X X/* This macro is true if the device number passed corresponds to */ X/* the MASTER side of a pty */ X#ifdef MASTERBIT X#define Master(dev) ((dev)&MASTERBIT) X#else X#define Master(dev) (minor((dev)) >= MASTERMINOR) X#endif MASTERBIT X X/* The tty structures must be local to this driver, since there X * is no conf.c X */ X Xstruct tty pty_tty[PTYCNT]; Xint ptystate[PTYCNT]; X Xint ptsproc(); X X Xptyopen(dev, flag) X dev_t dev; X int flag; X{ X register struct tty *tp; X X dev = minor(dev); X if (Master(dev)) { X# ifdef DEBUG X eprintf("pty: open(master): \n"); X# endif X dev -= MASTERMINOR; X tp = &pty_tty[dev]; X if (dev >= PTYCNT) { 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 ptystate[dev] |= MOPEN; X tp->t_state |= CARR_ON; X if (tp->t_state & WOPEN) X { X tp->t_state &= ~WOPEN; X wakeup((caddr_t)&tp->t_canq); X } X } else { X# ifdef DEBUG X eprintf("pty: open(slave): \n"); X# endif X tp = &pty_tty[dev]; X if (dev >= PTYCNT) { 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 (!(flag & FNDELAY)) { X while ((tp->t_state & CARR_ON) == 0) { X /* eprintf("slave_open going to sleep!"); */ X tp->t_state |= WOPEN; X if (sleep((caddr_t)&tp->t_canq, TTIPRI|PCATCH)) { X tp->t_state &= ~WOPEN; X wakeup((caddr_t)&tp->t_canq); X /* eprintf("slave open: interrupted"); */ X u.u_error = EINTR; X return; X } X /* eprintf("slave_open woke up! %x %x", X tp->t_state, u.u_procp->p_sig); */ X } X } X ptystate[dev] |= SOPEN; X (*linesw[tp->t_line].l_open)(tp); X } X} X Xptyclose(dev, flag) X dev_t dev; X int flag; X{ X register struct tty *tp; X X dev = minor(dev); X if (Master(dev)) { X# ifdef DEBUG X eprintf("pty: close(master): \n"); X# endif X dev -= MASTERMINOR; X tp = &pty_tty[dev]; X if (!(ptystate[dev] & SOPEN)) { X tp->t_tbuf.c_size -= tp->t_tbuf.c_count; X tp->t_tbuf.c_count = 0; X tp->t_rbuf.c_size -= tp->t_rbuf.c_count; X tp->t_rbuf.c_count = 0; X (*linesw[tp->t_line].l_close)(tp); X } else { 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("pty: close(slave): \n"); X# endif X tp = &pty_tty[dev]; X if (!(ptystate[dev] & MOPEN)) { X tp->t_tbuf.c_size -= tp->t_tbuf.c_count; X tp->t_tbuf.c_count = 0; X tp->t_rbuf.c_size -= tp->t_rbuf.c_count; X tp->t_rbuf.c_count = 0; X (*linesw[tp->t_line].l_close)(tp); X } X ptystate[dev] &= ~SOPEN; X if (ptystate[dev] & MRWAIT) X { X ptystate[dev] &= ~MRWAIT; X wakeup((caddr_t)&tp->t_rloc); X } X if (ptystate[dev] & MWWAIT) X { X ptystate[dev] &= ~MRWAIT; X wakeup((caddr_t)&tp->t_wloc); X } X } X} X Xptyread(dev) X dev_t dev; X{ X register struct tty *tp; X register n; X X dev = minor(dev); X if (Master(dev)) { X int didsome=0; X# ifdef DEBUG X eprintf("pty: read(master): \n"); X# endif X dev -= MASTERMINOR; X tp = &pty_tty[dev]; X while (u.u_count) { 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 (didsome) X break; X if ((ptystate[dev] & SOPEN) == 0) { X u.u_error = EIO; X return; X } X if (u.u_fmode & FNDELAY) X break; X# ifdef DEBUG X eprintf("pty: 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("pty: 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("pty: read(master): got some stuff\n"); X# endif X ++didsome; 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("pty: read(slave): \n"); X# endif X tp = &pty_tty[dev]; X# ifdef DEBUG X eprintf("pty: read(slave): got some stuff\n"); X# endif X (*linesw[tp->t_line].l_read)(tp); X } X} X Xptywrite(dev) X dev_t dev; X{ X register struct tty *tp; X register n; X int flg; X X dev = minor(dev); X if (Master(dev)) { X# ifdef DEBUG X eprintf("pty: write(master): \n"); X# endif X dev -= MASTERMINOR; X tp = &pty_tty[dev]; X while (u.u_count) { X if ((tp->t_state & TBLOCK) X || tp->t_rbuf.c_ptr == NULL) { X if ((ptystate[dev] & SOPEN) == 0) { X u.u_error = EIO; X return; X } X if (u.u_fmode & FNDELAY) X break; X ptystate[dev] |= MWWAIT; X# ifdef DEBUG X eprintf("pty: write(master): going to sleep\n"); X# endif X X sleep((caddr_t)&tp->t_wloc, TTOPRI); X X# ifdef DEBUG X eprintf("pty: 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("pty: write(master): sending some stuff\n"); X# endif X flg=tp->t_iflag; X if(flg & IXON) { X char ctmp; X copyin(u.u_base, &ctmp, 1); X ctmp &= 0177; X if(tp->t_state & TTSTOP) { X if(ctmp==CSTART || flg & IXANY) X (*tp->t_proc)(tp,T_RESUME); X } else if(ctmp==CSTOP) { X (*tp->t_proc)(tp,T_SUSPEND); X } X if(ctmp==CSTART || ctmp==CSTOP) { X u.u_base++; X u.u_count--; X continue; X } X } X if (copyin(u.u_base,tp->t_rbuf.c_ptr, 1)) { X u.u_error = EFAULT; X break; X } X tp->t_rbuf.c_count--; X u.u_base++; X u.u_count--; X } X (*linesw[tp->t_line].l_input)(tp); X } X } else { X# ifdef DEBUG X eprintf("pty: write(slave): \n"); X# endif X tp = &pty_tty[dev]; X# ifdef DEBUG X eprintf("pty: 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)) { X# ifdef DEBUG X eprintf("pty: ioctl(master): \n"); X# endif X dev -= MASTERMINOR; X tp = &pty_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 == 0) { /* 0 was NULL X --kmg */ 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 } else X u.u_error = EINVAL; X } else { X# ifdef DEBUG X eprintf("pty: ioctl(slave): \n"); X# endif X tp = &pty_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("pty: ptsproc: T_TIME:\n"); X# endif X tp->t_state &= ~TIMEOUT; X goto start; X case T_WFLUSH: X# ifdef DEBUG X eprintf("pty: 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("pty: ptsproc: T_RESUME:\n"); X# endif X tp->t_state &= ~TTSTOP; X /* fall through */ X case T_OUTPUT: Xstart: X# ifdef DEBUG X eprintf("pty: ptsproc: T_OUTPUT:\n"); X# endif X if (tp->t_state & (TTSTOP|TIMEOUT)) X break; X# ifdef DEBUG X eprintf("pty: 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("pty: 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-pty_tty] & MRWAIT)) { X# ifdef DEBUG X eprintf("pty: ptsproc: T_OUTPUT: waking up master\n"); X# endif X ptystate[tp-pty_tty] &= ~MRWAIT; X wakeup((caddr_t)&tp->t_rloc); X } X# ifdef DEBUG X eprintf("pty: ptsproc: T_OUTPUT: leaving end\n"); X# endif X break; X case T_SUSPEND: X# ifdef DEBUG X eprintf("pty: ptsproc: T_SUSPEND:\n"); X# endif X tp->t_state |= TTSTOP; X break; X case T_BLOCK: X# ifdef DEBUG X eprintf("pty: 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("pty: 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("pty: 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("pty: ptsproc: T_UNBLOCK:\n"); X# endif X tp->t_state &= ~(TTXOFF|TBLOCK); X /* fall through */ X case T_INPUT: X# ifdef DEBUG X eprintf("pty: ptsproc: T_INPUT:\n"); X# endif X if (ptystate[tp-pty_tty] & MWWAIT) { X ptystate[tp-pty_tty] &= ~MWWAIT; X# ifdef DEBUG X eprintf("pty: 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("pty: ptsproc: default:\n"); X# else X ; X# endif X } X} X X/* PTYRELEASE is a 3b1ism. X * X * ptyrelease() X * { X * register i; X * # ifdef DEBUG X * eprintf("pty: ptyrelease:\n"); X * # endif X * for ( i=0 ; i<PTYCNT ; ++i ) X * if ( (ptystate[i] & (SOPEN|MOPEN)) X * || (pty_tty[i].t_state & WOPEN) ) X * { X * u.u_error = EBUSY; X * return; X * } X * return; X * } X */ END_OF_FILE if test 12061 -ne `wc -c <'pty.c'`; then echo shar: \"'pty.c'\" unpacked with wrong size! fi # end of 'pty.c' fi echo shar: End of shell archive. exit 0