home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume32 / pol / part01 / pty.c < prev    next >
C/C++ Source or Header  |  1992-10-18  |  10KB  |  532 lines

  1. /*
  2.  * pty.c - Berkeley style pseudo tty driver for system V
  3.  *
  4.  * Copyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH
  5.  * Not derived from licensed software.
  6.  *
  7.  * Permission is granted to freely use, copy, modify, and redistribute
  8.  * this software, provided that no attempt is made to gain profit from it,
  9.  * the author is not construed to be liable for any results of using the
  10.  * software, alterations are clearly marked as such, and this notice is
  11.  * not modified.
  12.  */
  13. #define TTI            /* comment this define out for the original
  14.                  * posted code
  15.                  */
  16. #ifndef TTI
  17. /*
  18.  * the following are arbitrary 3 unused bits from t_state
  19.  * in sys/tty.h
  20.  */
  21. #endif TTI
  22.  
  23. #ifndef TTI
  24. #define MRWAIT    01000000    /* master waiting in read */
  25. #else TTI
  26. #define MRWAIT    01        /* master waiting in read */
  27. #endif TTI
  28. #define t_rloc    t_cc[0]        /* rchannel */
  29.  
  30. #ifndef TTI
  31. #define MWWAIT    02000000    /* master waiting in write */
  32. #else TTI
  33. #define MWWAIT    02        /* master waiting in write */
  34. #endif TTI
  35. #define t_wloc    t_cc[1]        /* wchannel */
  36.  
  37. #ifndef TTI
  38. #define MOPEN    04000000    /* master is open */
  39. #else TTI
  40. #define MOPEN    04        /* master is open */
  41. #endif TTI
  42.  
  43. #include "sys/param.h"
  44. #include "sys/types.h"
  45. #include "sys/sysmacros.h"
  46. #include "sys/seg.h"
  47. #include "sys/page.h"
  48. #include "sys/systm.h"
  49. #include "sys/file.h"
  50. #include "sys/conf.h"
  51.  
  52. #ifndef tower
  53. #ifdef TTI
  54. #include "sys/immu.h"
  55. #endif TTI
  56. #include "sys/region.h"
  57. #endif
  58.  
  59. #include "sys/proc.h"
  60. #include "sys/dir.h"
  61. #include "sys/tty.h"
  62. #include "sys/signal.h"
  63. #include "sys/user.h"
  64. #include "sys/errno.h"
  65. #include "sys/termio.h"
  66. #include "sys/ttold.h"
  67.  
  68. /*
  69.  * from config
  70.  */
  71. extern struct tty pts_tty[];
  72.  
  73. #ifdef TTI
  74. extern int pts_state[];
  75. #endif TTI
  76. extern int pts_cnt;
  77.  
  78. int    ptsflush = 0;
  79. /*
  80.  * slave side is a fairly standard system V tty driver
  81.  */
  82. #ifndef TTI
  83. ptsopen(dev, flag)
  84. #else TTI
  85. ptsopen(fdev, flag)
  86. #endif TTI
  87. {
  88. #ifdef TTI
  89.     register dev = minor(fdev);
  90. #endif TTI
  91.     register struct tty *tp = &pts_tty[dev];
  92.     extern int ptsproc();
  93.  
  94.     if (dev >= pts_cnt) {
  95.         u.u_error = ENXIO;
  96.         return;
  97.     }
  98.     if ((tp->t_state & (ISOPEN|WOPEN)) == 0) {
  99.         ttinit(tp);
  100.         tp->t_proc = ptsproc;
  101.     }
  102.     /*
  103.      * if master is still open, don't wait for carrier
  104.      */
  105. #ifndef TTI
  106.     if (tp->t_state & MOPEN)
  107. #else TTI
  108.     if (pts_state[dev] & MOPEN)
  109. #endif TTI
  110.         tp->t_state |= CARR_ON;
  111.     if (!(flag & FNDELAY)) {
  112.         while ((tp->t_state & CARR_ON) == 0) {
  113.             tp->t_state |= WOPEN;
  114.             sleep((caddr_t)&tp->t_canq, TTIPRI);
  115.         }
  116.     }
  117.     (*linesw[tp->t_line].l_open)(tp);
  118. }
  119.  
  120. #ifndef TTI
  121. ptswrite(dev)
  122. #else TTI
  123. ptswrite(fdev)
  124. #endif TTI
  125. {
  126. #ifdef TTI
  127.     register dev = minor(fdev);
  128. #endif TTI
  129.     register struct tty *tp = &pts_tty[dev];
  130.  
  131. #ifdef TTI
  132. #ifdef DEBUG
  133.         printf("T_TIME\n");
  134. #endif
  135.  
  136. #endif TTI
  137.     (*linesw[tp->t_line].l_write)(tp);
  138. }
  139.  
  140. #ifndef TTI
  141. ptsread(dev)
  142. #else TTI
  143. ptsread(fdev)
  144. #endif TTI
  145. {
  146. #ifdef TTI
  147.     register dev = minor(fdev);
  148. #endif TTI
  149.     register struct tty *tp = &pts_tty[dev];
  150.  
  151.     (*linesw[tp->t_line].l_read)(tp);
  152. }
  153.  
  154. #ifndef TTI
  155. ptsclose(dev)
  156. #else TTI
  157. ptsclose(fdev)
  158. #endif TTI
  159. {
  160. #ifdef TTI
  161.     register dev = minor(fdev);
  162. #endif TTI
  163.     register struct tty *tp = &pts_tty[dev];
  164.     
  165.     (*linesw[tp->t_line].l_close)(tp);
  166.     tp->t_state &= ~CARR_ON;
  167. }
  168.  
  169. #ifndef TTI
  170. ptsioctl(dev, cmd, arg, mode)
  171. #else TTI
  172. ptsioctl(fdev, cmd, arg, mode)
  173. #endif TTI
  174. {
  175. #ifdef TTI
  176.     register dev = minor(fdev);
  177. #endif TTI
  178.     register struct tty *tp = &pts_tty[dev];
  179.  
  180.         /* the driver hung on TCSETAF/W, so I have to do it myself, bjm */
  181.     if (cmd == TCSETAW || cmd == TCSETAF) 
  182.     {
  183.         ptsflush++;
  184.         while ( tp->t_tbuf.c_ptr != NULL && tp->t_tbuf.c_count != 0 &&
  185.                 tp->t_outq.c_cc != 0)
  186.             sleep((caddr_t *)&ptsflush, PSLEP);
  187.         if (cmd == TCSETAF)
  188.             ttyflush(tp, FREAD);
  189.         cmd = TCSETA;
  190.         ptsflush--;
  191.     }
  192.     ttiocom(tp, cmd, arg, mode);
  193. }
  194.  
  195. ptsproc(tp, cmd)
  196. register struct tty *tp;
  197. {
  198.     register struct ccblock *tbuf;
  199.     extern ttrstrt();
  200.  
  201.     switch (cmd) {
  202.     case T_TIME:
  203. #ifdef DEBUG
  204.         printf("T_TIME\n");
  205. #endif
  206.         tp->t_state &= ~TIMEOUT;
  207.         goto start;
  208.     case T_WFLUSH:
  209. #ifdef DEBUG
  210.         printf("T_WFLUSH\n");
  211. #endif
  212.         tp->t_tbuf.c_size  -= tp->t_tbuf.c_count;
  213.         tp->t_tbuf.c_count = 0;
  214.         if (ptsflush)
  215.             wakeup((caddr_t)&ptsflush);
  216.         /* fall through */
  217.     case T_RESUME:
  218. #ifdef DEBUG
  219.         printf("T_RESUME\n");
  220. #endif
  221.         tp->t_state &= ~TTSTOP;
  222.         /* fall through */
  223.     case T_OUTPUT:
  224. #ifdef DEBUG
  225.         printf("T_OUTPUT\n");
  226. #endif
  227. start:
  228.         if (tp->t_state & (TTSTOP|TIMEOUT))
  229.             break;
  230.         tbuf = &tp->t_tbuf;
  231.         if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
  232.             if (tbuf->c_ptr)
  233.                 tbuf->c_ptr -= tbuf->c_size;
  234.             if (!(CPRES & (*linesw[tp->t_line].l_output)(tp)))
  235.                 break;
  236.         }
  237. #ifndef TTI
  238.         if (tbuf->c_count && (tp->t_state & MRWAIT)) {
  239.             tp->t_state &= ~MRWAIT;
  240. #else TTI
  241.         if (tbuf->c_count && (pts_state[tp-pts_tty] & MRWAIT)) {
  242.             pts_state[tp-pts_tty] &= ~MRWAIT;
  243. #endif TTI
  244.             wakeup((caddr_t)&tp->t_rloc);
  245.         }
  246.         break;
  247.     case T_SUSPEND:
  248. #ifdef DEBUG
  249.         printf("T_SUSPEND\n");
  250. #endif
  251.         tp->t_state |= TTSTOP;
  252.         break;
  253.     case T_BLOCK:
  254. #ifdef DEBUG
  255.         printf("T_BLOCK\n");
  256. #endif
  257.         /*
  258.          * the check for ICANON appears to be neccessary
  259.          * to avoid a hang when overflowing input
  260.          */
  261.         if ((tp->t_iflag & ICANON) == 0)
  262.             tp->t_state |= TBLOCK;
  263.         break;
  264.     case T_BREAK:
  265. #ifdef DEBUG
  266.         printf("T_BREAK\n");
  267. #endif
  268.         tp->t_state |= TIMEOUT;
  269.         timeout(ttrstrt, tp, HZ/4);
  270.         break;
  271. #ifdef T_LOG_FLUSH
  272.     case T_LOG_FLUSH:
  273. #ifdef DEBUG
  274.         printf("T_LOG_FLUSH\n");
  275. #endif
  276. #endif
  277.     case T_RFLUSH:
  278. #ifdef DEBUG
  279.         printf("T_RFLUSH\n");
  280. #endif
  281.         if (!(tp->t_state & TBLOCK))
  282.             break;
  283.         /* fall through */
  284.     case T_UNBLOCK:
  285. #ifdef DEBUG
  286.         printf("T_UNBLOCK\n");
  287. #endif
  288.         tp->t_state &= ~(TTXOFF|TBLOCK);
  289.         /* fall through */
  290.     case T_INPUT:
  291. #ifdef DEBUG
  292.         printf("T_INPUT\n");
  293. #endif
  294. #ifndef TTI
  295.         if (tp->t_state & MWWAIT) {
  296.             tp->t_state &= ~MWWAIT;
  297. #else TTI
  298.         if (pts_state[tp-pts_tty] & MWWAIT) {
  299.             pts_state[tp-pts_tty] &= ~MWWAIT;
  300. #endif TTI
  301.             wakeup((caddr_t)&tp->t_wloc);
  302.         }
  303.         break;
  304. #ifdef DEBUG
  305.     default:
  306.         printf("ptsproc: cmd %d\n",cmd);
  307. #endif
  308.     }
  309. }
  310.  
  311. /*
  312.  * master part - not actually like a tty
  313.  */
  314.  
  315. #ifndef TTI
  316. ptmopen(dev, flag)
  317. #else TTI
  318. ptmopen(fdev, flag)
  319. #endif TTI
  320. {
  321. #ifdef TTI
  322.     register dev = minor(fdev);
  323. #endif TTI
  324.     register struct tty *tp = &pts_tty[dev];
  325.  
  326. #ifdef DEBUG
  327.     printf("ptmopen(%d)\n",dev);
  328. #endif
  329.     if (dev >= pts_cnt) {
  330.         u.u_error = ENXIO;
  331.         return;
  332.     }
  333.     /*
  334.      * allow only one controlling process
  335.      */
  336. #ifndef TTI
  337.     if (tp->t_state & MOPEN) {
  338. #else TTI
  339.     if (pts_state[dev] & MOPEN) {
  340. #endif TTI
  341.         u.u_error = EBUSY;
  342.         return;
  343.     }
  344.     if (tp->t_state & WOPEN)
  345.         wakeup((caddr_t)&tp->t_canq);
  346. #ifndef TTI
  347.     tp->t_state |= CARR_ON|MOPEN;
  348. #else TTI
  349.     tp->t_state |= CARR_ON;
  350.     pts_state[dev] |= MOPEN;
  351. #endif TTI
  352. }
  353.  
  354. #ifndef TTI
  355. ptmread(dev)
  356. #else TTI
  357. ptmread(fdev)
  358. #endif TTI
  359. {
  360. #ifdef TTI
  361.     register dev = minor(fdev);
  362. #endif TTI
  363.     register struct tty *tp = &pts_tty[dev];
  364.     register n;
  365.  
  366. #ifndef TTI
  367.     if ((tp->t_state & ISOPEN) == 0) {
  368. #else TTI
  369.     if ((tp->t_state & (ISOPEN|TTIOW)) == 0) {
  370. #ifdef DEBUG
  371.     printf("ptmread(%d) EIO\n",dev);
  372. #endif
  373. #endif TTI
  374.         u.u_error = EIO;
  375.         return;
  376.     }
  377. #ifdef DEBUG
  378.     printf("ptmread(%d)\n",dev);
  379. #endif
  380. #ifndef TTI
  381.     while (u.u_count) {
  382. #else TTI
  383.     while (u.u_count>0) {
  384. #endif TTI
  385.         ptsproc(tp, T_OUTPUT);
  386.         if ((tp->t_state & (TTSTOP|TIMEOUT))
  387.             || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) {
  388.             if (u.u_fmode & FNDELAY)
  389.                 break;
  390. #ifndef TTI
  391.             tp->t_state |= MRWAIT;
  392. #else TTI
  393.             pts_state[dev] |= MRWAIT;
  394. #endif TTI
  395.             sleep((caddr_t)&tp->t_rloc, TTIPRI);
  396.             continue;
  397.         }
  398.         n = min(u.u_count, tp->t_tbuf.c_count);
  399.         if (n) {
  400.             if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) {
  401.                 u.u_error = EFAULT;
  402.                 break;
  403.             }
  404.             tp->t_tbuf.c_count -= n;
  405.             tp->t_tbuf.c_ptr += n;
  406.             u.u_base += n;
  407.             u.u_count -= n;
  408.             if (ptsflush)
  409.                 wakeup((caddr_t)&ptsflush);
  410.             break;      /* bjm and jrm */
  411.         }
  412.     }
  413. }
  414.  
  415. #ifndef TTI
  416. ptmwrite(dev)
  417. #else TTI
  418. ptmwrite(fdev)
  419. #endif TTI
  420. {
  421. #ifdef TTI
  422.     register dev = minor(fdev);
  423. #endif TTI
  424.     register struct tty *tp = &pts_tty[dev];
  425.     register n;
  426.  
  427.     if ((tp->t_state & ISOPEN) == 0) {
  428.         u.u_error = EIO;
  429.         return;
  430.     }
  431. #ifdef DEBUG
  432.     printf("ptmwrite(%d)\n",dev);
  433. #endif
  434. #ifndef TTI
  435.     while (u.u_count) {
  436. #else TTI
  437.     while (u.u_count>0) {
  438. #endif TTI
  439.         if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
  440.             if (u.u_fmode & FNDELAY)
  441.                 break;
  442. #ifndef TTI
  443.             tp->t_state |= MWWAIT;
  444. #else TTI
  445.             pts_state[dev] |= MWWAIT;
  446. #endif TTI
  447.             sleep((caddr_t)&tp->t_wloc, TTOPRI);
  448.             continue;
  449.         }
  450.         n = min(u.u_count, tp->t_rbuf.c_count);
  451.         if (n) {
  452.             if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) {
  453.                 u.u_error = EFAULT;
  454.                 break;
  455.             }
  456.             tp->t_rbuf.c_count -= n;
  457.             u.u_base += n;
  458.             u.u_count -= n;
  459.         }
  460. #ifdef vax || m68k
  461.         /*
  462.          * somebody told me this is necessary on the vax
  463.          */
  464.         (*linesw[tp->t_line].l_input)(tp, L_BUF);
  465. #else
  466.         (*linesw[tp->t_line].l_input)(tp);
  467. #endif
  468.     }
  469. }
  470.  
  471. #ifndef TTI
  472. ptmclose(dev)
  473. #else TTI
  474. ptmclose(fdev)
  475. #endif TTI
  476. {
  477. #ifdef TTI
  478.     register dev = minor(fdev);
  479. #endif TTI
  480.     register struct tty *tp = &pts_tty[dev];
  481.  
  482. #ifdef DEBUG
  483.     printf("ptmclose(%d)\n",dev);
  484. #endif
  485.     if (tp->t_state & ISOPEN) {
  486.         signal(tp->t_pgrp, SIGHUP);
  487.         ttyflush(tp, FREAD|FWRITE);
  488.     }
  489.     /*
  490.      * virtual carrier gone
  491.      */
  492. #ifndef TTI
  493.     tp->t_state &= ~(CARR_ON|MOPEN);
  494. #else TTI
  495.     tp->t_state &= ~CARR_ON;
  496.     pts_state[dev] &= ~MOPEN;
  497. #endif TTI
  498. }
  499.  
  500. #ifndef TTI
  501. ptmioctl(dev, cmd, arg, mode)
  502. #else TTI
  503. ptmioctl(fdev, cmd, arg, mode)
  504. #endif TTI
  505. {
  506. #ifdef TTI
  507.     register dev = minor(fdev);
  508. #endif TTI
  509.     register struct tty *tp = &pts_tty[dev];
  510.  
  511.     /*
  512.      * sorry, but we can't fiddle with the tty struct without
  513.      * having done LDOPEN
  514.      */
  515.     if (tp->t_state & ISOPEN) {
  516.         if (cmd == TCSBRK && arg ==  NULL) {
  517.             signal(tp->t_pgrp, SIGINT);
  518.             if ((tp->t_iflag & NOFLSH) == 0)
  519.                 ttyflush(tp, FREAD|FWRITE);
  520.         } else {
  521.             /*
  522.              * we must flush output to avoid hang in ttywait
  523.              */
  524.             if (cmd == TCSETAW || cmd == TCSETAF || cmd == TCSBRK
  525.                 || cmd == TIOCSETP)
  526.                 ttyflush(FWRITE);
  527.             ttiocom(tp, cmd, arg, mode);
  528.         }
  529.     }
  530. }
  531.  
  532.