|
|
1.1 ! root 1: /* select.c - select() abstractions */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/compat/RCS/select.c,v 7.3 90/05/22 19:33:29 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/compat/RCS/select.c,v 7.3 90/05/22 19:33:29 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: select.c,v $ ! 12: * Revision 7.3 90/05/22 19:33:29 mrose ! 13: * update ! 14: * ! 15: * Revision 7.2 89/12/05 22:04:41 mrose ! 16: * touch-up ! 17: * ! 18: * Revision 7.1 89/11/30 23:53:31 mrose ! 19: * touch-up ! 20: * ! 21: * Revision 7.0 89/11/23 21:23:24 mrose ! 22: * Release 6.0 ! 23: * ! 24: */ ! 25: ! 26: /* ! 27: * NOTICE ! 28: * ! 29: * Acquisition, use, and distribution of this module and related ! 30: * materials are subject to the restrictions of a license agreement. ! 31: * Consult the Preface in the User's Manual for the full terms of ! 32: * this agreement. ! 33: * ! 34: */ ! 35: ! 36: ! 37: /* LINTLIBRARY */ ! 38: ! 39: #include <errno.h> ! 40: #include <stdio.h> ! 41: #include "manifest.h" ! 42: #include "tailor.h" ! 43: #include <sys/stat.h> ! 44: ! 45: ! 46: extern int errno; ! 47: ! 48: /* */ ! 49: ! 50: ! 51: #ifdef SOCKETS ! 52: ! 53: #include <sys/time.h> ! 54: ! 55: ! 56: /* Synchronous multiplexing: ! 57: < 0 : block indefinately ! 58: = 0 : poll ! 59: > 0 : wait ! 60: */ ! 61: ! 62: int selsocket (nfds, rfds, wfds, efds, secs) ! 63: int nfds; ! 64: fd_set *rfds, ! 65: *wfds, ! 66: *efds; ! 67: int secs; ! 68: { ! 69: int n; ! 70: fd_set ifds, ! 71: ofds, ! 72: xfds; ! 73: struct timeval tvs; ! 74: register struct timeval *tv = &tvs; ! 75: ! 76: if (secs != NOTOK) ! 77: tv -> tv_sec = secs, tv -> tv_usec = 0; ! 78: else ! 79: tv = NULL; ! 80: ! 81: if (rfds) ! 82: ifds = *rfds; ! 83: if (wfds) ! 84: ofds = *wfds; ! 85: if (efds) ! 86: xfds = *efds; ! 87: for (;;) { ! 88: switch (n = select (nfds, rfds, wfds, efds, tv)) { ! 89: case OK: ! 90: if (secs == NOTOK) ! 91: break; ! 92: return OK; ! 93: ! 94: case NOTOK: ! 95: default: ! 96: return n; ! 97: } ! 98: ! 99: if (rfds) ! 100: *rfds = ifds; ! 101: if (wfds) ! 102: *wfds = ofds; ! 103: if (efds) ! 104: *efds = xfds; ! 105: } ! 106: } ! 107: #endif ! 108: ! 109: /* */ ! 110: ! 111: #ifdef EXOS ! 112: ! 113: #ifdef SYS5 ! 114: ! 115: /* There seems to be a bug in the SYS5 EXOS select() routine when a socket can ! 116: be read immediately (don't know about write). The bug is that select() ! 117: returns ZERO, and the mask is zero'd as well. The code below explicitly ! 118: checks for this case. ! 119: */ ! 120: ! 121: #include "sys/soioctl.h" ! 122: ! 123: ! 124: int selsocket (nfds, rfds, wfds, efds, secs) ! 125: int nfds; ! 126: fd_set *rfds, ! 127: *wfds, ! 128: *efds; ! 129: int secs; ! 130: { ! 131: register int fd; ! 132: int n; ! 133: fd_set ifds, ! 134: ofds; ! 135: long nbytes, ! 136: usecs; ! 137: ! 138: if (secs != NOTOK) ! 139: usecs = secs * 1000; ! 140: else ! 141: usecs = 0xffff; /* used to be ~(1L << (8 * sizeof usecs - 1)) */ ! 142: ! 143: if (rfds) ! 144: ifds = *rfds; ! 145: if (wfds) ! 146: ofds = *wfds; ! 147: if (efds) ! 148: FD_ZERO (efds); ! 149: ! 150: for (;;) { ! 151: switch (n = select (nfds + 1, rfds, wfds, usecs)) { /* +1 for UNISYS */ ! 152: case OK: ! 153: if (rfds) ! 154: for (fd = 0; fd < nfds; fd++) ! 155: if (FD_ISSET (fd, &ifds) ! 156: && ioctl (fd, FIONREAD, (char *) &nbytes) ! 157: != NOTOK ! 158: && nbytes > 0) { ! 159: FD_SET (fd, rfds); ! 160: n++; ! 161: } ! 162: if (n == 0 && secs == NOTOK) ! 163: break; ! 164: return n; ! 165: ! 166: case NOTOK: ! 167: default: ! 168: return n; ! 169: } ! 170: ! 171: if (rfds) ! 172: *rfds = ifds; ! 173: if (wfds) ! 174: *wfds = ofds; ! 175: } ! 176: } ! 177: #endif ! 178: #endif ! 179: ! 180: /* */ ! 181: ! 182: /* These routines are necessary because some network interfaces (i.e., ! 183: the CAMTEC) don't support real select()'s. This code first calls any ! 184: special interface-specific select() routines, and then calls the ! 185: standard selsocket routine. ! 186: ! 187: In general, inter-working between network interfaces with a real select ! 188: and interfaces with a real select won't work well. You shouldn't expect ! 189: to be able to handle parallel notification of events on several transport ! 190: descriptors. Hopefully, you will only need to work synchronously on one or ! 191: two descriptors. ! 192: */ ! 193: ! 194: static IFP sfnx[FD_SETSIZE] = { NULL }; ! 195: ! 196: ! 197: IFP set_select_fd (fd, fnx) ! 198: int fd; ! 199: IFP fnx; ! 200: { ! 201: IFP ofnx; ! 202: ! 203: if (fd < 0 || fd >= FD_SETSIZE) ! 204: return NULLIFP; ! 205: ! 206: ofnx = sfnx[fd]; ! 207: sfnx[fd] = fnx; ! 208: ! 209: return ofnx; ! 210: } ! 211: ! 212: set_select_mask (mask,fnx) ! 213: fd_set *mask; ! 214: IFP fnx; ! 215: { ! 216: int fd; ! 217: ! 218: for (fd = 0; fd < FD_SETSIZE; fd++) ! 219: if (FD_ISSET (fd, mask)) ! 220: sfnx[fd] = fnx; ! 221: } ! 222: ! 223: /* */ ! 224: ! 225: int xselect (nfds, rfds, wfds, efds, secs) ! 226: int nfds; ! 227: fd_set *rfds, ! 228: *wfds, ! 229: *efds; ! 230: int secs; ! 231: { ! 232: int n; ! 233: register int fd; ! 234: fd_set ifds, ! 235: ofds, ! 236: xfds; ! 237: static int nsysfds = NOTOK; ! 238: ! 239: if (nsysfds == NOTOK) ! 240: nsysfds = getdtablesize (); ! 241: if (nfds > FD_SETSIZE) ! 242: nfds = FD_SETSIZE; ! 243: if (nfds > nsysfds + 1) ! 244: nfds = nsysfds + 1; ! 245: ! 246: for (fd = 0; fd < nfds; fd++) ! 247: if (sfnx[fd] != NULLIFP ! 248: && ((rfds && FD_ISSET (fd, rfds)) ! 249: || (wfds && FD_ISSET (fd, wfds)) ! 250: || (efds && FD_ISSET (fd, efds)))) ! 251: return ((*sfnx[fd]) (nfds, rfds, wfds, efds, secs)); ! 252: ! 253: if (rfds) ! 254: ifds = *rfds; /* struct copy */ ! 255: if (wfds) ! 256: ofds = *wfds; /* struct copy */ ! 257: if (efds) ! 258: xfds = *efds; /* struct copy */ ! 259: ! 260: if ((n = selsocket (nfds, rfds, wfds, efds, secs)) != NOTOK) ! 261: return n; ! 262: ! 263: if (errno == EBADF) { ! 264: struct stat st; ! 265: ! 266: if (rfds) ! 267: FD_ZERO (rfds); ! 268: if (wfds) ! 269: FD_ZERO (wfds); ! 270: if (efds) ! 271: FD_ZERO (efds); ! 272: ! 273: n = 0; ! 274: for (fd = 0; fd < nfds; fd++) ! 275: if (((rfds && FD_ISSET (fd, &ifds)) ! 276: || (wfds && FD_ISSET (fd, &ofds)) ! 277: || (efds && FD_ISSET (fd, &xfds))) ! 278: && fstat (fd, &st) == NOTOK) { ! 279: if (rfds && FD_ISSET (fd, &ifds)) ! 280: FD_SET (fd, rfds); ! 281: if (wfds && FD_ISSET (fd, &ofds)) ! 282: FD_SET (fd, wfds); ! 283: if (efds && FD_ISSET (fd, &xfds)) ! 284: FD_SET (fd, efds); ! 285: ! 286: SLOG (compat_log, LLOG_EXCEPTIONS, "", ! 287: ("fd %d has gone bad", fd)); ! 288: n++; ! 289: } ! 290: ! 291: if (n) ! 292: return n; ! 293: ! 294: errno = EBADF; ! 295: } ! 296: ! 297: return NOTOK; ! 298: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.