home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume4 / rlogin < prev    next >
Text File  |  1986-11-30  |  40KB  |  1,557 lines

  1. Subject:  4.2bsd rlogin enhancements
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 4, Issue 52
  6. Submitted by: genrad!decvax!philabs!nyit!rick
  7.  
  8. ---CUT HERE---CUT HERE---CUT HERE---CUT HERE---CUT HERE--CUT HERE--
  9. echo shar: extracting README
  10. cat - << \SHAR_EOF > README
  11. NYIT rlogin performance enhancements            01-Apr-86
  12.  
  13. INTRODUCTION
  14. This package contains a set of source code modifications to
  15. 4.2bsd UNIX to enhance the performance of rlogin connections.
  16. Performance improvement results from reducing the involvement
  17. of the agent processes (rlogin and rlogind) in the task of
  18. passing characters between the client and server hosts.
  19. In this implementation, the agent processes retain their
  20. previous function of establishing an rlogin-style connection
  21. between two hosts; however, once the connection is established,
  22. the agents sleep until the connection is interrrupted by an
  23. escape character on the client host, or terminated by either host.
  24. The character-switching functions formerly performed by rlogin
  25. and rlogind are now handled entirely within kernel interrupt
  26. logic, eliminating the delays and scheduling overhead of the
  27. original implementation and improving response and throughput.
  28.  
  29. It is important to note that, although the character traffic
  30. is now being handled exclusively in the kernel, the rlogin
  31. protocol has been maintained.  This ensures that an enhanced
  32. client can interoperate with a vanilla 4.2bsd server, and
  33. vice versa, still gaining an improvement in performance.
  34.  
  35. The implementation is separated into two logical parts:  client
  36. and server.  The client part is called the NVT, an acronym for
  37. Network Virtual Terminal; the server is called the NVS, meaning
  38. Network Virtual Server.  Within the kernel, NVT logic appears
  39. within a "#ifdef KNVT" conditional, and NVS logic appears
  40. within a "#ifdef KNVS" conditional.  All user-mode NVT logic
  41. resides in /usr/ucb/rlogin.  All user-mode NVS logic resides
  42. in /etc/rlogind.
  43.  
  44. AFFECTED SOFTWARE
  45. The following executables are affected:
  46.  
  47.     1.  The 4.2bsd kernel
  48.     2.  /usr/ucb/rlogin
  49.     3.  /etc/rlogind
  50.  
  51. The vanilla and enhanced versions of any of these programs can be
  52. used in any combination with no risk.  The NVT and NVS logic
  53. in the kernel remains dormant unless invoked by an enhanced
  54. rlogin or rlogind; the enhanced kernel support the vanilla
  55. rlogin/rlogind as well as their new counterparts.  The enhanced
  56. rlogin and rlogind determine if the kernel offers the enhanced
  57. NVT or NVS service, and, if not, they will operate in vanilla
  58. 4.2bsd rlogin mode.
  59.  
  60. BUGS
  61. The user interface of rlogin is slightly different with regard
  62. to the operation of the escape character.  This is not an
  63. unavoidable consequence of this implementation, but rather an
  64. issue of expediency made during development; it can be fixed.
  65.  
  66. The implementation within the kernel is practical, but not
  67. elegant.  I grovel in advance for the indulgence of the purists.
  68. [Remember:  you didn't *pay money* to buy this :-)]
  69.  
  70. No explicit aid is offered for telnet connections; however,
  71. inspection of this implementation might inspire those who
  72. use telnet to improve its performance in a similar fashion.
  73.  
  74.  
  75. CONTENTS OF THIS DISTRIBUTION
  76.   [Explanations of changes appear in brackets]
  77.  
  78.   README        This file
  79.   diff_files        diff -c of kernel conf/files
  80.             [add two new kernel source files: tty_nv[st].c]
  81.   diff_ioctl.h        diff -c of kernel h/ioctl.h
  82.             [add ioctl defs SIOCJNVS and SIOCJNVT]
  83.   diff_rlogin.c        diff -c of source for /usr/ucb/rlogin
  84.             [invoke SIOCJNVT ioctl to join socket and tty]
  85.   diff_rlogind.c    diff -c of source for /etc/rlogind
  86.             [invoke SIOCJNVS ioctl to join socket and pty]
  87.   diff_socketvar.h    diff -c of kernel h/socketvar.h
  88.             [add defs SB_NVS and SB_NVT]
  89.   diff_tcp_usrreq.c    diff -c of kernel netinet/tcp_usrreq.c
  90.             [add code to handle SIOCJNVS and SIOCJNVT ioctls]
  91.   diff_tty.c        diff -c of kernel sys/tty.c
  92.             [add hook in ttyinput() to intercept NVT characters]
  93.   diff_tty.h        diff -c of kernel h/tty.h
  94.             [add def TS_NVT]
  95.   diff_tty_pty.c    diff -c of kernel sys/tty_pty.c
  96.             [add subroutines driven off pty data structures]
  97.   diff_tty_subr.c    diff -c of kernel sys/tty_subr.c
  98.             [remove #ifdef notdef surrounding q_to_b]
  99.   diff_uipc_socket2.c    diff -c of kernel sys/uipc_socket2.c
  100.             [add hooks in sbwakeup() to intercept NVS/NVT traffic]
  101.   tty_nvs.c        New kernel source file sys/tty_nvs.c
  102.             [most of the logic to implement NVS service]
  103.   tty_nvt.c        New kernel source file sys/tty_nvt.c
  104.             [most of the logic to implement NVT service]
  105.  
  106. INSTALLATION
  107.     1.  Copy tty_nvs.c and tty_nvt.c into /sys/sys.
  108.     2.  Locate files whose names begin with "diff_".  These files
  109.     represent Berkeley 4.2bsd source modules that must be modified.
  110.     Apply the changes in each "diff_" file to their respective
  111.     4.2bsd source modules.
  112.     3.  cd to /sys/conf and add the following two lines to your
  113.     kernel configuration file:
  114.         options        NKVS
  115.         options        KNVT
  116.     4.  Run /etc/config to regenerate the kernel configuration files.
  117.     5.  cd to the kernel directory and run "make" to build a new kernel.
  118.     6.  Install the new kernel in /.
  119.     7.  Recompile and install /usr/ucb/rlogin (must be setuid-root).
  120.     8.  Recompile and install /etc/rlogind.
  121.     9.  Reboot and enjoy more responsive rlogin connections.
  122.  
  123.  
  124. Please address comments, questions, bugfixes (please, no flames
  125. about hooks in ttyinput() or sbwakeup()) to the author:
  126.  
  127. Rick Ace
  128. New York Institute of Technology
  129. Computer Graphics Laboratory
  130. Wheatley Road
  131. Old Westbury, NY  11568
  132.  
  133. (516) 686-7644
  134.  
  135. USENET:    {decvax,seismo}!philabs!nyit!rick
  136. SHAR_EOF
  137. echo shar: extracting diff_files
  138. cat - << \SHAR_EOF > diff_files
  139. *** conf/files420    Sun Jun 12 18:45:11 1983
  140. --- conf/files    Tue Apr  1 07:20:48 1986
  141. ***************
  142. *** 102,104
  143.   sys/vm_swap.c        standard
  144.   sys/vm_swp.c        standard
  145.   sys/vm_text.c        standard
  146.  
  147. --- 102,106 -----
  148.   sys/vm_swap.c        standard
  149.   sys/vm_swp.c        standard
  150.   sys/vm_text.c        standard
  151. + sys/tty_nvs.c        standard
  152. + sys/tty_nvt.c        standard
  153. SHAR_EOF
  154. echo shar: extracting diff_ioctl.h
  155. cat - << \SHAR_EOF > diff_ioctl.h
  156. *** h/ioctl.h420    Sat Aug 20 19:04:34 1983
  157. --- h/ioctl.h    Tue Apr  1 07:27:50 1986
  158. ***************
  159. *** 194,199
  160.   #define    SIOCATMARK    _IOR(s,  7, int)        /* at oob mark? */
  161.   #define    SIOCSPGRP    _IOW(s,  8, int)        /* set process group */
  162.   #define    SIOCGPGRP    _IOR(s,  9, int)        /* get process group */
  163.   
  164.   #define    SIOCADDRT    _IOW(r, 10, struct rtentry)    /* add route */
  165.   #define    SIOCDELRT    _IOW(r, 11, struct rtentry)    /* delete route */
  166.  
  167. --- 194,201 -----
  168.   #define    SIOCATMARK    _IOR(s,  7, int)        /* at oob mark? */
  169.   #define    SIOCSPGRP    _IOW(s,  8, int)        /* set process group */
  170.   #define    SIOCGPGRP    _IOR(s,  9, int)        /* get process group */
  171. + #define SIOCJNVT    _IOW(s, 70, int)        /* join NVT tty&socket */
  172. + #define SIOCJNVS    _IOW(s, 71, int)        /* join NVS pty&socket */
  173.   
  174.   #define    SIOCADDRT    _IOW(r, 10, struct rtentry)    /* add route */
  175.   #define    SIOCDELRT    _IOW(r, 11, struct rtentry)    /* delete route */
  176. SHAR_EOF
  177. echo shar: extracting diff_rlogin.c
  178. cat - << \SHAR_EOF > diff_rlogin.c
  179. *** 4.2rlogin.c    Tue Apr  1 12:12:32 1986
  180. --- rlogin.c    Tue Apr  1 11:17:44 1986
  181. ***************
  182. *** 144,149
  183.       signal(SIGINT, exit);
  184.       signal(SIGHUP, exit);
  185.       signal(SIGQUIT, exit);
  186.       child = fork();
  187.       if (child == -1) {
  188.           perror("rlogin: fork");
  189.  
  190. --- 144,150 -----
  191.       signal(SIGINT, exit);
  192.       signal(SIGHUP, exit);
  193.       signal(SIGQUIT, exit);
  194. +     knvt();                /* returns iff no kernel NVT service */
  195.       child = fork();
  196.       if (child == -1) {
  197.           perror("rlogin: fork");
  198. ***************
  199. *** 376,380
  200.   {
  201.       signal(SIGPIPE, SIG_IGN);
  202.       prf("\007Connection closed.");
  203.       done();
  204.   }
  205.  
  206. --- 377,429 -----
  207.   {
  208.       signal(SIGPIPE, SIG_IGN);
  209.       prf("\007Connection closed.");
  210. +     done();
  211. + }
  212. + nvtsig()
  213. + {
  214. +     signal(SIGINT, nvtsig);
  215. + }
  216. + /*
  217. +  * Invoke kernel NVT service
  218. +  *
  219. +  * Returns iff kernel does not support NVT service (i.e., do the
  220. +  * job the old-fashioned way) 
  221. +  */
  222. + knvt()
  223. + {
  224. +     char cmdc;
  225. +     static int ttyfd = 0;
  226. +     signal(SIGINT, nvtsig);
  227. +     notc.t_intrc = cmdchar;
  228. +     mode(1);
  229. +     while (ioctl(rem, SIOCJNVT, &ttyfd) < 0) {
  230. +         if (errno != EINTR) {
  231. +             /*
  232. +              * Unexpected error, assume the kernel does not
  233. +              * honor the ioctl call and return to doit().
  234. +              */
  235. +             notc.t_intrc = -1;
  236. +             return;
  237. +         }
  238. +         /*
  239. +          * The user typed the escape character.  Read the next
  240. +          * character from the terminal to see what I should do.
  241. +          */
  242. +         if (read(0, &cmdc, 1) != 1) 
  243. +             cmdc = deftc.t_eofc;
  244. +         if (cmdc == '.' || cmdc == deftc.t_eofc) 
  245. +             break;
  246. +         if (cmdc == defltc.t_suspc ||
  247. +             cmdc == defltc.t_dsuspc) {
  248. +             write(0, CRLF, sizeof(CRLF));
  249. +             mode(0);
  250. +             kill(getpid(), SIGTSTP);
  251. +             mode(1);
  252. +         }
  253. +     }
  254. +     prf("\r\nConnection closed");
  255.       done();
  256.   }
  257. SHAR_EOF
  258. echo shar: extracting diff_rlogind.c
  259. cat - << \SHAR_EOF > diff_rlogind.c
  260. *** 4.2rlogind.c    Tue Apr  1 12:12:50 1986
  261. --- rlogind.c    Tue Apr  1 09:32:50 1986
  262. ***************
  263. *** 200,205
  264.           ioctl(p, TIOCPKT, &on);
  265.           signal(SIGTSTP, SIG_IGN);
  266.           signal(SIGCHLD, cleanup);
  267.           for (;;) {
  268.               int ibits = 0, obits = 0;
  269.   
  270.  
  271. --- 200,219 -----
  272.           ioctl(p, TIOCPKT, &on);
  273.           signal(SIGTSTP, SIG_IGN);
  274.           signal(SIGCHLD, cleanup);
  275. +         /* BEGIN NVS support */
  276. +         /*
  277. +          * If kernel supports high-performance NVS operation,
  278. +          * invoke it and sleep until connection is broken.
  279. +          * If remote end dies: ioctl() returns 0.
  280. +          * If local job exits: ioctl() returns -1 / EINTR.
  281. +          * Any other return from ioctl() is interpreted to mean
  282. +          * the kernel doesn't support high-performance NVS
  283. +          * operation, so do the job the standard Berkeley way.
  284. +          */
  285. +         if (ioctl(f, SIOCJNVS, (char *)&p) == 0 ||
  286. +             errno == EINTR)
  287. +             cleanup();
  288. +         /* END NVS support */
  289.           for (;;) {
  290.               int ibits = 0, obits = 0;
  291.   
  292. ***************
  293. *** 292,297
  294.   
  295.       rmut();
  296.       vhangup();        /* XXX */
  297.       shutdown(netf, 2);
  298.       kill(0, SIGKILL);
  299.       exit(1);
  300.  
  301. --- 306,313 -----
  302.   
  303.       rmut();
  304.       vhangup();        /* XXX */
  305. + #ifdef notdef
  306. +     /* NYIT remove bogus statement (netf is never set!) */
  307.       shutdown(netf, 2);
  308.   #endif
  309.       kill(0, SIGKILL);
  310. ***************
  311. *** 293,298
  312.       rmut();
  313.       vhangup();        /* XXX */
  314.       shutdown(netf, 2);
  315.       kill(0, SIGKILL);
  316.       exit(1);
  317.   }
  318.  
  319. --- 309,315 -----
  320.   #ifdef notdef
  321.       /* NYIT remove bogus statement (netf is never set!) */
  322.       shutdown(netf, 2);
  323. + #endif
  324.       kill(0, SIGKILL);
  325.       exit(1);
  326.   }
  327. SHAR_EOF
  328. echo shar: extracting diff_socketvar.h
  329. cat - << \SHAR_EOF > diff_socketvar.h
  330. *** h/socketvar.h420    Fri Jul 29 09:49:20 1983
  331. --- h/socketvar.h    Tue Apr  1 07:24:02 1986
  332. ***************
  333. *** 49,54
  334.   #define    SB_WAIT        0x04        /* someone is waiting for data/space */
  335.   #define    SB_SEL        0x08        /* buffer is selected */
  336.   #define    SB_COLL        0x10        /* collision selecting */
  337.       short    so_timeo;        /* connection timeout */
  338.       u_short    so_error;        /* error affecting connection */
  339.       short    so_oobmark;        /* chars to oob mark */
  340.  
  341. --- 49,56 -----
  342.   #define    SB_WAIT        0x04        /* someone is waiting for data/space */
  343.   #define    SB_SEL        0x08        /* buffer is selected */
  344.   #define    SB_COLL        0x10        /* collision selecting */
  345. + #define SB_NVT        0x20        /* socket crossbared to NVT tty */
  346. + #define SB_NVS        0x40        /* socket crossbared to NVS tty/pty */
  347.       short    so_timeo;        /* connection timeout */
  348.       u_short    so_error;        /* error affecting connection */
  349.       short    so_oobmark;        /* chars to oob mark */
  350. SHAR_EOF
  351. echo shar: extracting diff_tcp_usrreq.c
  352. cat - << \SHAR_EOF > diff_tcp_usrreq.c
  353. *** netinet/tcp_usrreq.c420    Fri Jul 29 10:14:49 1983
  354. --- netinet/tcp_usrreq.c    Tue Apr  1 07:32:53 1986
  355. ***************
  356. *** 24,29
  357.   #include "../netinet/tcpip.h"
  358.   #include "../netinet/tcp_debug.h"
  359.   
  360.   /*
  361.    * TCP protocol interface to socket abstraction.
  362.    */
  363.  
  364. --- 24,33 -----
  365.   #include "../netinet/tcpip.h"
  366.   #include "../netinet/tcp_debug.h"
  367.   
  368. + #if defined(KNVS) || defined(KNVT)
  369. + #include "../h/ioctl.h"
  370. + #endif
  371.   /*
  372.    * TCP protocol interface to socket abstraction.
  373.    */
  374. ***************
  375. *** 233,238
  376.   
  377.   /* SOME AS YET UNIMPLEMENTED HOOKS */
  378.       case PRU_CONTROL:
  379.           error = EOPNOTSUPP;
  380.           break;
  381.   
  382.  
  383. --- 237,260 -----
  384.   
  385.   /* SOME AS YET UNIMPLEMENTED HOOKS */
  386.       case PRU_CONTROL:
  387. + #ifdef KNVS
  388. +         if ((int)m == SIOCJNVS) {
  389. +             if (tp->t_state == TCPS_ESTABLISHED)
  390. +                 error = nvs_ioc_join(so, *(int *)nam);
  391. +             else
  392. +                 error = ENOTCONN;
  393. +             break;
  394. +         }
  395. + #endif
  396. + #ifdef KNVT
  397. +         if ((int)m == SIOCJNVT) {
  398. +             if (tp->t_state == TCPS_ESTABLISHED)
  399. +                 error = nvt_ioc_join(so, *(int *)nam);
  400. +             else
  401. +                 error = ENOTCONN;
  402. +             break;
  403. +         }
  404. + #endif
  405.           error = EOPNOTSUPP;
  406.           break;
  407.   
  408. SHAR_EOF
  409. echo shar: extracting diff_tty.c
  410. cat - << \SHAR_EOF > diff_tty.c
  411. *** sys/tty.c420    Sun Oct  2 02:06:25 1983
  412. --- sys/tty.c    Tue Apr  1 08:04:59 1986
  413. ***************
  414. *** 826,831
  415.       }
  416.   
  417.   endcase:
  418.       /*
  419.        * If DEC-style start/stop is enabled don't restart
  420.        * output until seeing the start character.
  421.  
  422. --- 826,838 -----
  423.       }
  424.   
  425.   endcase:
  426. + #ifdef KNVT
  427. +     /*
  428. +      * If this tty is operating as an NVT, pass character to remote host
  429. +      */
  430. +     if (tp->t_state & TS_NVT)
  431. +         nvt_output(tp);
  432. + #endif KNVT
  433.       /*
  434.        * If DEC-style start/stop is enabled don't restart
  435.        * output until seeing the start character.
  436. SHAR_EOF
  437. echo shar: extracting diff_tty.h
  438. cat - << \SHAR_EOF > diff_tty.h
  439. *** h/tty.h420    Thu Aug  4 23:58:20 1983
  440. --- h/tty.h    Tue Apr  1 08:02:28 1986
  441. ***************
  442. *** 117,122
  443.   #define    TS_LNCH        0x080000    /* next character is literal */
  444.   #define    TS_TYPEN    0x100000    /* retyping suspended input (PENDIN) */
  445.   #define    TS_CNTTB    0x200000    /* counting tab width; leave FLUSHO alone */
  446.   
  447.   #define    TS_LOCAL    (TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
  448.   
  449.  
  450. --- 117,123 -----
  451.   #define    TS_LNCH        0x080000    /* next character is literal */
  452.   #define    TS_TYPEN    0x100000    /* retyping suspended input (PENDIN) */
  453.   #define    TS_CNTTB    0x200000    /* counting tab width; leave FLUSHO alone */
  454. + #define TS_NVT        0x400000    /* NVT tty is bound to a socket */
  455.   
  456.   #define    TS_LOCAL    (TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
  457.   
  458. SHAR_EOF
  459. echo shar: extracting diff_tty_pty.c
  460. cat - << \SHAR_EOF > diff_tty_pty.c
  461. *** sys/tty_pty.c420    Sun Oct  2 02:06:25 1983
  462. --- sys/tty_pty.c    Tue Apr  1 07:55:36 1986
  463. ***************
  464. *** 24,29
  465.   #define    NPTY    32        /* crude XXX */
  466.   #endif
  467.   
  468.   #define BUFSIZ 100        /* Chunk size iomoved from user */
  469.   
  470.   /*
  471.  
  472. --- 24,34 -----
  473.   #define    NPTY    32        /* crude XXX */
  474.   #endif
  475.   
  476. + #ifdef KNVS
  477. + #include "../h/socketvar.h"
  478. + struct socket    *ptynvsso[NPTY];    /* socket indexed by pty minor dev# */
  479. + #endif
  480.   #define BUFSIZ 100        /* Chunk size iomoved from user */
  481.   
  482.   /*
  483. ***************
  484. *** 78,83
  485.       tp = &pt_tty[minor(dev)];
  486.       (*linesw[tp->t_line].l_close)(tp);
  487.       ttyclose(tp);
  488.   }
  489.   
  490.   ptsread(dev, uio)
  491.  
  492. --- 83,89 -----
  493.       tp = &pt_tty[minor(dev)];
  494.       (*linesw[tp->t_line].l_close)(tp);
  495.       ttyclose(tp);
  496. +     ptcwakeup(tp);                /* wake master */
  497.   }
  498.   
  499.   ptsread(dev, uio)
  500. ***************
  501. *** 439,445
  502.                 tp->t_startc == ('q'&037));
  503.       if (pti->pt_flags & PF_NOSTOP) {
  504.           if (stop) {
  505. !             pti->pt_send &= TIOCPKT_NOSTOP;
  506.               pti->pt_send |= TIOCPKT_DOSTOP;
  507.               pti->pt_flags &= ~PF_NOSTOP;
  508.               ptcwakeup(tp);
  509.  
  510. --- 445,451 -----
  511.                 tp->t_startc == ('q'&037));
  512.       if (pti->pt_flags & PF_NOSTOP) {
  513.           if (stop) {
  514. !             pti->pt_send &= ~TIOCPKT_NOSTOP;
  515.               pti->pt_send |= TIOCPKT_DOSTOP;
  516.               pti->pt_flags &= ~PF_NOSTOP;
  517.               ptcwakeup(tp);
  518. ***************
  519. *** 455,458
  520.       }
  521.       return (error);
  522.   }
  523.   #endif
  524.  
  525. --- 461,511 -----
  526.       }
  527.       return (error);
  528.   }
  529. + #ifdef KNVS
  530. + /*
  531. +  * Transfer characters from NVS tty outq to associated socket
  532. +  * (Simply a jacket because timeout() accepts only 1 argument).
  533. +  *
  534. +  * Called at or below network IPL
  535. +  */
  536. + ptsnvsnet(tp)
  537. +     struct tty *tp;
  538. + {
  539. +     nvs_output(tp, &pt_ioctl[minor(tp->t_dev)].pt_send);
  540. + }
  541. + /*
  542. +  * Alternate t_oproc routine used when the pty is operating as an NVS
  543. +  */
  544. + ptsnvsstart(tp)
  545. +     register struct tty *tp;
  546. + {
  547. +     register int s;
  548. +     s = spl5();
  549. +     /*
  550. +      * TS_BUSY set means Ptsnvsnet() is either running or queued to run
  551. +      */
  552. +     if ((tp->t_state & TS_BUSY) == 0) {
  553. +         tp->t_state |= TS_BUSY;
  554. + #ifdef vax
  555. +         /*
  556. +          * If at low IPL, can make output happen now;
  557. +          * otherwise must sequence it through softclock
  558. +          */
  559. +         if (s == 0) {
  560. +             (void) spl0();        /* reduce IPL */
  561. +             nvs_output(tp, &pt_ioctl[minor(tp->t_dev)].pt_send);
  562. +         }
  563. +         else
  564. + #endif vax
  565. +             timeout(ptsnvsnet, (caddr_t)tp, 0);
  566. +     }
  567. +     splx(s);
  568. + }
  569. + #endif KNVS
  570.   #endif
  571. SHAR_EOF
  572. echo shar: extracting diff_tty_subr.c
  573. cat - << \SHAR_EOF > diff_tty_subr.c
  574. *** sys/tty_subr.c420    Fri Jul 29 10:07:23 1983
  575. --- sys/tty_subr.c    Tue Apr  1 09:04:49 1986
  576. ***************
  577. *** 54,60
  578.       return(c);
  579.   }
  580.   
  581. - #ifdef notdef
  582.   /*
  583.    * copy clist to buffer.
  584.    * return number of bytes moved.
  585.  
  586. --- 54,59 -----
  587.       return(c);
  588.   }
  589.   
  590.   /*
  591.    * copy clist to buffer.
  592.    * return number of bytes moved.
  593. ***************
  594. *** 110,116
  595.       splx(s);
  596.       return(cp-acp);
  597.   }
  598. - #endif
  599.   
  600.   /*
  601.    * Return count of contiguous characters
  602.  
  603. --- 109,114 -----
  604.       splx(s);
  605.       return(cp-acp);
  606.   }
  607.   
  608.   /*
  609.    * Return count of contiguous characters
  610. SHAR_EOF
  611. echo shar: extracting diff_uipc_socket2.c
  612. cat - << \SHAR_EOF > diff_uipc_socket2.c
  613. *** sys/uipc_socket2.c420    Fri Jul 29 10:07:27 1983
  614. --- sys/uipc_socket2.c    Tue Apr  1 07:59:50 1986
  615. ***************
  616. *** 243,248
  617.       register struct sockbuf *sb;
  618.   {
  619.   
  620.       if (sb->sb_sel) {
  621.           selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
  622.           sb->sb_sel = 0;
  623.  
  624. --- 243,260 -----
  625.       register struct sockbuf *sb;
  626.   {
  627.   
  628. + #ifdef KNVS
  629. +     if (sb->sb_flags & SB_NVS) {
  630. +         nvs_input(sb);
  631. +         return;
  632. +     }
  633. + #endif KNVS
  634. + #ifdef KNVT
  635. +     if (sb->sb_flags & SB_NVT) {
  636. +         nvt_input(sb);
  637. +         return;
  638. +     }
  639. + #endif KNVT
  640.       if (sb->sb_sel) {
  641.           selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
  642.           sb->sb_sel = 0;
  643. SHAR_EOF
  644. echo shar: extracting tty_nvs.c
  645. cat - << \SHAR_EOF > tty_nvs.c
  646. /*
  647.  * Network virtual terminals via sockets - server end
  648.  *
  649.  *    Rick Ace
  650.  *    New York Institute of Technology
  651.  *    Computer Graphics Laboratory
  652.  *    Old Westbury, New York  11568
  653.  */
  654.  
  655. /*
  656.  * The code in this module supports the NVS, or remote end of the connection
  657.  * (i.e., the link between the network and the pseudo-terminal).
  658.  * The purpose of this code is to emulate efficiently the character-
  659.  * shuffling functions performed by /etc/rlogind.  The rlogin on the other
  660.  * host will believe it is talking to rlogind, when it is in reality
  661.  * talking to the NVS kernel software herein.
  662.  *
  663.  * The NVS kernel software achieves performance improvements by handling
  664.  * incoming character traffic at interrupt level, eliminating the overhead
  665.  * and delays resulting from scheduling a user-mode process (rlogind).
  666.  * Outgoing character traffic is dumped directly into the socket by
  667.  * Ptsnvsstart() in tty_pty.c, further eliminating the need for service
  668.  * by a user-mode process.
  669.  *
  670.  * The implementation is broken into two main layers:
  671.  *    1)  high-level software, common to all NVSs (nvs_XXX subrs) 
  672.  *    2)  protocol-specific stuff (tcp_XXX, etc.) 
  673.  * Presently, there is only a TCP implementation for layer # 2.
  674.  */
  675.  
  676. #ifdef KNVS
  677.  
  678. #include "../h/param.h"
  679. #include "../h/conf.h"
  680. #include "../h/dir.h"
  681. #include "../h/user.h"
  682. #include "../h/proc.h"        /* for lint */
  683. #include "../h/file.h"
  684. #include "../h/tty.h"
  685. #include "../h/mbuf.h"
  686. #include "../h/protosw.h"
  687. #include "../h/socketvar.h"
  688. #ifdef NFS
  689. #include "../h/vnode.h"
  690. #include "../ufs/inode.h"
  691. #else NFS
  692. #include "../h/inode.h"
  693. #endif NFS
  694.  
  695. #define nvs_emsg    nvt_emsg
  696.  
  697. #define MAXNVS    16        /* should be in a parameter file */
  698.  
  699. /*
  700.  * tp-to-socket correspondence table.
  701.  *
  702.  * This table is searched linearly.  A highest-entry mark is maintained
  703.  * to keep search overhead low.  If there is a need to support large
  704.  * numbers of NVSs, the linear search should be replaced by hashing.
  705.  */
  706. struct nvsj {
  707.     struct tty    *nvs_tp;    /* tty/pty context, or 0 if free */
  708.     struct socket    *nvs_so;    /* socket context */
  709. } nvsj[MAXNVS + 1];
  710.  
  711. struct nvsj    *nvshij = &nvsj[0];    /* highest active entry */
  712.  
  713. #ifndef lint
  714. int    nvsj_n = MAXNVS;        /* for kernel debug utilities */
  715. #endif
  716.  
  717. int    nvsichz;
  718.  
  719. extern struct socket *ptynvsso[ /* NPTY */ ]; /* socket indexed by pty minor */
  720.  
  721. int    ptsstart(), ptsnvsstart(), ptsnvsnet();
  722.  
  723. /*
  724.  * Mate a tty and a socket
  725.  *
  726.  * Returns UNIX error code
  727.  * Must be called at splimp
  728.  */
  729. nvs_add(tp, so, anvs)
  730.     struct tty *tp;
  731.     struct socket *so;
  732.     struct nvsj **anvs;    /* return addr of NVS context here */
  733. {
  734.     register struct nvsj *nvs, *nx;
  735.     extern int hz;                /* XXX */
  736.  
  737.     if (nvsichz == 0) 
  738.         nvsichz = hz / 3;        /* XXX */
  739.     if (tp->t_oproc != ptsstart) 
  740.         return ENOTTY;        /* not a pty or not in right mode */
  741.     nvs = 0;
  742.     nx = &nvsj[MAXNVS - 1];
  743.     do {
  744.         if (nx->nvs_tp) {
  745.             if (nx->nvs_tp == tp || nx->nvs_so == so) 
  746.                 return EBUSY; /* tty or socket already an NVS */
  747.         }
  748.         else
  749.             nvs = nx;    /* remember lowest empty slot */
  750.     } while (--nx >= &nvsj[0]);
  751.     if (nvs == 0) 
  752.         return ENFILE;        /* all slots are in use */
  753.     /*
  754.      * All is clear, mate them
  755.      */
  756.     if (nvs > nvshij) 
  757.         nvshij = nvs;        /* update highest active entry */
  758.     *anvs = nvs;            /* pass context pointer to caller */
  759.     nvs->nvs_so = so;
  760.     nvs->nvs_tp = tp;
  761.     so->so_rcv.sb_flags |= SB_NVS;
  762.     tp->t_oproc = ptsnvsstart;
  763.     ptynvsso[minor(tp->t_dev)] = so;
  764.     sbwakeup(&so->so_rcv);        /* get characters flowing */
  765.     ptsnvsstart(tp);        /* ditto */
  766.     return 0;
  767. }
  768.  
  769. /*
  770.  * Undo a tty/socket correspondence
  771.  *
  772.  * Must be called at splimp
  773.  */
  774. nvs_del(nvs)
  775.     register struct nvsj *nvs;
  776. {
  777.     register struct tty *tp;
  778.  
  779.     nvs->nvs_so->so_rcv.sb_flags &= ~SB_NVS;
  780.     tp = nvs->nvs_tp;
  781.     if (tp->t_oproc == ptsnvsstart) 
  782.         tp->t_oproc = ptsstart;
  783.     ptynvsso[minor(tp->t_dev)] = 0;
  784.     /*
  785.      * Delete this entry and adjust Nvshij if necessary
  786.      */
  787.     nvs->nvs_tp = 0;        /* mark entry as free */
  788.     if (nvshij == nvs) 
  789.         while (nvshij > &nvsj[0] && nvshij->nvs_tp == 0) 
  790.             nvshij--;
  791. }
  792.  
  793. /*
  794.  * Called from sbwakeup() when NVS has incoming characters from the net,
  795.  * to transfer those characters from the socket to the tty's input queue
  796.  *
  797.  * Logic here is similar to that of soreceive() in uipc_socket.c
  798.  */
  799. nvs_input(sb)
  800.     struct sockbuf *sb;        /* so_rcv */
  801. {
  802. #define STRUCT_OFF(strnam, elem) \
  803.     ((char *)&((struct strnam *)0)->elem - (char *)0) 
  804.     register struct socket *so;
  805.     register struct nvsj *nvs;
  806.     register struct tty *tp;
  807.     register struct mbuf *m;
  808.     register unsigned char *cp;
  809.     register int n;
  810.     struct mbuf *mz;
  811.  
  812.     /*
  813.      * Convert so_rcv address to socket address (a bit gross),
  814.      * then search the active-connection table for that socket
  815.      */
  816.     so = (struct socket *)((char *)sb - STRUCT_OFF(socket, so_rcv));
  817.     nvs = &nvsj[0];
  818.     while (nvs->nvs_so != so || (tp = nvs->nvs_tp) == 0) {
  819.         if (++nvs > nvshij) {
  820.             nvs_emsg("nvs input no so %x\n", so);
  821.             return;
  822.         }
  823.     }
  824.     /*
  825.      * Have located the tty, now pass it the data
  826.      */
  827.     so->so_state &= ~SS_RCVATMARK;        /* ignore out-of-band data */
  828.     so->so_oobmark = 0;            /* ditto */
  829.     /*
  830.      * Process each mbuf on the socket's rcv queue
  831.      */
  832.     while (so->so_rcv.sb_cc > 0) {
  833.         m = so->so_rcv.sb_mb;
  834.         if (m == 0) 
  835.             panic("nvs_input");
  836.         cp = mtod(m, unsigned char *);
  837.         for (n = m->m_len; --n >= 0; ) 
  838.             (*linesw[tp->t_line].l_rint)(*cp++, tp);
  839.         sbfree(&so->so_rcv, m);
  840.         MFREE(m, mz);
  841.         so->so_rcv.sb_mb = m = mz;
  842.     }
  843.     /*
  844.      * Notify protocol that more space is available in the socket
  845.      */
  846.     if ((so->so_state & SS_CANTRCVMORE) == 0 &&
  847.         so->so_proto->pr_flags & PR_WANTRCVD &&
  848.         so->so_pcb) 
  849.         (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
  850.             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  851.     /*
  852.      * If socket closes at remote end first (not the most common case),
  853.      * wake up the agent process so it can exit.
  854.      */
  855.     if (so->so_state & (SS_CANTRCVMORE | SS_CANTSENDMORE)) {
  856.         so->so_rcv.sb_flags &= ~SB_NVS;
  857.         wakeup((caddr_t)nvs);
  858.     }
  859. }
  860.  
  861. /*
  862.  * Handle ioctl request on socket to join socket and pty, called
  863.  * from protocol ioctl logic.  Protocol-specific validation is
  864.  * done before you get here.
  865.  *
  866.  * If the connection was successfully established, sleep and wait
  867.  * until it is broken at the remote end, or until a signal is
  868.  * received on the local end.
  869.  *
  870.  * Returns
  871.  *    0 = remote NVT closed the connection
  872.  *    EINTR = interrupted by signal
  873.  *    Anything else = an error establishing the connection
  874.  */
  875. nvs_ioc_join(so, ptyfd)
  876.     register struct socket *so;
  877.     int ptyfd;        /* pty file descriptor */
  878. {
  879.     register struct file *fp;
  880.     register struct inode *ip;
  881.     register struct tty *tp;
  882.     int error, s;
  883.     struct nvsj *nvsp;
  884.     int ptcopen();
  885.  
  886.     /*
  887.      * Validate file descriptor and ensure it references a pty
  888.      */
  889.     if ((unsigned)ptyfd >= NOFILE || (fp = u.u_ofile[ptyfd]) == 0) 
  890.         return EBADF;
  891. #ifdef NFS
  892.     {
  893.         register struct vnode *vp;
  894.  
  895.         vp = (struct vnode *)fp->f_data;
  896.         if (fp->f_type != DTYPE_VNODE || vp->v_op != &ufs_vnodeops) 
  897.             return ENOTTY;
  898.         ip = VTOI(vp);
  899.         if ((ip->i_mode & IFMT) != IFCHR ||
  900.             cdevsw[major(ip->i_rdev)].d_open != ptcopen) 
  901.             return ENOTTY;        /* really ENOTPTY :-) */
  902.     }
  903. #else NFS
  904.     ip = (struct inode *)fp->f_data;
  905.     if (fp->f_type != DTYPE_INODE ||
  906.         (ip->i_mode & IFMT) != IFCHR ||
  907.         cdevsw[major(ip->i_rdev)].d_open != ptcopen) 
  908.         return ENOTTY;        /* really ENOTPTY :-) */
  909. #endif NFS
  910.     /*
  911.      * Argument socket and pty are valid, now join them and wait
  912.      */
  913.     tp = cdevsw[major(ip->i_rdev)].d_ttys;
  914.     s = splimp();
  915.     if (error = nvs_add(tp + minor(ip->i_rdev), so, &nvsp)) {
  916.         splx(s);
  917.         return error;
  918.     }
  919.     if (setjmp(&u.u_qsave)) {
  920.         /*
  921.          * The process received a signal
  922.          */
  923.         nvs_del(nvsp);        /* disassociate pty&socket */
  924.         splx(s);
  925.         return EINTR;
  926.     }
  927.     do sleep((caddr_t)nvsp, PZERO + 1); /* wait for signal or disconnect */
  928.      while (nvsp->nvs_so->so_rcv.sb_flags & SB_NVS);
  929.     /*
  930.      * The remote disconnected.
  931.      */
  932.     nvs_del(nvsp);            /* disassociate pty&socket */
  933.     splx(s);
  934.     return 0;
  935. }
  936.  
  937. /*
  938.  * Move characters from pty outq to network
  939.  * TS_BUSY is assumed to be set upon entry
  940.  *
  941.  * Must be called at or below net IPL
  942.  */
  943. /*ARGSUSED*/
  944. nvs_output(tp, urgentp)
  945.     register struct tty *tp;
  946.     int *urgentp;        /* call by reference because I can zero it */
  947. {
  948.     register struct mbuf *m;
  949.     register struct socket *so;
  950.     register int error, s, space;
  951.  
  952.     s = splnet();
  953.     if ((so = ptynvsso[minor(tp->t_dev)]) == 0) {    /* paranoid */
  954.         /*
  955.          * no longer an NVS!
  956.          */
  957.         tp->t_state &= ~TS_BUSY;
  958.         if (tp->t_oproc) 
  959.             (*tp->t_oproc)(tp);
  960.         goto rspl;
  961.     }
  962.     if (so->so_state & SS_CANTSENDMORE) {
  963.         while (getc(&tp->t_outq) >= 0) 
  964.             ;
  965.         *urgentp = 0;
  966.     }
  967.     MGET(m, M_DONTWAIT, MT_DATA);
  968.     if (m == 0) 
  969.         goto out;
  970.     /*
  971.      * If there is urgent data to send, ship it now
  972.      */
  973.     if (*urgentp) {
  974.         *mtod(m, unsigned char *) = *urgentp;
  975.         *urgentp = 0;
  976.         m->m_len = 1;
  977.         error = (*so->so_proto->pr_usrreq)(so,
  978.             PRU_SENDOOB, m, (struct mbuf *)0, (struct mbuf *)0);
  979.         if (error) 
  980.             nvs_emsg("nvs SENDOOB %d\n", error);
  981.         goto out;
  982.     }
  983.     while (1) {
  984.         /*
  985.          * Send a chunk of character traffic that may be pending
  986.          */
  987.         space = sbspace(&so->so_snd);
  988.         if (space > MLEN) 
  989.             space = MLEN;
  990.         if ((m->m_len = q_to_b(&tp->t_outq, mtod(m, char *), space)) == 0) {
  991.             /*
  992.              * No outq traffic or socket is saturated
  993.              */
  994.             (void) m_free(m);
  995.             goto out;
  996.         }
  997.         error = (*so->so_proto->pr_usrreq)(so,
  998.             PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
  999. #ifdef lint
  1000.         /* Same actuals as above, better information for lint */
  1001.         error = tcp_usrreq(so,
  1002.             PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
  1003. #endif
  1004.         /*
  1005.          * If space != MLEN then socket is saturating or I've drained
  1006.          * the tty's outq, so there's not much sense in continuing.
  1007.          * Otherwise, remain in loop to feed the socket.
  1008.          */
  1009.         if (space != MLEN) 
  1010.             goto out;
  1011.         MGET(m, M_DONTWAIT, MT_DATA);
  1012.         if (m == 0) 
  1013.             goto out;
  1014.     }
  1015.  
  1016. out:    /*
  1017.      * Perpetuate myself if work remains
  1018.      */
  1019.     (void) spl5();            /* block out tty activity */
  1020.     if (tp->t_outq.c_cc > 0 || *urgentp) 
  1021.         timeout(ptsnvsnet, (caddr_t)tp, nvsichz); /* TS_BUSY remains set */
  1022.     else
  1023.         tp->t_state &= ~TS_BUSY;
  1024.     /*
  1025.      * Wake up sleepers
  1026.      */
  1027.     if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
  1028.         if (tp->t_state&TS_ASLEEP) {
  1029.             tp->t_state &= ~TS_ASLEEP;
  1030.             wakeup((caddr_t)&tp->t_outq);
  1031.         }
  1032.         if (tp->t_wsel) {
  1033.             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
  1034.             tp->t_wsel = 0;
  1035.             tp->t_state &= ~TS_WCOLL;
  1036.         }
  1037.     }
  1038. rspl:    splx(s);
  1039. }
  1040.  
  1041. #endif KNVS
  1042. SHAR_EOF
  1043. echo shar: extracting tty_nvt.c
  1044. cat - << \SHAR_EOF > tty_nvt.c
  1045. /*
  1046.  * Network virtual terminals via sockets - client end
  1047.  *
  1048.  *    Rick Ace
  1049.  *    New York Institute of Technology
  1050.  *    Computer Graphics Laboratory
  1051.  *    Old Westbury, New York  11568
  1052.  */
  1053.  
  1054. /*
  1055.  * The code in this module supports the NVT, or local end of the connection
  1056.  * (i.e., the link between the network and the user's physical terminal).
  1057.  * The purpose of this code is to emulate efficiently the character-
  1058.  * shuffling functions performed by rlogin(1).  The rlogind on the remote
  1059.  * host will believe it is talking to an rlogin, when it is in reality
  1060.  * talking to the NVT kernel software herein.
  1061.  *
  1062.  * The NVT kernel software achieves performance improvements by handling
  1063.  * incoming and outgoing character traffic at interrupt level, eliminating
  1064.  * the overhead and delays resulting from scheduling a user-mode process.
  1065.  *
  1066.  * The implementation is broken into two main layers:
  1067.  *    1)  high-level software, common to all NVTs (nvt_XXX subrs) 
  1068.  *    2)  protocol-specific stuff (tcp_XXX, etc.) 
  1069.  * Presently, there is only a TCP implementation for layer # 2.
  1070.  */
  1071.  
  1072. #ifdef KNVT
  1073.  
  1074. #include "../h/param.h"
  1075. #include "../h/conf.h"
  1076. #include "../h/dir.h"
  1077. #include "../h/user.h"
  1078. #include "../h/file.h"
  1079. #include "../h/ioctl.h"
  1080. #include "../h/tty.h"
  1081. #include "../h/mbuf.h"
  1082. #include "../h/protosw.h"
  1083. #include "../h/socketvar.h"
  1084. #ifdef NFS
  1085. #include "../h/vnode.h"
  1086. #include "../ufs/inode.h"
  1087. #else NFS
  1088. #include "../h/inode.h"
  1089. #endif NFS
  1090.  
  1091. #define MAXNVT    16        /* should be in a parameter file */
  1092.  
  1093. /*
  1094.  * tp-to-socket correspondence table.
  1095.  *
  1096.  * This table is searched linearly.  A highest-entry mark is maintained
  1097.  * to keep search overhead low.  If there is a need to support large
  1098.  * numbers of NVTs, the linear search should be replaced by hashing.
  1099.  */
  1100. struct nvtj {
  1101.     struct tty    *nvt_tp;    /* tty context, or 0 if free slot */
  1102.     struct socket    *nvt_so;    /* socket context */
  1103.     char        nvt_ostopc;    /* original tty stop character */
  1104.     char        nvt_ostartc;    /* original tty start character */
  1105. } nvtj[MAXNVT];
  1106.  
  1107. struct nvtj    *nvthij = &nvtj[0];    /* highest active entry */
  1108.  
  1109. #ifndef lint
  1110. int    nvtj_n = MAXNVT;        /* for kernel debug utilities */
  1111. #endif
  1112.  
  1113. int    nvtichz;        /* hz between icpy scans */
  1114. int    nvtnmsg = 10;        /* # of kernel printfs remaining */
  1115. short    nvtricpy;        /* icpy: callout request exists */
  1116. short    nvtrocpy;        /* ocpy: callout request exists */
  1117.  
  1118. int    nvt_icpy();
  1119.  
  1120. /*
  1121.  * Mate a tty and a socket
  1122.  *
  1123.  * Returns UNIX error code
  1124.  * Must be called at splimp
  1125.  */
  1126. nvt_add(tp, so, anvt)
  1127.     struct tty *tp;
  1128.     struct socket *so;
  1129.     struct nvtj **anvt;    /* return addr of NVT context here */
  1130. {
  1131.     register struct nvtj *nvt, *nx;
  1132.     extern int hz;                /* XXX */
  1133.  
  1134.     if (nvtichz == 0) 
  1135.         nvtichz = hz / 3;        /* XXX */
  1136.     nvt = 0;
  1137.     nx = &nvtj[MAXNVT - 1];
  1138.     do {
  1139.         if (nx->nvt_tp) {
  1140.             if (nx->nvt_tp == tp || nx->nvt_so == so) 
  1141.                 return EBUSY; /* tty or socket already an NVT */
  1142.         }
  1143.         else
  1144.             nvt = nx;    /* remember lowest empty slot */
  1145.     } while (--nx >= &nvtj[0]);
  1146.     if (nvt == 0) 
  1147.         return ENFILE;        /* all slots are in use */
  1148.     /*
  1149.      * All is clear, mate them
  1150.      */
  1151.     if (nvt > nvthij) 
  1152.         nvthij = nvt;        /* update highest active entry */
  1153.     *anvt = nvt;            /* pass context pointer to caller */
  1154.     nvt->nvt_so = so;
  1155.     nvt->nvt_tp = tp;
  1156.     so->so_rcv.sb_flags |= SB_NVT;
  1157.     tp->t_state |= TS_NVT;
  1158.     nvt->nvt_ostopc = tp->t_stopc;
  1159.     nvt->nvt_ostartc = tp->t_startc;
  1160.     sbwakeup(&so->so_rcv);        /* get characters flowing */
  1161.     return 0;
  1162. }
  1163.  
  1164. /*
  1165.  * Undo a tty/socket correspondence
  1166.  *
  1167.  * Must be called at splimp
  1168.  */
  1169. nvt_del(nvt)
  1170.     register struct nvtj *nvt;
  1171. {
  1172.     register struct tty *tp;
  1173.  
  1174.     tp = nvt->nvt_tp;
  1175.     if (tp == 0) 
  1176.         panic("Nvt_del");
  1177.     tp->t_state &= ~TS_NVT;
  1178.     tp->t_stopc = nvt->nvt_ostopc;
  1179.     tp->t_startc = nvt->nvt_ostartc;
  1180.     nvt->nvt_so->so_rcv.sb_flags &= ~SB_NVT;
  1181.     /*
  1182.      * Delete this entry and adjust Nvthij if necessary
  1183.      */
  1184.     nvt->nvt_tp = 0;        /* mark entry as free */
  1185.     if (nvthij == nvt) 
  1186.         while (nvthij > &nvtj[0] && nvthij->nvt_tp == 0) 
  1187.             nvthij--;
  1188. }
  1189.  
  1190. /*
  1191.  * Kernel printf error message
  1192.  */
  1193. /*VARARGS1*/
  1194. nvt_emsg(msg, dat)
  1195.     char *msg;        /* error message with optional % */
  1196.     int dat;        /* optional data */
  1197. {
  1198.     if (--nvtnmsg >= 0) 
  1199.         printf(msg, dat);
  1200. }
  1201.  
  1202. /*
  1203.  * Copy incoming NVT characters from socket to tty
  1204.  *
  1205.  * Logic here is similar to that of soreceive() in uipc_socket.c
  1206.  */
  1207. nvt_i1cpy(nvt)
  1208.     struct nvtj *nvt;
  1209. {
  1210.     register struct socket *so = nvt->nvt_so;
  1211.     register struct tty *tp = nvt->nvt_tp;
  1212.     register struct mbuf *m;
  1213.     register int n, s;
  1214.  
  1215.     s = splnet();
  1216.     while (1) {
  1217.         /*
  1218.          * Handle out-of-band data if I'm at that point
  1219.          */
  1220.         if (so->so_state & SS_RCVATMARK) {
  1221.             m = m_get(M_DONTWAIT, MT_DATA);
  1222.             if (m == 0) 
  1223.                 goto out;
  1224.             if ((n = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
  1225.                 m, (struct mbuf *)0, (struct mbuf *)0)) == 0) {
  1226.                 nvt_oob(nvt, *mtod(m, unsigned char *));
  1227.                 so->so_state &= ~SS_RCVATMARK;
  1228.             }
  1229.             else
  1230.                 nvt_emsg("nvt RCVOOB %d\n", n);
  1231.             (void) m_free(m);
  1232.         }
  1233.         if (so->so_rcv.sb_cc <= 0) 
  1234.             goto out;
  1235.         /*
  1236.          * Check for out-of-band data preceded by character traffic.
  1237.          * If present, flush the precding character traffic;
  1238.          * otherwise, just transfer character traffic to the tty.
  1239.          */
  1240.         if ((n = so->so_oobmark) <= 0) {    /* if no OOB data... */
  1241.             n = TTHIWAT(tp);
  1242.             n -= tp->t_outq.c_cc;
  1243.             if (n <= 0) {
  1244.                 /*
  1245.                  * No room in tty's outq for more characters, so
  1246.                  * set up delay to retry after a brief interval.
  1247.                  */
  1248.                 if (!nvtricpy) {
  1249.                     nvtricpy++;
  1250.                     timeout(nvt_icpy, (caddr_t)0, nvtichz);
  1251.                 }
  1252.                 goto out;
  1253.             }
  1254.         }
  1255.         /*
  1256.          * Attack the first mbuf on the socket's rcv queue
  1257.          */
  1258.         m = so->so_rcv.sb_mb;
  1259.         if (m == 0) 
  1260.             panic("nvt_i1cpy");
  1261.         if (n > m->m_len) 
  1262.             n = m->m_len;
  1263.         if (so->so_oobmark <= 0 &&
  1264.             b_to_q(mtod(m, char *), n, &tp->t_outq)) 
  1265.             nvt_emsg("nvt b_to_q resid tp=%x\n", tp);
  1266.         ttstart(tp);
  1267.         if (n == m->m_len) {
  1268.             struct mbuf *mz;
  1269.  
  1270.             sbfree(&so->so_rcv, m);
  1271.             MFREE(m, mz);
  1272.             so->so_rcv.sb_mb = m = mz;
  1273.         }
  1274.         else {
  1275.             m->m_off += n;
  1276.             m->m_len -= n;
  1277.             so->so_rcv.sb_cc -= n;
  1278.         }
  1279.         if (so->so_oobmark > 0 && (so->so_oobmark -= n) == 0) 
  1280.             so->so_state |= SS_RCVATMARK;
  1281.         /*
  1282.          * Notify protocol that more space is available in the socket
  1283.          */
  1284.         if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 
  1285.             (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
  1286.                 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  1287.     }
  1288.  
  1289. out:    /*
  1290.      * If the remote has closed its output and I have passed all
  1291.      * incoming traffic to the tty, dissolve the NVT connection
  1292.      * between the socket and the local tty, and wake up rlogin.
  1293.      */
  1294.     if (so->so_state & SS_CANTRCVMORE && so->so_rcv.sb_cc <= 0) {
  1295.         so->so_rcv.sb_flags &= ~SB_NVT;
  1296.         tp->t_state &= ~TS_NVT;
  1297.         wakeup((caddr_t)nvt);
  1298.     }
  1299.     splx(s);
  1300. }
  1301.  
  1302. /*
  1303.  * Softclock interrupt routine to move characters from
  1304.  * socket receive buffer to tty output queue.  This
  1305.  * is used only to retry transfering characters to ttys
  1306.  * whose output queues were saturated.
  1307.  */
  1308. /*ARGSUSED*/
  1309. nvt_icpy(d)
  1310.     caddr_t d;    /* 2nd argument of timeout() */
  1311. {
  1312.     register struct nvtj *nvt;
  1313.  
  1314.     nvtricpy = 0;
  1315.     /*
  1316.      * Scan all NVT sockets for incoming traffic
  1317.      */
  1318.     nvt = &nvtj[0];
  1319.     do {
  1320.         if (nvt->nvt_tp && nvt->nvt_so->so_rcv.sb_cc > 0) 
  1321.             nvt_i1cpy(nvt);
  1322.     } while (++nvt <= nvthij);
  1323. }
  1324.  
  1325. /*
  1326.  * Called to report that an NVT has incoming characters from the net
  1327.  */
  1328. nvt_input(sb)
  1329.     struct sockbuf *sb;        /* so_rcv */
  1330. {
  1331. #define STRUCT_OFF(strnam, elem) \
  1332.     ((char *)&((struct strnam *)0)->elem - (char *)0) 
  1333.     register struct socket *so;
  1334.     register struct nvtj *nvt;
  1335.  
  1336.     /*
  1337.      * Convert so_rcv address to socket address (a bit gross),
  1338.      * then search the active-connection table for that socket
  1339.      */
  1340.     so = (struct socket *)((char *)sb - STRUCT_OFF(socket, so_rcv));
  1341.     nvt = &nvtj[0];
  1342.     do {
  1343.         if (nvt->nvt_so == so && nvt->nvt_tp) {
  1344.             /*
  1345.              * Have located the tty, now pass it the data
  1346.              */
  1347.             nvt_i1cpy(nvt);
  1348.             return;
  1349.         }
  1350.     } while (++nvt <= nvthij);
  1351.     nvt_emsg("nvt input no so %x\n", so);
  1352. }
  1353.  
  1354. /*
  1355.  * Handle ioctl request on socket to join socket and tty, called
  1356.  * from protocol ioctl logic.  Protocol-specific validation is
  1357.  * done before you get here.
  1358.  *
  1359.  * If the connection was successfully established, sleep and wait
  1360.  * until it is broken at the remote end, or until a signal is
  1361.  * received on the local end (viz., from the local tty driver
  1362.  * when the user types the escape character).
  1363.  *
  1364.  * Returns
  1365.  *    0 = remote closed the connection
  1366.  *    EINTR = signal from local tty (connection can be re-established) 
  1367.  *    Anything else = an error establishing the connection
  1368.  */
  1369. nvt_ioc_join(so, ttyfd)
  1370.     register struct socket *so;
  1371.     int ttyfd;        /* tty file descriptor */
  1372. {
  1373.     register struct file *fp;
  1374.     register struct inode *ip;
  1375.     register struct tty *tp;
  1376.     int error, s;
  1377.     struct nvtj *nvtp;
  1378.  
  1379.     /*
  1380.      * Validate file descriptor and ensure it references a tty
  1381.      */
  1382.     if ((unsigned)ttyfd >= NOFILE || (fp = u.u_ofile[ttyfd]) == 0) 
  1383.         return EBADF;
  1384. #ifdef NFS
  1385.     {
  1386.         register struct vnode *vp;
  1387.  
  1388.         vp = (struct vnode *)fp->f_data;
  1389.         if (fp->f_type != DTYPE_VNODE || vp->v_op != &ufs_vnodeops) 
  1390.             return ENOTTY;
  1391.         ip = VTOI(vp);
  1392.         if ((ip->i_mode & IFMT) != IFCHR ||
  1393.             (tp = cdevsw[major(ip->i_rdev)].d_ttys) == 0) 
  1394.             return ENOTTY;
  1395.     }
  1396. #else NFS
  1397.     ip = (struct inode *)fp->f_data;
  1398.     if (fp->f_type != DTYPE_INODE ||
  1399.         (ip->i_mode & IFMT) != IFCHR ||
  1400.         (tp = cdevsw[major(ip->i_rdev)].d_ttys) == 0) 
  1401.         return ENOTTY;
  1402. #endif NFS
  1403.     /*
  1404.      * Argument socket and tty are valid, now join them and wait
  1405.      */
  1406.     s = splimp();
  1407.     if (error = nvt_add(tp + minor(ip->i_rdev), so, &nvtp)) {
  1408.         splx(s);
  1409.         return error;
  1410.     }
  1411.     if (setjmp(&u.u_qsave)) {
  1412.         /*
  1413.          * The process received a signal
  1414.          */
  1415.         nvt_del(nvtp);        /* disassociate tty&socket */
  1416.         splx(s);
  1417.         return EINTR;
  1418.     }
  1419.     do sleep((caddr_t)nvtp, PZERO + 1); /* wait for signal or disconnect */
  1420.      while (nvtp->nvt_so->so_rcv.sb_flags & SB_NVT);
  1421.     /*
  1422.      * The remote disconnected.
  1423.      */
  1424.     nvt_del(nvtp);            /* disassociate tty&socket */
  1425.     splx(s);
  1426.     return 0;
  1427. }
  1428.  
  1429. /*
  1430.  * Softclock interrupt routine to move characters from local tty
  1431.  * input queues to network
  1432.  */
  1433. /*ARGSUSED*/
  1434. nvt_ocpy(d)
  1435.     caddr_t d;    /* 2nd argument of Timeout() */
  1436. {
  1437.     register struct mbuf *m;
  1438.     register struct tty *tp;
  1439.     register int c;
  1440.     register unsigned char *cp, *cplim;
  1441.     register struct nvtj *nvt;
  1442.     int error;
  1443.  
  1444.     nvtrocpy = 0;
  1445.     /*
  1446.      * Scan all NVT ttys for outbound characters
  1447.      */
  1448.     nvt = &nvtj[0];
  1449.     do {
  1450.         if ((tp = nvt->nvt_tp) == 0) 
  1451.             continue;        /* slot is not active */
  1452.         if (tp->t_rawq.c_cc <= 0 && tp->t_canq.c_cc <= 0) 
  1453.             continue;        /* no data */
  1454.         if (nvt->nvt_so->so_state & SS_CANTSENDMORE) 
  1455.             continue;
  1456.         MGET(m, M_DONTWAIT, MT_DATA);
  1457.         if (m == 0) 
  1458.             continue;
  1459.         cp = m->m_dat;
  1460.         cplim = cp + MLEN;
  1461.         if (tp->t_canq.c_cc > 0)          /* unlikely */
  1462.             while ((c = getc(&tp->t_canq)) >= 0) {
  1463.                 *cp++ = c;
  1464.                 if (cp >= cplim) 
  1465.                     goto mfull;
  1466.             }
  1467.         while ((c = getc(&tp->t_rawq)) >= 0) {
  1468.             if (tp->t_flags & RAW && (c & 0177) == tp->t_intrc) {
  1469.                 /*
  1470.                  * rlogin escape character typed in raw mode,
  1471.                  * simulate ttyinput() processing thereof
  1472.                  */
  1473.                 gsignal(tp->t_pgrp, SIGINT);
  1474.                 continue;
  1475.             }
  1476.             *cp++ = c;
  1477.             if (cp >= cplim) 
  1478.                 goto mfull;
  1479.         }
  1480. mfull:        m->m_len = cp - m->m_dat;
  1481.         error = (*nvt->nvt_so->so_proto->pr_usrreq)(nvt->nvt_so,
  1482.             PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
  1483. #ifdef lint
  1484.         /* Same actuals as above, better information for lint */
  1485.         error = tcp_usrreq(nvt->nvt_so,
  1486.             PRU_SEND, m, (struct mbuf *)0, (struct mbuf *)0);
  1487. #endif
  1488.         if (error) 
  1489.             nvt_emsg("nvt SEND %d\n", error);
  1490.     } while (++nvt <= nvthij);
  1491. }
  1492.  
  1493. /*
  1494.  * Process out-of-band data from remote
  1495.  */
  1496. nvt_oob(nvt, od)
  1497.     register struct nvtj *nvt;
  1498.     unsigned char od;        /* data */
  1499. {
  1500.     register struct tty *tp = nvt->nvt_tp;
  1501.  
  1502.     ttyflush(tp, FWRITE);
  1503.     if (od & TIOCPKT_NOSTOP) {
  1504.         tp->t_stopc = -1;
  1505.         tp->t_startc = -1;
  1506.     }
  1507.     if (od & TIOCPKT_DOSTOP) {
  1508.         tp->t_stopc = nvt->nvt_ostopc;
  1509.         tp->t_startc = nvt->nvt_ostartc;
  1510.     }
  1511.     if (nvtnmsg > 10) 
  1512.         nvt_emsg("nvt oob %x\n", od);
  1513. }
  1514.  
  1515. /*
  1516.  * Send characters typed at a local terminal across the net
  1517.  *
  1518.  * Called from tty hardware interrupt handler, so must queue request
  1519.  * to be handled at net IPL
  1520.  */
  1521. nvt_output(tp)
  1522.     register struct tty *tp;
  1523. {
  1524.     register struct nvtj *nvt;
  1525.  
  1526.     nvt = &nvtj[0];
  1527.     do {
  1528.         if (nvt->nvt_tp == tp) {
  1529.             if (!nvtrocpy) {
  1530.                 nvtrocpy++;
  1531.                 timeout(nvt_ocpy, (caddr_t)0, 0);
  1532.             }
  1533.             return;
  1534.         }
  1535.     } while (++nvt <= nvthij);
  1536.     /*
  1537.      * Not in my list, this tty is no longer associated with a socket
  1538.      */
  1539.     tp->t_state &= ~TS_NVT;
  1540. }
  1541.  
  1542. #endif KNVT
  1543. SHAR_EOF
  1544.  
  1545.  
  1546.