pedicone@mozart.steinmetz (07/14/88)
I have an application in which I need to query tty input from a C program. I can't use getc because I have other processing that must continue. It seems that I have to use ioctl in order to query the terminal directly. Is this the best way to do it? If so, does anybody have an example of a driver that uses it. If this is not the best way, what should I do? I'm using a Sun 3/260. Any insight would be appreciated! John
ron@topaz.rutgers.edu (Ron Natalie) (07/15/88)
I believe what you are asking is how to detect when there
is TTY input to read. This can be done with the select
call. A simplistic example:
int rflags;
int ttyfd = 0; /* Standard input, usually 0 */
struct timeval tv;
rflags = 1; /* Really 1 << ttyfd, but not sure to be defined */
tv.sec = 0; /* Setting timeout to zero causes select to return */
tv.usec =0; /* Immediately */
select(1, &rflags, (int *) 0, (int *) 0, &tv);
if(rflags) {
/* There is something to read */
read(ttyfd, &c, 1);
}
daveh@marob.MASA.COM (Dave Hammond) (07/18/88)
In article <Jul.14.21.26.56.1988.8739@topaz.rutgers.edu> ron@topaz.rutgers.edu (Ron Natalie) writes: >I believe what you are asking is how to detect when there >is TTY input to read. This can be done with the select >call. A simplistic example: >[...stuff deleted...] > select(1, &rflags, (int *) 0, (int *) 0, &tv); > if(rflags) { > /* There is something to read */ > read(ttyfd, &c, 1); > } Or in SysV land- #include <fcntl.h> int fcntl_flags = fcntl(0, F_GETFL, 0); /* get fcntl flags */ fcntl(0, F_SETFL, fcntl_flags | O_NDELAY); /* set "no delay" */ if (read(0, &ch, 1) > 0) /* there's a char queued */ do_something(); fcntl(0, F_SETFL, fcntl_flags); /* unset "no delay" */ Read in O_NDELAY mode will return -1 of the read would block (i.e. there are no chars waiting in the tty queue). This allows you to check for pending input without causing the program to "block" waiting for input. Dave Hammond UUCP: {uunet|rutgers|spl1|...}!hombre!marob!daveh -----------------------------------------------------
rml@hpfcdc.HP.COM (Bob Lenk) (07/21/88)
> Or in SysV land- > > #include <fcntl.h> > > int fcntl_flags = fcntl(0, F_GETFL, 0); /* get fcntl flags */ ^^^^^^^ O_GETFL > fcntl(0, F_SETFL, fcntl_flags | O_NDELAY); /* set "no delay" */ ^^^^^^^ O_SETFL > if (read(0, &ch, 1) > 0) /* there's a char queued */ > do_something(); > fcntl(0, F_SETFL, fcntl_flags); /* unset "no delay" */ ^^^^^^^ O_GETFL > > Read in O_NDELAY mode will return -1 of the read would block (i.e. there ^^ 0 > are no chars waiting in the tty queue). This allows you to check for > pending input without causing the program to "block" waiting for input. Note that the 0 return from read() cannot be distinguished from an end-of-file condition. This same code should work on a BSD system, but there are two differences (not necessarily relevant as the code is written). First, the return value for no data is -1 (with errno EWOULDBLOCK) rather than 0. Second, on System V "no delay" mode is a property of the file descriptor (including copies shared across fork, dup, or equivalent), while on BSD it is a property of the terminal. Because of this, code using the fcntl() O_NDELAY model will be more generally portable than code using select(). The POSIX standard uses this model, but renames O_NDELAY to O_NONBLOCK so that both flavors of system can conform without hurting backward compatibility. Bob Lenk {ihnp4, hplabs}!hpfcla!rml rml%hpfcla@hplabs.hp.com
daveh@marob.MASA.COM (Dave Hammond) (07/25/88)
In article <5740024@hpfcdc.HP.COM> rml@hpfcdc.HP.COM (Bob Lenk) writes: >> int fcntl_flags = fcntl(0, F_GETFL, 0); /* get fcntl flags */ > ^^^^^^^ > O_GETFL >> fcntl(0, F_SETFL, fcntl_flags | O_NDELAY); /* set "no delay" */ > ^^^^^^^ > O_SETFL >> if (read(0, &ch, 1) > 0) /* there's a char queued */ >> do_something(); >> fcntl(0, F_SETFL, fcntl_flags); /* unset "no delay" */ > ^^^^^^^ > O_GETFL From the XENIX man page for fcntl: F_GETFL Gets file status flags: O_RDONLY, O_WRONLY, O_RDWR, O_NDELAY, or O_APPEND. F_SETFL Sets file status flags to arg. Only certain flags can be set. While I'll agree that XENIX is not virgin SysV, it is a certified SysV port. I can't recall programs written non-XENIX systems having to be modified (relative to the above F_GETFL/O_GETFL question) to compile under XENIX, or vice-versa. >> Read in O_NDELAY mode will return -1 of the read would block (i.e. there > ^^ > 0 I stand corrected. Indeed, read() returns 0 if O_NDELAY is set and a dry read() occurs. The above code fragment likely works because it tests for a success rather than failure return value. Dave Hammond UUCP: !{uunet|rutgers|spl1|...}!hombre!{marob|dsix2}!daveh ---------------------------------------------------------------
guy@gorodish.Sun.COM (Guy Harris) (07/26/88)
> > Or in SysV land- > > > > #include <fcntl.h> > > > > int fcntl_flags = fcntl(0, F_GETFL, 0); /* get fcntl flags */ > ^^^^^^^ > O_GETFL ^^^^^^^ F_GETFL, *NOT* "O_GETFL"! There is no "O_GETFL" in any UNIX version I know of.
rml@hpfcdc.HP.COM (Bob Lenk) (07/27/88)
As others have pointed out, it is indeed F_GETFL/F_SETFL, not O_. Sorry for the confusion. Bob Lenk (rml@hpfcla)