home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / unix / bsd / 11134 < prev    next >
Encoding:
Text File  |  1993-01-11  |  3.9 KB  |  116 lines

  1. Xref: sparky comp.unix.bsd:11134 comp.lang.c:19552
  2. Path: sparky!uunet!noc.near.net!hri.com!spool.mu.edu!olivea!sgigate!odin!sgihub!zola!delhi!dps
  3. From: dps@delhi.esd.sgi.com (D.P. Suresh)
  4. Newsgroups: comp.unix.bsd,comp.lang.c
  5. Subject: Re: a unix terminal question
  6. Message-ID: <uonuhjc@zola.esd.sgi.com>
  7. Date: 11 Jan 93 22:48:02 GMT
  8. References: <1iql6kINNisk@ub.d.umn.edu> <1993Jan11.215312.2080@fcom.cc.utah.edu>
  9. Sender: news@zola.esd.sgi.com (Net News)
  10. Organization: Silicon Graphics, Inc.  Mountain View, CA
  11. Lines: 103
  12.  
  13.  
  14. In article <1993Jan11.215312.2080@fcom.cc.utah.edu>, terry@cs.weber.edu writes:
  15. > In article <1iql6kINNisk@ub.d.umn.edu> cbusch@ub.d.umn.edu (Chris) writes:
  16. > >
  17. > >   How does one read in a character from standard input without having
  18. > >the program wait for the key.  Basically, I want to do something like:
  19. > >    if(kbhit()) c=getch();
  20. > >Except that is not standard, and I want it to work on all platforms.
  21. > This is a bad thing to do, unless you have processing to do when characters
  22. > aren't present, and you do your checks relatively infrequently compared to
  23. > the procesing itself; otherwise, you will be in a buzz-loop and suck your
  24. > CPU through the floor.  This is common practice under DOS where there is
  25. > nothing else running, but is a generally bad thing to do.
  26. >
  27. > The CORRECT way to do this:  use the select() or poll() system call to
  28. > wait for an interval or a character to be present.  Resoloution is
  29. > generally 1/1000th of a second; you can effect a poll by having a
  30. > zero-valued timeval struct (as opposed to passing (struct timeval *)NULL).
  31. > This will cause the behaviour you have asked for.  When the select()
  32. > returns that there are characters available, do a read() on the descriptor
  33. > (otherwise, return as if the read() has returned 0 characters).  It
  34. > should be noted that some systems are sensitive to select/read pairing,
  35. > and if you do this, you should have a select() call prior to every read()
  36. > call, regardless of whther or not you use the select information aro simply
  37. > read anyway.
  38.  
  39. select() or poll() in itself will not get you the desired result.
  40. If my memory of DOS does not fail me, kbhit() is a non-blocking call.
  41. It just tells you *at once* whether zero or more keys are waiting for
  42. his/her highness to be read. To get this effect on UNIX, one should
  43. combine select()/poll() with putting the terminal in raw mode.
  44.  
  45. If you dont put the terminal in raw mode and try select()/poll()
  46. then even if you press a key, select()/poll() will not detect them
  47. until CR is given.
  48.  
  49. Here is a code sample:
  50.  
  51. /* Test code for kbhit function */
  52. #include <stdio.h>
  53. #include <termio.h>
  54. #include <unistd.h>
  55. #include <sys/types.h>
  56. #include <sys/time.h>
  57. #include <sys/file.h>
  58.  
  59. kbhit()
  60. {
  61.     fd_set readfds, writefds, exceptfds;
  62.     struct timeval timeout;
  63.     static struct termio    otty, ntty;
  64.     int ret;
  65.  
  66.     /* Create proper environment for select() */
  67.     FD_ZERO( &readfds );
  68.     FD_ZERO( &writefds );
  69.     FD_ZERO( &exceptfds );
  70.     FD_SET( fileno(stdin), &readfds );
  71.  
  72.     /* We shall specify 0.5 sec as the waiting time */
  73.     timeout.tv_sec  = 0;    /*   0 seconds */
  74.     timeout.tv_usec = 500;    /* 500 microseconds */
  75.  
  76.     /* Put tty in raw mode */
  77.     ioctl(fileno(stdout), TCGETA, &otty);
  78.     ntty = otty;
  79.     ntty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL);
  80.     ntty.c_lflag &= ~ICANON;
  81.     ntty.c_lflag |= ISIG;
  82.     ntty.c_cflag &= ~(CSIZE|PARENB);
  83.     ntty.c_cflag |= CS8;
  84.     ntty.c_iflag &= (ICRNL|ISTRIP);
  85.     ntty.c_cc[VMIN] = ntty.c_cc[VTIME] = 1;
  86.     ioctl(fileno(stderr), TCSETAW, &ntty);
  87.  
  88.     /* Do a select */
  89.     ret = select( 1, &readfds, &writefds, &exceptfds, &timeout );
  90.  
  91.     /* Reset the tty back to its original mode */
  92.     ioctl(fileno(stderr), TCSETAW, &otty);
  93.  
  94.     return( ret );
  95. }
  96.  
  97. main()
  98. {
  99.     while( !kbhit() ) {
  100.         /* No key was hit. Do your own processing. */
  101.     }
  102.     printf("Hey. you hit a key.\n");
  103. }
  104.  
  105. /* End of listing */
  106.  
  107.  
  108. WARNING:
  109. This feature should be used wisely. One could incur quite a lot of
  110. performance penalties as expressed by terry.
  111.  
  112. --
  113. D.P.Suresh
  114. dps@esd.sgi.com
  115.