home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume32 / pol / part01 / pol.c < prev    next >
C/C++ Source or Header  |  1992-10-18  |  11KB  |  458 lines

  1.  /*
  2.     pol.c    - poll/select() implemented as a device driver
  3.     version 1.04    9/17/92
  4.     
  5.     Bruce Momjian (root%candle.uucp@bts.com)
  6.  
  7. */
  8.  
  9. /* tabs = 4 */
  10. /* Include files */
  11.  
  12. #ifdef DEBUG
  13. #define    DB(x)    x
  14. #else
  15. #define DB(x)
  16. #endif
  17.  
  18. #include <errno.h>
  19. #include <limits.h>
  20. #include <sys/pol.h>
  21. #include <sys/types.h>
  22. #include <sys/param.h>
  23. #include <sys/ioctl.h>
  24. #include <sys/dir.h>
  25. #include <sys/signal.h>
  26. #include <sys/user.h>
  27. #include <sys/file.h>
  28. #include <sys/inode.h>
  29. #include <sys/conf.h>
  30. #include <sys/tty.h>
  31. #include <sys/termio.h>
  32. #include <sys/sxt.h>
  33. #include <sys/sysmacros.h>
  34.  
  35. #define TTIN_FUNCT        ttin
  36. #define TTWRITE_FUNCT    ttwrite
  37.  
  38. #define POL_READ_FLAG        0
  39. #define POL_WRITE_FLAG        1
  40.  
  41. #define IS_PTM                1
  42. #define IS_PIPE                4
  43.  
  44. #define TBUF_CNT_OFF    (int)&(((struct tty *)0)->t_tbuf.c_count)
  45. #define TOUTQ_CC_OFF       (int)&(((struct tty *)0)->t_outq.c_cc)
  46. #define TCANQ_CC_OFF       (int)&(((struct tty *)0)->t_canq.c_cc)
  47. #define TRAWQ_CC_OFF       (int)&(((struct tty *)0)->t_rawq.c_cc)
  48. #define T_CFLAG_OFF       (int)&(((struct tty *)0)->t_cflag)
  49. #define T_STATE_OFF       (int)&(((struct tty *)0)->t_state)
  50.  
  51. int    pol_in_use = 0;                    /* is pol opened, also sleep addr. */
  52. int pol_intr = 0;                    /* was pol interupted during scan */
  53.  
  54. /* pty and sxt external symbols */
  55. extern struct tty sxt_tty[], pts_tty[];
  56. extern int sxtopen(), ptmopen();
  57. extern char sxt_buf[];
  58.  
  59. /* kernel symbols */
  60. extern int ttin(), ttwrite();
  61.  
  62. /* my function symbols */
  63. int ttinpol(), ttwrpol(), poltimeo();
  64.  
  65. extern time_t lbolt;                    /* ticks since boot */
  66.  
  67. struct pol_table {
  68.         caddr_t addr;                    /* usually struct tty pointer */
  69.         short    fd;
  70.         short    ttyflags;
  71. };
  72.  
  73. /*---------------------------------------------------------------------------
  74. **
  75. **    polopen - called for each open() call
  76. **
  77. **--------------------------------------------------------------------------*/
  78. polopen(fdev, flags)
  79. int    fdev, flags;
  80. {
  81.     if (pol_in_use == 0)
  82.     {
  83.         if (linesw[0].l_input != TTIN_FUNCT)    /* is linesw[] ok? */
  84.         {
  85.             printf("pol error:  linesw structure corrupted.\n");
  86.               u.u_error = ENOMSG;
  87.               u.u_rval1 = -1;
  88.             return -1;
  89.         }
  90.         if (linesw[0].l_write != TTWRITE_FUNCT)
  91.         {
  92.             printf("pol error:  linesw structure corrupted.\n");
  93.             u.u_error = ENOMSG;
  94.             u.u_rval1 = -1;
  95.             return -1;
  96.         }
  97.         spltty();                    /* don't let anyone use them yet */ 
  98.         linesw[0].l_input = ttinpol;/* substitute our own functions */
  99.         linesw[0].l_write = ttwrpol;
  100.         spl0();
  101.         pol_in_use = 1;                /* mark pol in use */
  102.     }        
  103.     return 0;
  104. }
  105.  
  106. /*---------------------------------------------------------------------------
  107. **
  108. **    polclose - called only for last close() call
  109. **
  110. **--------------------------------------------------------------------------*/
  111. polclose(fdev)
  112. int    fdev;
  113. {
  114.     pol_in_use = 0;
  115.     if (linesw[0].l_input != ttinpol)    /* is linesw[] ok? */
  116.     {
  117.         printf("pol error:  linesw structure corrupted.\n");
  118.         u.u_error = ENOMSG;
  119.         u.u_rval1 = -1;
  120.     }
  121.     else if (linesw[0].l_write != ttwrpol)
  122.     {
  123.         printf("pol error:  linesw structure corrupted.\n");
  124.         u.u_error = ENOMSG;
  125.         u.u_rval1 = -1;
  126.     }
  127.     else    u.u_rval1 = 0;
  128.     spltty();                    /* don't let anyone use them */
  129.     linesw[0].l_input = ttin;    /* replace the originals */
  130.     linesw[0].l_write = ttwrite;
  131.     spl0();
  132.     return u.u_rval1;
  133. }
  134.  
  135. /*---------------------------------------------------------------------------
  136. **
  137. **    polioctl - called for each ioctl() call
  138. **
  139. **--------------------------------------------------------------------------*/
  140. polioctl(fdev, command, polfd_p, mode) 
  141. int    fdev, command, mode;
  142. struct polfd *polfd_p;
  143. {
  144.     int     i,
  145.             rfds_num = 0,
  146.             wfds_num = 0,
  147.             hits = 0,
  148.             char_cnt,
  149.             timeout_idx = 0;
  150.     time_t    start_ticks = lbolt,
  151.             timeout_ticks;
  152.     struct polfd pol_s;
  153.     struct pol_table rfds_pol[NPOLFILE],
  154.                      wfds_pol[NPOLFILE];
  155.     
  156.     DB(printf("Start func\n"));
  157.     if (copyin(polfd_p, &pol_s, sizeof(struct polfd)) != 0)
  158.     {
  159.         u.u_error = EFAULT;
  160.         u.u_rval1 = -1;
  161.         return -1;
  162.     }
  163.     if (command != POL_FDS)        /* illegal ioctl() request */
  164.     {
  165.         u.u_error = EINVAL;        
  166.         u.u_rval1 = -1;
  167.         return -1;
  168.     }
  169.     
  170.     if (pol_s.timeout != -1 && pol_s.timeout != 0)    /* is there a timeout? */
  171.     {
  172.         timeout_ticks = start_ticks + pol_s.timeout * (HZ)/1000;
  173.         timeout_idx = timeout(    poltimeo,        /* wake us up later */
  174.                                 (caddr_t)NULL,
  175.                                 pol_s.timeout * (HZ)/1000);
  176.     }
  177.  
  178.     DB(printf("Start for loop.\n"));    
  179.     DB(printf("Start while loop.\n"));
  180.  
  181.                 /* COLLECT READ AND WRITE ADDRESSES TO SCAN */
  182.                 
  183.     if (poladdr( pol_s.rfds, rfds_pol, &rfds_num, POL_READ_FLAG) == -1)
  184.     {
  185.         if (timeout_idx != 0 && lbolt < timeout_ticks)
  186.             untimeout(timeout_idx);
  187.         return -1;
  188.     }
  189.     if (poladdr( pol_s.wfds, wfds_pol, &wfds_num, POL_WRITE_FLAG) == -1)
  190.     {
  191.         if (timeout_idx != 0 && lbolt < timeout_ticks)
  192.             untimeout(timeout_idx);
  193.         return -1;
  194.     }
  195.  
  196.     pol_s.rfds = pol_s.wfds = 0;
  197.  
  198.                         /* MAIN POLLING LOOP */
  199.     while(1)
  200.     {
  201.         do
  202.         {
  203.             pol_intr = 0;
  204.             spl0();
  205.                     /* READS */
  206.             for (i=0; i < rfds_num; i++)
  207.             {
  208.                 if (rfds_pol[i].ttyflags != IS_PIPE &&
  209.                     !(*(short *)(rfds_pol[i].addr + T_CFLAG_OFF) & CLOCAL) &&
  210.                     !(*(short *)(rfds_pol[i].addr + T_STATE_OFF) & CARR_ON))
  211.                         char_cnt = 1;
  212.                 else
  213.                     switch (rfds_pol[i].ttyflags)
  214.                     {
  215.                     case IS_PTM      :    char_cnt =
  216.                                   *(int *)(rfds_pol[i].addr + TOUTQ_CC_OFF) +
  217.                                 *(short *)(rfds_pol[i].addr + TBUF_CNT_OFF);
  218.                                     break;
  219.                     case IS_PIPE  :    char_cnt = *(int *)(rfds_pol[i].addr);
  220.                                     break;
  221.                     default          :
  222.                                     char_cnt =
  223.                                  *(int *)(rfds_pol[i].addr + TCANQ_CC_OFF);
  224.                                    if ((((struct tty *)rfds_pol->addr)->t_lflag
  225.                                                             & ICANON) == 0)
  226.                                     char_cnt +=
  227.                                  *(int *)(rfds_pol[i].addr + TRAWQ_CC_OFF);
  228.                                 break;
  229.                     }                
  230.                 if (char_cnt != 0)
  231.                 {
  232.                     pol_s.rfds |= (1 << rfds_pol[i].fd);
  233.                     hits++;
  234.                 }
  235.             }
  236.  
  237.                     /* WRITES */
  238.             for (i=0; i < wfds_num; i++)
  239.             {
  240.                 char_cnt = 0;
  241.                 if (wfds_pol[i].ttyflags != IS_PIPE &&
  242.                     !(*(short *)(wfds_pol[i].addr + T_CFLAG_OFF) & CLOCAL) &&
  243.                     !(*(short *)(wfds_pol[i].addr + T_STATE_OFF) & CARR_ON))
  244.                         char_cnt = 1;
  245.                 else
  246.                     switch (wfds_pol[i].ttyflags)
  247.                     {
  248.                         case IS_PIPE  :
  249.                             if (*(int *)(wfds_pol[i].addr) < PIPE_MAX)
  250.                                 char_cnt = 1;
  251.                         default          :
  252.                             if (!(*(short *)(wfds_pol[i].addr + T_STATE_OFF)
  253.                                                             & TBLOCK))
  254.                                 char_cnt = 1;
  255.                     }
  256.  
  257.                 if (char_cnt != 0)
  258.                 {
  259.                     pol_s.wfds |= (1 << wfds_pol[i].fd);
  260.                     hits++;
  261.                 }
  262.             }
  263.                         /* DO WE HAVE SOMETHING TO REPORT? */
  264.                         
  265.             if (hits != 0)
  266.             {
  267.                 if (timeout_idx != 0 && lbolt < timeout_ticks)
  268.                     untimeout(timeout_idx);
  269.                 DB(printf("got result\n"));
  270.                 if (copyout(&pol_s, polfd_p, sizeof(struct polfd)) != 0)
  271.                 {
  272.                     u.u_error = EFAULT;
  273.                     u.u_rval1 = -1;
  274.                 }
  275.                 else u.u_rval1 = hits;
  276.                 return u.u_rval1;
  277.             }
  278.             
  279.             spltty();
  280.         } while (pol_intr != 0);    /* was there activity during scan */
  281.  
  282.                             /* GO TO SLEEP */
  283.  
  284.         DB(printf("Going to sleep\n"));
  285.         if (pol_s.timeout == 0 || (
  286.             pol_s.timeout != -1 && lbolt >= timeout_ticks))
  287.         {
  288.                 spl0();
  289.                 if (timeout_idx != 0 && lbolt < timeout_ticks)
  290.                     untimeout(timeout_idx);
  291.                 u.u_rval1 = 0;
  292.                 return 0;
  293.         }
  294.         sleep((caddr_t *)&pol_in_use, PSLEP);
  295.         spl0();
  296.     }
  297. }
  298.  
  299. /*---------------------------------------------------------------------------
  300. **
  301. **    wakepl - this is our wakeup substitute
  302. **
  303. **--------------------------------------------------------------------------*/
  304. wakepl(caddr)
  305. caddr_t caddr;
  306. {
  307.     if (pol_in_use > 0)
  308.     {
  309.         DB(printf("wakepl called\n"));
  310.         wakeup((caddr_t)&pol_in_use);
  311.     }
  312.     return wakeup(caddr);        /* call original wakeup() */
  313. }
  314.  
  315. /*---------------------------------------------------------------------------
  316. **
  317. **    poltimeo - this is our timeout() wakeup so we can return on timeout
  318. **
  319. **--------------------------------------------------------------------------*/
  320. poltimeo()
  321. {
  322.     if (pol_in_use > 0)
  323.     {
  324.         DB(printf("timedout wakeup\n"));
  325.         wakeup((caddr_t)&pol_in_use);        /* wake up all pol's */
  326.     }
  327. }
  328.     
  329. /*---------------------------------------------------------------------------
  330. **
  331. **    ttinpol - out ttin() substitute
  332. **
  333. **--------------------------------------------------------------------------*/
  334. ttinpol(tty_p, flag)
  335. struct tty *tty_p;
  336. int flag;
  337. {
  338.     if (pol_in_use > 0)
  339.     {
  340.         DB(printf("ttinpol called\n"));
  341.         wakeup((caddr_t)&pol_in_use);
  342.     }
  343.     pol_intr = 1;
  344.     return ttin(tty_p, flag);        /* call original ttin() */
  345. }
  346.  
  347. /*---------------------------------------------------------------------------
  348. **
  349. **    ttwrpol - out ttwrite() substitute
  350. **
  351. **--------------------------------------------------------------------------*/
  352. ttwrpol(tty_p)
  353. struct tty *tty_p;
  354. {
  355.     if (pol_in_use > 0)
  356.     {
  357.         DB(printf("ttwrpol called\n"));
  358.         wakeup((caddr_t)&pol_in_use);
  359.     }
  360.     pol_intr = 1;
  361.     return ttwrite(tty_p);            /* call original ttwrite() */
  362. }
  363.  
  364.  
  365. /*---------------------------------------------------------------------------
  366. **
  367. **    poladdr - collects addresses to scan after each char in or out
  368. **
  369. **--------------------------------------------------------------------------*/
  370. poladdr(fmask, fds_pol, num_fds, flag)
  371. int fmask, *num_fds, flag;
  372. struct pol_table *fds_pol;
  373. {
  374.     int i, j;
  375.     struct inode *fd_inode;
  376.     struct tty *major_tty;
  377.     struct Link *fd_link;
  378.     
  379.     for (i = 0; i != -1 && i <= NPOLFILE; i++)    /* for each fd */
  380.     {        
  381.         if ( (fmask & (1 << i)) == 0)            /* is it marked? */
  382.             continue;
  383.         DB(printf("Found fd\n"));
  384.         fds_pol->fd = i;
  385.         fds_pol->ttyflags = 0;
  386.         if (u.u_ofile[i] == NULL)                /* is it active? */
  387.         {
  388.             u.u_error = EBADF;        
  389.             u.u_rval1 = -1;
  390.             return -1;
  391.         }
  392.          fd_inode = (u.u_ofile[i])->f_up.f_uinode; /*is it active? */
  393.         if (fd_inode == NULL)
  394.         {
  395.             u.u_error = EBADF;        
  396.             u.u_rval1 = -1;
  397.             return -1;
  398.         }
  399.  
  400.  
  401.                     /* IS IT A CHARACTER SPECIAL DEVICE? */
  402.                     
  403.         if ( (fd_inode->i_ftype & IFMT) == IFCHR)
  404.         {
  405.             DB(printf("char device\n"));
  406.             DB(printf("major %d\n",major(fd_inode->i_rdev)));
  407.             DB(printf("minor %d\n",minor(fd_inode->i_rdev)));
  408.             
  409.                 /* DOES THIS MAJOR NUMBER LACK A TTY STRUCTURE? */
  410.  
  411.             if ( (major_tty=cdevsw[major(fd_inode->i_rdev)].d_ttys) == 0)
  412.                             /* IS IT AN SXT DEVICE */
  413.                 if (cdevsw[major(fd_inode->i_rdev)].d_open == sxtopen)
  414.                     fds_pol->addr = (char *)sxt_buf +
  415.                             (long)LINK(minor(fd_inode->i_rdev)) *
  416.                             (long)(sizeof(struct Link) +
  417.                              sizeof(struct Channel) * (MAXPCHAN-1)) +
  418.                             (long)&((struct Link *)0)->chans[0] +
  419.                                 CHAN(minor(fd_inode->i_rdev)) *
  420.                                 sizeof(struct Channel) +
  421.                                 (long)&((struct Channel *)0)->tty;
  422.                         /* IS IT A MASTER PTY DEVICE? */
  423.                 else if (cdevsw[major(fd_inode->i_rdev)].d_open == ptmopen)
  424.                 {            /* master ptys */
  425.                         fds_pol->addr = (char *)pts_tty +
  426.                             minor(fd_inode->i_rdev) * sizeof(struct tty);
  427.                         fds_pol->ttyflags = IS_PTM;
  428.                 }                    
  429.                 else
  430.                 {
  431.                     u.u_error = ENXIO;        
  432.                     u.u_rval1 = -1;
  433.                     return -1;
  434.                 }
  435.             else        /* it has a tty structure */
  436.                 fds_pol->addr = (char *)major_tty +
  437.                     minor(fd_inode->i_rdev) * sizeof(struct tty);
  438.         }
  439.         else if ( (fd_inode->i_ftype & IFMT) == IFIFO)    /* is it a pipe? */
  440.         {
  441.                     fds_pol->addr = (char *)&fd_inode->i_size;
  442.                      fds_pol->ttyflags = IS_PIPE;
  443.         }                    
  444.         else
  445.         {
  446.             u.u_error = EBADF;        
  447.             u.u_rval1 = -1;
  448.             return -1;
  449.         }
  450.         DB(printf("Got address\n"));
  451.         (*num_fds)++;
  452.         fds_pol++;
  453.         if ( (fmask &= ~(1 <<i)) == 0)    /* remove bit from mask */
  454.             break;
  455.     }
  456.     return 0;
  457. }
  458.