Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!decwrl!amdcad!lll-crg!gymble!umcp-cs!steve From: steve@umcp-cs.UUCP (Steve D. Miller) Newsgroups: net.unix-wizards,net.unix,net.dcom Subject: Re: Need Non-Blocking Terminal Input Function For Berkeley 4.2 Message-ID: <2877@umcp-cs.UUCP> Date: Sun, 26-Jan-86 13:25:16 EST Article-I.D.: umcp-cs.2877 Posted: Sun Jan 26 13:25:16 1986 Date-Received: Tue, 28-Jan-86 05:18:22 EST References: <482@kontron.UUCP> Reply-To: steve@tove.UUCP (Steve D. Miller) Distribution: net Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 100 Xref: watmath net.unix-wizards:16554 net.unix:6945 net.dcom:1634 In article <482@kontron.UUCP> cramer@kontron.UUCP writes: >Does anyone know of a way to do read from a terminal under Berkeley 4.2 UNIX >so that after a specified number of seconds control is returned to the >program if there is no response? ... Methinks that what you want to use is select(2). Something similar to what I think you want to do would probably look like: #include /* for struct timeval */ ... struct timeval timeout; int s, readfds, nfound; /* s = fd we want to look at */ ... timeout.tv_sec = ; timeout.tv_usec = readfds = 1 << s; /* form bit mask */ /* * This will time out after the period specified in timeout * (and return zero in &readfds), or return before that with * nfound == 1 and (1 << s) set in readfds). See the man entry * for more details; select() falls into the category of * "really massively useful system calls that you want to * know about". */ nfound = select(32, &readfds, (int *) 0, (int *) 0, &timeout); if (nfound < 0) { /* error */ } if (nfound > 0) { /* got something */ read(s, buf, ); ... } else { /* whatever happens when you don't get input */ } In general, select() will let you multiplex input over a number of file descriptors in which you are interested in reading from, writing to, or knowing about "exceptional conditions" (means nothing in 4.2, though I could be wrong, but means at least "out-of-band data" in 4.3) on. If you're select()ing on more than one descriptor, then you want to check the returned bit masks (i.e., "if (readfds & (1 << s)) { .. }) for each descriptor you're interested in; the above example is simplified since it deals with only one descriptor. Note (for those of you who are interested) that all this changes in 4.3BSD. The above code will still work, but is no longer correct. Since there are more than 32 fds available, a more general scheme has been devised, using struct fd_set's (which are really just arrays of integer bit masks, though you don't need to know that; they're defined in , and can also be referred to as fd_sets, since they're typedef'ed). Four macros are defined for use in manipulating fd_sets: FD_SET(n, p), which adds fd n to the fd_set pointed to by p; FD_CLR(n, p), which removes fd n from the fd_set pointed to by p; FD_ISSET(n, p), which returns an indication of whether or not fd n is a member of the fd_set pointed to by p; and FD_ZERO(p), which clears the fd_set pointed to by p. Therefore, the code above would, under 4.3BSD, look like: #include #include /* for struct timeval */ ... struct timeval timeout; int s, nfound; /* s = fd we want to look at */ fd_set readfds; ... timeout.tv_sec = ; timeout.tv_usec = FD_ZERO(&readfds); FD_SET(s, &readfds); /* * This will time out after the period specified in timeout * (and return readfds with no bits set), or return before that with * nfound == 1 and FD_ISSET(s, &readfds) == true. See the man entry * for more details; select() falls into the category of * "really massively useful system calls that you want to * know about". */ nfound = select(32, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); if (nfound < 0) { /* error */ } if (nfound > 0) { /* got something */ read(s, buf, ); ... } else { /* whatever happens when you don't get input */ } Again, if we were select()ing on more than one descriptor, we'd want to check the status of the returned fd_set with FD_ISSET, since the number of fds available for reading (as indicated by nfound) would in that case not indicate that we could read off of any given fd. I hope this is of some use (to you or to someone else)... -Steve