home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8707 / 74 / pty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  6.8 KB  |  357 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.  
  14. /*
  15.  * the following are arbitrary 3 unused bits from t_state
  16.  * in sys/tty.h
  17.  */
  18. #define MRWAIT    01000000    /* master waiting in read */
  19. #define t_rloc    t_cc[0]        /* wchannel */
  20. #define MWWAIT    02000000    /* master waiting in write */
  21. #define t_wloc    t_cc[1]        /* wchannel */
  22. #define MOPEN    04000000    /* master is open */
  23.  
  24. #include "sys/param.h"
  25. #include "sys/types.h"
  26. #include "sys/sysmacros.h"
  27. #include "sys/seg.h"
  28. #include "sys/page.h"
  29. #include "sys/systm.h"
  30. #include "sys/file.h"
  31. #include "sys/conf.h"
  32. #ifndef tower
  33. #include "sys/region.h"
  34. #endif
  35. #include "sys/proc.h"
  36. #include "sys/dir.h"
  37. #include "sys/tty.h"
  38. #include "sys/signal.h"
  39. #include "sys/user.h"
  40. #include "sys/errno.h"
  41. #include "sys/termio.h"
  42. #include "sys/ttold.h"
  43.  
  44. /*
  45.  * from config
  46.  */
  47. extern struct tty pts_tty[];
  48. extern int pts_cnt;
  49.  
  50. /*
  51.  * slave side is a fairly standard system V tty driver
  52.  */
  53. ptsopen(dev, flag)
  54. {
  55.     register struct tty *tp = &pts_tty[dev];
  56.     extern int ptsproc();
  57.  
  58.     if (dev >= pts_cnt) {
  59.         u.u_error = ENXIO;
  60.         return;
  61.     }
  62.     if ((tp->t_state & (ISOPEN|WOPEN)) == 0) {
  63.         ttinit(tp);
  64.         tp->t_proc = ptsproc;
  65.     }
  66.     /*
  67.      * if master is still open, don't wait for carrier
  68.      */
  69.     if (tp->t_state & MOPEN)
  70.         tp->t_state |= CARR_ON;
  71.     if (!(flag & FNDELAY)) {
  72.         while ((tp->t_state & CARR_ON) == 0) {
  73.             tp->t_state |= WOPEN;
  74.             sleep((caddr_t)&tp->t_canq, TTIPRI);
  75.         }
  76.     }
  77.     (*linesw[tp->t_line].l_open)(tp);
  78. }
  79.  
  80. ptswrite(dev)
  81. {
  82.     register struct tty *tp = &pts_tty[dev];
  83.  
  84.     (*linesw[tp->t_line].l_write)(tp);
  85. }
  86.  
  87. ptsread(dev)
  88. {
  89.     register struct tty *tp = &pts_tty[dev];
  90.  
  91.     (*linesw[tp->t_line].l_read)(tp);
  92. }
  93.  
  94. ptsclose(dev)
  95. {
  96.     register struct tty *tp = &pts_tty[dev];
  97.     
  98.     (*linesw[tp->t_line].l_close)(tp);
  99.     tp->t_state &= ~CARR_ON;
  100. }
  101.  
  102. ptsioctl(dev, cmd, arg, mode)
  103. {
  104.     register struct tty *tp = &pts_tty[dev];
  105.  
  106.     ttiocom(tp, cmd, arg, mode);
  107. }
  108.  
  109. ptsproc(tp, cmd)
  110. register struct tty *tp;
  111. {
  112.     register struct ccblock *tbuf;
  113.     extern ttrstrt();
  114.  
  115.     switch (cmd) {
  116.     case T_TIME:
  117. #ifdef DEBUG
  118.         printf("T_TIME\n");
  119. #endif
  120.         tp->t_state &= ~TIMEOUT;
  121.         goto start;
  122.     case T_WFLUSH:
  123. #ifdef DEBUG
  124.         printf("T_WFLUSH\n");
  125. #endif
  126.         tp->t_tbuf.c_size  -= tp->t_tbuf.c_count;
  127.         tp->t_tbuf.c_count = 0;
  128.         /* fall through */
  129.     case T_RESUME:
  130. #ifdef DEBUG
  131.         printf("T_RESUME\n");
  132. #endif
  133.         tp->t_state &= ~TTSTOP;
  134.         /* fall through */
  135.     case T_OUTPUT:
  136. #ifdef DEBUG
  137.         printf("T_OUTPUT\n");
  138. #endif
  139. start:
  140.         if (tp->t_state & (TTSTOP|TIMEOUT))
  141.             break;
  142.         tbuf = &tp->t_tbuf;
  143.         if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
  144.             if (tbuf->c_ptr)
  145.                 tbuf->c_ptr -= tbuf->c_size;
  146.             if (!(CPRES & (*linesw[tp->t_line].l_output)(tp)))
  147.                 break;
  148.         }
  149.         if (tbuf->c_count && (tp->t_state & MRWAIT)) {
  150.             tp->t_state &= ~MRWAIT;
  151.             wakeup((caddr_t)&tp->t_rloc);
  152.         }
  153.         break;
  154.     case T_SUSPEND:
  155. #ifdef DEBUG
  156.         printf("T_SUSPEND\n");
  157. #endif
  158.         tp->t_state |= TTSTOP;
  159.         break;
  160.     case T_BLOCK:
  161. #ifdef DEBUG
  162.         printf("T_BLOCK\n");
  163. #endif
  164.         /*
  165.          * the check for ICANON appears to be neccessary
  166.          * to avoid a hang when overflowing input
  167.          */
  168.         if ((tp->t_iflag & ICANON) == 0)
  169.             tp->t_state |= TBLOCK;
  170.         break;
  171.     case T_BREAK:
  172. #ifdef DEBUG
  173.         printf("T_BREAK\n");
  174. #endif
  175.         tp->t_state |= TIMEOUT;
  176.         timeout(ttrstrt, tp, HZ/4);
  177.         break;
  178. #ifdef T_LOG_FLUSH
  179.     case T_LOG_FLUSH:
  180. #ifdef DEBUG
  181.         printf("T_LOG_FLUSH\n");
  182. #endif
  183.     case T_RFLUSH:
  184. #ifdef DEBUG
  185.         printf("T_RFLUSH\n");
  186. #endif
  187.         if (!(tp->t_state & TBLOCK))
  188.             break;
  189.         /* fall through */
  190.     case T_UNBLOCK:
  191. #ifdef DEBUG
  192.         printf("T_UNBLOCK\n");
  193. #endif
  194.         tp->t_state &= ~(TTXOFF|TBLOCK);
  195.         /* fall through */
  196.     case T_INPUT:
  197. #ifdef DEBUG
  198.         printf("T_INPUT\n");
  199. #endif
  200.         if (tp->t_state & MWWAIT) {
  201.             tp->t_state &= ~MWWAIT;
  202.             wakeup((caddr_t)&tp->t_wloc);
  203.         }
  204.         break;
  205. #ifdef DEBUG
  206.     default:
  207.         printf("ptsproc: cmd %d\n",cmd);
  208. #endif
  209.     }
  210. }
  211.  
  212. /*
  213.  * master part - not actually like a tty
  214.  */
  215.  
  216. ptmopen(dev, flag)
  217. {
  218.     register struct tty *tp = &pts_tty[dev];
  219.  
  220. #ifdef DEBUG
  221.     printf("ptmopen(%d)\n",dev);
  222. #endif
  223.     if (dev >= pts_cnt) {
  224.         u.u_error = ENXIO;
  225.         return;
  226.     }
  227.     /*
  228.      * allow only one controlling process
  229.      */
  230.     if (tp->t_state & MOPEN) {
  231.         u.u_error = EBUSY;
  232.         return;
  233.     }
  234.     if (tp->t_state & WOPEN)
  235.         wakeup((caddr_t)&tp->t_canq);
  236.     tp->t_state |= CARR_ON|MOPEN;
  237. }
  238.  
  239. ptmread(dev)
  240. {
  241.     register struct tty *tp = &pts_tty[dev];
  242.     register n;
  243.  
  244.     if ((tp->t_state & ISOPEN) == 0) {
  245.         u.u_error = EIO;
  246.         return;
  247.     }
  248. #ifdef DEBUG
  249.     printf("ptmread(%d)\n",dev);
  250. #endif
  251.     while (u.u_count) {
  252.         ptsproc(tp, T_OUTPUT);
  253.         if ((tp->t_state & (TTSTOP|TIMEOUT))
  254.             || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) {
  255.             if (u.u_fmode & FNDELAY)
  256.                 break;
  257.             tp->t_state |= MRWAIT;
  258.             sleep((caddr_t)&tp->t_rloc, TTIPRI);
  259.             continue;
  260.         }
  261.         n = min(u.u_count, tp->t_tbuf.c_count);
  262.         if (n) {
  263.             if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) {
  264.                 u.u_error = EFAULT;
  265.                 break;
  266.             }
  267.             tp->t_tbuf.c_count -= n;
  268.             tp->t_tbuf.c_ptr += n;
  269.             u.u_base += n;
  270.             u.u_count -= n;
  271.         }
  272.     }
  273. }
  274.  
  275. ptmwrite(dev)
  276. {
  277.     register struct tty *tp = &pts_tty[dev];
  278.     register n;
  279.  
  280.     if ((tp->t_state & ISOPEN) == 0) {
  281.         u.u_error = EIO;
  282.         return;
  283.     }
  284. #ifdef DEBUG
  285.     printf("ptmwrite(%d)\n",dev);
  286. #endif
  287.     while (u.u_count) {
  288.         if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
  289.             if (u.u_fmode & FNDELAY)
  290.                 break;
  291.             tp->t_state |= MWWAIT;
  292.             sleep((caddr_t)&tp->t_wloc, TTOPRI);
  293.             continue;
  294.         }
  295.         n = min(u.u_count, tp->t_rbuf.c_count);
  296.         if (n) {
  297.             if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) {
  298.                 u.u_error = EFAULT;
  299.                 break;
  300.             }
  301.             tp->t_rbuf.c_count -= n;
  302.             u.u_base += n;
  303.             u.u_count -= n;
  304.         }
  305. #ifdef vax
  306.         /*
  307.          * somebody told me this is necessary on the vax
  308.          */
  309.         (*linesw[tp->t_line].l_input)(tp, L_BUF);
  310. #else
  311.         (*linesw[tp->t_line].l_input)(tp);
  312. #endif
  313.     }
  314. }
  315.  
  316. ptmclose(dev)
  317. {
  318.     register struct tty *tp = &pts_tty[dev];
  319.  
  320. #ifdef DEBUG
  321.     printf("ptmclose(%d)\n",dev);
  322. #endif
  323.     if (tp->t_state & ISOPEN) {
  324.         signal(tp->t_pgrp, SIGHUP);
  325.         ttyflush(tp, FREAD|FWRITE);
  326.     }
  327.     /*
  328.      * virtual carrier gone
  329.      */
  330.     tp->t_state &= ~(CARR_ON|MOPEN);
  331. }
  332.  
  333. ptmioctl(dev, cmd, arg, mode)
  334. {
  335.     register struct tty *tp = &pts_tty[dev];
  336.  
  337.     /*
  338.      * sorry, but we can't fiddle with the tty struct without
  339.      * having done LDOPEN
  340.      */
  341.     if (tp->t_state & ISOPEN) {
  342.         if (cmd == TCSBRK && arg ==  NULL) {
  343.             signal(tp->t_pgrp, SIGINT);
  344.             if ((tp->t_iflag & NOFLSH) == 0)
  345.                 ttyflush(tp, FREAD|FWRITE);
  346.         } else {
  347.             /*
  348.              * we must flush output to avoid hang in ttywait
  349.              */
  350.             if (cmd == TCSETAW || cmd == TCSETAF || cmd == TCSBRK
  351.                 || cmd == TIOCSETP)
  352.                 ttyflush(FWRITE);
  353.             ttiocom(tp, cmd, arg, mode);
  354.         }
  355.     }
  356. }
  357.