home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-09-11 | 39.4 KB | 1,557 lines |
- Subject: 4.2bsd rlogin enhancements
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 4, Issue 52
- Submitted by: genrad!decvax!philabs!nyit!rick
-
- ---CUT HERE---CUT HERE---CUT HERE---CUT HERE---CUT HERE--CUT HERE--
- echo shar: extracting README
- cat - << \SHAR_EOF > README
- NYIT rlogin performance enhancements 01-Apr-86
-
- INTRODUCTION
- This package contains a set of source code modifications to
- 4.2bsd UNIX to enhance the performance of rlogin connections.
- Performance improvement results from reducing the involvement
- of the agent processes (rlogin and rlogind) in the task of
- passing characters between the client and server hosts.
- In this implementation, the agent processes retain their
- previous function of establishing an rlogin-style connection
- between two hosts; however, once the connection is established,
- the agents sleep until the connection is interrrupted by an
- escape character on the client host, or terminated by either host.
- The character-switching functions formerly performed by rlogin
- and rlogind are now handled entirely within kernel interrupt
- logic, eliminating the delays and scheduling overhead of the
- original implementation and improving response and throughput.
-
- It is important to note that, although the character traffic
- is now being handled exclusively in the kernel, the rlogin
- protocol has been maintained. This ensures that an enhanced
- client can interoperate with a vanilla 4.2bsd server, and
- vice versa, still gaining an improvement in performance.
-
- The implementation is separated into two logical parts: client
- and server. The client part is called the NVT, an acronym for
- Network Virtual Terminal; the server is called the NVS, meaning
- Network Virtual Server. Within the kernel, NVT logic appears
- within a "#ifdef KNVT" conditional, and NVS logic appears
- within a "#ifdef KNVS" conditional. All user-mode NVT logic
- resides in /usr/ucb/rlogin. All user-mode NVS logic resides
- in /etc/rlogind.
-
- AFFECTED SOFTWARE
- The following executables are affected:
-
- 1. The 4.2bsd kernel
- 2. /usr/ucb/rlogin
- 3. /etc/rlogind
-
- The vanilla and enhanced versions of any of these programs can be
- used in any combination with no risk. The NVT and NVS logic
- in the kernel remains dormant unless invoked by an enhanced
- rlogin or rlogind; the enhanced kernel support the vanilla
- rlogin/rlogind as well as their new counterparts. The enhanced
- rlogin and rlogind determine if the kernel offers the enhanced
- NVT or NVS service, and, if not, they will operate in vanilla
- 4.2bsd rlogin mode.
-
- BUGS
- The user interface of rlogin is slightly different with regard
- to the operation of the escape character. This is not an
- unavoidable consequence of this implementation, but rather an
- issue of expediency made during development; it can be fixed.
-
- The implementation within the kernel is practical, but not
- elegant. I grovel in advance for the indulgence of the purists.
- [Remember: you didn't *pay money* to buy this :-)]
-
- No explicit aid is offered for telnet connections; however,
- inspection of this implementation might inspire those who
- use telnet to improve its performance in a similar fashion.
-
-
- CONTENTS OF THIS DISTRIBUTION
- [Explanations of changes appear in brackets]
-
- README This file
- diff_files diff -c of kernel conf/files
- [add two new kernel source files: tty_nv[st].c]
- diff_ioctl.h diff -c of kernel h/ioctl.h
- [add ioctl defs SIOCJNVS and SIOCJNVT]
- diff_rlogin.c diff -c of source for /usr/ucb/rlogin
- [invoke SIOCJNVT ioctl to join socket and tty]
- diff_rlogind.c diff -c of source for /etc/rlogind
- [invoke SIOCJNVS ioctl to join socket and pty]
- diff_socketvar.h diff -c of kernel h/socketvar.h
- [add defs SB_NVS and SB_NVT]
- diff_tcp_usrreq.c diff -c of kernel netinet/tcp_usrreq.c
- [add code to handle SIOCJNVS and SIOCJNVT ioctls]
- diff_tty.c diff -c of kernel sys/tty.c
- [add hook in ttyinput() to intercept NVT characters]
- diff_tty.h diff -c of kernel h/tty.h
- [add def TS_NVT]
- diff_tty_pty.c diff -c of kernel sys/tty_pty.c
- [add subroutines driven off pty data structures]
- diff_tty_subr.c diff -c of kernel sys/tty_subr.c
- [remove #ifdef notdef surrounding q_to_b]
- diff_uipc_socket2.c diff -c of kernel sys/uipc_socket2.c
- [add hooks in sbwakeup() to intercept NVS/NVT traffic]
- tty_nvs.c New kernel source file sys/tty_nvs.c
- [most of the logic to implement NVS service]
- tty_nvt.c New kernel source file sys/tty_nvt.c
- [most of the logic to implement NVT service]
-
- INSTALLATION
- 1. Copy tty_nvs.c and tty_nvt.c into /sys/sys.
- 2. Locate files whose names begin with "diff_". These files
- represent Berkeley 4.2bsd source modules that must be modified.
- Apply the changes in each "diff_" file to their respective
- 4.2bsd source modules.
- 3. cd to /sys/conf and add the following two lines to your
- kernel configuration file:
- options NKVS
- options KNVT
- 4. Run /etc/config to regenerate the kernel configuration files.
- 5. cd to the kernel directory and run "make" to build a new kernel.
- 6. Install the new kernel in /.
- 7. Recompile and install /usr/ucb/rlogin (must be setuid-root).
- 8. Recompile and install /etc/rlogind.
- 9. Reboot and enjoy more responsive rlogin connections.
-
-
- Please address comments, questions, bugfixes (please, no flames
- about hooks in ttyinput() or sbwakeup()) to the author:
-
- Rick Ace
- New York Institute of Technology
- Computer Graphics Laboratory
- Wheatley Road
- Old Westbury, NY 11568
-
- (516) 686-7644
-
- USENET: {decvax,seismo}!philabs!nyit!rick
- SHAR_EOF
- echo shar: extracting diff_files
- cat - << \SHAR_EOF > diff_files
- *** conf/files420 Sun Jun 12 18:45:11 1983
- --- conf/files Tue Apr 1 07:20:48 1986
- ***************
- *** 102,104
- sys/vm_swap.c standard
- sys/vm_swp.c standard
- sys/vm_text.c standard
-
- --- 102,106 -----
- sys/vm_swap.c standard
- sys/vm_swp.c standard
- sys/vm_text.c standard
- + sys/tty_nvs.c standard
- + sys/tty_nvt.c standard
- SHAR_EOF
- echo shar: extracting diff_ioctl.h
- cat - << \SHAR_EOF > diff_ioctl.h
- *** h/ioctl.h420 Sat Aug 20 19:04:34 1983
- --- h/ioctl.h Tue Apr 1 07:27:50 1986
- ***************
- *** 194,199
- #define SIOCATMARK _IOR(s, 7, int) /* at oob mark? */
- #define SIOCSPGRP _IOW(s, 8, int) /* set process group */
- #define SIOCGPGRP _IOR(s, 9, int) /* get process group */
-
- #define SIOCADDRT _IOW(r, 10, struct rtentry) /* add route */
- #define SIOCDELRT _IOW(r, 11, struct rtentry) /* delete route */
-
- --- 194,201 -----
- #define SIOCATMARK _IOR(s, 7, int) /* at oob mark? */
- #define SIOCSPGRP _IOW(s, 8, int) /* set process group */
- #define SIOCGPGRP _IOR(s, 9, int) /* get process group */
- + #define SIOCJNVT _IOW(s, 70, int) /* join NVT tty&socket */
- + #define SIOCJNVS _IOW(s, 71, int) /* join NVS pty&socket */
-
- #define SIOCADDRT _IOW(r, 10, struct rtentry) /* add route */
- #define SIOCDELRT _IOW(r, 11, struct rtentry) /* delete route */
- SHAR_EOF
- echo shar: extracting diff_rlogin.c
- cat - << \SHAR_EOF > diff_rlogin.c
- *** 4.2rlogin.c Tue Apr 1 12:12:32 1986
- --- rlogin.c Tue Apr 1 11:17:44 1986
- ***************
- *** 144,149
- signal(SIGINT, exit);
- signal(SIGHUP, exit);
- signal(SIGQUIT, exit);
- child = fork();
- if (child == -1) {
- perror("rlogin: fork");
-
- --- 144,150 -----
- signal(SIGINT, exit);
- signal(SIGHUP, exit);
- signal(SIGQUIT, exit);
- + knvt(); /* returns iff no kernel NVT service */
- child = fork();
- if (child == -1) {
- perror("rlogin: fork");
- ***************
- *** 376,380
- {
- signal(SIGPIPE, SIG_IGN);
- prf("\007Connection closed.");
- done();
- }
-
- --- 377,429 -----
- {
- signal(SIGPIPE, SIG_IGN);
- prf("\007Connection closed.");
- + done();
- + }
- +
- + nvtsig()
- + {
- + signal(SIGINT, nvtsig);
- + }
- +
- + /*
- + * Invoke kernel NVT service
- + *
- + * Returns iff kernel does not support NVT service (i.e., do the
- + * job the old-fashioned way)
- + */
- + knvt()
- + {
- + char cmdc;
- + static int ttyfd = 0;
- +
- + signal(SIGINT, nvtsig);
- + notc.t_intrc = cmdchar;
- + mode(1);
- + while (ioctl(rem, SIOCJNVT, &ttyfd) < 0) {
- + if (errno != EINTR) {
- + /*
- + * Unexpected error, assume the kernel does not
- + * honor the ioctl call and return to doit().
- + */
- + notc.t_intrc = -1;
- + return;
- + }
- + /*
- + * The user typed the escape character. Read the next
- + * character from the terminal to see what I should do.
- + */
- + if (read(0, &cmdc, 1) != 1)
- + cmdc = deftc.t_eofc;
- + if (cmdc == '.' || cmdc == deftc.t_eofc)
- + break;
- + if (cmdc == defltc.t_suspc ||
- + cmdc == defltc.t_dsuspc) {
- + write(0, CRLF, sizeof(CRLF));
- + mode(0);
- + kill(getpid(), SIGTSTP);
- + mode(1);
- + }
- + }
- + prf("\r\nConnection closed");
- done();
- }
- SHAR_EOF
- echo shar: extracting diff_rlogind.c
- cat - << \SHAR_EOF > diff_rlogind.c
- *** 4.2rlogind.c Tue Apr 1 12:12:50 1986
- --- rlogind.c Tue Apr 1 09:32:50 1986
- ***************
- *** 200,205
- ioctl(p, TIOCPKT, &on);
- signal(SIGTSTP, SIG_IGN);
- signal(SIGCHLD, cleanup);
- for (;;) {
- int ibits = 0, obits = 0;
-
-
- --- 200,219 -----
- ioctl(p, TIOCPKT, &on);
- signal(SIGTSTP, SIG_IGN);
- signal(SIGCHLD, cleanup);
- + /* BEGIN NVS support */
- + /*
- + * If kernel supports high-performance NVS operation,
- + * invoke it and sleep until connection is broken.
- + * If remote end dies: ioctl() returns 0.
- + * If local job exits: ioctl() returns -1 / EINTR.
- + * Any other return from ioctl() is interpreted to mean
- + * the kernel doesn't support high-performance NVS
- + * operation, so do the job the standard Berkeley way.
- + */
- + if (ioctl(f, SIOCJNVS, (char *)&p) == 0 ||
- + errno == EINTR)
- + cleanup();
- + /* END NVS support */
- for (;;) {
- int ibits = 0, obits = 0;
-
- ***************
- *** 292,297
-
- rmut();
- vhangup(); /* XXX */
- shutdown(netf, 2);
- kill(0, SIGKILL);
- exit(1);
-
- --- 306,313 -----
-
- rmut();
- vhangup(); /* XXX */
- + #ifdef notdef
- + /* NYIT remove bogus statement (netf is never set!) */
- shutdown(netf, 2);
- #endif
- kill(0, SIGKILL);
- ***************
- *** 293,298
- rmut();
- vhangup(); /* XXX */
- shutdown(netf, 2);
- kill(0, SIGKILL);
- exit(1);
- }
-
- --- 309,315 -----
- #ifdef notdef
- /* NYIT remove bogus statement (netf is never set!) */
- shutdown(netf, 2);
- + #endif
- kill(0, SIGKILL);
- exit(1);
- }
- SHAR_EOF
- echo shar: extracting diff_socketvar.h
- cat - << \SHAR_EOF > diff_socketvar.h
- *** h/socketvar.h420 Fri Jul 29 09:49:20 1983
- --- h/socketvar.h Tue Apr 1 07:24:02 1986
- ***************
- *** 49,54
- #define SB_WAIT 0x04 /* someone is waiting for data/space */
- #define SB_SEL 0x08 /* buffer is selected */
- #define SB_COLL 0x10 /* collision selecting */
- short so_timeo; /* connection timeout */
- u_short so_error; /* error affecting connection */
- short so_oobmark; /* chars to oob mark */
-
- --- 49,56 -----
- #define SB_WAIT 0x04 /* someone is waiting for data/space */
- #define SB_SEL 0x08 /* buffer is selected */
- #define SB_COLL 0x10 /* collision selecting */
- + #define SB_NVT 0x20 /* socket crossbared to NVT tty */
- + #define SB_NVS 0x40 /* socket crossbared to NVS tty/pty */
- short so_timeo; /* connection timeout */
- u_short so_error; /* error affecting connection */
- short so_oobmark; /* chars to oob mark */
- SHAR_EOF
- echo shar: extracting diff_tcp_usrreq.c
- cat - << \SHAR_EOF > diff_tcp_usrreq.c
- *** netinet/tcp_usrreq.c420 Fri Jul 29 10:14:49 1983
- --- netinet/tcp_usrreq.c Tue Apr 1 07:32:53 1986
- ***************
- *** 24,29
- #include "../netinet/tcpip.h"
- #include "../netinet/tcp_debug.h"
-
- /*
- * TCP protocol interface to socket abstraction.
- */
-
- --- 24,33 -----
- #include "../netinet/tcpip.h"
- #include "../netinet/tcp_debug.h"
-
- + #if defined(KNVS) || defined(KNVT)
- + #include "../h/ioctl.h"
- + #endif
- +
- /*
- * TCP protocol interface to socket abstraction.
- */
- ***************
- *** 233,238
-
- /* SOME AS YET UNIMPLEMENTED HOOKS */
- case PRU_CONTROL:
- error = EOPNOTSUPP;
- break;
-
-
- --- 237,260 -----
-
- /* SOME AS YET UNIMPLEMENTED HOOKS */
- case PRU_CONTROL:
- + #ifdef KNVS
- + if ((int)m == SIOCJNVS) {
- + if (tp->t_state == TCPS_ESTABLISHED)
- + error = nvs_ioc_join(so, *(int *)nam);
- + else
- + error = ENOTCONN;
- + break;
- + }
- + #endif
- + #ifdef KNVT
- + if ((int)m == SIOCJNVT) {
- + if (tp->t_state == TCPS_ESTABLISHED)
- + error = nvt_ioc_join(so, *(int *)nam);
- + else
- + error = ENOTCONN;
- + break;
- + }
- + #endif
- error = EOPNOTSUPP;
- break;
-
- SHAR_EOF
- echo shar: extracting diff_tty.c
- cat - << \SHAR_EOF > diff_tty.c
- *** sys/tty.c420 Sun Oct 2 02:06:25 1983
- --- sys/tty.c Tue Apr 1 08:04:59 1986
- ***************
- *** 826,831
- }
-
- endcase:
- /*
- * If DEC-style start/stop is enabled don't restart
- * output until seeing the start character.
-
- --- 826,838 -----
- }
-
- endcase:
- + #ifdef KNVT
- + /*
- + * If this tty is operating as an NVT, pass character to remote host
- + */
- + if (tp->t_state & TS_NVT)
- + nvt_output(tp);
- + #endif KNVT
- /*
- * If DEC-style start/stop is enabled don't restart
- * output until seeing the start character.
- SHAR_EOF
- echo shar: extracting diff_tty.h
- cat - << \SHAR_EOF > diff_tty.h
- *** h/tty.h420 Thu Aug 4 23:58:20 1983
- --- h/tty.h Tue Apr 1 08:02:28 1986
- ***************
- *** 117,122
- #define TS_LNCH 0x080000 /* next character is literal */
- #define TS_TYPEN 0x100000 /* retyping suspended input (PENDIN) */
- #define TS_CNTTB 0x200000 /* counting tab width; leave FLUSHO alone */
-
- #define TS_LOCAL (TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
-
-
- --- 117,123 -----
- #define TS_LNCH 0x080000 /* next character is literal */
- #define TS_TYPEN 0x100000 /* retyping suspended input (PENDIN) */
- #define TS_CNTTB 0x200000 /* counting tab width; leave FLUSHO alone */
- + #define TS_NVT 0x400000 /* NVT tty is bound to a socket */
-
- #define TS_LOCAL (TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
-
- SHAR_EOF
- echo shar: extracting diff_tty_pty.c
- cat - << \SHAR_EOF > diff_tty_pty.c
- *** sys/tty_pty.c420 Sun Oct 2 02:06:25 1983
- --- sys/tty_pty.c Tue Apr 1 07:55:36 1986
- ***************
- *** 24,29
- #define NPTY 32 /* crude XXX */
- #endif
-
- #define BUFSIZ 100 /* Chunk size iomoved from user */
-
- /*
-
- --- 24,34 -----
- #define NPTY 32 /* crude XXX */
- #endif
-
- + #ifdef KNVS
- + #include "../h/socketvar.h"
- + struct socket *ptynvsso[NPTY]; /* socket indexed by pty minor dev# */
- + #endif
- +
- #define BUFSIZ 100 /* Chunk size iomoved from user */
-
- /*
- ***************
- *** 78,83
- tp = &pt_tty[minor(dev)];
- (*linesw[tp->t_line].l_close)(tp);
- ttyclose(tp);
- }
-
- ptsread(dev, uio)
-
- --- 83,89 -----
- tp = &pt_tty[minor(dev)];
- (*linesw[tp->t_line].l_close)(tp);
- ttyclose(tp);
- + ptcwakeup(tp); /* wake master */
- }
-
- ptsread(dev, uio)
- ***************
- *** 439,445
- tp->t_startc == ('q'&037));
- if (pti->pt_flags & PF_NOSTOP) {
- if (stop) {
- ! pti->pt_send &= TIOCPKT_NOSTOP;
- pti->pt_send |= TIOCPKT_DOSTOP;
- pti->pt_flags &= ~PF_NOSTOP;
- ptcwakeup(tp);
-
- --- 445,451 -----
- tp->t_startc == ('q'&037));
- if (pti->pt_flags & PF_NOSTOP) {
- if (stop) {
- ! pti->pt_send &= ~TIOCPKT_NOSTOP;
- pti->pt_send |= TIOCPKT_DOSTOP;
- pti->pt_flags &= ~PF_NOSTOP;
- ptcwakeup(tp);
- ***************
- *** 455,458
- }
- return (error);
- }
- #endif
-
- --- 461,511 -----
- }
- return (error);
- }
- +
- + #ifdef KNVS
- +
- + /*
- + * Transfer characters from NVS tty outq to associated socket
- + * (Simply a jacket because timeout() accepts only 1 argument).
- + *
- + * Called at or below network IPL
- + */
- + ptsnvsnet(tp)
- + struct tty *tp;
- + {
- + nvs_output(tp, &pt_ioctl[minor(tp->t_dev)].pt_send);
- + }
- +
- + /*
- + * Alternate t_oproc routine used when the pty is operating as an NVS
- + */
- + ptsnvsstart(tp)
- + register struct tty *tp;
- + {
- + register int s;
- +
- + s = spl5();
- + /*
- + * TS_BUSY set means Ptsnvsnet() is either running or queued to run
- + */
- + if ((tp->t_state & TS_BUSY) == 0) {
- + tp->t_state |= TS_BUSY;
- + #ifdef vax
- + /*
- + * If at low IPL, can make output happen now;
- + * otherwise must sequence it through softclock
- + */
- + if (s == 0) {
- + (void) spl0(); /* reduce IPL */
- + nvs_output(tp, &pt_ioctl[minor(tp->t_dev)].pt_send);
- + }
- + else
- + #endif vax
- + timeout(ptsnvsnet, (caddr_t)tp, 0);
- + }
- + splx(s);
- + }
- +
- + #endif KNVS
- +
- #endif
- SHAR_EOF
- echo shar: extracting diff_tty_subr.c
- cat - << \SHAR_EOF > diff_tty_subr.c
- *** sys/tty_subr.c420 Fri Jul 29 10:07:23 1983
- --- sys/tty_subr.c Tue Apr 1 09:04:49 1986
- ***************
- *** 54,60
- return(c);
- }
-
- - #ifdef notdef
- /*
- * copy clist to buffer.
- * return number of bytes moved.
-
- --- 54,59 -----
- return(c);
- }
-
- /*
- * copy clist to buffer.
- * return number of bytes moved.
- ***************
- *** 110,116
- splx(s);
- return(cp-acp);
- }
- - #endif
-
- /*
- * Return count of contiguous characters
-
- --- 109,114 -----
- splx(s);
- return(cp-acp);
- }
-
- /*
- * Return count of contiguous characters
- SHAR_EOF
- echo shar: extracting diff_uipc_socket2.c
- cat - << \SHAR_EOF > diff_uipc_socket2.c
- *** sys/uipc_socket2.c420 Fri Jul 29 10:07:27 1983
- --- sys/uipc_socket2.c Tue Apr 1 07:59:50 1986
- ***************
- *** 243,248
- register struct sockbuf *sb;
- {
-
- if (sb->sb_sel) {
- selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
- sb->sb_sel = 0;
-
- --- 243,260 -----
- register struct sockbuf *sb;
- {
-
- + #ifdef KNVS
- + if (sb->sb_flags & SB_NVS) {
- + nvs_input(sb);
- + return;
- + }
- + #endif KNVS
- + #ifdef KNVT
- + if (sb->sb_flags & SB_NVT) {
- + nvt_input(sb);
- + return;
- + }
- + #endif KNVT
- if (sb->sb_sel) {
- selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
- sb->sb_sel = 0;
- SHAR_EOF
- echo shar: extracting tty_nvs.c
- cat - << \SHAR_EOF > tty_nvs.c
- /*
- * Network virtual terminals via sockets - server end
- *
- * Rick Ace
- * New York Institute of Technology
- * Computer Graphics Laboratory
- * Old Westbury, New York 11568
- */
-
- /*
- * The code in this module supports the NVS, or remote end of the connection
- * (i.e., the link between the network and the pseudo-terminal).
- * The purpose of this code is to emulate efficiently the character-
- * shuffling functions performed by /etc/rlogind. The rlogin on the other
- * host will believe it is talking to rlogind, when it is in reality
- * talking to the NVS kernel software herein.
- *
- * The NVS kernel software achieves performance improvements by handling
- * incoming character traffic at interrupt level, eliminating the overhead
- * and delays resulting from scheduling a user-mode process (rlogind).
- * Outgoing character traffic is dumped directly into the socket by
- * Ptsnvsstart() in tty_pty.c, further eliminating the need for service
- * by a user-mode process.
- *
- * The implementation is broken into two main layers:
- * 1) high-level software, common to all NVSs (nvs_XXX subrs)
- * 2) protocol-specific stuff (tcp_XXX, etc.)
- * Presently, there is only a TCP implementation for layer # 2.
- */
-
- #ifdef KNVS
-
- #include "../h/param.h"
- #include "../h/conf.h"
- #include "../h/dir.h"
- #include "../h/user.h"
- #include "../h/proc.h" /* for lint */
- #include "../h/file.h"
- #include "../h/tty.h"
- #include "../h/mbuf.h"
- #include "../h/protosw.h"
- #include "../h/socketvar.h"
- #ifdef NFS
- #include "../h/vnode.h"
- #include "../ufs/inode.h"
- #else NFS
- #include "../h/inode.h"
- #endif NFS
-
- #define nvs_emsg nvt_emsg
-
- #define MAXNVS 16 /* should be in a parameter file */
-
- /*
- * tp-to-socket correspondence table.
- *
- * This table is searched linearly. A highest-entry mark is maintained
- * to keep search overhead low. If there is a need to support large
- * numbers of NVSs, the linear search should be replaced by hashing.
- */
- struct nvsj {
- struct tty *nvs_tp; /* tty/pty context, or 0 if free */
- struct socket *nvs_so; /* socket context */
- } nvsj[MAXNVS + 1];
-
- struct nvsj *nvshij = &nvsj[0]; /* highest active entry */
-
- #ifndef lint
- int nvsj_n = MAXNVS; /* for kernel debug utilities */
- #endif
-
- int nvsichz;
-
- extern struct socket *ptynvsso[ /* NPTY */ ]; /* socket indexed by pty minor */
-
- int ptsstart(), ptsnvsstart(), ptsnvsnet();
-
- /*
- * Mate a tty and a socket
- *
- * Returns UNIX error code
- * Must be called at splimp
- */
- nvs_add(tp, so, anvs)
- struct tty *tp;
- struct socket *so;
- struct nvsj **anvs; /* return addr of NVS context here */
- {
- register struct nvsj *nvs, *nx;
- extern int hz; /* XXX */
-
- if (nvsichz == 0)
- nvsichz = hz / 3; /* XXX */
- if (tp->t_oproc != ptsstart)
- return ENOTTY; /* not a pty or not in right mode */
- nvs = 0;
- nx = &nvsj[MAXNVS - 1];
- do {
- if (nx->nvs_tp) {
- if (nx->nvs_tp == tp || nx->nvs_so == so)
- return EBUSY; /* tty or socket already an NVS */
- }
- else
- nvs = nx; /* remember lowest empty slot */
- } while (--nx >= &nvsj[0]);
- if (nvs == 0)
- return ENFILE; /* all slots are in use */
- /*
- * All is clear, mate them
- */
- if (nvs > nvshij)
- nvshij = nvs; /* update highest active entry */
- *anvs = nvs; /* pass context pointer to caller */
- nvs->nvs_so = so;
- nvs->nvs_tp = tp;
- so->so_rcv.sb_flags |= SB_NVS;
- tp->t_oproc = ptsnvsstart;
- ptynvsso[minor(tp->t_dev)] = so;
- sbwakeup(&so->so_rcv); /* get characters flowing */
- ptsnvsstart(tp); /* ditto */
- return 0;
- }
-
- /*
- * Undo a tty/socket correspondence
- *
- * Must be called at splimp
- */
- nvs_del(nvs)
- register struct nvsj *nvs;
- {
- register struct tty *tp;
-
- nvs->nvs_so->so_rcv.sb_flags &= ~SB_NVS;
- tp = nvs->nvs_tp;
- if (tp->t_oproc == ptsnvsstart)
- tp->t_oproc = ptsstart;
- ptynvsso[minor(tp->t_dev)] = 0;
- /*
- * Delete this entry and adjust Nvshij if necessary
- */
- nvs->nvs_tp = 0; /* mark entry as free */
- if (nvshij == nvs)
- while (nvshij > &nvsj[0] && nvshij->nvs_tp == 0)
- nvshij--;
- }
-
- /*
- * Called from sbwakeup() when NVS has incoming characters from the net,
- * to transfer those characters from the socket to the tty's input queue
- *
- * Logic here is similar to that of soreceive() in uipc_socket.c
- */
- nvs_input(sb)
- struct sockbuf *sb; /* so_rcv */
- {
- #define STRUCT_OFF(strnam, elem) \
- ((char *)&((struct strnam *)0)->elem - (char *)0)
- register struct socket *so;
- register struct nvsj *nvs;
- register struct tty *tp;
- register struct mbuf *m;
- register unsigned char *cp;
- register int n;
- struct mbuf *mz;
-
- /*
- * Convert so_rcv address to socket address (a bit gross),
- * then search the active-connection table for that socket
- */
- so = (struct socket *)((char *)sb - STRUCT_OFF(socket, so_rcv));
- nvs = &nvsj[0];
- while (nvs->nvs_so != so || (tp = nvs->nvs_tp) == 0) {
- if (++nvs > nvshij) {
- nvs_emsg("nvs input no so %x\n", so);
- return;
- }
- }
- /*
- * Have located the tty, now pass it the data
- */
- so->so_state &= ~SS_RCVATMARK; /* ignore out-of-band data */
- so->so_oobmark = 0; /* ditto */
- /*
- * Process each mbuf on the socket's rcv queue
- */
- while (so->so_rcv.sb_cc > 0) {
- m = so->so_rcv.sb_mb;
- if (m == 0)
- panic("nvs_input");
- cp = mtod(m, unsigned char *);
- for (n = m->m_len; --n >= 0; )
- (*linesw[tp->t_line].l_rint)(*cp++, tp);
- sbfree(&so->so_rcv, m);
- MFREE(m, mz);
- so->so_rcv.sb_mb = m = mz;
- }
- /*
- * Notify protocol that more space is available in the socket
- */
- if ((so->so_state & SS_CANTRCVMORE) == 0 &&
- so->so_proto->pr_flags & PR_WANTRCVD &&
- so->so_pcb)
- (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
- /*
- * If socket closes at remote end first (not the most common case),
- * wake up the agent process so it can exit.
- */
- if (so->so_state & (SS_CANTRCVMORE | SS_CANTSENDMORE)) {
- so->so_rcv.sb_flags &= ~SB_NVS;
- wakeup((caddr_t)nvs);
- }
- }
-
- /*
- * Handle ioctl request on socket to join socket and pty, called
- * from protocol ioctl logic. Protocol-specific validation is
- * done before you get here.
- *
- * If the connection was successfully established, sleep and wait
- * until it is broken at the remote end, or until a signal is
- * received on the local end.
- *
- * Returns
- * 0 = remote NVT closed the connection
- * EINTR = interrupted by signal
- * Anything else = an error establishing the connection
- */
- nvs_ioc_join(so, ptyfd)
- register struct socket *so;
- int ptyfd; /* pty file descriptor */
- {
- register struct file *fp;
- register struct inode *ip;
- register struct tty *tp;
- int error, s;
- struct nvsj *nvsp;
- int ptcopen();
-
- /*
- * Validate file descriptor and ensure it references a pty
- */
- if ((unsigned)ptyfd >= NOFILE || (fp = u.u_ofile[ptyfd]) == 0)
- return EBADF;
- #ifdef NFS
- {
- register struct vnode *vp;
-
- vp = (struct vnode *)fp->f_data;
- if (fp->f_type != DTYPE_VNODE || vp->v_op != &ufs_vnodeops)
- return ENOTTY;
- ip = VTOI(vp);
- if ((ip->i_mode & IFMT) != IFCHR ||
- cdevsw[major(ip->i_rdev)].d_open != ptcopen)
- return ENOTTY; /* really ENOTPTY :-) */
- }
- #else NFS
- ip = (struct inode *)fp->f_data;
- if (fp->f_type != DTYPE_INODE ||
- (ip->i_mode & IFMT) != IFCHR ||
- cdevsw[major(ip->i_rdev)].d_open != ptcopen)
- return ENOTTY; /* really ENOTPTY :-) */
- #endif NFS
- /*
- * Argument socket and pty are valid, now join them and wait
- */
- tp = cdevsw[major(ip->i_rdev)].d_ttys;
- s = splimp();
- if (error = nvs_add(tp + minor(ip->i_rdev), so, &nvsp)) {
- splx(s);
- return error;
- }
- if (setjmp(&u.u_qsave)) {
- /*
- * The process received a signal
- */
- nvs_del(nvsp); /* disassociate pty&socket */
- splx(s);
- return EINTR;
- }
- do sleep((caddr_t)nvsp, PZERO + 1); /* wait for signal or disconnect */
- while (nvsp->nvs_so->so_rcv.sb_flags & SB_NVS);
- /*
- * The remote disconnected.
- */
- nvs_del(nvsp); /* disassociate pty&socket */
- splx(s);
- return 0;
- }
-
- /*
- * Move characters from pty outq to network
- * TS_BUSY is assumed to be set upon entry
- *
- * Must be called at or below net IPL
- */
- /*ARGSUSED*/
- nvs_output(tp, urgentp)
- register struct tty *tp;
- int *urgentp; /* call by reference because I can zero it */
- {
- register struct mbuf *m;
- register struct socket *so;
- register int error, s, space;
-
- s = splnet();
- if ((so = ptynvsso[minor(tp->t_dev)]) == 0) { /* paranoid */
- /*
- * no longer an NVS!
- */
- tp->t_state &= ~TS_BUSY;
- if (tp->t_oproc)
- (*tp->t_oproc)(tp);
- goto rspl;
- }
- if (so->so_state & SS_CANTSENDMORE) {
- while (getc(&tp->t_outq) >= 0)
- ;
- *urgentp = 0;
- }
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0)
- goto out;
- /*
- * If there is urgent data to send, ship it now
- */
- if (*urgentp) {
- *mtod(m, unsigned char *) = *urgentp;
- *urgentp = 0;
- m->m_len = 1;
- error = (*so->so_proto->pr_usrreq)(so,
- PRU_SENDOOB, m, (struct mbuf *)0, (struct mbuf *)0);
- if (error)
- nvs_emsg("nvs SENDOOB %d\n", error);
- goto out;
- }
- while (1) {
- /*
- * Send a chunk of character traffic that may be pending
- */
- space = sbspace(&so->so_snd);
- if (space > MLEN)
- space = MLEN;
- if ((m->m_len = q_to_b(&tp->t_outq, mtod(m, char *), space)) == 0) {
- /*
- * No outq traffic or socket is saturated
- */
- (void) m_free(m);
- goto out;
- }
- error = (*so->so_proto->pr_usrreq)(so,
- PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
- #ifdef lint
- /* Same actuals as above, better information for lint */
- error = tcp_usrreq(so,
- PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
- #endif
- /*
- * If space != MLEN then socket is saturating or I've drained
- * the tty's outq, so there's not much sense in continuing.
- * Otherwise, remain in loop to feed the socket.
- */
- if (space != MLEN)
- goto out;
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0)
- goto out;
- }
-
- out: /*
- * Perpetuate myself if work remains
- */
- (void) spl5(); /* block out tty activity */
- if (tp->t_outq.c_cc > 0 || *urgentp)
- timeout(ptsnvsnet, (caddr_t)tp, nvsichz); /* TS_BUSY remains set */
- else
- tp->t_state &= ~TS_BUSY;
- /*
- * Wake up sleepers
- */
- if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
- if (tp->t_state&TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
- }
- if (tp->t_wsel) {
- selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
- tp->t_wsel = 0;
- tp->t_state &= ~TS_WCOLL;
- }
- }
- rspl: splx(s);
- }
-
- #endif KNVS
- SHAR_EOF
- echo shar: extracting tty_nvt.c
- cat - << \SHAR_EOF > tty_nvt.c
- /*
- * Network virtual terminals via sockets - client end
- *
- * Rick Ace
- * New York Institute of Technology
- * Computer Graphics Laboratory
- * Old Westbury, New York 11568
- */
-
- /*
- * The code in this module supports the NVT, or local end of the connection
- * (i.e., the link between the network and the user's physical terminal).
- * The purpose of this code is to emulate efficiently the character-
- * shuffling functions performed by rlogin(1). The rlogind on the remote
- * host will believe it is talking to an rlogin, when it is in reality
- * talking to the NVT kernel software herein.
- *
- * The NVT kernel software achieves performance improvements by handling
- * incoming and outgoing character traffic at interrupt level, eliminating
- * the overhead and delays resulting from scheduling a user-mode process.
- *
- * The implementation is broken into two main layers:
- * 1) high-level software, common to all NVTs (nvt_XXX subrs)
- * 2) protocol-specific stuff (tcp_XXX, etc.)
- * Presently, there is only a TCP implementation for layer # 2.
- */
-
- #ifdef KNVT
-
- #include "../h/param.h"
- #include "../h/conf.h"
- #include "../h/dir.h"
- #include "../h/user.h"
- #include "../h/file.h"
- #include "../h/ioctl.h"
- #include "../h/tty.h"
- #include "../h/mbuf.h"
- #include "../h/protosw.h"
- #include "../h/socketvar.h"
- #ifdef NFS
- #include "../h/vnode.h"
- #include "../ufs/inode.h"
- #else NFS
- #include "../h/inode.h"
- #endif NFS
-
- #define MAXNVT 16 /* should be in a parameter file */
-
- /*
- * tp-to-socket correspondence table.
- *
- * This table is searched linearly. A highest-entry mark is maintained
- * to keep search overhead low. If there is a need to support large
- * numbers of NVTs, the linear search should be replaced by hashing.
- */
- struct nvtj {
- struct tty *nvt_tp; /* tty context, or 0 if free slot */
- struct socket *nvt_so; /* socket context */
- char nvt_ostopc; /* original tty stop character */
- char nvt_ostartc; /* original tty start character */
- } nvtj[MAXNVT];
-
- struct nvtj *nvthij = &nvtj[0]; /* highest active entry */
-
- #ifndef lint
- int nvtj_n = MAXNVT; /* for kernel debug utilities */
- #endif
-
- int nvtichz; /* hz between icpy scans */
- int nvtnmsg = 10; /* # of kernel printfs remaining */
- short nvtricpy; /* icpy: callout request exists */
- short nvtrocpy; /* ocpy: callout request exists */
-
- int nvt_icpy();
-
- /*
- * Mate a tty and a socket
- *
- * Returns UNIX error code
- * Must be called at splimp
- */
- nvt_add(tp, so, anvt)
- struct tty *tp;
- struct socket *so;
- struct nvtj **anvt; /* return addr of NVT context here */
- {
- register struct nvtj *nvt, *nx;
- extern int hz; /* XXX */
-
- if (nvtichz == 0)
- nvtichz = hz / 3; /* XXX */
- nvt = 0;
- nx = &nvtj[MAXNVT - 1];
- do {
- if (nx->nvt_tp) {
- if (nx->nvt_tp == tp || nx->nvt_so == so)
- return EBUSY; /* tty or socket already an NVT */
- }
- else
- nvt = nx; /* remember lowest empty slot */
- } while (--nx >= &nvtj[0]);
- if (nvt == 0)
- return ENFILE; /* all slots are in use */
- /*
- * All is clear, mate them
- */
- if (nvt > nvthij)
- nvthij = nvt; /* update highest active entry */
- *anvt = nvt; /* pass context pointer to caller */
- nvt->nvt_so = so;
- nvt->nvt_tp = tp;
- so->so_rcv.sb_flags |= SB_NVT;
- tp->t_state |= TS_NVT;
- nvt->nvt_ostopc = tp->t_stopc;
- nvt->nvt_ostartc = tp->t_startc;
- sbwakeup(&so->so_rcv); /* get characters flowing */
- return 0;
- }
-
- /*
- * Undo a tty/socket correspondence
- *
- * Must be called at splimp
- */
- nvt_del(nvt)
- register struct nvtj *nvt;
- {
- register struct tty *tp;
-
- tp = nvt->nvt_tp;
- if (tp == 0)
- panic("Nvt_del");
- tp->t_state &= ~TS_NVT;
- tp->t_stopc = nvt->nvt_ostopc;
- tp->t_startc = nvt->nvt_ostartc;
- nvt->nvt_so->so_rcv.sb_flags &= ~SB_NVT;
- /*
- * Delete this entry and adjust Nvthij if necessary
- */
- nvt->nvt_tp = 0; /* mark entry as free */
- if (nvthij == nvt)
- while (nvthij > &nvtj[0] && nvthij->nvt_tp == 0)
- nvthij--;
- }
-
- /*
- * Kernel printf error message
- */
- /*VARARGS1*/
- nvt_emsg(msg, dat)
- char *msg; /* error message with optional % */
- int dat; /* optional data */
- {
- if (--nvtnmsg >= 0)
- printf(msg, dat);
- }
-
- /*
- * Copy incoming NVT characters from socket to tty
- *
- * Logic here is similar to that of soreceive() in uipc_socket.c
- */
- nvt_i1cpy(nvt)
- struct nvtj *nvt;
- {
- register struct socket *so = nvt->nvt_so;
- register struct tty *tp = nvt->nvt_tp;
- register struct mbuf *m;
- register int n, s;
-
- s = splnet();
- while (1) {
- /*
- * Handle out-of-band data if I'm at that point
- */
- if (so->so_state & SS_RCVATMARK) {
- m = m_get(M_DONTWAIT, MT_DATA);
- if (m == 0)
- goto out;
- if ((n = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
- m, (struct mbuf *)0, (struct mbuf *)0)) == 0) {
- nvt_oob(nvt, *mtod(m, unsigned char *));
- so->so_state &= ~SS_RCVATMARK;
- }
- else
- nvt_emsg("nvt RCVOOB %d\n", n);
- (void) m_free(m);
- }
- if (so->so_rcv.sb_cc <= 0)
- goto out;
- /*
- * Check for out-of-band data preceded by character traffic.
- * If present, flush the precding character traffic;
- * otherwise, just transfer character traffic to the tty.
- */
- if ((n = so->so_oobmark) <= 0) { /* if no OOB data... */
- n = TTHIWAT(tp);
- n -= tp->t_outq.c_cc;
- if (n <= 0) {
- /*
- * No room in tty's outq for more characters, so
- * set up delay to retry after a brief interval.
- */
- if (!nvtricpy) {
- nvtricpy++;
- timeout(nvt_icpy, (caddr_t)0, nvtichz);
- }
- goto out;
- }
- }
- /*
- * Attack the first mbuf on the socket's rcv queue
- */
- m = so->so_rcv.sb_mb;
- if (m == 0)
- panic("nvt_i1cpy");
- if (n > m->m_len)
- n = m->m_len;
- if (so->so_oobmark <= 0 &&
- b_to_q(mtod(m, char *), n, &tp->t_outq))
- nvt_emsg("nvt b_to_q resid tp=%x\n", tp);
- ttstart(tp);
- if (n == m->m_len) {
- struct mbuf *mz;
-
- sbfree(&so->so_rcv, m);
- MFREE(m, mz);
- so->so_rcv.sb_mb = m = mz;
- }
- else {
- m->m_off += n;
- m->m_len -= n;
- so->so_rcv.sb_cc -= n;
- }
- if (so->so_oobmark > 0 && (so->so_oobmark -= n) == 0)
- so->so_state |= SS_RCVATMARK;
- /*
- * Notify protocol that more space is available in the socket
- */
- if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
- (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
- }
-
- out: /*
- * If the remote has closed its output and I have passed all
- * incoming traffic to the tty, dissolve the NVT connection
- * between the socket and the local tty, and wake up rlogin.
- */
- if (so->so_state & SS_CANTRCVMORE && so->so_rcv.sb_cc <= 0) {
- so->so_rcv.sb_flags &= ~SB_NVT;
- tp->t_state &= ~TS_NVT;
- wakeup((caddr_t)nvt);
- }
- splx(s);
- }
-
- /*
- * Softclock interrupt routine to move characters from
- * socket receive buffer to tty output queue. This
- * is used only to retry transfering characters to ttys
- * whose output queues were saturated.
- */
- /*ARGSUSED*/
- nvt_icpy(d)
- caddr_t d; /* 2nd argument of timeout() */
- {
- register struct nvtj *nvt;
-
- nvtricpy = 0;
- /*
- * Scan all NVT sockets for incoming traffic
- */
- nvt = &nvtj[0];
- do {
- if (nvt->nvt_tp && nvt->nvt_so->so_rcv.sb_cc > 0)
- nvt_i1cpy(nvt);
- } while (++nvt <= nvthij);
- }
-
- /*
- * Called to report that an NVT has incoming characters from the net
- */
- nvt_input(sb)
- struct sockbuf *sb; /* so_rcv */
- {
- #define STRUCT_OFF(strnam, elem) \
- ((char *)&((struct strnam *)0)->elem - (char *)0)
- register struct socket *so;
- register struct nvtj *nvt;
-
- /*
- * Convert so_rcv address to socket address (a bit gross),
- * then search the active-connection table for that socket
- */
- so = (struct socket *)((char *)sb - STRUCT_OFF(socket, so_rcv));
- nvt = &nvtj[0];
- do {
- if (nvt->nvt_so == so && nvt->nvt_tp) {
- /*
- * Have located the tty, now pass it the data
- */
- nvt_i1cpy(nvt);
- return;
- }
- } while (++nvt <= nvthij);
- nvt_emsg("nvt input no so %x\n", so);
- }
-
- /*
- * Handle ioctl request on socket to join socket and tty, called
- * from protocol ioctl logic. Protocol-specific validation is
- * done before you get here.
- *
- * If the connection was successfully established, sleep and wait
- * until it is broken at the remote end, or until a signal is
- * received on the local end (viz., from the local tty driver
- * when the user types the escape character).
- *
- * Returns
- * 0 = remote closed the connection
- * EINTR = signal from local tty (connection can be re-established)
- * Anything else = an error establishing the connection
- */
- nvt_ioc_join(so, ttyfd)
- register struct socket *so;
- int ttyfd; /* tty file descriptor */
- {
- register struct file *fp;
- register struct inode *ip;
- register struct tty *tp;
- int error, s;
- struct nvtj *nvtp;
-
- /*
- * Validate file descriptor and ensure it references a tty
- */
- if ((unsigned)ttyfd >= NOFILE || (fp = u.u_ofile[ttyfd]) == 0)
- return EBADF;
- #ifdef NFS
- {
- register struct vnode *vp;
-
- vp = (struct vnode *)fp->f_data;
- if (fp->f_type != DTYPE_VNODE || vp->v_op != &ufs_vnodeops)
- return ENOTTY;
- ip = VTOI(vp);
- if ((ip->i_mode & IFMT) != IFCHR ||
- (tp = cdevsw[major(ip->i_rdev)].d_ttys) == 0)
- return ENOTTY;
- }
- #else NFS
- ip = (struct inode *)fp->f_data;
- if (fp->f_type != DTYPE_INODE ||
- (ip->i_mode & IFMT) != IFCHR ||
- (tp = cdevsw[major(ip->i_rdev)].d_ttys) == 0)
- return ENOTTY;
- #endif NFS
- /*
- * Argument socket and tty are valid, now join them and wait
- */
- s = splimp();
- if (error = nvt_add(tp + minor(ip->i_rdev), so, &nvtp)) {
- splx(s);
- return error;
- }
- if (setjmp(&u.u_qsave)) {
- /*
- * The process received a signal
- */
- nvt_del(nvtp); /* disassociate tty&socket */
- splx(s);
- return EINTR;
- }
- do sleep((caddr_t)nvtp, PZERO + 1); /* wait for signal or disconnect */
- while (nvtp->nvt_so->so_rcv.sb_flags & SB_NVT);
- /*
- * The remote disconnected.
- */
- nvt_del(nvtp); /* disassociate tty&socket */
- splx(s);
- return 0;
- }
-
- /*
- * Softclock interrupt routine to move characters from local tty
- * input queues to network
- */
- /*ARGSUSED*/
- nvt_ocpy(d)
- caddr_t d; /* 2nd argument of Timeout() */
- {
- register struct mbuf *m;
- register struct tty *tp;
- register int c;
- register unsigned char *cp, *cplim;
- register struct nvtj *nvt;
- int error;
-
- nvtrocpy = 0;
- /*
- * Scan all NVT ttys for outbound characters
- */
- nvt = &nvtj[0];
- do {
- if ((tp = nvt->nvt_tp) == 0)
- continue; /* slot is not active */
- if (tp->t_rawq.c_cc <= 0 && tp->t_canq.c_cc <= 0)
- continue; /* no data */
- if (nvt->nvt_so->so_state & SS_CANTSENDMORE)
- continue;
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0)
- continue;
- cp = m->m_dat;
- cplim = cp + MLEN;
- if (tp->t_canq.c_cc > 0) /* unlikely */
- while ((c = getc(&tp->t_canq)) >= 0) {
- *cp++ = c;
- if (cp >= cplim)
- goto mfull;
- }
- while ((c = getc(&tp->t_rawq)) >= 0) {
- if (tp->t_flags & RAW && (c & 0177) == tp->t_intrc) {
- /*
- * rlogin escape character typed in raw mode,
- * simulate ttyinput() processing thereof
- */
- gsignal(tp->t_pgrp, SIGINT);
- continue;
- }
- *cp++ = c;
- if (cp >= cplim)
- goto mfull;
- }
- mfull: m->m_len = cp - m->m_dat;
- error = (*nvt->nvt_so->so_proto->pr_usrreq)(nvt->nvt_so,
- PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
- #ifdef lint
- /* Same actuals as above, better information for lint */
- error = tcp_usrreq(nvt->nvt_so,
- PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
- #endif
- if (error)
- nvt_emsg("nvt SEND %d\n", error);
- } while (++nvt <= nvthij);
- }
-
- /*
- * Process out-of-band data from remote
- */
- nvt_oob(nvt, od)
- register struct nvtj *nvt;
- unsigned char od; /* data */
- {
- register struct tty *tp = nvt->nvt_tp;
-
- ttyflush(tp, FWRITE);
- if (od & TIOCPKT_NOSTOP) {
- tp->t_stopc = -1;
- tp->t_startc = -1;
- }
- if (od & TIOCPKT_DOSTOP) {
- tp->t_stopc = nvt->nvt_ostopc;
- tp->t_startc = nvt->nvt_ostartc;
- }
- if (nvtnmsg > 10)
- nvt_emsg("nvt oob %x\n", od);
- }
-
- /*
- * Send characters typed at a local terminal across the net
- *
- * Called from tty hardware interrupt handler, so must queue request
- * to be handled at net IPL
- */
- nvt_output(tp)
- register struct tty *tp;
- {
- register struct nvtj *nvt;
-
- nvt = &nvtj[0];
- do {
- if (nvt->nvt_tp == tp) {
- if (!nvtrocpy) {
- nvtrocpy++;
- timeout(nvt_ocpy, (caddr_t)0, 0);
- }
- return;
- }
- } while (++nvt <= nvthij);
- /*
- * Not in my list, this tty is no longer associated with a socket
- */
- tp->t_state &= ~TS_NVT;
- }
-
- #endif KNVT
- SHAR_EOF
-
-
-