home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / ISP / bind.4.8.3.lzh / BIND483 / RES / select.c < prev    next >
Text File  |  1994-09-23  |  6KB  |  287 lines

  1. /* ------------------------------------------------------------------- *
  2.  |
  3.  | OS9Lib:  select()
  4.  |
  5.  |
  6.  |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
  7.  |                           Ulli Dessauer, Germering and
  8.  |                           Reimer Mellin, Muenchen
  9.  |                           (W-Germany)
  10.  |
  11.  |  This  programm can  be  copied and  distributed freely  for any
  12.  |  non-commercial  purposes.   It can only  be  incorporated  into
  13.  |  commercial software with the written permission of the authors.
  14.  |
  15.  |  If you should modify this program, the authors would appreciate
  16.  |  a notice about the changes. Please send a (context) diff or the
  17.  |  complete source to:
  18.  * ----------------------------------------------------------------- */
  19.  
  20. /* modified by Andrzej Kotanski to works also on socket paths - 1994 */
  21.  
  22. #include <time.h>
  23. #include <stdio.h>
  24. #include <errno.h>
  25. #include <signal.h>
  26.  
  27. #define reg         register
  28. #define READY_SIG   (31)
  29. #define ALM_SIG     (2000)
  30.  
  31. /*#define SEL_PRT_FLG*/
  32.  
  33. static int sigarrived = 0;     /* READY_SIG occurred ? */
  34. extern int  ev_id;
  35.  
  36. static void sighand(sig)
  37. int sig;
  38. {
  39.    sigarrived = sig;
  40. }
  41.  
  42. /*
  43.  * S E L E C T
  44.  *  returns # of fd's ready for read/write/network, -1 if interrupted or
  45.  *  a bad fd was encountered or 0 if none fd is ready for the action.
  46.  */
  47.  
  48. int select(fds, rdp, wrp, exp, timeout)
  49. int fds;
  50. reg int *rdp, *wrp, *exp;
  51. struct timeval *timeout;
  52. {
  53.    reg int i, ii = -2;
  54.    reg unsigned int shift;
  55.    int tout;
  56.    reg int rd, wr, ex;
  57.    int leave = 0;
  58.    int tmp = 0;
  59.    int signaled = 0;
  60.    int alm_id, pid;
  61.    int ev_value = 0;
  62.    char evname[15];
  63.    int poll = 0;
  64.  
  65. /*
  66. **  if required....
  67. */
  68.  
  69.    pid = getpid();
  70.  
  71. /*
  72. **  Calculate time dependents of action
  73. */
  74.  
  75.    poll = ( (timeout != NULL) && 
  76.         (timeout->tv_sec == 0) && 
  77.         (timeout->tv_usec == 0) )
  78.         ? 1
  79.         : 0;
  80.  
  81.    tout = ( timeout != NULL ) 
  82.         ? (1 + timeout->tv_sec * CLK_TCK + (timeout->tv_usec *
  83.                                                     CLK_TCK) / 1000000) 
  84.         : 0;
  85.  
  86. /* 
  87. **  set pointers to dummy value if unspecified.
  88. **  these dummies are important as the value of the pointer is not used 
  89. **  as a check.
  90. */
  91.  
  92.    if (rdp == 0) rdp = &tmp;
  93.    if (wrp == 0) wrp = &tmp;
  94.    if (exp == 0) exp = &tmp;
  95.  
  96.    rd = wr = ex = 0;
  97.  
  98. /*
  99. **  signal handlers....
  100. */
  101.  
  102.     if ( poll != 1 ) {
  103.     signal(READY_SIG, sighand);
  104.     signal(ALM_SIG, sighand);
  105.     sigarrived = 0;
  106.     }
  107.  
  108. /*
  109. **  action
  110. */
  111.  
  112.     while (leave == 0) {
  113.  
  114. /*
  115. **  check for ready IO on rdp and network if selected
  116. */
  117.     shift = (1 << (fds - 1));
  118.     for (i = fds - 1; i >= 0; shift >>= 1, --i) {
  119.  
  120. /* 
  121. **  if data is available for reading mark it as ready.
  122. **  _gs_rdy() returns the number of bytes on path or -1 if invalid
  123. **    path and if no data is present in which case errno is set to 246
  124. **    i.e. device not ready.
  125. **  E_UNKSVC on this path device you cannot ask for ready bytes
  126. */
  127.  
  128.         if (*rdp & shift && (_gs_rdy(i) > 0 || (errno == E_UNKSVC))) {
  129.         rd |= shift;
  130.         leave++;
  131.         }
  132.  
  133. /* 
  134. **  if network condition is ready mark leave as ready 
  135. **  ev_value is initialized to 0 and can only be modified later.
  136. **  THE LOGIC HERE DOES NOT ALLOW POLLING THE NETWORK - yet
  137. */
  138.  
  139.         if (*exp & shift && (ev_value > 0)) {
  140.         ex |= shift;
  141.         leave++;
  142.         }
  143.  
  144.         }
  145.  
  146. /*
  147. **  if polling is required then that is all...
  148. */
  149.  
  150.     if ( poll == 1 ) {
  151.         break;
  152.         }
  153.  
  154. /*
  155. **  you requested a timeout i.e. now set the signals to break this wait
  156. **  state which will be tsleep() for actions without the network
  157. */
  158.  
  159.     if (leave == 0) {
  160.  
  161. /* 
  162. **  prepare for waiting .., block signals 
  163. */
  164.  
  165.         sigmask(1);
  166.  
  167.         shift = (1 << (fds - 1));
  168.         for (i = fds - 1; i >= 0; shift >>= 1, --i) {
  169.  
  170.         if (*rdp & shift) {
  171.             _ss_ssig(i, READY_SIG);
  172.             signaled |= shift;
  173.             }
  174.  
  175.         if (*exp & shift) {
  176.             signaled |= shift;
  177.             }
  178.  
  179.         }
  180.  
  181. /*
  182. **  two possibilities the first (*exp == 0) no network and just 
  183. **  pipes are envolved, second a network device is also specified.
  184. */
  185.  
  186.         if (*exp == 0) {
  187.  
  188. /* 
  189. **  wait specified timeout (implicit unblock signal !!) 
  190. */
  191.  
  192.         i = 0;
  193.         i = tsleep(tout);
  194.         ii = i;
  195.  
  196. /* 
  197. **  if we are interupted by one of our own signals 
  198. **  or timed-out then we are finished...
  199. */
  200.  
  201.         if (sigarrived == 0) {
  202.  
  203.             if (i < 0) {        /* error ? */
  204.             leave = -1;
  205.             }
  206.             else if ( i == 0 ) {    /* no ticks left */
  207.             if ( tout == 0 ) {    /* but.infinite timout wanted */
  208.                 leave = -2;
  209.                 }
  210.             else {        /* must have timed out */
  211.                 leave = 0;
  212.                 }
  213.             }
  214.             else {        /* ticks remain ? pretend interrupt */
  215.             leave = -2;
  216.             }
  217.  
  218.             break;        /* exit while */
  219.             }
  220.  
  221.         } 
  222.         else {
  223.  
  224. /*
  225. **  network also there then wait on event
  226. */
  227.  
  228.         if (tout < 50) tout = 50;    /* XXX */
  229.  
  230.         alm_id = alm_set(ALM_SIG, tout);
  231.         ev_value = _ev_wait(ev_id, 1, 32767);
  232.         sigmask(0);
  233.  
  234.         alm_delete(alm_id);
  235.         if (sigarrived == ALM_SIG) {
  236. /*            printf("select: ALM_SIG ev_value %d\n",ev_value);    */
  237.             break;
  238.             }
  239.         else if ( sigarrived == READY_SIG ) {
  240. /*              printf("select: READY_SIG ev_value %d\n",ev_value);    */
  241.             continue;
  242.             }
  243.         else {
  244. /*            printf("select: ELSE ev_value %d\n",ev_value);  */
  245.             leave++;
  246.             ex = *exp;
  247.             }
  248.         }
  249.         }                         /* if ( leave ) */
  250.  
  251.     }                            /* while */
  252.  
  253. /* 
  254. **  reset signals .. 
  255. */
  256.  
  257.     if ( poll != 1 ) {
  258.     shift = (1 << (fds - 1));
  259.     for (i = fds - 1; i >= 0; shift >>= 1, --i) {
  260.         if (signaled & shift) _ss_rel(i);
  261.         }
  262.     }
  263.  
  264. /* 
  265. **  get results.. 
  266. */
  267.  
  268.    *rdp = rd;
  269.    *wrp = wr;
  270.    *exp = ex;
  271.  
  272. /*
  273.    if ( timeout != NULL && poll != 1 && leave == 0 ) {
  274.     printf 
  275.       ("select: timeout %d tout %d ii %d sigarrived %d leave %d poll %d\n",
  276.       timeout->tv_sec,tout,ii,sigarrived,leave,poll );
  277.     }
  278. */
  279.  
  280.     if ( poll != 1 && leave == -1 ) {
  281.           ("select: timeout %d tout %d ii %d sigarrived %d leave %d poll %d\n",
  282.           timeout->tv_sec,tout,ii,sigarrived,leave,poll );
  283.         }
  284.  
  285.    return leave;
  286. }
  287.